Skip to content

Commit c19b76a

Browse files
committed
fix(md)!: warn if region not found, strip #regions
when a region is not in the source file, instead of including the whole file, warn that the #region was not found in it. fix #4625 --- `<<<` snippets now also strip out all #region markers: ```file.ts // #region A // #region B console.log("Hello, World!"); // #endregion // #endregion ``` <<< file.ts#A ...does not include "#region B" anymore
1 parent f950739 commit c19b76a

File tree

4 files changed

+103
-12
lines changed

4 files changed

+103
-12
lines changed

__tests__/e2e/markdown-extensions/markdown-extensions.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ describe('Line Numbers', () => {
216216
describe('Import Code Snippets', () => {
217217
test('basic', async () => {
218218
const lines = page.locator('#basic-code-snippet + div code > span')
219-
expect(await lines.count()).toBe(11)
219+
expect(await lines.count()).toBe(9)
220220
})
221221

222222
test('specify region', async () => {
@@ -269,7 +269,7 @@ describe('Code Groups', () => {
269269

270270
// blocks
271271
const blocks = div.locator('.blocks > div')
272-
expect(await blocks.nth(0).locator('code > span').count()).toBe(11)
272+
expect(await blocks.nth(0).locator('code > span').count()).toBe(9)
273273
expect(await getClassList(blocks.nth(1))).toContain('line-numbers-mode')
274274
expect(await getClassList(blocks.nth(1))).toContain('language-ts')
275275
expect(await blocks.nth(1).locator('code > span').count()).toBe(3)

__tests__/unit/node/markdown/plugins/snippet.test.ts

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import {
22
dedent,
33
findRegions,
4-
rawPathToToken
4+
rawPathToToken,
5+
stripRegionMarkers
56
} from 'node/markdown/plugins/snippet'
67
import { expect } from 'vitest'
78

@@ -406,5 +407,74 @@ describe('node/markdown/plugins/snippet', () => {
406407
expect(extracted).toBe(expected)
407408
}
408409
})
410+
411+
it('handles region names with hyphens and special characters', () => {
412+
const lines = [
413+
'// #region complex-name_123',
414+
'const x = 1;',
415+
'// #endregion complex-name_123'
416+
]
417+
const result = findRegions(lines, 'complex-name_123')
418+
expect(result).toHaveLength(1)
419+
if (result) {
420+
const extracted = result
421+
.flatMap((r) =>
422+
lines
423+
.slice(r.start, r.end)
424+
.filter((l) => !(r.re.start.test(l) || r.re.end.test(l)))
425+
)
426+
.join('\n')
427+
expect(extracted).toBe('const x = 1;')
428+
}
429+
})
430+
})
431+
432+
describe('stripRegionMarkers', () => {
433+
it('removes #region and #endregion lines', () => {
434+
const src = [
435+
'// #region A',
436+
'// #region B',
437+
'console.log("Hello, World!");',
438+
'// #endregion B',
439+
'// #endregion A'
440+
]
441+
expect(stripRegionMarkers(src)).toBe('console.log("Hello, World!");')
442+
})
443+
444+
it('removes region markers for various syntaxes', () => {
445+
const src = [
446+
'<!-- #region html -->',
447+
'<div>hi</div>',
448+
'<!-- #endregion html -->',
449+
'/* #region css */',
450+
'body {}',
451+
'/* #endregion css */',
452+
'#pragma region cpp',
453+
'int main(){}',
454+
'#pragma endregion cpp',
455+
'::#region bat',
456+
'ECHO ON',
457+
'REM #endregion bat'
458+
]
459+
const out = stripRegionMarkers(src)
460+
expect(out).not.toContain('#region')
461+
expect(out).not.toContain('#endregion')
462+
expect(out).toContain('<div>hi</div>')
463+
expect(out).toContain('body {}')
464+
expect(out).toContain('int main(){}')
465+
expect(out).toContain('ECHO ON')
466+
})
467+
468+
it('removes markers even if indented or with extra spaces', () => {
469+
const src = [
470+
' // #region spaced ',
471+
'\t/* #region */',
472+
'code();',
473+
' // #endregion spaced',
474+
'/* #endregion */'
475+
]
476+
const out = stripRegionMarkers(src)
477+
expect(out.trim()).toBe('code();')
478+
})
409479
})
410480
})

src/node/markdown/plugins/snippet.ts

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,17 @@ export function findRegions(lines: string[], regionName: string) {
126126
return returned
127127
}
128128

129+
export function stripRegionMarkers(lines: string[]): string {
130+
return lines
131+
.filter((l) => {
132+
for (const m of markers) {
133+
if (m.start.test(l) || m.end.test(l)) return false
134+
}
135+
return true
136+
})
137+
.join('\n')
138+
}
139+
129140
export const snippetPlugin = (md: MarkdownItAsync, srcDir: string) => {
130141
const parser: RuleBlock = (state, startLine, endLine, silent) => {
131142
const CH = '<'.charCodeAt(0)
@@ -182,7 +193,7 @@ export const snippetPlugin = (md: MarkdownItAsync, srcDir: string) => {
182193
const [tokens, idx, , { includes }] = args
183194
const token = tokens[idx]
184195
// @ts-ignore
185-
const [src, regionName] = token.src ?? []
196+
const [src, region] = token.src ?? []
186197

187198
if (!src) return fence(...args)
188199

@@ -204,21 +215,27 @@ export const snippetPlugin = (md: MarkdownItAsync, srcDir: string) => {
204215

205216
let content = fs.readFileSync(src, 'utf8').replace(/\r\n/g, '\n')
206217

207-
if (regionName) {
218+
if (region) {
208219
const lines = content.split('\n')
209-
const regions = findRegions(lines, regionName)
220+
const regions = findRegions(lines, region)
210221

211222
if (regions.length > 0) {
212223
content = dedent(
213-
regions
214-
.flatMap((r) =>
224+
stripRegionMarkers(
225+
regions.flatMap((r) =>
215226
lines
216227
.slice(r.start, r.end)
217228
.filter((l) => !(r.re.start.test(l) || r.re.end.test(l)))
218229
)
219-
.join('\n')
230+
)
220231
)
232+
} else {
233+
token.content = `No region #${region} found in path: ${src}`
234+
token.info = ''
235+
return fence(...args)
221236
}
237+
} else {
238+
content = stripRegionMarkers(content.split('\n'))
222239
}
223240

224241
token.content = content

src/node/utils/processIncludes.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,13 @@ export function processIncludes(
7171
}
7272
}
7373

74-
content = regions
75-
.flatMap((region) => lines.slice(region.start, region.end))
76-
.join('\n')
74+
if (regions.length > 0) {
75+
content = regions
76+
.flatMap((region) => lines.slice(region.start, region.end))
77+
.join('\n')
78+
} else {
79+
content = `No region or heading #${region} found in path: ${includePath}`
80+
}
7781
}
7882

7983
if (range) {

0 commit comments

Comments
 (0)