Skip to content

Commit 6efc897

Browse files
committed
fix(transformers): support matching comments in comments, fix #934
1 parent cc5913e commit 6efc897

File tree

5 files changed

+89
-11
lines changed

5 files changed

+89
-11
lines changed

packages/transformers/src/shared/notation-transformer.ts

+3-5
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,8 @@ export function createCommentNotationTransformer(
5050
if (comment.info[1].length === 0)
5151
continue
5252

53-
const isLineCommentOnly = comment.line.children.length === (comment.isJsxStyle ? 3 : 1)
5453
let lineIdx = lines.indexOf(comment.line)
55-
if (isLineCommentOnly && matchAlgorithm !== 'v1')
54+
if (comment.isLineCommentOnly && matchAlgorithm !== 'v1')
5655
lineIdx++
5756

5857
let replaced = false
@@ -68,16 +67,15 @@ export function createCommentNotationTransformer(
6867
if (!replaced)
6968
continue
7069

71-
if (matchAlgorithm === 'v1') {
70+
if (matchAlgorithm === 'v1')
7271
comment.info[1] = v1ClearEndCommentPrefix(comment.info[1])
73-
}
7472

7573
const isEmpty = comment.info[1].trim().length === 0
7674
// ignore comment node
7775
if (isEmpty)
7876
comment.info[1] = ''
7977

80-
if (isEmpty && isLineCommentOnly) {
78+
if (isEmpty && comment.isLineCommentOnly) {
8179
linesToRemove.push(comment.line)
8280
}
8381
else if (isEmpty && comment.isJsxStyle) {

packages/transformers/src/shared/parse-comments.ts

+66-5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export type ParsedComments = {
55
line: Element
66
token: Element
77
info: [prefix: string, content: string, suffix?: string]
8+
isLineCommentOnly: boolean
89
isJsxStyle: boolean
910
}[]
1011

@@ -35,6 +36,49 @@ export function parseComments(
3536
const out: ParsedComments = []
3637

3738
for (const line of lines) {
39+
// We split nested comments
40+
if (matchAlgorithm === 'v3') {
41+
const splittedElements = line.children.flatMap((element, idx) => {
42+
if (element.type !== 'element')
43+
return element
44+
45+
const token = element.children[0]
46+
if (token.type !== 'text')
47+
return element
48+
49+
const isLast = idx === line.children.length - 1
50+
const isComment = matchToken(token.value, isLast)
51+
if (!isComment)
52+
return element
53+
const rawSplits = token.value.split(/(\s+\/\/)/)
54+
if (rawSplits.length <= 1)
55+
return element
56+
57+
let splits: string[] = [rawSplits[0]]
58+
for (let i = 1; i < rawSplits.length; i += 2) {
59+
splits.push(rawSplits[i] + (rawSplits[i + 1] || ''))
60+
}
61+
splits = splits.filter(Boolean)
62+
if (splits.length <= 1)
63+
return element
64+
65+
return splits.map((split) => {
66+
return <Element>{
67+
...element,
68+
children: [
69+
{
70+
type: 'text',
71+
value: split,
72+
},
73+
],
74+
}
75+
})
76+
})
77+
78+
if (splittedElements.length !== line.children.length)
79+
line.children = splittedElements
80+
}
81+
3882
const elements = line.children
3983
let start = elements.length - 1
4084
if (matchAlgorithm === 'v1')
@@ -57,18 +101,21 @@ export function parseComments(
57101
continue
58102

59103
if (jsx && !isLast && i !== 0) {
104+
const isJsxStyle = isValue(elements[i - 1], '{') && isValue(elements[i + 1], '}')
60105
out.push({
61106
info: match,
62107
line,
63108
token,
64-
isJsxStyle: isValue(elements[i - 1], '{') && isValue(elements[i + 1], '}'),
109+
isLineCommentOnly: elements.length === 3 && token.children.length === 1,
110+
isJsxStyle,
65111
})
66112
}
67113
else {
68114
out.push({
69115
info: match,
70116
line,
71117
token,
118+
isLineCommentOnly: elements.length === 1 && token.children.length === 1,
72119
isJsxStyle: false,
73120
})
74121
}
@@ -123,11 +170,25 @@ function matchToken(text: string, isLast: boolean): [prefix: string, content: st
123170
* For matchAlgorithm v1
124171
*/
125172
export function v1ClearEndCommentPrefix(text: string): string {
126-
const regex = /(?:\/\/|["'#]|;{1,2}|%{1,2}|--)(.*)$/
127-
const result = regex.exec(text)
173+
const match = text.match(/(?:\/\/|["'#]|;{1,2}|%{1,2}|--)(\s*)$/)
174+
175+
if (match && match[1].trim().length === 0) {
176+
return text.slice(0, match.index)
177+
}
178+
179+
return text
180+
}
181+
182+
/**
183+
* Remove empty comment prefixes at line end, e.g. `// `
184+
*
185+
* For matchAlgorithm v3
186+
*/
187+
export function v3ClearEndCommentPrefix(text: string): string {
188+
const match = text.match(/(?:\/\/|#|;{1,2}|%{1,2}|--)(\s*)$/)
128189

129-
if (result && result[1].trim().length === 0) {
130-
return text.slice(0, result.index)
190+
if (match && match[1].trim().length === 0) {
191+
return text.slice(0, match.index).trimEnd()
131192
}
132193

133194
return text

packages/transformers/test/fixtures.test.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ import {
1414
transformerRenderWhitespace,
1515
} from '../src'
1616

17+
const ONLY: string[] = [
18+
// 'comment-highlight',
19+
]
20+
1721
function suite(
1822
name: string,
1923
files: Record<string, string>,
@@ -26,7 +30,8 @@ function suite(
2630
if (path.endsWith('.output.html'))
2731
continue
2832

29-
it(path, async () => {
33+
const skip = ONLY.length && !ONLY.some(i => path.includes(i))
34+
it.skipIf(skip)(path, async () => {
3035
const ext = path.split('.').pop()!
3136

3237
let code = await codeToHtml(files[path], {

packages/transformers/test/fixtures/highlight/comment-highlight.js

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/transformers/test/fixtures/highlight/comment-highlight.js.output.html

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)