Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

endregion snippet extraction does not require tag #4287

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 142 additions & 1 deletion __tests__/unit/node/markdown/plugins/snippet.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { dedent, rawPathToToken } from 'node/markdown/plugins/snippet'
import {
dedent,
findRegion,
rawPathToToken
} from 'node/markdown/plugins/snippet'
import { expect } from 'vitest'

const removeEmptyKeys = <T extends Record<string, unknown>>(obj: T) => {
return Object.fromEntries(
Expand Down Expand Up @@ -99,4 +104,140 @@ describe('node/markdown/plugins/snippet', () => {
expect(removeEmptyKeys(rawPathToToken(rawPath))).toEqual(token)
})
})

describe('findRegion', () => {
test('when c# region with matching tag', () => {
const lines = `Console.WriteLine("Before region");
#region hello
Console.WriteLine("Hello, World!");
#endregion hello
Console.WriteLine("After region");`.split('\n')
const result = findRegion(lines, 'hello')

expect(lines.slice(result?.start, result?.end).join('\n')).toBe(
'Console.WriteLine("Hello, World!");'
)
})
test('when c# region is not indented with spaces and no matching tag', () => {
const lines = `Console.WriteLine("Before region");
#region hello
Console.WriteLine("Hello, World!");
#endregion
Console.WriteLine("After region");`.split('\n')
const result = findRegion(lines, 'hello')

expect(lines.slice(result?.start, result?.end).join('\n')).toBe(
'Console.WriteLine("Hello, World!");'
)
})
test('when c# region is indented with spaces and no matching tag', () => {
const lines = ` Console.WriteLine("Before region");
#region hello
Console.WriteLine("Hello, World!");
#endregion hello
Console.WriteLine("After region");`.split('\n')
const result = findRegion(lines, 'hello')

expect(lines.slice(result?.start, result?.end).join('\n')).toBe(
' Console.WriteLine("Hello, World!");'
)
})
test('when c# region with matching tag', () => {
const lines = `Console.WriteLine("Before region");
#region hello
Console.WriteLine("Hello, World!");
#endregion hello
Console.WriteLine("After region");`.split('\n')
const result = findRegion(lines, 'hello')

expect(lines.slice(result?.start, result?.end).join('\n')).toBe(
'Console.WriteLine("Hello, World!");'
)
})
test('when c# region is not indented with spaces and no matching tag', () => {
const lines = `Console.WriteLine("Before region");
#region hello
Console.WriteLine("Hello, World!");
#endregion
Console.WriteLine("After region");`.split('\n')
const result = findRegion(lines, 'hello')

expect(lines.slice(result?.start, result?.end).join('\n')).toBe(
'Console.WriteLine("Hello, World!");'
)
})

test('when typescript region has matching tag', () => {
const lines = `let regexp: RegExp[] = []
// #region foo
let start = -1
// #endregion foo`.split('\n')
const result = findRegion(lines, 'foo')

expect(lines.slice(result?.start, result?.end).join('\n')).toBe(
'let start = -1'
)
})
test('when typescript region is indented with spaces and no matching tag', () => {
const lines = ` let regexp: RegExp[] = []
// #region foo
let start = -1
// #endregion`.split('\n')
const result = findRegion(lines, 'foo')

expect(lines.slice(result?.start, result?.end).join('\n')).toBe(
' let start = -1'
)
})

test('when css region has matching tag', () => {
const lines = `.body-content {
/* #region foo */
padding-left: 15px;
/* #endregion foo */
padding-right: 15px;
}`.split('\n')
const result = findRegion(lines, 'foo')

expect(lines.slice(result?.start, result?.end).join('\n')).toBe(
' padding-left: 15px;'
)
})
test('when css region is indented with spaces and no matching tag', () => {
const lines = `.body-content {
/* #region foo */
padding-left: 15px;
/* #endregion */
padding-right: 15px;
}`.split('\n')
const result = findRegion(lines, 'foo')

expect(lines.slice(result?.start, result?.end).join('\n')).toBe(
' padding-left: 15px;'
)
})

test('when html region has matching tag', () => {
const lines = `<!-- #region foo -->
<h1>Hello world</h1>
<!-- #endregion foo -->
<p>more text</p>`.split('\n')
const result = findRegion(lines, 'foo')

expect(lines.slice(result?.start, result?.end).join('\n')).toBe(
' <h1>Hello world</h1>'
)
})
test('when html region is indented with spaces and no matching tag', () => {
const lines = ` <!-- #region foo -->
<h1>Hello world</h1>
<!-- #endregion foo -->
<p>more text</p>`.split('\n')
const result = findRegion(lines, 'foo')

expect(lines.slice(result?.start, result?.end).join('\n')).toBe(
' <h1>Hello world</h1>'
)
})
})
})
46 changes: 28 additions & 18 deletions src/node/markdown/plugins/snippet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,38 +59,42 @@ function testLine(
) {
const [full, tag, name] = regexp.exec(line.trim()) || []

return (
full &&
tag &&
name === regionName &&
tag.match(end ? /^[Ee]nd ?[rR]egion$/ : /^[rR]egion$/)
)
return full && tag && end
? true
: name === regionName &&
tag.match(end ? /^[Ee]nd ?[rR]egion$/ : /^[rR]egion$/)
}

export function findRegion(lines: Array<string>, regionName: string) {
const regionRegexps = [
/^\/\/ ?#?((?:end)?region) ([\w*-]+)$/, // javascript, typescript, java
/^\/\* ?#((?:end)?region) ([\w*-]+) ?\*\/$/, // css, less, scss
/^#pragma ((?:end)?region) ([\w*-]+)$/, // C, C++
/^<!-- #?((?:end)?region) ([\w*-]+) -->$/, // HTML, markdown
/^#((?:End )Region) ([\w*-]+)$/, // Visual Basic
/^::#((?:end)region) ([\w*-]+)$/, // Bat
/^# ?((?:end)?region) ([\w*-]+)$/ // C#, PHP, Powershell, Python, perl & misc
[
/^[ \t]*\/\/ ?#?(region) ([\w*-]+)$/,
/^[ \t]*\/\/ ?#?(endregion) ?([\w*-]*)$/
], // javascript, typescript, java
[
/^\/\* ?#(region) ([\w*-]+) ?\*\/$/,
/^\/\* ?#(endregion) ?([\w*-]*) ?\*\/$/
], // css, less, scss
[/^#pragma (region) ([\w*-]+)$/, /^#pragma (endregion) ?([\w*-]*)$/], // C, C++
[/^<!-- #?(region) ([\w*-]+) -->$/, /^<!-- #?(endregion) ?([\w*-]*) -->$/], // HTML, markdown
[/^[ \t]*#(Region) ([\w*-]+)$/, /^[ \t]*#(End Region) ?([\w*-]*)$/], // Visual Basic
[/^::#(region) ([\w*-]+)$/, /^::#(endregion) ?([\w*-]*)$/], // Bat
[/^[ \t]*# ?(region) ([\w*-]+)$/, /^[ \t]*# ?(endregion) ?([\w*-]*)$/] // C#, PHP, Powershell, Python, perl & misc
]

let regexp = null
let regexp: RegExp[] = []
let start = -1

for (const [lineId, line] of lines.entries()) {
if (regexp === null) {
if (regexp.length === 0) {
for (const reg of regionRegexps) {
if (testLine(line, reg, regionName)) {
if (testLine(line, reg[0], regionName)) {
start = lineId + 1
regexp = reg
break
}
}
} else if (testLine(line, regexp, regionName, true)) {
} else if (testLine(line, regexp[1], regionName, true)) {
return { start, end: lineId, regexp }
}
}
Expand Down Expand Up @@ -181,7 +185,13 @@ export const snippetPlugin = (md: MarkdownIt, srcDir: string) => {
content = dedent(
lines
.slice(region.start, region.end)
.filter((line) => !region.regexp.test(line.trim()))
.filter((line) => {
const trimmed = line.trim()
return (
!region.regexp[0].test(trimmed) &&
!region.regexp[1].test(trimmed)
)
})
.join('\n')
)
}
Expand Down