summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Swithinbank2024-05-08 00:22:07 +0200
committerGitHub2024-05-08 00:22:07 +0200
commit9fe847544f1edb85bf5b25cd81db39227814335e (patch)
treeb6aca9e1f4192f89e272d9a78c9205a477d10d3a
parentf84f571ea2c32c5bb7b4e260504f0271d027868e (diff)
downloadIT.starlight-9fe847544f1edb85bf5b25cd81db39227814335e.tar.gz
IT.starlight-9fe847544f1edb85bf5b25cd81db39227814335e.tar.bz2
IT.starlight-9fe847544f1edb85bf5b25cd81db39227814335e.zip
Add more diagnostic help to error messages thrown by `<Steps>` (#1838)
-rw-r--r--.changeset/breezy-cats-taste.md5
-rw-r--r--packages/starlight/__tests__/remark-rehype/rehype-steps.test.ts28
-rw-r--r--packages/starlight/package.json1
-rw-r--r--packages/starlight/user-components/rehype-steps.ts26
-rw-r--r--pnpm-lock.yaml53
5 files changed, 101 insertions, 12 deletions
diff --git a/.changeset/breezy-cats-taste.md b/.changeset/breezy-cats-taste.md
new file mode 100644
index 00000000..3f2add68
--- /dev/null
+++ b/.changeset/breezy-cats-taste.md
@@ -0,0 +1,5 @@
+---
+'@astrojs/starlight': patch
+---
+
+Adds extra information to the errors thrown by the `<Steps>` component to help locate misformatted code
diff --git a/packages/starlight/__tests__/remark-rehype/rehype-steps.test.ts b/packages/starlight/__tests__/remark-rehype/rehype-steps.test.ts
index d97f7db8..36f4082c 100644
--- a/packages/starlight/__tests__/remark-rehype/rehype-steps.test.ts
+++ b/packages/starlight/__tests__/remark-rehype/rehype-steps.test.ts
@@ -29,16 +29,36 @@ test('component with non-`<ol>` content throws an error', () => {
"[AstroUserError]:
The \`<Steps>\` component expects its content to be a single ordered list (\`<ol>\`) but found the following element: \`<p>\`.
Hint:
- To learn more about the \`<Steps>\` component, see https://starlight.astro.build/guides/components/#steps"
+ To learn more about the \`<Steps>\` component, see https://starlight.astro.build/guides/components/#steps
+
+ Full HTML passed to \`<Steps>\`:
+
+ <p>A paragraph is not an ordered list</p>
+ "
`);
});
test('component with multiple children throws an error', () => {
- expect(() => processSteps('<ol></ol><ol></ol>')).toThrowErrorMatchingInlineSnapshot(`
+ expect(() =>
+ processSteps(
+ '<ol><li>List item</li></ol><p>I intended this to be part of the same list item</p><ol><li>Other list item</li></ol>'
+ )
+ ).toThrowErrorMatchingInlineSnapshot(`
"[AstroUserError]:
- The \`<Steps>\` component expects its content to be a single ordered list (\`<ol>\`) but found multiple child elements: \`<ol>\`, \`<ol>\`.
+ The \`<Steps>\` component expects its content to be a single ordered list (\`<ol>\`) but found multiple child elements: \`<ol>\`, \`<p>\`, \`<ol>\`.
Hint:
- To learn more about the \`<Steps>\` component, see https://starlight.astro.build/guides/components/#steps"
+ To learn more about the \`<Steps>\` component, see https://starlight.astro.build/guides/components/#steps
+
+ Full HTML passed to \`<Steps>\`:
+
+ <ol>
+ <li>List item</li>
+ </ol>
+ <p>I intended this to be part of the same list item</p>
+ <ol>
+ <li>Other list item</li>
+ </ol>
+ "
`);
});
diff --git a/packages/starlight/package.json b/packages/starlight/package.json
index 70ff9ed4..2e503cf8 100644
--- a/packages/starlight/package.json
+++ b/packages/starlight/package.json
@@ -206,6 +206,7 @@
"mdast-util-to-markdown": "^2.1.0",
"pagefind": "^1.0.3",
"rehype": "^13.0.1",
+ "rehype-format": "^5.0.0",
"remark-directive": "^3.0.0",
"unified": "^11.0.4",
"unist-util-visit": "^5.0.0",
diff --git a/packages/starlight/user-components/rehype-steps.ts b/packages/starlight/user-components/rehype-steps.ts
index dd912ced..ff9c9593 100644
--- a/packages/starlight/user-components/rehype-steps.ts
+++ b/packages/starlight/user-components/rehype-steps.ts
@@ -1,11 +1,17 @@
import { AstroError } from 'astro/errors';
import type { Element, Root } from 'hast';
import { rehype } from 'rehype';
+import rehypeFormat from 'rehype-format';
+import type { VFile } from 'vfile';
+
+const prettyPrintProcessor = rehype().data('settings', { fragment: true }).use(rehypeFormat);
+const prettyPrintHtml = (html: string) =>
+ prettyPrintProcessor.processSync({ value: html }).toString();
const stepsProcessor = rehype()
.data('settings', { fragment: true })
.use(function steps() {
- return (tree: Root) => {
+ return (tree: Root, vfile: VFile) => {
const rootElements = tree.children.filter((item): item is Element => item.type === 'element');
const [rootElement] = rootElements;
@@ -17,12 +23,14 @@ const stepsProcessor = rehype()
throw new StepsError(
'The `<Steps>` component expects its content to be a single ordered list (`<ol>`) but found multiple child elements: ' +
rootElements.map((element: Element) => `\`<${element.tagName}>\``).join(', ') +
- '.'
+ '.',
+ vfile.value.toString()
);
} else if (rootElement.tagName !== 'ol') {
throw new StepsError(
'The `<Steps>` component expects its content to be a single ordered list (`<ol>`) but found the following element: ' +
- `\`<${rootElement.tagName}>\`.`
+ `\`<${rootElement.tagName}>\`.`,
+ vfile.value.toString()
);
}
@@ -49,10 +57,12 @@ export const processSteps = (html: string | undefined) => {
};
class StepsError extends AstroError {
- constructor(message: string) {
- super(
- message,
- 'To learn more about the `<Steps>` component, see https://starlight.astro.build/guides/components/#steps'
- );
+ constructor(message: string, html?: string) {
+ let hint =
+ 'To learn more about the `<Steps>` component, see https://starlight.astro.build/guides/components/#steps';
+ if (html) {
+ hint += '\n\nFull HTML passed to `<Steps>`:\n' + prettyPrintHtml(html);
+ }
+ super(message, hint);
}
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index b2c15cfc..97c6b646 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -175,6 +175,9 @@ importers:
rehype:
specifier: ^13.0.1
version: 13.0.1
+ rehype-format:
+ specifier: ^5.0.0
+ version: 5.0.0
remark-directive:
specifier: ^3.0.0
version: 3.0.0
@@ -3461,6 +3464,13 @@ packages:
dependencies:
function-bind: 1.1.2
+ /hast-util-embedded@3.0.0:
+ resolution: {integrity: sha512-naH8sld4Pe2ep03qqULEtvYr7EjrLK2QHY8KJR6RJkTUjPGObe1vnx585uzem2hGra+s1q08DZZpfgDVYRbaXA==}
+ dependencies:
+ '@types/hast': 3.0.3
+ hast-util-is-element: 3.0.0
+ dev: false
+
/hast-util-from-html@2.0.1:
resolution: {integrity: sha512-RXQBLMl9kjKVNkJTIO6bZyb2n+cUH8LFaSSzo82jiLT6Tfc+Pt7VQCS+/h3YwG4jaNE2TA2sdJisGWR+aJrp0g==}
dependencies:
@@ -3488,6 +3498,12 @@ packages:
dependencies:
'@types/hast': 3.0.3
+ /hast-util-is-body-ok-link@3.0.0:
+ resolution: {integrity: sha512-VFHY5bo2nY8HiV6nir2ynmEB1XkxzuUffhEGeVx7orbu/B1KaGyeGgMZldvMVx5xWrDlLLG/kQ6YkJAMkBEx0w==}
+ dependencies:
+ '@types/hast': 3.0.3
+ dev: false
+
/hast-util-is-element@3.0.0:
resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==}
dependencies:
@@ -3499,6 +3515,16 @@ packages:
dependencies:
'@types/hast': 3.0.3
+ /hast-util-phrasing@3.0.1:
+ resolution: {integrity: sha512-6h60VfI3uBQUxHqTyMymMZnEbNl1XmEGtOxxKYL7stY2o601COo62AWAYBQR9lZbYXYSBoxag8UpPRXK+9fqSQ==}
+ dependencies:
+ '@types/hast': 3.0.3
+ hast-util-embedded: 3.0.0
+ hast-util-has-property: 3.0.0
+ hast-util-is-body-ok-link: 3.0.0
+ hast-util-is-element: 3.0.0
+ dev: false
+
/hast-util-raw@9.0.1:
resolution: {integrity: sha512-5m1gmba658Q+lO5uqL5YNGQWeh1MYWZbZmWrM5lncdcuiXuo5E2HT/CIOp0rLF8ksfSwiCVJ3twlgVRyTGThGA==}
dependencies:
@@ -3692,6 +3718,10 @@ packages:
/html-void-elements@3.0.0:
resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
+ /html-whitespace-sensitive-tag-names@3.0.0:
+ resolution: {integrity: sha512-KlClZ3/Qy5UgvpvVvDomGhnQhNWH5INE8GwvSIQ9CWt1K0zbbXrl7eN5bWaafOZgtmO3jMPwUqmrmEwinhPq1w==}
+ dev: false
+
/html_codesniffer@2.5.1:
resolution: {integrity: sha512-vcz0yAaX/OaV6sdNHuT9alBOKkSxYb8h5Yq26dUqgi7XmCgGUSa7U9PiY1PBXQFMjKv1wVPs5/QzHlGuxPDUGg==}
engines: {node: '>=6'}
@@ -5711,6 +5741,29 @@ packages:
expressive-code: 0.35.2
dev: false
+ /rehype-format@5.0.0:
+ resolution: {integrity: sha512-kM4II8krCHmUhxrlvzFSptvaWh280Fr7UGNJU5DCMuvmAwGCNmGfi9CvFAQK6JDjsNoRMWQStglK3zKJH685Wg==}
+ dependencies:
+ '@types/hast': 3.0.3
+ hast-util-embedded: 3.0.0
+ hast-util-is-element: 3.0.0
+ hast-util-phrasing: 3.0.1
+ hast-util-whitespace: 3.0.0
+ html-whitespace-sensitive-tag-names: 3.0.0
+ rehype-minify-whitespace: 6.0.0
+ unist-util-visit-parents: 6.0.1
+ dev: false
+
+ /rehype-minify-whitespace@6.0.0:
+ resolution: {integrity: sha512-i9It4YHR0Sf3GsnlR5jFUKXRr9oayvEk9GKQUkwZv6hs70OH9q3OCZrq9PpLvIGKt3W+JxBOxCidNVpH/6rWdA==}
+ dependencies:
+ '@types/hast': 3.0.3
+ hast-util-embedded: 3.0.0
+ hast-util-is-element: 3.0.0
+ hast-util-whitespace: 3.0.0
+ unist-util-is: 6.0.0
+ dev: false
+
/rehype-parse@9.0.0:
resolution: {integrity: sha512-WG7nfvmWWkCR++KEkZevZb/uw41E8TsH4DsY9UxsTbIXCVGbAs4S+r8FrQ+OtH5EEQAs+5UxKC42VinkmpA1Yw==}
dependencies: