|
1 | 1 | import fs from 'fs-extra' |
2 | | -import type MarkdownIt from 'markdown-it' |
| 2 | +import type { MarkdownItAsync } from 'markdown-it-async' |
3 | 3 | import type { RuleBlock } from 'markdown-it/lib/parser_block.mjs' |
4 | 4 | import path from 'node:path' |
5 | 5 | import type { MarkdownEnv } from '../../shared' |
@@ -51,78 +51,75 @@ export function dedent(text: string): string { |
51 | 51 | return text |
52 | 52 | } |
53 | 53 |
|
| 54 | +const markers = [ |
| 55 | + { |
| 56 | + start: /^\s*\/\/\s*#?region\b\s*(.*?)\s*$/, |
| 57 | + end: /^\s*\/\/\s*#?endregion\b\s*(.*?)\s*$/ |
| 58 | + }, |
| 59 | + { |
| 60 | + start: /^\s*<!--\s*#?region\b\s*(.*?)\s*-->/, |
| 61 | + end: /^\s*<!--\s*#?endregion\b\s*(.*?)\s*-->/ |
| 62 | + }, |
| 63 | + { |
| 64 | + start: /^\s*\/\*\s*#region\b\s*(.*?)\s*\*\//, |
| 65 | + end: /^\s*\/\*\s*#endregion\b\s*(.*?)\s*\*\// |
| 66 | + }, |
| 67 | + { |
| 68 | + start: /^\s*#[rR]egion\b\s*(.*?)\s*$/, |
| 69 | + end: /^\s*#[eE]nd ?[rR]egion\b\s*(.*?)\s*$/ |
| 70 | + }, |
| 71 | + { |
| 72 | + start: /^\s*#\s*#?region\b\s*(.*?)\s*$/, |
| 73 | + end: /^\s*#\s*#?endregion\b\s*(.*?)\s*$/ |
| 74 | + }, |
| 75 | + { |
| 76 | + start: /^\s*(?:--|::|@?REM)\s*#region\b\s*(.*?)\s*$/, |
| 77 | + end: /^\s*(?:--|::|@?REM)\s*#endregion\b\s*(.*?)\s*$/ |
| 78 | + }, |
| 79 | + { |
| 80 | + start: /^\s*#pragma\s+region\b\s*(.*?)\s*$/, |
| 81 | + end: /^\s*#pragma\s+endregion\b\s*(.*?)\s*$/ |
| 82 | + }, |
| 83 | + { |
| 84 | + start: /^\s*\(\*\s*#region\b\s*(.*?)\s*\*\)/, |
| 85 | + end: /^\s*\(\*\s*#endregion\b\s*(.*?)\s*\*\)/ |
| 86 | + } |
| 87 | +] |
| 88 | + |
54 | 89 | export function findRegion(lines: Array<string>, regionName: string) { |
55 | | - const regionRegexps: [RegExp, RegExp][] = [ |
56 | | - [ |
57 | | - /^[ \t]*\/\/ ?#?(region) ([\w*-]+)$/, |
58 | | - /^[ \t]*\/\/ ?#?(endregion) ?([\w*-]*)$/ |
59 | | - ], // javascript, typescript, java |
60 | | - [ |
61 | | - /^\/\* ?#(region) ([\w*-]+) ?\*\/$/, |
62 | | - /^\/\* ?#(endregion) ?([\w*-]*) ?\*\/$/ |
63 | | - ], // css, less, scss |
64 | | - [/^#pragma (region) ([\w*-]+)$/, /^#pragma (endregion) ?([\w*-]*)$/], // C, C++ |
65 | | - [/^<!-- #?(region) ([\w*-]+) -->$/, /^<!-- #?(endregion) ?([\w*-]*) -->$/], // HTML, markdown |
66 | | - [/^[ \t]*#(Region) ([\w*-]+)$/, /^[ \t]*#(End Region) ?([\w*-]*)$/], // Visual Basic |
67 | | - [/^::#(region) ([\w*-]+)$/, /^::#(endregion) ?([\w*-]*)$/], // Bat |
68 | | - [/^[ \t]*# ?(region) ([\w*-]+)$/, /^[ \t]*# ?(endregion) ?([\w*-]*)$/] // C#, PHP, Powershell, Python, perl & misc |
69 | | - ] |
70 | | - |
71 | | - let chosenRegex: [RegExp, RegExp] | null = null |
72 | | - let startLine = -1 |
| 90 | + let chosen: { re: (typeof markers)[number]; start: number } | null = null |
73 | 91 | // find the regex pair for a start marker that matches the given region name |
74 | 92 | for (let i = 0; i < lines.length; i++) { |
75 | | - const line = lines[i].trim() |
76 | | - for (const [startRegex, endRegex] of regionRegexps) { |
77 | | - const startMatch = startRegex.exec(line) |
78 | | - if ( |
79 | | - startMatch && |
80 | | - startMatch[2] === regionName && |
81 | | - /^[rR]egion$/.test(startMatch[1]) |
82 | | - ) { |
83 | | - chosenRegex = [startRegex, endRegex] |
84 | | - startLine = i + 1 |
| 93 | + for (const re of markers) { |
| 94 | + if (re.start.exec(lines[i])?.[1] === regionName) { |
| 95 | + chosen = { re, start: i + 1 } |
85 | 96 | break |
86 | 97 | } |
87 | 98 | } |
88 | | - if (chosenRegex) break |
| 99 | + if (chosen) break |
89 | 100 | } |
90 | | - if (!chosenRegex) return null |
| 101 | + if (!chosen) return null |
91 | 102 |
|
92 | | - const [startRegex, endRegex] = chosenRegex |
93 | 103 | let counter = 1 |
94 | 104 | // scan the rest of the lines to find the matching end marker, handling nested markers |
95 | | - for (let i = startLine; i < lines.length; i++) { |
96 | | - const trimmed = lines[i].trim() |
| 105 | + for (let i = chosen.start; i < lines.length; i++) { |
97 | 106 | // check for an inner start marker for the same region |
98 | | - const startMatch = startRegex.exec(trimmed) |
99 | | - if ( |
100 | | - startMatch && |
101 | | - startMatch[2] === regionName && |
102 | | - /^[rR]egion$/.test(startMatch[1]) |
103 | | - ) { |
| 107 | + if (chosen.re.start.exec(lines[i])?.[1] === regionName) { |
104 | 108 | counter++ |
105 | 109 | continue |
106 | 110 | } |
107 | 111 | // check for an end marker for the same region |
108 | | - const endMatch = endRegex.exec(trimmed) |
109 | | - if ( |
110 | | - endMatch && |
111 | | - // allow empty region name on the end marker as a fallback |
112 | | - (endMatch[2] === regionName || endMatch[2] === '') && |
113 | | - /^[Ee]nd ?[rR]egion$/.test(endMatch[1]) |
114 | | - ) { |
115 | | - counter-- |
116 | | - if (counter === 0) { |
117 | | - return { start: startLine, end: i, regexp: chosenRegex } |
118 | | - } |
| 112 | + const endRegion = chosen.re.end.exec(lines[i])?.[1] |
| 113 | + // allow empty region name on the end marker as a fallback |
| 114 | + if (endRegion === regionName || endRegion === '') { |
| 115 | + if (--counter === 0) return { ...chosen, end: i } |
119 | 116 | } |
120 | 117 | } |
121 | 118 |
|
122 | 119 | return null |
123 | 120 | } |
124 | 121 |
|
125 | | -export const snippetPlugin = (md: MarkdownIt, srcDir: string) => { |
| 122 | +export const snippetPlugin = (md: MarkdownItAsync, srcDir: string) => { |
126 | 123 | const parser: RuleBlock = (state, startLine, endLine, silent) => { |
127 | 124 | const CH = '<'.charCodeAt(0) |
128 | 125 | const pos = state.bMarks[startLine] + state.tShift[startLine] |
@@ -205,13 +202,7 @@ export const snippetPlugin = (md: MarkdownIt, srcDir: string) => { |
205 | 202 | content = dedent( |
206 | 203 | lines |
207 | 204 | .slice(region.start, region.end) |
208 | | - .filter((line) => { |
209 | | - const trimmed = line.trim() |
210 | | - return ( |
211 | | - !region.regexp[0].test(trimmed) && |
212 | | - !region.regexp[1].test(trimmed) |
213 | | - ) |
214 | | - }) |
| 205 | + .filter((l) => !(region.re.start.test(l) || region.re.end.test(l))) |
215 | 206 | .join('\n') |
216 | 207 | ) |
217 | 208 | } |
|
0 commit comments