Skip to content

Commit 2fb6e3c

Browse files
committed
fix: highlight backtick spans that start at the beginning of a line
The highlightSpans pattern required a non-backtick character immediately before the opening backtick, so spans at the start of a line (or the start of a string) were never matched and rendered as plain text. Changed the leading capture group from ([^`]) to (^|[^`]) with the /m flag so that the start-of-line anchor is a valid alternative to a preceding character. Applied the same fix to the custom RegExp path. Closes #2
1 parent 4f1cda0 commit 2fb6e3c

2 files changed

Lines changed: 52 additions & 2 deletions

File tree

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { describe, it, expect } from 'vitest';
2+
3+
// Test the highlight-spans regex behaviour directly.
4+
// The bug (issue #2): a backtick span at the very start of a line was not
5+
// recognised because the pattern required a non-backtick character before the
6+
// opening backtick. The fix adds `^` as an alternative via the `m` flag.
7+
8+
function applyHighlightPattern(html: string): string {
9+
// Mirrors the fixed pattern in highlightBlockSpans (highlightSpans === true).
10+
const pattern = /(^|[^`])`([^`]+?)`/gm;
11+
return html.replace(pattern, (m, e, c) => {
12+
if (e === '\\') return m.slice(1);
13+
return e + `<span class="remark-code-span-highlighted">${c}</span>`;
14+
});
15+
}
16+
17+
describe('highlightSpans regex (issue #2)', () => {
18+
it('highlights a span preceded by a non-backtick character', () => {
19+
const result = applyHighlightPattern('call `method`(arg)');
20+
expect(result).toContain('<span class="remark-code-span-highlighted">method</span>');
21+
});
22+
23+
it('highlights a span at the very start of a string', () => {
24+
const result = applyHighlightPattern('`highlightedMethod`(arg1, arg2)');
25+
expect(result).toContain('<span class="remark-code-span-highlighted">highlightedMethod</span>');
26+
});
27+
28+
it('highlights a span at the start of a new line', () => {
29+
const html = 'normalMethod(a)\n`highlightedMethod`(b)';
30+
const result = applyHighlightPattern(html);
31+
expect(result).toContain('<span class="remark-code-span-highlighted">highlightedMethod</span>');
32+
expect(result).toContain('normalMethod(a)');
33+
});
34+
35+
it('does not double-highlight adjacent backtick spans', () => {
36+
const result = applyHighlightPattern('`a` and `b`');
37+
expect(result).toContain('<span class="remark-code-span-highlighted">a</span>');
38+
expect(result).toContain('<span class="remark-code-span-highlighted">b</span>');
39+
});
40+
41+
it('does not highlight a backtick span that is escaped', () => {
42+
const result = applyHighlightPattern('\\`notHighlighted`');
43+
expect(result).not.toContain('remark-code-span-highlighted');
44+
});
45+
46+
it('does not treat fenced code delimiters (```) as highlight spans', () => {
47+
const result = applyHighlightPattern('```js\ncode\n```');
48+
expect(result).not.toContain('remark-code-span-highlighted');
49+
});
50+
});

src/mdeck/views/slideView.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,10 +211,10 @@ function highlightBlockLines(block: HTMLElement, lines: number[]): void {
211211
function highlightBlockSpans(block: HTMLElement, highlightSpans: boolean | RegExp): void {
212212
let pattern: RegExp;
213213
if (highlightSpans === true) {
214-
pattern = /([^`])`([^`]+?)`/g;
214+
pattern = /(^|[^`])`([^`]+?)`/gm;
215215
} else if (highlightSpans instanceof RegExp) {
216216
if (!highlightSpans.global) throw new Error('highlightSpans RegExp must have /g flag');
217-
pattern = new RegExp('([^])' + highlightSpans.source, highlightSpans.flags || 'g');
217+
pattern = new RegExp('(^|[\\s\\S])' + highlightSpans.source, (highlightSpans.flags || 'g') + 'm');
218218
} else {
219219
throw new Error('Illegal value for highlightSpans');
220220
}

0 commit comments

Comments
 (0)