Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/src/content/docs/reference/plugin-compatibility.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ starlightLlmsTxt({
}),
```

The code in `llms-full.txt` is then the code that the copy button copies. Placeholder fields keep their text. Annotations, callouts and footnote badges go. Notes that show under a block, such as the list of footnotes, stay.
The code in `llms-full.txt` is then the code that the copy button copies. Placeholder fields keep their text. Annotations, callouts and footnote badges go. Notes that show under a block, such as the list of footnotes, stay as a plain numbered list.

Pagefind needs no set-up. It does not index these elements, because each one has `data-pagefind-ignore`.

Expand Down
2 changes: 2 additions & 0 deletions packages/starlight-codeblocks/src/expressive-code/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ const decorations = [
'state-label',
'annotation',
'annotation-popover',
'annotation-note-num',
'footnote-badge',
'footnote-num',
'callout',
'hidden-marker',
'expandable-bar',
Expand Down
18 changes: 12 additions & 6 deletions packages/starlight-codeblocks/test/decorations.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,18 @@ const blocks = [
block('sh placeholder="TOKEN"', 'curl -H "Bearer TOKEN"'),
];

/** The text of each rendered line without the marked decorations, as a tool that drops `.scb-deco` reads it. */
function codeText(html: string) {
/** The text of each element that matches `selector` without the marked decorations, as a tool that drops `.scb-deco` reads it. */
function textOf(html: string, selector: string) {
const root = fromHtml(html, { fragment: true });
for (const element of selectAll('.scb-deco, input', root)) element.children = [];
const text = (node: { type: string; value?: string; children?: unknown[] }): string =>
node.type === 'text' ? (node.value ?? '') : (node.children ?? []).map((c) => text(c as never)).join('');
return selectAll('.ec-line', root)
.map((line) => text(line))
.join('\n');
return selectAll(selector, root).map((element) => text(element));
}

test.each(blocks)('drops every decoration and keeps the code text: %s', async (markdown) => {
const { rawHtml, copyText } = await render(markdown);
expect(codeText(rawHtml)).toBe(copyText);
expect(textOf(rawHtml, '.ec-line').join('\n')).toBe(copyText);
});

test('marks each decoration for Pagefind too, and leaves the code unmarked', async () => {
Expand All @@ -36,3 +34,11 @@ test('marks each decoration for Pagefind too, and leaves the code unmarked', asy
expect(marked.every((element) => element.properties.dataPagefindIgnore === '')).toBe(true);
expect(selectAll('.ec-line, .code', root).some((element) => matches('.scb-deco', element))).toBe(false);
});

test.each([
[block('py', '# [!ref] Needs uv.', 'run()'), '.scb-footnotes li', 'Needs uv.'],
[block('py annotations="side"', 'run() # [!annotate] Runs it.'), '.scb-annotation-notes li', 'Runs it.'],
])('drops the numbers that repeat the list numbers under the code: %s', async (markdown, item, note) => {
const { rawHtml } = await render(markdown);
expect(textOf(rawHtml, item)).toEqual([note]);
});
Loading