diff options
author | Chris Swithinbank | 2024-05-08 00:22:07 +0200 |
---|---|---|
committer | GitHub | 2024-05-08 00:22:07 +0200 |
commit | 9fe847544f1edb85bf5b25cd81db39227814335e (patch) | |
tree | b6aca9e1f4192f89e272d9a78c9205a477d10d3a | |
parent | f84f571ea2c32c5bb7b4e260504f0271d027868e (diff) | |
download | IT.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.md | 5 | ||||
-rw-r--r-- | packages/starlight/__tests__/remark-rehype/rehype-steps.test.ts | 28 | ||||
-rw-r--r-- | packages/starlight/package.json | 1 | ||||
-rw-r--r-- | packages/starlight/user-components/rehype-steps.ts | 26 | ||||
-rw-r--r-- | pnpm-lock.yaml | 53 |
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: |