diff options
author | Chris Swithinbank | 2023-08-21 13:16:11 +0200 |
---|---|---|
committer | GitHub | 2023-08-21 13:16:11 +0200 |
commit | 87caf21adaac98cf8342dac4db97ace327849616 (patch) | |
tree | 3a55ac3e2b8a5220035314f8cd634cd951944ba0 | |
parent | e287d6fe158ac6d590d0371fa9cf6ffe83cc02e2 (diff) | |
download | IT.starlight-87caf21adaac98cf8342dac4db97ace327849616.tar.gz IT.starlight-87caf21adaac98cf8342dac4db97ace327849616.tar.bz2 IT.starlight-87caf21adaac98cf8342dac4db97ace327849616.zip |
Improve inline code and code block support in RTL languages (#525)
Co-authored-by: Kevin Zuniga Cuellar <46791833+kevinzunigacuellar@users.noreply.github.com>
-rw-r--r-- | .changeset/long-parrots-give.md | 5 | ||||
-rw-r--r-- | packages/starlight/__tests__/remark-rehype/code-rtl-support.test.ts | 25 | ||||
-rw-r--r-- | packages/starlight/__tests__/remark-rehype/vitest.config.ts | 3 | ||||
-rw-r--r-- | packages/starlight/index.ts | 2 | ||||
-rw-r--r-- | packages/starlight/integrations/code-rtl-support.ts | 31 |
5 files changed, 66 insertions, 0 deletions
diff --git a/.changeset/long-parrots-give.md b/.changeset/long-parrots-give.md new file mode 100644 index 00000000..269c5130 --- /dev/null +++ b/.changeset/long-parrots-give.md @@ -0,0 +1,5 @@ +--- +'@astrojs/starlight': patch +--- + +Improve inline code and code block support in RTL languages diff --git a/packages/starlight/__tests__/remark-rehype/code-rtl-support.test.ts b/packages/starlight/__tests__/remark-rehype/code-rtl-support.test.ts new file mode 100644 index 00000000..69aa85ad --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/code-rtl-support.test.ts @@ -0,0 +1,25 @@ +import { rehype } from 'rehype'; +import { expect, test } from 'vitest'; +import { rehypeRtlCodeSupport } from '../../integrations/code-rtl-support'; + +const processor = rehype().data('settings', { fragment: true }).use(rehypeRtlCodeSupport()); + +test('applies `dir="auto"` to inline code', async () => { + const input = `<p>Some text with <code>inline code</code>.</p>`; + const output = String(await processor.process(input)); + expect(output).not.toEqual(input); + expect(output).includes('dir="auto"'); + expect(output).toMatchInlineSnapshot( + '"<p>Some text with <code dir=\\"auto\\">inline code</code>.</p>"' + ); +}); + +test('applies `dir="ltr"` to code blocks', async () => { + const input = `<p>Some text in a paragraph:</p><pre><code>console.log('test')</code></pre>`; + const output = String(await processor.process(input)); + expect(output).not.toEqual(input); + expect(output).includes('dir="ltr"'); + expect(output).toMatchInlineSnapshot( + '"<p>Some text in a paragraph:</p><pre dir=\\"ltr\\"><code>console.log(\'test\')</code></pre>"' + ); +}); diff --git a/packages/starlight/__tests__/remark-rehype/vitest.config.ts b/packages/starlight/__tests__/remark-rehype/vitest.config.ts new file mode 100644 index 00000000..0b12dc3a --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/vitest.config.ts @@ -0,0 +1,3 @@ +import { defineVitestConfig } from '../test-config'; + +export default defineVitestConfig({ title: 'Remark-Rehype' }); diff --git a/packages/starlight/index.ts b/packages/starlight/index.ts index dbd487bd..5909777e 100644 --- a/packages/starlight/index.ts +++ b/packages/starlight/index.ts @@ -8,6 +8,7 @@ import { starlightSitemap } from './integrations/sitemap'; import { vitePluginStarlightUserConfig } from './integrations/virtual-user-config'; import { errorMap } from './utils/error-map'; import { StarlightConfigSchema, StarlightUserConfig } from './utils/user-config'; +import { rehypeRtlCodeSupport } from './integrations/code-rtl-support'; export default function StarlightIntegration(opts: StarlightUserConfig): AstroIntegration[] { const parsedConfig = StarlightConfigSchema.safeParse(opts, { errorMap }); @@ -39,6 +40,7 @@ export default function StarlightIntegration(opts: StarlightUserConfig): AstroIn }, markdown: { remarkPlugins: [...starlightAsides()], + rehypePlugins: [rehypeRtlCodeSupport()], shikiConfig: // Configure Shiki theme if the user is using the default github-dark theme. config.markdown.shikiConfig.theme !== 'github-dark' ? {} : { theme: 'css-variables' }, diff --git a/packages/starlight/integrations/code-rtl-support.ts b/packages/starlight/integrations/code-rtl-support.ts new file mode 100644 index 00000000..b8f7c3a6 --- /dev/null +++ b/packages/starlight/integrations/code-rtl-support.ts @@ -0,0 +1,31 @@ +import type { Root } from 'hastscript/lib/core'; +import { CONTINUE, SKIP, visit } from 'unist-util-visit'; + +/** + * rehype plugin that adds `dir` attributes to `<code>` and `<pre>` + * elements that donβt already have them. + * + * `<code>` will become `<code dir="auto">` + * `<pre>` will become `<pre dir="ltr">` + * + * `<code>` _inside_ `<pre>` is skipped, so respects the `ltr` on its parent. + * + * Reasoning: + * - `<pre>` is usually a code block and code should be LTR even in an RTL document + * - `<code>` is often LTR, but could also be RTL. `dir="auto"` ensures the bidirectional + * algorithm treats the contents of `<code>` in isolation and gives its best guess. + */ +export function rehypeRtlCodeSupport() { + return () => (root: Root) => { + visit(root, 'element', (el) => { + if (el.tagName === 'pre' || el.tagName === 'code') { + el.properties ||= {}; + if (!('dir' in el.properties)) { + el.properties.dir = { pre: 'ltr', code: 'auto' }[el.tagName]; + } + return SKIP; + } + return CONTINUE; + }); + }; +} |