From bc4dff1d8c311cd99a9dceea6659707054446a2d Mon Sep 17 00:00:00 2001 From: Brett Zamir Date: Fri, 16 Jan 2026 20:10:58 -0700 Subject: [PATCH] fix: fully exclude slash-containing strings like @npm/package from tag detection --- src/parser/block-parser.ts | 4 +- tests/unit/block-parser.spec.ts | 80 +++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 2 deletions(-) diff --git a/src/parser/block-parser.ts b/src/parser/block-parser.ts index 627749e7..410eb2b8 100644 --- a/src/parser/block-parser.ts +++ b/src/parser/block-parser.ts @@ -1,12 +1,12 @@ import { Line } from '../primitives.js'; -const reTag = /^@\S+/; +const reTag = /^@[^\s/]+(?=\s|$)/; /** * Groups source lines in sections representing tags. * First section is a block description if present. Last section captures lines starting with * the last tag to the end of the block, including dangling closing marker. - * @param {Line[]} block souce lines making a single comment block + * @param {Line[]} block source lines making a single comment block */ export type Parser = (block: Line[]) => Line[][]; diff --git a/tests/unit/block-parser.spec.ts b/tests/unit/block-parser.spec.ts index e15187a1..df9ac5df 100644 --- a/tests/unit/block-parser.spec.ts +++ b/tests/unit/block-parser.spec.ts @@ -167,3 +167,83 @@ test('fence function', () => { expect(groups.length).toBe(2); expect(groups).toEqual([source.slice(0, 5), source.slice(5)]); }); + +test('should not treat @npm/package or @ember/debug as tags', () => { + const parser = getParser(); + const lines: Line[] = [ + { + number: 1, + source: '/**', + tokens: seedTokens({ + start: '', + delimiter: '/**', + postDelimiter: '', + description: '', + end: '', + }), + }, + { + number: 2, + source: ' * Description line', + tokens: seedTokens({ + start: ' ', + delimiter: '*', + postDelimiter: ' ', + description: 'Description line', + end: '', + }), + }, + { + number: 3, + source: ' * @ember/debug should not be treated as tag', + tokens: seedTokens({ + start: ' ', + delimiter: '*', + postDelimiter: ' ', + description: '@ember/debug should not be treated as tag', + end: '', + }), + }, + { + number: 4, + source: ' * @npm/package should not be treated as tag either', + tokens: seedTokens({ + start: ' ', + delimiter: '*', + postDelimiter: ' ', + description: '@npm/package should not be treated as tag either', + end: '', + }), + }, + { + number: 5, + source: ' * @param {string} value', + tokens: seedTokens({ + start: ' ', + delimiter: '*', + postDelimiter: ' ', + description: '@param {string} value', + end: '', + }), + }, + { + number: 6, + source: ' */', + tokens: seedTokens({ + start: ' ', + delimiter: '', + postDelimiter: '', + description: '', + end: '*/', + }), + }, + ]; + + const groups: Line[][] = parser(lines); + + // Should have 2 sections: description (lines 0-3) and @param tag (lines 4-5) + // @ember/debug and @npm/package should stay in description, not create new sections + expect(groups.length).toBe(2); + expect(groups[0]).toEqual([lines[0], lines[1], lines[2], lines[3]]); + expect(groups[1]).toEqual([lines[4], lines[5]]); +});