nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: exadel-inc/esl
Pull request #278 (2021-06-21 00:55:03)

fix(esl-utils): isRtl check updated to use computed styles instead of attribute


Patch:
diff --git a/src/modules/esl-utils/dom/rtl.ts b/src/modules/esl-utils/dom/rtl.ts
index dfb6cb0cc..be3261c01 100644
--- a/src/modules/esl-utils/dom/rtl.ts
+++ b/src/modules/esl-utils/dom/rtl.ts
@@ -7,8 +7,7 @@ export type ScrollType = 'default' | 'negative' | 'reverse';
 export abstract class RTLUtils {
   /** Check if the element in a RTL direction context */
   static isRtl(el: HTMLElement = document.body) {
-    const parent = el.closest('[dir]') as HTMLElement;
-    return parent?.dir === 'rtl';
+    return getComputedStyle(el).direction === 'rtl';
   }
 
   /**


Test patch:
diff --git a/src/modules/esl-utils/dom/test/rtl.test.ts b/src/modules/esl-utils/dom/test/rtl.test.ts
index 1d0d32131..80a0047b3 100644
--- a/src/modules/esl-utils/dom/test/rtl.test.ts
+++ b/src/modules/esl-utils/dom/test/rtl.test.ts
@@ -14,33 +14,13 @@ describe('RTLUtils', () => {
       const root = document.createElement('div');
       const el = document.createElement('div');
       root.appendChild(el);
-      root.dir = 'rtl';
 
-      expect(RTLUtils.isRtl(root)).toBe(true);
-      expect(RTLUtils.isRtl(el)).toBe(true);
-    });
-    test('nested', () => {
-      const root = document.createElement('div');
-      const nested1 = document.createElement('div');
-      const nested2 = document.createElement('div');
-      const nested3 = document.createElement('div');
-      nested2.appendChild(nested3);
-      nested1.appendChild(nested2);
-      root.appendChild(nested1);
-      root.dir = 'rtl';
-      nested2.dir = 'ltr';
+      const gcsSpy = jest.spyOn(window, 'getComputedStyle');
 
+      gcsSpy.mockImplementationOnce(() => ({direction: 'rtl'} as CSSStyleDeclaration));
       expect(RTLUtils.isRtl(root)).toBe(true);
-      expect(RTLUtils.isRtl(nested1)).toBe(true);
-      expect(RTLUtils.isRtl(nested2)).toBe(false);
-      expect(RTLUtils.isRtl(nested3)).toBe(false);
-    });
-    test('body', () => {
-      expect(RTLUtils.isRtl()).toBe(false);
-      document.body.setAttribute('dir', 'rtl');
-      expect(RTLUtils.isRtl()).toBe(true);
-      document.body.removeAttribute('dir');
-      expect(RTLUtils.isRtl()).toBe(false);
+      gcsSpy.mockImplementationOnce(() => ({direction: 'rtl'} as CSSStyleDeclaration));
+      expect(RTLUtils.isRtl(el)).toBe(true);
     });
   });
Repository: exadel-inc/esl
Pull request #725 (2021-12-15 13:05:04)

chore: `actions/setup-node@v1` migrated to `actions/setup-node@v2` 
- `actions/setup-node@v1` migrated to `actions/setup-node@v2` 
- enable cache option

Closes: #724


Patch:
diff --git a/.github/workflows/commit.yml b/.github/workflows/commit.yml
index 2327c169c..4a5d26be2 100644
--- a/.github/workflows/commit.yml
+++ b/.github/workflows/commit.yml
@@ -16,8 +16,9 @@ jobs:
         with:
           fetch-depth: 0
       - name: Use Node v${{ env.node-version }}
-        uses: actions/setup-node@v1
+        uses: actions/setup-node@v2
         with:
+          cache: 'npm'
           node-version: ${{ env.node-version }}
       - name: Install NPM Dependencies
         run: npm ci
diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml
index 39f68f347..1332b9f82 100644
--- a/.github/workflows/pages.yml
+++ b/.github/workflows/pages.yml
@@ -17,15 +17,16 @@ jobs:
     steps:
       - uses: actions/checkout@v2
       - name: Use Node v${{ env.node-version }}
-        uses: actions/setup-node@v1
+        uses: actions/setup-node@v2
         with:
+          cache: 'npm'
           node-version: ${{ env.node-version }}
       - name: Install NPM Dependencies
         run: npm ci
       - name: Build
         run: npm run build-pages
       - name: Deploy
-        uses: JamesIves/github-pages-deploy-action@4.1.0
+        uses: JamesIves/github-pages-deploy-action@4
         with:
           branch: gh-pages
           folder: pages/dist
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 1f304ef91..5e4a0fca6 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -16,8 +16,9 @@ jobs:
           persist-credentials: false
 
       - name: Use Node v${{ env.node-version }}
-        uses: actions/setup-node@v1
+        uses: actions/setup-node@v2
         with:
+          cache: 'npm'
           node-version: ${{ env.node-version }}
 
       - name: Install NPM Dependencies
diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml
index 15cd961d0..1b339bef5 100644
--- a/.github/workflows/validate.yml
+++ b/.github/workflows/validate.yml
@@ -18,8 +18,9 @@ jobs:
     steps:
       - uses: actions/checkout@v2
       - name: Use Node v${{ env.node-version }}
-        uses: actions/setup-node@v1
+        uses: actions/setup-node@v2
         with:
+          cache: 'npm'
           node-version: ${{ env.node-version }}
       - name: Install NPM Dependencies
         run: npm ci


Test patch:
diff --git a/.github/workflows/test-pack.yml b/.github/workflows/test-pack.yml
index 0a0e3793d..a3d4bc4e2 100644
--- a/.github/workflows/test-pack.yml
+++ b/.github/workflows/test-pack.yml
@@ -14,8 +14,9 @@ jobs:
     steps:
       - uses: actions/checkout@v2
       - name: Use Node v${{ env.node-version }}
-        uses: actions/setup-node@v1
+        uses: actions/setup-node@v2
         with:
+          cache: 'npm'
           node-version: ${{ env.node-version }}
       - name: Install NPM Dependencies
         run: npm ci
Repository: hhursev/recipe-scrapers
Pull request #192 (2020-07-20 11:46:04)

Handle additional ISO8601 date parsing case
It *should* be the case that schema.org time values are formatted as ISO-8601 durations (see details in the [`totalTime` field spec](https://schema.org/totalTime), and similarly for `prepTime`, etc).

The existing `get_minutes` logic is left as-is to reduce any unintended side-effects on non-schema.org recipe crawling; and it's still used as a fallback if ISO-8601 parsing fails for schema.org-enabled pages.


Patch:
diff --git a/recipe_scrapers/_utils.py b/recipe_scrapers/_utils.py
index d07496ed..f6d1b6e4 100644
--- a/recipe_scrapers/_utils.py
+++ b/recipe_scrapers/_utils.py
@@ -23,6 +23,8 @@ def get_minutes(element):
         time_text = element
     else:
         time_text = element.get_text()
+    if time_text.startswith("P") and "T" in time_text:
+        time_text = time_text.split("T", 1)[1]
     if "-" in time_text:
         time_text = time_text.split("-")[
             1


Test patch:
diff --git a/tests/library/__init__.py b/tests/library/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/library/test_utils.py b/tests/library/test_utils.py
new file mode 100644
index 00000000..35c85832
--- /dev/null
+++ b/tests/library/test_utils.py
@@ -0,0 +1,29 @@
+import unittest
+
+from recipe_scrapers._utils import get_minutes
+
+
+class UtilsTest(unittest.TestCase):
+    def test_get_minutes_english_description(self):
+        text = "1 hour 15 mins"
+        result = get_minutes(text)
+
+        assert result == 75
+
+    def test_get_minutes_english_abbreviation(self):
+        text = "3h10m"
+        result = get_minutes(text)
+
+        assert result == 190
+
+    def test_get_minutes_short_iso_format(self):
+        text = "PT2H30M"
+        result = get_minutes(text)
+
+        assert result == 150
+
+    def test_get_minutes_long_iso_format(self):
+        text = "P0DT1H10M"
+        result = get_minutes(text)
+
+        assert result == 70
Repository: pmndrs/zustand
Pull request #280 (2021-01-08 20:07:41)

feat: works with useLayoutEffect
close https://github.com/pmndrs/zustand/issues/276

codesandbox[bot]: This pull request is automatically built and testable in [CodeSandbox](https://codesandbox.io).

  To see build info of the built libraries, click [here](https://ci.codesandbox.io/status/pmndrs/zustand/pr/280/builds/89866) or the icon next to each commit SHA.

Latest deployment of this branch, based on commit cc874cff3edafd51ad27caf6f9f3384c360acf8d:

|Sandbox| Source |
|--|--|
|[React](https://codesandbox.io/s/react-mhjrh)| Configuration |
|[React Typescript](https://codesandbox.io/s/react-typescript-zn5nu)| Configuration |

leobastiani: I just added a cleanup because we aren't using react-testing-library in this test
dai-shi: Nice.
Unless anyone else says anything, I'll merge this and release a patch version later.

Patch:
diff --git a/src/index.ts b/src/index.ts
index fbc4b12..5ff3978 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -80,7 +80,7 @@ export default function create<TState extends State>(
     })
 
     const stateBeforeSubscriptionRef = useRef(state)
-    useEffect(() => {
+    useIsoLayoutEffect(() => {
       const listener = () => {
         try {
           const nextState = api.getState()


Test patch:
diff --git a/tests/basic.test.tsx b/tests/basic.test.tsx
index 5fd09b5..6faef96 100644
--- a/tests/basic.test.tsx
+++ b/tests/basic.test.tsx
@@ -147,6 +147,23 @@ it('only re-renders if selected state has changed', async () => {
   expect(controlRenderCount).toBe(1)
 })
 
+it('re-renders with useLayoutEffect', async () => {
+  const useStore = create(() => ({ state: false }))
+
+  function Component() {
+    const { state } = useStore()
+    React.useLayoutEffect(() => {
+      useStore.setState({ state: true })
+    }, [])
+    return <>{`${state}`}</>
+  }
+
+  const container = document.createElement('div')
+  ReactDOM.render(<Component />, container)
+  expect(container.innerHTML).toBe('true')
+  ReactDOM.unmountComponentAtNode(container)
+})
+
 it('can batch updates', async () => {
   const useStore = create<any>((set) => ({
     count: 0,
Repository: hyrodium/BasicBSpline.jl
Pull request #129 (2021-12-30 08:51:46)

broadcast
This PR enables broadcasting like this:
```julia
P = BSplineSpace{2}(KnotVector(1:18))
bsplinebasis.(P, 1:dim(P), t)
```


Patch:
diff --git a/src/_BSplineSpace.jl b/src/_BSplineSpace.jl
index 056f0b88..fc320da3 100644
--- a/src/_BSplineSpace.jl
+++ b/src/_BSplineSpace.jl
@@ -2,6 +2,9 @@
 
 abstract type AbstractBSplineSpace{p,T} end
 
+# Broadcast like a scalar
+Base.Broadcast.broadcastable(P::AbstractBSplineSpace) = Ref(P)
+
 @doc raw"""
 Construct B-spline space from given polynominal degree and knot vector.
 ```math
diff --git a/src/_DerivativeSpace.jl b/src/_DerivativeSpace.jl
index b2ca0fe0..90be278b 100644
--- a/src/_DerivativeSpace.jl
+++ b/src/_DerivativeSpace.jl
@@ -7,6 +7,9 @@ struct BSplineDerivativeSpace{r, T<:AbstractBSplineSpace}
     end
 end
 
+# Broadcast like a scalar
+Base.Broadcast.broadcastable(dP::BSplineDerivativeSpace) = Ref(dP)
+
 bsplinespace(dP::BSplineDerivativeSpace) = dP.bsplinespace
 knotvector(dP::BSplineDerivativeSpace) = knotvector(bsplinespace(dP))
 degree(dP::BSplineDerivativeSpace{r,<:AbstractBSplineSpace{p}}) where {r,p} = p - r


Test patch:
diff --git a/test/test_BSplineBasis.jl b/test/test_BSplineBasis.jl
index f1abe9d6..292a2d0f 100644
--- a/test/test_BSplineBasis.jl
+++ b/test/test_BSplineBasis.jl
@@ -71,16 +71,14 @@ end
             for t in ts
                 j = intervalindex(P,t)
                 B = collect(bsplinebasisall(P,j,t))
-                _B = [bsplinebasis(P,i,t) for i in j:j+p]
-                @test _B ≈ B
 
-                _B = [bsplinebasis(P,i,t) for i in j:j+p]
+                _B = bsplinebasis.(P,j:j+p,t)
                 @test _B ≈ B
 
-                _B = [bsplinebasis₊₀(P,i,t) for i in j:j+p]
+                _B = bsplinebasis₊₀.(P,j:j+p,t)
                 @test _B ≈ B
 
-                _B = [bsplinebasis₋₀(P,i,t) for i in j:j+p]
+                _B = bsplinebasis₋₀.(P,j:j+p,t)
                 @test _B ≈ B
             end
         end
diff --git a/test/test_Derivative.jl b/test/test_Derivative.jl
index b00bb31f..b2648ae1 100644
--- a/test/test_Derivative.jl
+++ b/test/test_Derivative.jl
@@ -75,16 +75,14 @@
                 for t in ts
                     j = intervalindex(dP,t)
                     B = collect(bsplinebasisall(dP,j,t))
-                    _B = [bsplinebasis(dP,i,t) for i in j:j+p]
-                    @test _B ≈ B
 
-                    _B = [bsplinebasis(dP,i,t) for i in j:j+p]
+                    _B = bsplinebasis.(dP,j:j+p,t)
                     @test _B ≈ B
 
-                    _B = [bsplinebasis₊₀(dP,i,t) for i in j:j+p]
+                    _B = bsplinebasis₊₀.(dP,j:j+p,t)
                     @test _B ≈ B
 
-                    _B = [bsplinebasis₋₀(dP,i,t) for i in j:j+p]
+                    _B = bsplinebasis₋₀.(dP,j:j+p,t)
                     @test _B ≈ B
                 end
             end
Repository: hyrodium/BasicBSpline.jl
Pull request #139 (2022-01-13 07:49:00)

Fix around `zero` methods for `KnotVector`
Before this PR
```julia
julia> using BasicBSpline

julia> k = KnotVector{Int}(0)
KnotVector([0])

julia> 0*k
KnotVector([])

julia> typeof(0*k)
KnotVector{Float64}

julia> typeof(2*k)
KnotVector{Int64}

julia> zero(k)
ERROR: MethodError: no method matching zero(::KnotVector{Int64})
Closest candidates are:
  zero(::Union{Type{P}, P}) where P<:Dates.Period at ~/julia/julia-1.7.0/share/julia/stdlib/v1.7/Dates/src/periods.jl:53
  zero(::AbstractIrrational) at ~/julia/julia-1.7.0/share/julia/base/irrationals.jl:150
  zero(::CartesianIndex{N}) where N at ~/julia/julia-1.7.0/share/julia/base/multidimensional.jl:106
  ...
Stacktrace:
 [1] top-level scope
   @ REPL[6]:1
```

After this PR
```julia
julia> using BasicBSpline

julia> k = KnotVector{Int}(0)
KnotVector([0])

julia> 0*k
KnotVector([])

julia> typeof(0*k)
KnotVector{Int64}

julia> typeof(2*k)
KnotVector{Int64}

julia> zero(k)
KnotVector([])
```


Patch:
diff --git a/src/_KnotVector.jl b/src/_KnotVector.jl
index 08ea586a..a03d827d 100644
--- a/src/_KnotVector.jl
+++ b/src/_KnotVector.jl
@@ -52,6 +52,7 @@ function KnotVector{T}(knots::Real...) where T<:Real
     return unsafe_knotvector(T, sort!(collect(knots)))
 end
 KnotVector() = unsafe_knotvector(Float64, Float64[])
+KnotVector{T}() where T<:Real = unsafe_knotvector(T, T[])
 
 function Base.show(io::IO, k::KnotVector)
     if k.vector == Float64[]
@@ -62,6 +63,7 @@ function Base.show(io::IO, k::KnotVector)
 end
 
 Base.zero(::Type{<:KnotVector}) = KnotVector()
+Base.zero(::KnotVector{T}) where T = KnotVector{T}()
 Base.:(==)(k₁::KnotVector, k₂::KnotVector) = (k₁.vector == k₂.vector)
 
 Base.eltype(::KnotVector{T}) where T = T
@@ -114,7 +116,7 @@ KnotVector([1.0, 1.0, 2.0, 2.0, 2.0, 2.0, 5.0, 5.0])
 """
 function Base.:*(m::Integer, k::AbstractKnotVector)
     if m == 0
-        return zero(KnotVector)
+        return zero(k)
     elseif m > 0
         return sum(k for _ in 1:m)
     else


Test patch:
diff --git a/test/test_KnotVector.jl b/test/test_KnotVector.jl
index e6f101e8..f9989ab3 100644
--- a/test/test_KnotVector.jl
+++ b/test/test_KnotVector.jl
@@ -21,7 +21,7 @@
 
     @testset "zeros" begin
         @test KnotVector() == zero(KnotVector)
-        @test KnotVector() == 0*k1 == k1*0
+        @test KnotVector() == 0*k1 == k1*0 == zero(k1)
         @test KnotVector() == KnotVector(Float64[])
     end
 
@@ -39,6 +39,9 @@
         # type promotion
         @test KnotVector{Int}(1,2) + KnotVector{Rational{Int}}(3) == KnotVector(1,2,3)
         @test KnotVector{Int}(1,2) + KnotVector{Rational{Int}}(3) isa KnotVector{Rational{Int}}
+        @test KnotVector{Int}(1,2)*0 == KnotVector()
+        @test KnotVector{Int}(1,2)*0 isa KnotVector{Int}
+        @test KnotVector{Int}() isa KnotVector{Int}
     end
 
     @testset "unique" begin
Repository: fredrikekre/Runic.jl
Pull request #67 (2024-10-18 14:12:03)

Fix commas after trailing macrocalls hidden inside of list items


Patch:
diff --git a/src/chisels.jl b/src/chisels.jl
index 5bd8046..ef8f759 100644
--- a/src/chisels.jl
+++ b/src/chisels.jl
@@ -630,6 +630,20 @@ function last_leaf_predicate(node::Node, pred::F) where {F}
     end
 end
 
+function predicate_contains(pred::F, node::Node) where {F}
+    if pred(node)::Bool
+        return true
+    elseif is_leaf(node)
+        return false
+    else
+        for k in verified_kids(node)
+            r = predicate_contains(pred, k)
+            r && return r
+        end
+        return false
+    end
+end
+
 function contains_outer_newline(kids::Vector{Node}, oidx::Int, cidx::Int; recurse = true)
     pred = x -> kind(x) === K"NewlineWs" || !JuliaSyntax.is_whitespace(x)
     for i in (oidx + 1):(cidx - 1)
diff --git a/src/runestone.jl b/src/runestone.jl
index 56ab3df..fe77730 100644
--- a/src/runestone.jl
+++ b/src/runestone.jl
@@ -387,9 +387,11 @@ function spaces_in_listlike(ctx::Context, node::Node)
         # For parameters the trailing comma is configured from the parent
         require_trailing_comma = has_tag(node, TAG_TRAILING_COMMA)
         allow_trailing_comma = has_tag(node, TAG_TRAILING_COMMA_OPT)
-    elseif n_items > 0 && kind(kids[last_item_idx]) === K"macrocall" &&
-            !JuliaSyntax.has_flags(kids[last_item_idx], JuliaSyntax.PARENS_FLAG) &&
-            !is_string_macro(kids[last_item_idx])
+    elseif n_items > 0 && predicate_contains(kids[last_item_idx]) do nd
+            return kind(nd) === K"macrocall" &&
+                !JuliaSyntax.has_flags(nd, JuliaSyntax.PARENS_FLAG) && !is_string_macro(nd)
+        end
+        # Unparenthesized macrocalls are scary even if hidden deep in the tree
         require_trailing_comma = false
     elseif multiline
         require_trailing_comma = true


Test patch:
diff --git a/test/runtests.jl b/test/runtests.jl
index b7ca4f2..219b137 100644
--- a/test/runtests.jl
+++ b/test/runtests.jl
@@ -379,6 +379,9 @@ end
     @test format_string("f(r\"\"\"\nf\n\"\"\")") == "f(\n    r\"\"\"\n    f\n    \"\"\"\n)"
     @test format_string("f(```\nf\n```)") == "f(\n    ```\n    f\n    ```\n)"
     @test format_string("f(x```\nf\n```)") == "f(\n    x```\n    f\n    ```\n)"
+    @test format_string("(a, @m begin\nend)") == "(\n    a, @m begin\n    end\n)"
+    @test format_string("(\na, x -> @m x[i]\n)") == "(\n    a, x -> @m x[i]\n)"
+    @test format_string("(\na, x -> @m(x[i])\n)") == "(\n    a, x -> @m(x[i]),\n)"
     # Weird cornercase where a trailing comma messes some cases up (don't recall...)
     @test format_string("{\n@f\n}") == "{\n    @f\n}"
 end
Repository: fredrikekre/Runic.jl
Pull request #72 (2024-10-21 12:21:18)

Fix indentation of documented modules in files with more toplevel code


Patch:
diff --git a/src/runestone.jl b/src/runestone.jl
index e343894..6a42d87 100644
--- a/src/runestone.jl
+++ b/src/runestone.jl
@@ -2936,9 +2936,31 @@ function indent_comparison(ctx::Context, node::Node)
     return continue_all_newlines(ctx, node)
 end
 
+# Indent a nested documented module
+function indent_doc_module(ctx::Context, node::Node; do_indent::Bool)
+    @assert kind(node) === K"doc"
+    kids = verified_kids(node)
+    mod_idx = findfirst(x -> kind(x) === K"module", kids)::Int
+    pos = position(ctx.fmt_io)
+    for i in 1:(mod_idx - 1)
+        accept_node!(ctx, kids[i])
+    end
+    mod′ = indent_module(ctx, kids[mod_idx]; do_indent = do_indent)
+    seek(ctx.fmt_io, pos)
+    if mod′ === nothing
+        return nothing
+    end
+    kids′ = copy(kids)
+    kids′[mod_idx] = mod′
+    return make_node(node, kids′)
+end
+
 # Indent a nested module
 function indent_module(ctx::Context, node::Node; do_indent::Bool = true)
-    @assert kind(node) === K"module"
+    @assert kind(node) in KSet"module doc"
+    if kind(node) === K"doc"
+        return indent_doc_module(ctx, node; do_indent = do_indent)
+    end
     kids = verified_kids(node)
     any_kid_changed = false
     pos = position(ctx.fmt_io)
@@ -2998,7 +3020,10 @@ end
 function indent_toplevel(ctx::Context, node::Node)
     @assert kind(node) === K"toplevel"
     kids = verified_kids(node)
-    mod_idx = findfirst(x -> kind(x) === K"module", kids)
+    mod_idx = findfirst(kids) do x
+        kind(x) === K"module" ||
+            (kind(x) === K"doc" && findfirst(y -> kind(y) === K"module", verified_kids(x)) !== nothing)
+    end
     if mod_idx === nothing
         # No module here
         return nothing


Test patch:
diff --git a/test/runtests.jl b/test/runtests.jl
index 1a4fece..f66b755 100644
--- a/test/runtests.jl
+++ b/test/runtests.jl
@@ -673,6 +673,9 @@ end
             # nested documented modules
             @test format_string("\"doc\"\n$(b)module A\n\"doc\"\n$(b)module B\n$(sp)x\n$(sp)end\n$(sp)end") ==
                 "\"doc\"\n$(b)module A\n\"doc\"\n$(b)module B\n    x\nend\nend"
+            # toplevel documented module with more things
+            @test format_string("\"doc\"\n$(b)module A\n$(sp)x\nend\nf") ==
+                "\"doc\"\n$(b)module A\n    x\nend\nf"
             # var"" as module name
             @test format_string("$(b)module var\"A\"\n$(sp)x\n$(sp)end\nf") ==
                 "$(b)module var\"A\"\n    x\nend\nf"
Repository: fredrikekre/Runic.jl
Pull request #74 (2024-10-22 14:57:13)

Don't use spaces around `..`
`..` is typically used similarly to `:` which is already excluded from the space-around-operator rule.


Patch:
diff --git a/README.md b/README.md
index ce36d9e..4755796 100644
--- a/README.md
+++ b/README.md
@@ -536,7 +536,7 @@ arguments in function definitions and calls. Examples:
 +foo(a = 1)
 ```
 
-Exceptions to the rule above are `:`, `^`, `::`, and unary `<:` and `>:`. These are
+Exceptions to the rule above are `:`, `..`, `^`, `::`, and unary `<:` and `>:`. These are
 formatted *without* spaces around them. Examples:
 ```diff
 -a : b
diff --git a/src/runestone.jl b/src/runestone.jl
index 0f72f4d..bb1d060 100644
--- a/src/runestone.jl
+++ b/src/runestone.jl
@@ -802,7 +802,7 @@ end
 # <: and >: operators.
 function spaces_around_operators(ctx::Context, node::Node)
     if !(
-            (is_infix_op_call(node) && !(kind(infix_op_call_op(node)) in KSet": ^")) ||
+            (is_infix_op_call(node) && !(kind(infix_op_call_op(node)) in KSet": .. ^")) ||
                 (kind(node) in KSet"<: >:" && meta_nargs(node) == 3) ||
                 (kind(node) === K"comparison" && !JuliaSyntax.is_trivia(node))
         )
@@ -1205,17 +1205,17 @@ function spaces_in_import_using(ctx::Context, node::Node)
     end
 end
 
-# no spaces around `:`, `^`, and `::`
+# no spaces around `:`, `..`, `^`, and `::`
 function no_spaces_around_colon_etc(ctx::Context, node::Node)
     if !(
-            (is_infix_op_call(node) && kind(infix_op_call_op(node)) in KSet": ^") ||
+            (is_infix_op_call(node) && kind(infix_op_call_op(node)) in KSet": .. ^") ||
                 (kind(node) === K"::" && !is_leaf(node)) ||
                 (kind(node) in KSet"<: >:" && meta_nargs(node) == 2)
         )
         return nothing
     end
     @assert kind(node) in KSet"call :: <: >:"
-    is_x = x -> is_leaf(x) && kind(x) in KSet": ^ :: <: >:"
+    is_x = x -> is_leaf(x) && kind(x) in KSet": .. ^ :: <: >:"
     return no_spaces_around_x(ctx, node, is_x)
 end
 


Test patch:
diff --git a/test/runtests.jl b/test/runtests.jl
index 9065eca..2670646 100644
--- a/test/runtests.jl
+++ b/test/runtests.jl
@@ -180,7 +180,7 @@ end
             @test format_string("$(sp)a$(sp)$(op)$(sp)# comment\nb$(sp)") ==
                 "$(sp)a $(op) # comment\n    b$(sp)"
         end
-        # Exceptions to the rule: `:` and `^`
+        # Exceptions to the rule: `:`, `..`, and `^`
         # a:b
         @test format_string("$(sp)a$(sp):$(sp)b$(sp)") == "$(sp)a:b$(sp)"
         @test format_string("$(sp)a + a$(sp):$(sp)b + b$(sp)") == "$(sp)(a + a):(b + b)$(sp)"
@@ -190,6 +190,8 @@ end
         @test format_string("$(sp)a$(sp):$(sp)b$(sp):$(sp)c$(sp)") == "$(sp)a:b:c$(sp)"
         @test format_string("$(sp)(1 + 2)$(sp):$(sp)(1 + 3)$(sp):$(sp)(1 + 4)$(sp)") ==
             "$(sp)(1 + 2):(1 + 3):(1 + 4)$(sp)"
+        # a..b
+        @test format_string("$(sp)a$(sp)..$(sp)b$(sp)") == "$(sp)a..b$(sp)"
         # a^b
         @test format_string("$(sp)a$(sp)^$(sp)b$(sp)") == "$(sp)a^b$(sp)"
         # Edgecase when formatting whitespace in the next leaf, when the next leaf is a