diff --git a/packages/twoslash-svelte/package.json b/packages/twoslash-svelte/package.json
index a326c115..a1771ab0 100644
--- a/packages/twoslash-svelte/package.json
+++ b/packages/twoslash-svelte/package.json
@@ -46,11 +46,13 @@
"start": "esno src/index.ts"
},
"peerDependencies": {
+ "svelte": ">=5",
"typescript": "*"
},
"dependencies": {
"@jridgewell/sourcemap-codec": "catalog:",
"@volar/language-core": "catalog:",
+ "estree-walker": "catalog:",
"svelte2tsx": "catalog:",
"twoslash": "workspace:*",
"twoslash-protocol": "workspace:*"
diff --git a/packages/twoslash-svelte/src/index.ts b/packages/twoslash-svelte/src/index.ts
index 49e260bd..c0736c9e 100644
--- a/packages/twoslash-svelte/src/index.ts
+++ b/packages/twoslash-svelte/src/index.ts
@@ -4,8 +4,10 @@ import { createRequire } from 'node:module'
import { decode } from '@jridgewell/sourcemap-codec'
import { SourceMap } from '@volar/language-core'
import { svelte2tsx } from 'svelte2tsx'
+import { parse } from 'svelte/compiler'
import { createTwoslasher as createTwoSlasherBase, defaultCompilerOptions, defaultHandbookOptions, findFlagNotations, findQueryMarkers } from 'twoslash'
import { createPositionConverter, removeCodeRanges, resolveNodePositions } from 'twoslash-protocol'
+import { findCutNotations } from 'twoslash/core'
import ts from 'typescript'
export interface CreateTwoslashSvelteOptions extends CreateTwoslashOptions {
@@ -78,6 +80,7 @@ export function createTwoslasher(createOptions: CreateTwoslashSvelteOptions = {}
}
const compiled = svelte2tsx(strippedCode)
+
const map = generateSourceMap(strippedCode, compiled.code, compiled.map.mappings)
function getLastGeneratedOffset(pos: number) {
@@ -146,16 +149,20 @@ export function createTwoslasher(createOptions: CreateTwoslashSvelteOptions = {}
})
.filter(value => value != null)
+ const ast = parse(strippedCode, { modern: true })
+
+ findCutNotations(code, sourceMeta, {
+ reCutBefore: /^$/,
+ reCutAfter: /^$/,
+ reCutStart: /^$/,
+ reCutEnd: /^$/,
+ })
+
const mappedRemovals = [
...sourceMeta.removals,
- ...result.meta.removals.map((r) => {
- const start = get(map.toSourceLocation(r[0]), 0)?.[0] ?? code.match(/(?<=
-
\ No newline at end of file
diff --git a/packages/twoslash-svelte/test/fixtures/script/cut-after.svelte b/packages/twoslash-svelte/test/fixtures/script/cut-after.svelte
new file mode 100644
index 00000000..8f641aff
--- /dev/null
+++ b/packages/twoslash-svelte/test/fixtures/script/cut-after.svelte
@@ -0,0 +1,10 @@
+
+
\ No newline at end of file
diff --git a/packages/twoslash-svelte/test/fixtures/cut-around.svelte b/packages/twoslash-svelte/test/fixtures/script/cut-before.svelte
similarity index 86%
rename from packages/twoslash-svelte/test/fixtures/cut-around.svelte
rename to packages/twoslash-svelte/test/fixtures/script/cut-before.svelte
index 3e25b2d0..7230c851 100644
--- a/packages/twoslash-svelte/test/fixtures/cut-around.svelte
+++ b/packages/twoslash-svelte/test/fixtures/script/cut-before.svelte
@@ -1,13 +1,10 @@
-
\ No newline at end of file
diff --git a/packages/twoslash-svelte/test/fixtures/cut-in.svelte b/packages/twoslash-svelte/test/fixtures/script/cut-region.svelte
similarity index 97%
rename from packages/twoslash-svelte/test/fixtures/cut-in.svelte
rename to packages/twoslash-svelte/test/fixtures/script/cut-region.svelte
index f5c9365d..de7803ae 100644
--- a/packages/twoslash-svelte/test/fixtures/cut-in.svelte
+++ b/packages/twoslash-svelte/test/fixtures/script/cut-region.svelte
@@ -1,13 +1,11 @@
-
\ No newline at end of file
diff --git a/packages/twoslash-svelte/test/fixtures/script/cut.svelte b/packages/twoslash-svelte/test/fixtures/script/cut.svelte
new file mode 100644
index 00000000..7dbf3e91
--- /dev/null
+++ b/packages/twoslash-svelte/test/fixtures/script/cut.svelte
@@ -0,0 +1,10 @@
+
+
\ No newline at end of file
diff --git a/packages/twoslash-svelte/test/fixtures/hover.svelte b/packages/twoslash-svelte/test/fixtures/script/hover.svelte
similarity index 98%
rename from packages/twoslash-svelte/test/fixtures/hover.svelte
rename to packages/twoslash-svelte/test/fixtures/script/hover.svelte
index 17188e75..188fe471 100644
--- a/packages/twoslash-svelte/test/fixtures/hover.svelte
+++ b/packages/twoslash-svelte/test/fixtures/script/hover.svelte
@@ -1,11 +1,9 @@
-
\ No newline at end of file
diff --git a/packages/twoslash-svelte/test/fixtures/query.svelte b/packages/twoslash-svelte/test/fixtures/script/query.svelte
similarity index 98%
rename from packages/twoslash-svelte/test/fixtures/query.svelte
rename to packages/twoslash-svelte/test/fixtures/script/query.svelte
index e2b073bb..2132af7c 100644
--- a/packages/twoslash-svelte/test/fixtures/query.svelte
+++ b/packages/twoslash-svelte/test/fixtures/script/query.svelte
@@ -1,12 +1,10 @@
-
\ No newline at end of file
diff --git a/packages/twoslash-svelte/test/fixtures/script/throws/cut-region-missing-end.svelte b/packages/twoslash-svelte/test/fixtures/script/throws/cut-region-missing-end.svelte
new file mode 100644
index 00000000..ddc51836
--- /dev/null
+++ b/packages/twoslash-svelte/test/fixtures/script/throws/cut-region-missing-end.svelte
@@ -0,0 +1,10 @@
+
+
\ No newline at end of file
diff --git a/packages/twoslash-svelte/test/fixtures/script/throws/cut-region-missing-start.svelte b/packages/twoslash-svelte/test/fixtures/script/throws/cut-region-missing-start.svelte
new file mode 100644
index 00000000..960a9821
--- /dev/null
+++ b/packages/twoslash-svelte/test/fixtures/script/throws/cut-region-missing-start.svelte
@@ -0,0 +1,10 @@
+
+
\ No newline at end of file
diff --git a/packages/twoslash-svelte/test/fixtures/template/cut-after.svelte b/packages/twoslash-svelte/test/fixtures/template/cut-after.svelte
new file mode 100644
index 00000000..c63e1c03
--- /dev/null
+++ b/packages/twoslash-svelte/test/fixtures/template/cut-after.svelte
@@ -0,0 +1,10 @@
+
+
+
\ No newline at end of file
diff --git a/packages/twoslash-svelte/test/fixtures/template/cut-before.svelte b/packages/twoslash-svelte/test/fixtures/template/cut-before.svelte
new file mode 100644
index 00000000..980745b2
--- /dev/null
+++ b/packages/twoslash-svelte/test/fixtures/template/cut-before.svelte
@@ -0,0 +1,10 @@
+
+
+
\ No newline at end of file
diff --git a/packages/twoslash-svelte/test/fixtures/template/cut-region.svelte b/packages/twoslash-svelte/test/fixtures/template/cut-region.svelte
new file mode 100644
index 00000000..011191a9
--- /dev/null
+++ b/packages/twoslash-svelte/test/fixtures/template/cut-region.svelte
@@ -0,0 +1,11 @@
+
+
+
+
\ No newline at end of file
diff --git a/packages/twoslash-svelte/test/fixtures/template/cut.svelte b/packages/twoslash-svelte/test/fixtures/template/cut.svelte
new file mode 100644
index 00000000..5b3076d8
--- /dev/null
+++ b/packages/twoslash-svelte/test/fixtures/template/cut.svelte
@@ -0,0 +1,10 @@
+
+
+
diff --git a/packages/twoslash-svelte/test/fixtures/template/throws/cut-region-missing-end.svelte b/packages/twoslash-svelte/test/fixtures/template/throws/cut-region-missing-end.svelte
new file mode 100644
index 00000000..0b6a8043
--- /dev/null
+++ b/packages/twoslash-svelte/test/fixtures/template/throws/cut-region-missing-end.svelte
@@ -0,0 +1,10 @@
+
+
+
diff --git a/packages/twoslash-svelte/test/fixtures/template/throws/cut-region-missing-start.svelte b/packages/twoslash-svelte/test/fixtures/template/throws/cut-region-missing-start.svelte
new file mode 100644
index 00000000..1345c62b
--- /dev/null
+++ b/packages/twoslash-svelte/test/fixtures/template/throws/cut-region-missing-start.svelte
@@ -0,0 +1,10 @@
+
+
+
\ No newline at end of file
diff --git a/packages/twoslash-svelte/test/results/completion.json b/packages/twoslash-svelte/test/results/script/completion.json
similarity index 90%
rename from packages/twoslash-svelte/test/results/completion.json
rename to packages/twoslash-svelte/test/results/script/completion.json
index 8a8816e6..66abf840 100644
--- a/packages/twoslash-svelte/test/results/completion.json
+++ b/packages/twoslash-svelte/test/results/script/completion.json
@@ -1,5 +1,5 @@
{
- "code": "\n\n",
+ "code": "\n",
"nodes": [
{
"type": "hover",
@@ -98,37 +98,37 @@
{
"type": "hover",
"text": "(local function) increment(): void",
- "start": 50,
+ "start": 49,
"length": 9,
"target": "increment",
- "line": 3,
+ "line": 2,
"character": 13
},
{
"type": "hover",
"text": "let count: number",
- "start": 72,
+ "start": 71,
"length": 5,
"target": "count",
- "line": 4,
+ "line": 3,
"character": 8
},
{
"type": "hover",
"text": "(local function) increment(): void",
- "start": 115,
+ "start": 113,
"length": 9,
"target": "increment",
- "line": 8,
+ "line": 6,
"character": 17
},
{
"type": "hover",
"text": "let count: number",
- "start": 142,
+ "start": 140,
"length": 5,
"target": "count",
- "line": 9,
+ "line": 7,
"character": 15
}
],
diff --git a/packages/twoslash-svelte/test/results/script/cut-after.json b/packages/twoslash-svelte/test/results/script/cut-after.json
new file mode 100644
index 00000000..1f4872e8
--- /dev/null
+++ b/packages/twoslash-svelte/test/results/script/cut-after.json
@@ -0,0 +1,35 @@
+{
+ "code": "\n",
+ "nodes": [
+ {
+ "type": "hover",
+ "text": "let count: number",
+ "start": 17,
+ "length": 5,
+ "target": "count",
+ "line": 1,
+ "character": 8
+ },
+ {
+ "type": "hover",
+ "text": "function $state<0>(initial: 0): 0 (+1 overload)\nnamespace $state",
+ "docs": "Declares reactive state.\n\nExample:\n```ts\nlet count = $state(0);\n```",
+ "tags": [
+ [
+ "see",
+ "{@link https://svelte.dev/docs/svelte/$state Documentation}"
+ ],
+ [
+ "param",
+ "initial The initial value"
+ ]
+ ],
+ "start": 25,
+ "length": 6,
+ "target": "$state",
+ "line": 1,
+ "character": 16
+ }
+ ],
+ "flags": []
+}
\ No newline at end of file
diff --git a/packages/twoslash-svelte/test/results/script/cut-before.json b/packages/twoslash-svelte/test/results/script/cut-before.json
new file mode 100644
index 00000000..3482dc8a
--- /dev/null
+++ b/packages/twoslash-svelte/test/results/script/cut-before.json
@@ -0,0 +1,42 @@
+{
+ "code": "\n",
+ "nodes": [
+ {
+ "type": "hover",
+ "text": "(local function) increment(): void",
+ "start": 21,
+ "length": 9,
+ "target": "increment",
+ "line": 0,
+ "character": 21
+ },
+ {
+ "type": "hover",
+ "text": "let count: number",
+ "start": 43,
+ "length": 5,
+ "target": "count",
+ "line": 1,
+ "character": 8
+ },
+ {
+ "type": "hover",
+ "text": "(local function) increment(): void",
+ "start": 85,
+ "length": 9,
+ "target": "increment",
+ "line": 4,
+ "character": 17
+ },
+ {
+ "type": "hover",
+ "text": "let count: number",
+ "start": 112,
+ "length": 5,
+ "target": "count",
+ "line": 5,
+ "character": 15
+ }
+ ],
+ "flags": []
+}
\ No newline at end of file
diff --git a/packages/twoslash-svelte/test/results/cut-in.json b/packages/twoslash-svelte/test/results/script/cut-region.json
similarity index 83%
rename from packages/twoslash-svelte/test/results/cut-in.json
rename to packages/twoslash-svelte/test/results/script/cut-region.json
index 7b69cb24..2d31fc88 100644
--- a/packages/twoslash-svelte/test/results/cut-in.json
+++ b/packages/twoslash-svelte/test/results/script/cut-region.json
@@ -1,5 +1,5 @@
{
- "code": "\n\n",
+ "code": "\n",
"nodes": [
{
"type": "hover",
@@ -33,19 +33,19 @@
{
"type": "hover",
"text": "(local function) increment(): void",
- "start": 69,
+ "start": 63,
"length": 9,
"target": "increment",
- "line": 5,
+ "line": 3,
"character": 17
},
{
"type": "hover",
"text": "let count: number",
- "start": 96,
+ "start": 90,
"length": 5,
"target": "count",
- "line": 6,
+ "line": 4,
"character": 15
}
],
diff --git a/packages/twoslash-svelte/test/results/script/cut.json b/packages/twoslash-svelte/test/results/script/cut.json
new file mode 100644
index 00000000..3482dc8a
--- /dev/null
+++ b/packages/twoslash-svelte/test/results/script/cut.json
@@ -0,0 +1,42 @@
+{
+ "code": "\n",
+ "nodes": [
+ {
+ "type": "hover",
+ "text": "(local function) increment(): void",
+ "start": 21,
+ "length": 9,
+ "target": "increment",
+ "line": 0,
+ "character": 21
+ },
+ {
+ "type": "hover",
+ "text": "let count: number",
+ "start": 43,
+ "length": 5,
+ "target": "count",
+ "line": 1,
+ "character": 8
+ },
+ {
+ "type": "hover",
+ "text": "(local function) increment(): void",
+ "start": 85,
+ "length": 9,
+ "target": "increment",
+ "line": 4,
+ "character": 17
+ },
+ {
+ "type": "hover",
+ "text": "let count: number",
+ "start": 112,
+ "length": 5,
+ "target": "count",
+ "line": 5,
+ "character": 15
+ }
+ ],
+ "flags": []
+}
\ No newline at end of file
diff --git a/packages/twoslash-svelte/test/results/hover.json b/packages/twoslash-svelte/test/results/script/hover.json
similarity index 81%
rename from packages/twoslash-svelte/test/results/hover.json
rename to packages/twoslash-svelte/test/results/script/hover.json
index 99056edd..43642528 100644
--- a/packages/twoslash-svelte/test/results/hover.json
+++ b/packages/twoslash-svelte/test/results/script/hover.json
@@ -1,5 +1,5 @@
{
- "code": "\n\n",
+ "code": "\n",
"nodes": [
{
"type": "hover",
@@ -33,37 +33,37 @@
{
"type": "hover",
"text": "(local function) increment(): void",
- "start": 50,
+ "start": 49,
"length": 9,
"target": "increment",
- "line": 3,
+ "line": 2,
"character": 13
},
{
"type": "hover",
"text": "let count: number",
- "start": 72,
+ "start": 71,
"length": 5,
"target": "count",
- "line": 4,
+ "line": 3,
"character": 8
},
{
"type": "hover",
"text": "(local function) increment(): void",
- "start": 115,
+ "start": 113,
"length": 9,
"target": "increment",
- "line": 8,
+ "line": 6,
"character": 17
},
{
"type": "hover",
"text": "let count: number",
- "start": 142,
+ "start": 140,
"length": 5,
"target": "count",
- "line": 9,
+ "line": 7,
"character": 15
}
],
diff --git a/packages/twoslash-svelte/test/results/query.json b/packages/twoslash-svelte/test/results/script/query.json
similarity index 85%
rename from packages/twoslash-svelte/test/results/query.json
rename to packages/twoslash-svelte/test/results/script/query.json
index 13e09080..33f6d133 100644
--- a/packages/twoslash-svelte/test/results/query.json
+++ b/packages/twoslash-svelte/test/results/script/query.json
@@ -1,5 +1,5 @@
{
- "code": "\n\n",
+ "code": "\n",
"nodes": [
{
"type": "hover",
@@ -53,37 +53,37 @@
{
"type": "hover",
"text": "(local function) increment(): void",
- "start": 50,
+ "start": 49,
"length": 9,
"target": "increment",
- "line": 3,
+ "line": 2,
"character": 13
},
{
"type": "hover",
"text": "let count: number",
- "start": 72,
+ "start": 71,
"length": 5,
"target": "count",
- "line": 4,
+ "line": 3,
"character": 8
},
{
"type": "hover",
"text": "(local function) increment(): void",
- "start": 115,
+ "start": 113,
"length": 9,
"target": "increment",
- "line": 8,
+ "line": 6,
"character": 17
},
{
"type": "hover",
"text": "let count: number",
- "start": 142,
+ "start": 140,
"length": 5,
"target": "count",
- "line": 9,
+ "line": 7,
"character": 15
}
],
diff --git a/packages/twoslash-svelte/test/results/script/throws/cut-region-missing-end.txt b/packages/twoslash-svelte/test/results/script/throws/cut-region-missing-end.txt
new file mode 100644
index 00000000..a5030398
--- /dev/null
+++ b/packages/twoslash-svelte/test/results/script/throws/cut-region-missing-end.txt
@@ -0,0 +1,6 @@
+
+## Mismatched cut markers
+
+You have unclosed cut-starts at line(s) 5
+
+Add a cut-end after each cut-start.
\ No newline at end of file
diff --git a/packages/twoslash-svelte/test/results/script/throws/cut-region-missing-start.txt b/packages/twoslash-svelte/test/results/script/throws/cut-region-missing-start.txt
new file mode 100644
index 00000000..b28a698b
--- /dev/null
+++ b/packages/twoslash-svelte/test/results/script/throws/cut-region-missing-start.txt
@@ -0,0 +1,6 @@
+
+## Mismatched cut markers
+
+You have an unclosed cut-end at line 8
+
+Add a cut-start before line 8.
\ No newline at end of file
diff --git a/packages/twoslash-svelte/test/results/template/cut-after.json b/packages/twoslash-svelte/test/results/template/cut-after.json
new file mode 100644
index 00000000..002c8a67
--- /dev/null
+++ b/packages/twoslash-svelte/test/results/template/cut-after.json
@@ -0,0 +1,53 @@
+{
+ "code": "\n",
+ "nodes": [
+ {
+ "type": "hover",
+ "text": "let count: number",
+ "start": 17,
+ "length": 5,
+ "target": "count",
+ "line": 1,
+ "character": 8
+ },
+ {
+ "type": "hover",
+ "text": "function $state<0>(initial: 0): 0 (+1 overload)\nnamespace $state",
+ "docs": "Declares reactive state.\n\nExample:\n```ts\nlet count = $state(0);\n```",
+ "tags": [
+ [
+ "see",
+ "{@link https://svelte.dev/docs/svelte/$state Documentation}"
+ ],
+ [
+ "param",
+ "initial The initial value"
+ ]
+ ],
+ "start": 25,
+ "length": 6,
+ "target": "$state",
+ "line": 1,
+ "character": 16
+ },
+ {
+ "type": "hover",
+ "text": "(local function) increment(): void",
+ "start": 49,
+ "length": 9,
+ "target": "increment",
+ "line": 2,
+ "character": 13
+ },
+ {
+ "type": "hover",
+ "text": "let count: number",
+ "start": 71,
+ "length": 5,
+ "target": "count",
+ "line": 3,
+ "character": 8
+ }
+ ],
+ "flags": []
+}
\ No newline at end of file
diff --git a/packages/twoslash-svelte/test/results/cut-around.json b/packages/twoslash-svelte/test/results/template/cut-before.json
similarity index 55%
rename from packages/twoslash-svelte/test/results/cut-around.json
rename to packages/twoslash-svelte/test/results/template/cut-before.json
index 75817fde..f412d47b 100644
--- a/packages/twoslash-svelte/test/results/cut-around.json
+++ b/packages/twoslash-svelte/test/results/template/cut-before.json
@@ -1,14 +1,14 @@
{
- "code": "\n\n",
+ "code": "",
"nodes": [
{
"type": "hover",
"text": "(local function) increment(): void",
- "start": 22,
+ "start": 17,
"length": 9,
"target": "increment",
- "line": 1,
- "character": 13
+ "line": 0,
+ "character": 17
},
{
"type": "hover",
@@ -16,8 +16,8 @@
"start": 44,
"length": 5,
"target": "count",
- "line": 2,
- "character": 8
+ "line": 1,
+ "character": 15
}
],
"flags": []
diff --git a/packages/twoslash-svelte/test/results/template/cut-region.json b/packages/twoslash-svelte/test/results/template/cut-region.json
new file mode 100644
index 00000000..002c8a67
--- /dev/null
+++ b/packages/twoslash-svelte/test/results/template/cut-region.json
@@ -0,0 +1,53 @@
+{
+ "code": "\n",
+ "nodes": [
+ {
+ "type": "hover",
+ "text": "let count: number",
+ "start": 17,
+ "length": 5,
+ "target": "count",
+ "line": 1,
+ "character": 8
+ },
+ {
+ "type": "hover",
+ "text": "function $state<0>(initial: 0): 0 (+1 overload)\nnamespace $state",
+ "docs": "Declares reactive state.\n\nExample:\n```ts\nlet count = $state(0);\n```",
+ "tags": [
+ [
+ "see",
+ "{@link https://svelte.dev/docs/svelte/$state Documentation}"
+ ],
+ [
+ "param",
+ "initial The initial value"
+ ]
+ ],
+ "start": 25,
+ "length": 6,
+ "target": "$state",
+ "line": 1,
+ "character": 16
+ },
+ {
+ "type": "hover",
+ "text": "(local function) increment(): void",
+ "start": 49,
+ "length": 9,
+ "target": "increment",
+ "line": 2,
+ "character": 13
+ },
+ {
+ "type": "hover",
+ "text": "let count: number",
+ "start": 71,
+ "length": 5,
+ "target": "count",
+ "line": 3,
+ "character": 8
+ }
+ ],
+ "flags": []
+}
\ No newline at end of file
diff --git a/packages/twoslash-svelte/test/results/template/cut.json b/packages/twoslash-svelte/test/results/template/cut.json
new file mode 100644
index 00000000..2ba673d7
--- /dev/null
+++ b/packages/twoslash-svelte/test/results/template/cut.json
@@ -0,0 +1,24 @@
+{
+ "code": "\n",
+ "nodes": [
+ {
+ "type": "hover",
+ "text": "(local function) increment(): void",
+ "start": 17,
+ "length": 9,
+ "target": "increment",
+ "line": 0,
+ "character": 17
+ },
+ {
+ "type": "hover",
+ "text": "let count: number",
+ "start": 44,
+ "length": 5,
+ "target": "count",
+ "line": 1,
+ "character": 15
+ }
+ ],
+ "flags": []
+}
\ No newline at end of file
diff --git a/packages/twoslash-svelte/test/results/template/throws/cut-region-missing-end.txt b/packages/twoslash-svelte/test/results/template/throws/cut-region-missing-end.txt
new file mode 100644
index 00000000..1f1b463c
--- /dev/null
+++ b/packages/twoslash-svelte/test/results/template/throws/cut-region-missing-end.txt
@@ -0,0 +1,6 @@
+
+## Mismatched cut markers
+
+You have unclosed cut-starts at line(s) 7
+
+Add a cut-end after each cut-start.
\ No newline at end of file
diff --git a/packages/twoslash-svelte/test/results/template/throws/cut-region-missing-start.txt b/packages/twoslash-svelte/test/results/template/throws/cut-region-missing-start.txt
new file mode 100644
index 00000000..a385c5a1
--- /dev/null
+++ b/packages/twoslash-svelte/test/results/template/throws/cut-region-missing-start.txt
@@ -0,0 +1,6 @@
+
+## Mismatched cut markers
+
+You have an unclosed cut-end at line 10
+
+Add a cut-start before line 10.
\ No newline at end of file
diff --git a/packages/twoslash/src/utils.ts b/packages/twoslash/src/utils.ts
index 88180baa..473f955c 100644
--- a/packages/twoslash/src/utils.ts
+++ b/packages/twoslash/src/utils.ts
@@ -259,10 +259,22 @@ export function findFlagNotations(code: string, customTags: string[], tsOptionDe
return flagNotations
}
-export function findCutNotations(code: string, meta: Pick) {
+export interface FindCutNotationsOptions {
+ reCutBefore?: RegExp
+ reCutAfter?: RegExp
+ reCutStart?: RegExp
+ reCutEnd?: RegExp
+}
+
+export function findCutNotations(code: string, meta: Pick, options: FindCutNotationsOptions = {}) {
+ const mergedReCutBefore = options.reCutBefore || reCutBefore
+ const mergedReCutAfter = options.reCutAfter || reCutAfter
+ const mergedReCutStart = options.reCutStart || reCutStart
+ const mergedReCutEnd = options.reCutEnd || reCutEnd
+
let removals: Range[] = []
const lines = code.split('\n')
- const cutStarts: number[] = []
+ const cutStarts: Array<{ idx: number, line: number }> = []
// start character after \n
let idx = 0
let lineIndex = 0
@@ -270,38 +282,38 @@ export function findCutNotations(code: string, meta: Pick i > lineIndex && line.trim().match(reCutStart))
+ if (start === undefined) {
+ const startLine = lines.findIndex((l, i) => i > lineIndex && l.trim().match(mergedReCutStart))
if (startLine === -1) {
throw new TwoslashError(
`Mismatched cut markers`,
- `You have an unclosed the cut-end at line ${lineIndex + 1}`,
- `Make sure you have a matching pair for each.`,
+ `You have an unclosed cut-end at line ${lineIndex + 1}`,
+ `Add a cut-start before line ${lineIndex + 1}.`,
)
}
throw new TwoslashError(
`Mismatched cut markers`,
`You have a cut-start at line ${startLine + 1} which is after the cut-end at line ${lineIndex + 1}`,
- `Make sure you have a matching pair for each.`,
+ `Move the cut-start to before line ${lineIndex + 1}.`,
)
}
- removals.push([startIdx, idx + line.length + 1])
+ removals.push([start.idx, idx + line.length + 1])
}
lineIndex++
@@ -311,8 +323,8 @@ export function findCutNotations(code: string, meta: Pick 0) {
throw new TwoslashError(
`Mismatched cut markers`,
- `You have unclosed cut-starts at lines ${cutStarts.join(', ')}`,
- `Make sure you have a matching pair for each.`,
+ `You have unclosed cut-starts at line(s) ${cutStarts.map(s => s.line + 1).join(', ')}`,
+ `Add a cut-end after each cut-start.`,
)
}
diff --git a/packages/twoslash/test/results/throws/unmatched-cut-range-count.txt b/packages/twoslash/test/results/throws/unmatched-cut-range-count.txt
index f214c475..a5030398 100644
--- a/packages/twoslash/test/results/throws/unmatched-cut-range-count.txt
+++ b/packages/twoslash/test/results/throws/unmatched-cut-range-count.txt
@@ -1,6 +1,6 @@
## Mismatched cut markers
-You have unclosed cut-starts at lines 60
+You have unclosed cut-starts at line(s) 5
-Make sure you have a matching pair for each.
\ No newline at end of file
+Add a cut-end after each cut-start.
\ No newline at end of file
diff --git a/packages/twoslash/test/results/throws/unmatched-cut-ranges.txt b/packages/twoslash/test/results/throws/unmatched-cut-ranges.txt
index 5e4c1b62..236a52a4 100644
--- a/packages/twoslash/test/results/throws/unmatched-cut-ranges.txt
+++ b/packages/twoslash/test/results/throws/unmatched-cut-ranges.txt
@@ -3,4 +3,4 @@
You have a cut-start at line 4 which is after the cut-end at line 2
-Make sure you have a matching pair for each.
\ No newline at end of file
+Move the cut-start to before line 2.
\ No newline at end of file
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index eac12cdb..5593f1c4 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -75,6 +75,9 @@ catalogs:
esno:
specifier: ^4.8.0
version: 4.8.0
+ estree-walker:
+ specifier: ^3.0.3
+ version: 3.0.3
fast-glob:
specifier: ^3.3.3
version: 3.3.3
@@ -450,6 +453,12 @@ importers:
'@volar/language-core':
specifier: 'catalog:'
version: 2.4.28
+ estree-walker:
+ specifier: 'catalog:'
+ version: 3.0.3
+ svelte:
+ specifier: '>=5'
+ version: 5.56.1(@typescript-eslint/types@8.58.1)
svelte2tsx:
specifier: 'catalog:'
version: 0.7.56(svelte@5.56.1(@typescript-eslint/types@8.58.1))(typescript@6.0.2)
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index 43bb88dd..014a3901 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -42,6 +42,7 @@ catalog:
chokidar: ^5.0.0
eslint: ^10.2.0
esno: ^4.8.0
+ estree-walker: ^3.0.3
fast-glob: ^3.3.3
floating-vue: ^5.2.2
fuse.js: ^7.3.0