summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Bjorn Lu <bjornlu.dev@gmail.com> 2023-05-04 00:15:00 +0800
committerGravatar GitHub <noreply@github.com> 2023-05-03 12:15:00 -0400
commitcac4a321e814fb805eb0e3ced469e25261a50885 (patch)
tree540c271e96a6db952425de0c5bd86bc57f8ce443
parent6916e5c79fb21310634d65897d3ae9990bae6af4 (diff)
downloadastro-cac4a321e814fb805eb0e3ced469e25261a50885.tar.gz
astro-cac4a321e814fb805eb0e3ced469e25261a50885.tar.zst
astro-cac4a321e814fb805eb0e3ced469e25261a50885.zip
Support `<Code inline />` to output inline code (#6959)
* Support `<Code inline />` to output inline code * Fix typo * Fix typo again * Remove expected error --------- Co-authored-by: Matthew Phillips <matthew@skypack.dev>
-rw-r--r--.changeset/nine-geckos-act.md5
-rw-r--r--packages/astro/components/Code.astro67
-rw-r--r--packages/astro/test/astro-component-code.test.js10
-rw-r--r--packages/astro/test/fixtures/astro-component-code/src/pages/inline.astro10
4 files changed, 71 insertions, 21 deletions
diff --git a/.changeset/nine-geckos-act.md b/.changeset/nine-geckos-act.md
new file mode 100644
index 000000000..164dbbfd5
--- /dev/null
+++ b/.changeset/nine-geckos-act.md
@@ -0,0 +1,5 @@
+---
+'astro': minor
+---
+
+Support `<Code inline />` to output inline code HTML (no `pre` tag)
diff --git a/packages/astro/components/Code.astro b/packages/astro/components/Code.astro
index 0c5f946af..40f99bcd1 100644
--- a/packages/astro/components/Code.astro
+++ b/packages/astro/components/Code.astro
@@ -1,5 +1,6 @@
---
import type * as shiki from 'shiki';
+import { renderToHtml } from 'shiki';
import { getHighlighter } from './Shiki.js';
export interface Props {
@@ -30,36 +31,60 @@ export interface Props {
* @default false
*/
wrap?: boolean | null;
+ /**
+ * Generate inline code element only, without the pre element wrapper.
+ *
+ * @default false
+ */
+ inline?: boolean;
}
-const { code, lang = 'plaintext', theme = 'github-dark', wrap = false } = Astro.props;
-
-/** Replace the shiki class name with a custom astro class name. */
-function repairShikiTheme(html: string): string {
- // Replace "shiki" class naming with "astro"
- html = html.replace(/<pre class="(.*?)shiki(.*?)"/, '<pre class="$1astro-code$2"');
- // Handle code wrapping
- // if wrap=null, do nothing.
- if (wrap === false) {
- html = html.replace(/style="(.*?)"/, 'style="$1; overflow-x: auto;"');
- } else if (wrap === true) {
- html = html.replace(
- /style="(.*?)"/,
- 'style="$1; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;"'
- );
- }
- return html;
-}
+const {
+ code,
+ lang = 'plaintext',
+ theme = 'github-dark',
+ wrap = false,
+ inline = false,
+} = Astro.props;
+// 1. Get the shiki syntax highlighter
const highlighter = await getHighlighter({
theme,
// Load custom lang if passed an object, otherwise load the default
langs: typeof lang !== 'string' ? [lang] : undefined,
});
-const _html = highlighter.codeToHtml(code, {
- lang: typeof lang === 'string' ? lang : lang.id,
+
+// 2. Turn code into shiki theme tokens
+const tokens = highlighter.codeToThemedTokens(code, typeof lang === 'string' ? lang : lang.id);
+
+// 3. Get shiki theme object
+const _theme = highlighter.getTheme();
+
+// 4. Render the theme tokens as html
+const html = renderToHtml(tokens, {
+ themeName: _theme.name,
+ fg: _theme.fg,
+ bg: _theme.bg,
+ elements: {
+ pre({ className, style, children }) {
+ // Swap to `code` tag if inline
+ const tag = inline ? 'code' : 'pre';
+ // Replace "shiki" class naming with "astro-code"
+ className = className.replace(/shiki/g, 'astro-code');
+ // Handle code wrapping
+ // if wrap=null, do nothing.
+ if (wrap === false) {
+ style += '; overflow-x: auto;"';
+ } else if (wrap === true) {
+ style += '; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;"';
+ }
+ return `<${tag} class="${className}" style="${style}" tabindex="0">${children}</${tag}>`;
+ },
+ code({ children }) {
+ return inline ? children : `<code>${children}</code>`;
+ },
+ },
});
-const html = repairShikiTheme(_html);
---
<Fragment set:html={html} />
diff --git a/packages/astro/test/astro-component-code.test.js b/packages/astro/test/astro-component-code.test.js
index e721f9498..6a525f58d 100644
--- a/packages/astro/test/astro-component-code.test.js
+++ b/packages/astro/test/astro-component-code.test.js
@@ -100,4 +100,14 @@ describe('<Code>', () => {
expect($('#lang > pre')).to.have.lengthOf(1);
expect($('#lang > pre > code span').length).to.equal(3);
});
+
+ it('<Code inline> has no pre tag', async () => {
+ let html = await fixture.readFile('/inline/index.html');
+ const $ = cheerio.load(html);
+ const codeEl = $('.astro-code');
+
+ expect(codeEl.prop('tagName')).to.eq('CODE');
+ expect(codeEl.attr('style')).to.include('background-color:');
+ expect($('pre')).to.have.lengthOf(0);
+ });
});
diff --git a/packages/astro/test/fixtures/astro-component-code/src/pages/inline.astro b/packages/astro/test/fixtures/astro-component-code/src/pages/inline.astro
new file mode 100644
index 000000000..05422c8bf
--- /dev/null
+++ b/packages/astro/test/fixtures/astro-component-code/src/pages/inline.astro
@@ -0,0 +1,10 @@
+---
+import {Code} from 'astro/components';
+---
+<html>
+<head><title>Code component</title></head>
+<body>
+ Simple:
+ <Code code="console.log('inline code');" lang="js" inline />
+</body>
+</html>