summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHiDeoo2024-02-13 14:26:43 +0100
committerGitHub2024-02-13 14:26:43 +0100
commitb0d36de3398d4895603a787b612b1f0747defbdc (patch)
tree727587d7bc0f88ad9ee84a7f3a4b408355d3924f
parentf5a7652713917e8798cd213be7006b1339859e37 (diff)
downloadIT.starlight-b0d36de3398d4895603a787b612b1f0747defbdc.tar.gz
IT.starlight-b0d36de3398d4895603a787b612b1f0747defbdc.tar.bz2
IT.starlight-b0d36de3398d4895603a787b612b1f0747defbdc.zip
Fix rendering issue for text with unhandled Markdown directives (#1489)
-rw-r--r--.changeset/many-knives-type.md5
-rw-r--r--packages/starlight/__tests__/remark-rehype/asides.test.ts19
-rw-r--r--packages/starlight/integrations/asides.ts49
-rw-r--r--packages/starlight/package.json1
-rw-r--r--pnpm-lock.yaml3
5 files changed, 75 insertions, 2 deletions
diff --git a/.changeset/many-knives-type.md b/.changeset/many-knives-type.md
new file mode 100644
index 00000000..0a006cdb
--- /dev/null
+++ b/.changeset/many-knives-type.md
@@ -0,0 +1,5 @@
+---
+'@astrojs/starlight': patch
+---
+
+Fixes a potential text rendering issue with text containing colons.
diff --git a/packages/starlight/__tests__/remark-rehype/asides.test.ts b/packages/starlight/__tests__/remark-rehype/asides.test.ts
index 6b055def..ba3548c9 100644
--- a/packages/starlight/__tests__/remark-rehype/asides.test.ts
+++ b/packages/starlight/__tests__/remark-rehype/asides.test.ts
@@ -143,3 +143,22 @@ test('runs without locales config', async () => {
const res = await processor.render(':::note\nTest\n::');
expect(res.code.includes('aria-label=Note"'));
});
+
+test('tranforms back unhandled text directives', async () => {
+ const res = await processor.render(
+ `This is a:test of a sentence with a text:name[content]{key=val} directive.`
+ );
+ expect(res.code).toMatchInlineSnapshot(`
+ "<p>This is a:test
+ of a sentence with a text:name[content]{key="val"}
+ directive.</p>"
+ `);
+});
+
+test('tranforms back unhandled leaf directives', async () => {
+ const res = await processor.render(`::video[Title]{v=xxxxxxxxxxx}`);
+ expect(res.code).toMatchInlineSnapshot(`
+ "<p>::video[Title]{v="xxxxxxxxxxx"}
+ </p>"
+ `);
+});
diff --git a/packages/starlight/integrations/asides.ts b/packages/starlight/integrations/asides.ts
index 0b4f9c0c..9e834968 100644
--- a/packages/starlight/integrations/asides.ts
+++ b/packages/starlight/integrations/asides.ts
@@ -2,7 +2,14 @@
import type { AstroConfig, AstroUserConfig } from 'astro';
import { h as _h, s as _s, type Properties } from 'hastscript';
-import type { Paragraph as P, Root } from 'mdast';
+import type { Node, Paragraph as P, Parent, Root } from 'mdast';
+import {
+ type Directives,
+ directiveToMarkdown,
+ type TextDirective,
+ type LeafDirective,
+} from 'mdast-util-directive';
+import { toMarkdown } from 'mdast-util-to-markdown';
import remarkDirective from 'remark-directive';
import type { Plugin, Transformer } from 'unified';
import { remove } from 'unist-util-remove';
@@ -37,6 +44,40 @@ function s(el: string, attrs: Properties = {}, children: any[] = []): P {
};
}
+/** Checks if a node is a directive. */
+function isNodeDirective(node: Node): node is Directives {
+ return (
+ node.type === 'textDirective' ||
+ node.type === 'leafDirective' ||
+ node.type === 'containerDirective'
+ );
+}
+
+/**
+ * Transforms back directives not handled by Starlight to avoid breaking user content.
+ * For example, a user might write `x:y` in the middle of a sentence, where `:y` would be
+ * identified as a text directive, which are not used by Starlight, and we definitely want that
+ * text to be rendered verbatim in the output.
+ */
+function transformUnhandledDirective(
+ node: TextDirective | LeafDirective,
+ index: number,
+ parent: Parent
+) {
+ const textNode = {
+ type: 'text',
+ value: toMarkdown(node, { extensions: [directiveToMarkdown()] }),
+ } as const;
+ if (node.type === 'textDirective') {
+ parent.children[index] = textNode;
+ } else {
+ parent.children[index] = {
+ type: 'paragraph',
+ children: [textNode],
+ };
+ }
+}
+
/**
* remark plugin that converts blocks delimited with `:::` into styled
* asides (a.k.a. “callouts”, “admonitions”, etc.). Depends on the
@@ -102,7 +143,11 @@ function remarkAsides(options: AsidesOptions): Plugin<[], Root> {
const locale = pathToLocale(file.history[0], options);
const t = options.useTranslations(locale);
visit(tree, (node, index, parent) => {
- if (!parent || index === undefined || node.type !== 'containerDirective') {
+ if (!parent || index === undefined || !isNodeDirective(node)) {
+ return;
+ }
+ if (node.type === 'textDirective' || node.type === 'leafDirective') {
+ transformUnhandledDirective(node, index, parent);
return;
}
const variant = node.name;
diff --git a/packages/starlight/package.json b/packages/starlight/package.json
index 385e5a3a..0905f3ea 100644
--- a/packages/starlight/package.json
+++ b/packages/starlight/package.json
@@ -187,6 +187,7 @@
"hast-util-select": "^6.0.2",
"hastscript": "^8.0.0",
"mdast-util-directive": "^3.0.0",
+ "mdast-util-to-markdown": "^2.1.0",
"pagefind": "^1.0.3",
"rehype": "^13.0.1",
"remark-directive": "^3.0.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index fde73e13..9aacfa78 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -159,6 +159,9 @@ importers:
mdast-util-directive:
specifier: ^3.0.0
version: 3.0.0
+ mdast-util-to-markdown:
+ specifier: ^2.1.0
+ version: 2.1.0
pagefind:
specifier: ^1.0.3
version: 1.0.3