Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
512 changes: 230 additions & 282 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@
"@clack/prompts": "^0.11.0",
"@heroicons/react": "^2.2.0",
"@minify-html/node": "^0.16.4",
"@node-core/rehype-shiki": "1.1.0",
"@node-core/ui-components": "1.2.0",
"@node-core/rehype-shiki": "1.3.0",
"@node-core/ui-components": "1.3.0",
"@orama/orama": "^3.1.14",
"@orama/react-components": "^0.8.1",
"@rollup/plugin-virtual": "^3.0.2",
Expand Down
4 changes: 2 additions & 2 deletions src/generators/jsx-ast/utils/buildSignature.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { highlightToHast } from '@node-core/rehype-shiki';
import { h as createElement } from 'hastscript';

import { highlighter } from '../../../utils/highlighter.mjs';
import createQueries from '../../../utils/queries/index.mjs';
import { parseListItem } from '../../legacy-json/utils/parseList.mjs';
import parseSignature from '../../legacy-json/utils/parseSignature.mjs';
Expand Down Expand Up @@ -50,7 +50,7 @@ export const generateSignature = (
*/
export const createSignatureCodeBlock = (functionName, signature, prefix) => {
const sig = generateSignature(functionName, signature, prefix);
const highlighted = highlightToHast(sig, 'typescript');
const highlighted = highlighter.highlightToHast(sig, 'typescript');

return createElement('div', { class: 'signature' }, [highlighted]);
};
Expand Down
15 changes: 15 additions & 0 deletions src/generators/web/constants.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,21 @@ export const JSX_IMPORTS = {
name: 'CodeTabs',
source: '@node-core/ui-components/MDX/CodeTabs',
},
MDXTooltip: {
name: 'MDXTooltip',
isDefaultExport: false,
source: '@node-core/ui-components/MDX/Tooltip',
},
MDXTooltipContent: {
name: 'MDXTooltipContent',
isDefaultExport: false,
source: '@node-core/ui-components/MDX/Tooltip',
},
MDXTooltipTrigger: {
name: 'MDXTooltipTrigger',
isDefaultExport: false,
source: '@node-core/ui-components/MDX/Tooltip',
},
ChangeHistory: {
name: 'ChangeHistory',
source: '@node-core/ui-components/Common/ChangeHistory',
Expand Down
33 changes: 6 additions & 27 deletions src/generators/web/utils/data.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { shiki } from '@node-core/rehype-shiki';
import { LANGS } from '@node-core/rehype-shiki';

/**
* Constructs a set of static, minimal data to send from server to client.
Expand All @@ -14,32 +14,11 @@ export const createStaticData = () => {
// Create a display name map with aliases from Shiki's loaded languages
const shikiDisplayNameMap = [
...new Map(
// 1. Get all currently loaded language identifiers (e.g., 'js', 'ts', 'python')
shiki
.getLoadedLanguages()

// 2. Map each ID to its full language object
.map(shiki.getLanguage)

// 3. Extract:
// - `name`: canonical ID (e.g., "javascript")
// - `_grammar.aliases`: alternate names for the language (e.g., ["js"])
// - `displayName`: user-friendly name for UI (e.g., "JavaScript")
//
// 4. Build key-value pairs of:
// name => [[aliases + name], displayName]
//
// Example output:
// "javascript" => [["js", "javascript"], "JavaScript"]
//
// This structure allows clients to match by any alias and still show a clean label.
.map(({ name, _grammar: { aliases = [], displayName } }) => [
name,
[[...aliases, name], displayName],
])

// Step 5: Deduplicate by canonical name using a `Map`
// The `Map` constructor ensures uniqueness by key (`name`)
// Get all languages, and map aliases to display names
LANGS.map(({ name, aliases = [], displayName }) => [
name,
[[...aliases, name], displayName],
])
).values(), // Get just the values (alias/displayName pairs)
];

Expand Down
6 changes: 4 additions & 2 deletions src/utils/highlighter.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

import { shiki } from '@node-core/rehype-shiki';
import createHighlighter from '@node-core/rehype-shiki';
import { toString } from 'hast-util-to-string';
import { h as createElement } from 'hastscript';
import { SKIP, visit } from 'unist-util-visit';
Expand Down Expand Up @@ -32,6 +32,8 @@ function isCodeBlock(node) {
);
}

export const highlighter = await createHighlighter();

/**
* Creates a HAST transformer for Shiki which is used for transforming our codeboxes
*
Expand Down Expand Up @@ -87,7 +89,7 @@ export default function rehypeShikiji() {
const languageId = codeLanguage.slice(languagePrefix.length);

// Parses the <pre> contents and returns a HAST tree with the highlighted code
const { children } = shiki.codeToHast(preElementContents, {
const { children } = highlighter.shiki.codeToHast(preElementContents, {
lang: languageId,
// Allows support for dual themes (light, dark) for Shiki
themes: { light: shikiConfig.themes[0], dark: shikiConfig.themes[1] },
Expand Down
6 changes: 4 additions & 2 deletions src/utils/remark.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import remarkRehype from 'remark-rehype';
import remarkStringify from 'remark-stringify';
import { unified } from 'unified';

import syntaxHighlighter from './highlighter.mjs';
import syntaxHighlighter, { highlighter } from './highlighter.mjs';
import { AST_NODE_TYPES } from '../generators/jsx-ast/constants.mjs';
import transformElements from '../generators/jsx-ast/utils/transformer.mjs';

Expand Down Expand Up @@ -45,6 +45,8 @@ export const getRemarkRehype = () =>
// and we trust the sources of the Markdown files
.use(rehypeStringify, { allowDangerousHtml: true });

const singletonShiki = await rehypeShikiji({ highlighter });

/**
* Retrieves an instance of Remark configured to output JSX code.
* including parsing Code Boxes with syntax highlighting
Expand All @@ -62,7 +64,7 @@ export const getRemarkRecma = () =>
})
// Any `raw` HTML in the markdown must be converted to AST in order for Recma to understand it
.use(rehypeRaw, { passThrough })
.use(rehypeShikiji)
.use(() => singletonShiki)
.use(transformElements)
.use(rehypeRecma)
.use(recmaJsx)
Expand Down
Loading