|
1 |
| -import { dedent, rawPathToToken } from 'node/markdown/plugins/snippet' |
| 1 | +import { |
| 2 | + dedent, |
| 3 | + findRegion, |
| 4 | + rawPathToToken |
| 5 | +} from 'node/markdown/plugins/snippet' |
| 6 | +import { expect } from 'vitest' |
2 | 7 |
|
3 | 8 | const removeEmptyKeys = <T extends Record<string, unknown>>(obj: T) => {
|
4 | 9 | return Object.fromEntries(
|
@@ -94,9 +99,228 @@ describe('node/markdown/plugins/snippet', () => {
|
94 | 99 | })
|
95 | 100 | })
|
96 | 101 |
|
97 |
| - test('rawPathToToken', () => { |
98 |
| - rawPathTokenMap.forEach(([rawPath, token]) => { |
| 102 | + describe('rawPathToToken', () => { |
| 103 | + test.each(rawPathTokenMap)('%s', (rawPath, token) => { |
99 | 104 | expect(removeEmptyKeys(rawPathToToken(rawPath))).toEqual(token)
|
100 | 105 | })
|
101 | 106 | })
|
| 107 | + |
| 108 | + describe('findRegion', () => { |
| 109 | + it('returns null when no region markers are present', () => { |
| 110 | + const lines = ['function foo() {', ' console.log("hello");', '}'] |
| 111 | + expect(findRegion(lines, 'foo')).toBeNull() |
| 112 | + }) |
| 113 | + |
| 114 | + it('ignores non-matching region names', () => { |
| 115 | + const lines = [ |
| 116 | + '// #region regionA', |
| 117 | + 'some code here', |
| 118 | + '// #endregion regionA' |
| 119 | + ] |
| 120 | + expect(findRegion(lines, 'regionC')).toBeNull() |
| 121 | + }) |
| 122 | + |
| 123 | + it('returns null if a region start marker exists without a matching end marker', () => { |
| 124 | + const lines = [ |
| 125 | + '// #region missingEnd', |
| 126 | + 'console.log("inside region");', |
| 127 | + 'console.log("still inside");' |
| 128 | + ] |
| 129 | + expect(findRegion(lines, 'missingEnd')).toBeNull() |
| 130 | + }) |
| 131 | + |
| 132 | + it('returns null if an end marker exists without a preceding start marker', () => { |
| 133 | + const lines = [ |
| 134 | + '// #endregion ghostRegion', |
| 135 | + 'console.log("stray end marker");' |
| 136 | + ] |
| 137 | + expect(findRegion(lines, 'ghostRegion')).toBeNull() |
| 138 | + }) |
| 139 | + |
| 140 | + it('detects C#/JavaScript style region markers with matching tags', () => { |
| 141 | + const lines = [ |
| 142 | + 'Console.WriteLine("Before region");', |
| 143 | + '#region hello', |
| 144 | + 'Console.WriteLine("Hello, World!");', |
| 145 | + '#endregion hello', |
| 146 | + 'Console.WriteLine("After region");' |
| 147 | + ] |
| 148 | + const result = findRegion(lines, 'hello') |
| 149 | + expect(result).not.toBeNull() |
| 150 | + if (result) { |
| 151 | + expect(lines.slice(result.start, result.end).join('\n')).toBe( |
| 152 | + 'Console.WriteLine("Hello, World!");' |
| 153 | + ) |
| 154 | + } |
| 155 | + }) |
| 156 | + |
| 157 | + it('detects region markers even when the end marker omits the region name', () => { |
| 158 | + const lines = [ |
| 159 | + 'Console.WriteLine("Before region");', |
| 160 | + '#region hello', |
| 161 | + 'Console.WriteLine("Hello, World!");', |
| 162 | + '#endregion', |
| 163 | + 'Console.WriteLine("After region");' |
| 164 | + ] |
| 165 | + const result = findRegion(lines, 'hello') |
| 166 | + expect(result).not.toBeNull() |
| 167 | + if (result) { |
| 168 | + expect(lines.slice(result.start, result.end).join('\n')).toBe( |
| 169 | + 'Console.WriteLine("Hello, World!");' |
| 170 | + ) |
| 171 | + } |
| 172 | + }) |
| 173 | + |
| 174 | + it('handles indented region markers correctly', () => { |
| 175 | + const lines = [ |
| 176 | + ' Console.WriteLine("Before region");', |
| 177 | + ' #region hello', |
| 178 | + ' Console.WriteLine("Hello, World!");', |
| 179 | + ' #endregion hello', |
| 180 | + ' Console.WriteLine("After region");' |
| 181 | + ] |
| 182 | + const result = findRegion(lines, 'hello') |
| 183 | + expect(result).not.toBeNull() |
| 184 | + if (result) { |
| 185 | + expect(lines.slice(result.start, result.end).join('\n')).toBe( |
| 186 | + ' Console.WriteLine("Hello, World!");' |
| 187 | + ) |
| 188 | + } |
| 189 | + }) |
| 190 | + |
| 191 | + it('detects TypeScript style region markers', () => { |
| 192 | + const lines = [ |
| 193 | + 'let regexp: RegExp[] = [];', |
| 194 | + '// #region foo', |
| 195 | + 'let start = -1;', |
| 196 | + '// #endregion foo' |
| 197 | + ] |
| 198 | + const result = findRegion(lines, 'foo') |
| 199 | + expect(result).not.toBeNull() |
| 200 | + if (result) { |
| 201 | + expect(lines.slice(result.start, result.end).join('\n')).toBe( |
| 202 | + 'let start = -1;' |
| 203 | + ) |
| 204 | + } |
| 205 | + }) |
| 206 | + |
| 207 | + it('detects CSS style region markers', () => { |
| 208 | + const lines = [ |
| 209 | + '.body-content {', |
| 210 | + '/* #region foo */', |
| 211 | + ' padding-left: 15px;', |
| 212 | + '/* #endregion foo */', |
| 213 | + ' padding-right: 15px;', |
| 214 | + '}' |
| 215 | + ] |
| 216 | + const result = findRegion(lines, 'foo') |
| 217 | + expect(result).not.toBeNull() |
| 218 | + if (result) { |
| 219 | + expect(lines.slice(result.start, result.end).join('\n')).toBe( |
| 220 | + ' padding-left: 15px;' |
| 221 | + ) |
| 222 | + } |
| 223 | + }) |
| 224 | + |
| 225 | + it('detects HTML style region markers', () => { |
| 226 | + const lines = [ |
| 227 | + '<div>Some content</div>', |
| 228 | + '<!-- #region foo -->', |
| 229 | + ' <h1>Hello world</h1>', |
| 230 | + '<!-- #endregion foo -->', |
| 231 | + '<div>Other content</div>' |
| 232 | + ] |
| 233 | + const result = findRegion(lines, 'foo') |
| 234 | + expect(result).not.toBeNull() |
| 235 | + if (result) { |
| 236 | + expect(lines.slice(result.start, result.end).join('\n')).toBe( |
| 237 | + ' <h1>Hello world</h1>' |
| 238 | + ) |
| 239 | + } |
| 240 | + }) |
| 241 | + |
| 242 | + it('detects Visual Basic style region markers (with case-insensitive "End")', () => { |
| 243 | + const lines = [ |
| 244 | + 'Console.WriteLine("VB")', |
| 245 | + '#Region VBRegion', |
| 246 | + ' Console.WriteLine("Inside region")', |
| 247 | + '#End Region VBRegion', |
| 248 | + 'Console.WriteLine("Done")' |
| 249 | + ] |
| 250 | + const result = findRegion(lines, 'VBRegion') |
| 251 | + expect(result).not.toBeNull() |
| 252 | + if (result) { |
| 253 | + expect(lines.slice(result.start, result.end).join('\n')).toBe( |
| 254 | + ' Console.WriteLine("Inside region")' |
| 255 | + ) |
| 256 | + } |
| 257 | + }) |
| 258 | + |
| 259 | + it('detects Bat style region markers', () => { |
| 260 | + const lines = ['::#region foo', 'echo off', '::#endregion foo'] |
| 261 | + const result = findRegion(lines, 'foo') |
| 262 | + expect(result).not.toBeNull() |
| 263 | + if (result) { |
| 264 | + expect(lines.slice(result.start, result.end).join('\n')).toBe( |
| 265 | + 'echo off' |
| 266 | + ) |
| 267 | + } |
| 268 | + }) |
| 269 | + |
| 270 | + it('detects C/C++ style region markers using #pragma', () => { |
| 271 | + const lines = [ |
| 272 | + '#pragma region foo', |
| 273 | + 'int a = 1;', |
| 274 | + '#pragma endregion foo' |
| 275 | + ] |
| 276 | + const result = findRegion(lines, 'foo') |
| 277 | + expect(result).not.toBeNull() |
| 278 | + if (result) { |
| 279 | + expect(lines.slice(result.start, result.end).join('\n')).toBe( |
| 280 | + 'int a = 1;' |
| 281 | + ) |
| 282 | + } |
| 283 | + }) |
| 284 | + |
| 285 | + it('returns the first complete region when multiple regions exist', () => { |
| 286 | + const lines = [ |
| 287 | + '// #region foo', |
| 288 | + 'first region content', |
| 289 | + '// #endregion foo', |
| 290 | + '// #region foo', |
| 291 | + 'second region content', |
| 292 | + '// #endregion foo' |
| 293 | + ] |
| 294 | + const result = findRegion(lines, 'foo') |
| 295 | + expect(result).not.toBeNull() |
| 296 | + if (result) { |
| 297 | + expect(lines.slice(result.start, result.end).join('\n')).toBe( |
| 298 | + 'first region content' |
| 299 | + ) |
| 300 | + } |
| 301 | + }) |
| 302 | + |
| 303 | + it('handles nested regions with different names properly', () => { |
| 304 | + const lines = [ |
| 305 | + '// #region foo', |
| 306 | + "console.log('line before nested');", |
| 307 | + '// #region bar', |
| 308 | + "console.log('nested content');", |
| 309 | + '// #endregion bar', |
| 310 | + '// #endregion foo' |
| 311 | + ] |
| 312 | + const result = findRegion(lines, 'foo') |
| 313 | + expect(result).not.toBeNull() |
| 314 | + if (result) { |
| 315 | + const extracted = lines.slice(result.start, result.end).join('\n') |
| 316 | + const expected = [ |
| 317 | + "console.log('line before nested');", |
| 318 | + '// #region bar', |
| 319 | + "console.log('nested content');", |
| 320 | + '// #endregion bar' |
| 321 | + ].join('\n') |
| 322 | + expect(extracted).toBe(expected) |
| 323 | + } |
| 324 | + }) |
| 325 | + }) |
102 | 326 | })
|
0 commit comments