Local MD: support native JS + MDX

This commit is contained in:
Fuma Nama
2026-04-17 20:31:58 +08:00
parent ac730ca83f
commit a23c59f92e
17 changed files with 430 additions and 1311 deletions
+14 -10
View File
@@ -17,6 +17,9 @@
"exports": {
".": "./dist/index.js",
"./dev": "./dist/dev/index.js",
"./js/executor": "./dist/js/executor.js",
"./js/executor-native": "./dist/js/executor-native.js",
"./js/executor-virtual": "./dist/js/executor-virtual.js",
"./package.json": "./package.json"
},
"publishConfig": {
@@ -30,12 +33,12 @@
"types:check": "tsc --noEmit"
},
"dependencies": {
"@mdx-js/mdx": "^3.1.1",
"@standard-schema/spec": "^1.1.0",
"chokidar": "^5.0.0",
"estree-util-to-js": "^2.0.0",
"hast-util-to-jsx-runtime": "^2.3.6",
"remark": "^15.0.1",
"remark-mdx": "^3.1.1",
"remark-rehype": "^11.1.2",
"tinyglobby": "^0.2.16",
"unified": "^11.0.5",
@@ -45,7 +48,6 @@
"@types/estree": "^1.0.8",
"@types/estree-jsx": "^1.0.5",
"@types/hast": "^3.0.4",
"@types/mdx": "^2.0.13",
"@types/node": "25.6.0",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
@@ -59,28 +61,30 @@
"tsdown": "0.21.8"
},
"peerDependencies": {
"@types/estree": "*",
"@types/estree-jsx": "*",
"@types/hast": "*",
"@types/mdx": "*",
"@types/react": "*",
"@types/unist": "*",
"fumadocs-core": "^16.7.17",
"react": "^19.2.0"
"react": "^19.2.0",
"react-dom": "^19.2.0"
},
"peerDependenciesMeta": {
"@types/estree": {
"optional": true
},
"@types/estree-jsx": {
"optional": true
},
"@types/hast": {
"optional": true
},
"@types/unist": {
"optional": true
},
"@types/mdx": {
"optional": true
},
"@types/react": {
"optional": true
},
"react": {
"optional": true
}
},
"inlinedDependencies": {
+1 -1
View File
@@ -3,7 +3,7 @@ import type { StandardSchemaV1 } from '@standard-schema/spec';
import { createStorage } from './storage';
import type * as defaultSchemas from 'fumadocs-core/source/schema';
import { createMarkdownRenderer, MarkdownRendererOptions, PageRenderer } from './md/renderer';
import { createMarkdownCompiler, MarkdownCompilerOptions } from './md/compiler-full';
import { createMarkdownCompiler, MarkdownCompilerOptions } from './md/compiler';
export interface LocalMarkdownConfig<
FrontmatterSchema extends StandardSchemaV1,
+153 -59
View File
@@ -11,25 +11,23 @@ import type {
JSXSpreadAttribute,
JSXSpreadChild,
JSXText,
Pattern,
Program,
Statement,
} from 'estree-jsx';
import type { Handler, Handlers, State } from 'estree-util-to-js';
import { toJs } from 'estree-util-to-js';
import type * as JsxRuntime from 'react/jsx-runtime';
import { JSExecutor } from './executor';
import type { JSExecutor, JSExecutorConfig } from './executor';
const JSX_VAR_NAMES = {
const INTERNAL_VAR_NAMES = {
jsx: '__fumadocs_jsx',
jsxs: '__fumadocs_jsxs',
fragment: '__fumadocs_fragment',
exports: '__fumadocs_exports',
} as const;
type Generator = ThisParameterType<Handler>;
interface NativeExecutorOptions {
jsx: typeof JsxRuntime;
}
const jsxHandlers: Handlers = {
JSXElement(node, state) {
return writeJsxElement.call(this as Generator, node, state);
@@ -39,52 +37,161 @@ const jsxHandlers: Handlers = {
},
};
export function executorNative(options?: NativeExecutorOptions): JSExecutor {
const jsxContext = options?.jsx
? {
[JSX_VAR_NAMES.jsx]: options.jsx.jsx,
[JSX_VAR_NAMES.jsxs]: options.jsx.jsxs,
[JSX_VAR_NAMES.fragment]: options.jsx.Fragment,
/**
* Execute JavaScript with `new Function()`, this is unsafe.
*/
export function executorNative(options: JSExecutorConfig): JSExecutor {
const { filePath, jsx } = options;
const exports: Record<string, unknown> = {};
const globalContext: Record<string, unknown> = {
[INTERNAL_VAR_NAMES.exports]: exports,
};
if (jsx) {
Object.assign(globalContext, {
[INTERNAL_VAR_NAMES.jsx]: jsx.jsx,
[INTERNAL_VAR_NAMES.jsxs]: jsx.jsxs,
[INTERNAL_VAR_NAMES.fragment]: jsx.Fragment,
});
}
function generateExportAssign(name: string, expression: Expression): ExpressionStatement {
return {
type: 'ExpressionStatement',
expression: {
type: 'AssignmentExpression',
left: {
type: 'MemberExpression',
object: { type: 'Identifier', name: INTERNAL_VAR_NAMES.exports },
property: { type: 'Identifier', name },
computed: false,
optional: false,
},
right: expression,
operator: '=',
},
};
}
function allNames(pattern: Pattern): string[] {
switch (pattern.type) {
case 'Identifier':
return [pattern.name];
case 'ArrayPattern': {
const out: string[] = [];
for (const element of pattern.elements) {
if (element) out.push(...allNames(element));
}
return out;
}
: {};
case 'AssignmentPattern':
return allNames(pattern.left);
case 'MemberExpression':
return [];
case 'ObjectPattern': {
const out: string[] = [];
for (const prop of pattern.properties) {
if (prop.type === 'Property') {
if ('value' in prop && typeof prop.value === 'string') out.push(prop.value);
else if ('name' in prop && typeof prop.name === 'string') out.push(prop.name);
} else {
out.push(...allNames(prop.argument));
}
}
return out;
}
case 'RestElement':
return allNames(pattern.argument);
}
}
return {
expression(expression, context) {
const code = serializeExpression(expression);
return executeExpression(code, { ...context, ...jsxContext });
const code = toJs(
{
type: 'Program',
sourceType: 'module',
body: [
{
type: 'ReturnStatement',
argument: expression,
},
],
},
{ filePath, handlers: jsxHandlers },
).value;
return execute(code, { ...globalContext, ...context });
},
program(program, context) {
const code = serializeProgram(program);
return execute(code, { ...context, ...jsxContext });
const cloned: Program = { ...program };
cloned.body = cloned.body.flatMap((statement) => {
if (statement.type === 'ExportAllDeclaration') {
throw new Error(`${statement.type} is not supported`);
}
if (statement.type === 'ExportDefaultDeclaration') {
if (!statement.declaration) {
throw new Error(`${statement.type} is not supported without an initializer`);
}
let right: Expression;
switch (statement.declaration.type) {
case 'ClassDeclaration':
right = {
...statement.declaration,
type: 'ClassExpression',
};
break;
case 'FunctionDeclaration':
right = {
...statement.declaration,
type: 'FunctionExpression',
};
break;
default:
right = statement.declaration;
}
return generateExportAssign('default', right);
}
if (statement.type === 'ExportNamedDeclaration') {
if (!statement.declaration) {
throw new Error(`${statement.type} is not supported without an initializer`);
}
switch (statement.declaration.type) {
case 'ClassDeclaration':
case 'FunctionDeclaration':
return [
statement.declaration,
generateExportAssign(statement.declaration.id.name, statement.declaration.id),
];
case 'VariableDeclaration': {
const out: Statement[] = [statement.declaration];
for (const d of statement.declaration.declarations) {
for (const name of allNames(d.id)) {
out.push(generateExportAssign(name, { type: 'Identifier', name }));
}
}
return out;
}
}
}
return statement;
});
return execute(toJs(cloned, { filePath, handlers: jsxHandlers }).value, {
...globalContext,
...context,
});
},
getExports() {
return {};
return exports;
},
};
}
function serializeExpression(expression: Expression): string {
const code = toJs(
{
type: 'Program',
sourceType: 'module',
body: [
{
type: 'ExpressionStatement',
expression,
} satisfies ExpressionStatement,
],
},
{ handlers: jsxHandlers },
).value;
return code.replace(/;\s*$/, '');
}
function serializeProgram(program: Program): string {
return toJs(program, { handlers: jsxHandlers }).value;
}
function execute(code: string, context: Record<string, unknown>) {
const argNames = Object.keys(context);
const argValues = Object.values(context);
@@ -92,15 +199,11 @@ function execute(code: string, context: Record<string, unknown>) {
return evaluator(...argValues);
}
function executeExpression(code: string, context: Record<string, unknown>) {
return execute(`return (${code});`, context);
}
function writeJsxElement(this: Generator, node: JSXElement, state: State) {
const children = normalizeJsxChildren(node.children);
const hasArrayChildren =
children.length > 1 || children.some((child) => child.type === 'JSXSpreadChild');
const runtime = hasArrayChildren ? JSX_VAR_NAMES.jsxs : JSX_VAR_NAMES.jsx;
const runtime = hasArrayChildren ? INTERNAL_VAR_NAMES.jsxs : INTERNAL_VAR_NAMES.jsx;
state.write(`${runtime}(`, node);
writeJsxType.call(this, node.openingElement.name, state);
@@ -113,9 +216,9 @@ function writeJsxFragment(this: Generator, node: JSXFragment, state: State) {
const children = normalizeJsxChildren(node.children);
const hasArrayChildren =
children.length > 1 || children.some((child) => child.type === 'JSXSpreadChild');
const runtime = hasArrayChildren ? JSX_VAR_NAMES.jsxs : JSX_VAR_NAMES.jsx;
const runtime = hasArrayChildren ? INTERNAL_VAR_NAMES.jsxs : INTERNAL_VAR_NAMES.jsx;
state.write(`${runtime}(${JSX_VAR_NAMES.fragment}, `, node);
state.write(`${runtime}(${INTERNAL_VAR_NAMES.fragment}, `, node);
writeJsxProps.call(this, [], children, state);
state.write(')');
}
@@ -127,12 +230,7 @@ function writeJsxType(
) {
switch (node.type) {
case 'JSXIdentifier':
if (/^[a-z]/.test(node.name) || node.name.includes('-')) {
state.write(JSON.stringify(node.name), node);
return;
}
state.write(node.name, node);
state.write(JSON.stringify(node.name), node);
return;
case 'JSXMemberExpression':
@@ -210,11 +308,7 @@ function writeJsxProps(
function writeObjectKey(node: JSXAttribute['name'], state: State) {
if (node.type === 'JSXIdentifier') {
if (/^[A-Za-z_$][\w$]*$/.test(node.name)) {
state.write(node.name, node);
} else {
state.write(JSON.stringify(node.name), node);
}
state.write(JSON.stringify(node.name), node);
return;
}
+3 -3
View File
@@ -1,10 +1,10 @@
import { EvaluateOptions, ExpressionSync } from '@/eval-estree-expression';
import { JSExecutor } from './executor';
import { ExpressionSync } from '@/eval-estree-expression';
import type { JSExecutor, JSExecutorConfig } from './executor';
/**
* Execute JavaScript with a faked JS engine, limited features but works on workerd.
*/
export function executorVirtual(options?: EvaluateOptions): JSExecutor {
export function executorVirtual(options: JSExecutorConfig): JSExecutor {
const sync = new ExpressionSync(options);
return {
+6
View File
@@ -1,3 +1,4 @@
import type * as JsxRuntime from 'react/jsx-runtime';
import type { Expression, Program } from 'estree-jsx';
export interface JSExecutor {
@@ -8,3 +9,8 @@ export interface JSExecutor {
*/
getExports: () => Record<string, unknown>;
}
export interface JSExecutorConfig {
jsx: typeof JsxRuntime;
filePath: string;
}
-55
View File
@@ -1,55 +0,0 @@
import { remarkGfm } from 'fumadocs-core/mdx-plugins/remark-gfm';
import { createBaseCompiler, BaseCompilerOptions, plugin, BaseCompiler, plugins } from './compiler';
import { remarkHeading } from 'fumadocs-core/mdx-plugins/remark-heading';
import { remarkNpm } from 'fumadocs-core/mdx-plugins/remark-npm';
import { remarkCodeTab } from 'fumadocs-core/mdx-plugins/remark-code-tab';
import { rehypeCode } from 'fumadocs-core/mdx-plugins/rehype-code';
import { rehypeToc } from 'fumadocs-core/mdx-plugins/rehype-toc';
import { remarkStructure } from 'fumadocs-core/mdx-plugins/remark-structure';
import { VFile } from 'vfile';
import remarkMdx from 'remark-mdx';
export type MarkdownCompilerOptions = BaseCompilerOptions;
export type MarkdownCompiler = BaseCompiler;
export function createMarkdownCompiler(options?: MarkdownCompilerOptions): MarkdownCompiler {
const compilers = new Map<'md' | 'mdx', BaseCompiler>();
function createCompiler(preset: 'md' | 'mdx') {
return createBaseCompiler({
...options,
remarkPlugins: plugins(
remarkGfm,
preset === 'mdx' && remarkMdx,
plugin(remarkHeading, { generateToc: false }),
plugin(remarkNpm, { persist: { id: 'package-manager' } }),
remarkCodeTab,
remarkStructure,
...(options?.remarkPlugins ?? []),
),
remarkRehypeOptions: {
passThrough: ['mdxJsxFlowElement', 'mdxJsxTextElement'],
...options?.remarkRehypeOptions,
},
rehypePlugins: [
plugin(rehypeCode, { lazy: true, fallbackLanguage: 'text' }),
plugin(rehypeToc, { exportToc: { as: 'data' } }),
...(options?.rehypePlugins ?? []),
],
});
}
return {
compile(input) {
const file = new VFile(input);
const format = file.extname === '.mdx' ? 'mdx' : 'md';
let compiler = compilers.get(format);
if (!compiler) {
compiler = createCompiler(format);
compilers.set(format, compiler);
}
return compiler.compile(file);
},
};
}
+96 -35
View File
@@ -1,55 +1,116 @@
import { remark } from 'remark';
import remarkRehype, { type Options as RemarkRehypeOptions } from 'remark-rehype';
import { type Compatible, VFile } from 'vfile';
import { remarkGfm } from 'fumadocs-core/mdx-plugins/remark-gfm';
import { plugin, plugins } from './utils';
import { remarkHeading } from 'fumadocs-core/mdx-plugins/remark-heading';
import { remarkNpm } from 'fumadocs-core/mdx-plugins/remark-npm';
import { remarkCodeTab } from 'fumadocs-core/mdx-plugins/remark-code-tab';
import { rehypeCode } from 'fumadocs-core/mdx-plugins/rehype-code';
import { rehypeToc } from 'fumadocs-core/mdx-plugins/rehype-toc';
import { remarkStructure } from 'fumadocs-core/mdx-plugins/remark-structure';
import { Compatible, VFile } from 'vfile';
import type { Root } from 'hast';
import type { Pluggable, PluggableList, Plugin } from 'unified';
import * as Mdx from '@mdx-js/mdx';
import { remark } from 'remark';
import type { PluggableList } from 'unified';
import remarkRehype, { type Options as RemarkRehypeOptions } from 'remark-rehype';
export interface BaseCompilerOptions {
export interface MarkdownCompilerOptions {
mdOptions?: MarkdownProcessorOptions;
mdxOptions?: Mdx.ProcessorOptions;
}
export interface MarkdownProcessorOptions {
remarkPlugins?: PluggableList;
rehypePlugins?: PluggableList;
remarkRehypeOptions?: RemarkRehypeOptions;
}
export interface CompileResult {
tree: Root;
file: VFile;
}
export interface BaseCompiler {
export interface MarkdownCompiler {
compile: (input: Compatible) => Promise<CompileResult>;
}
export function createBaseCompiler({
rehypePlugins = [],
remarkPlugins = [],
remarkRehypeOptions,
}: BaseCompilerOptions = {}): BaseCompiler {
const processor = remark()
.use(remarkPlugins)
.use(remarkRehype, remarkRehypeOptions)
.use(rehypePlugins);
export type CompileResult =
| {
type: 'ast';
tree: Root;
file: VFile;
}
| {
type: 'js';
file: VFile;
code: string;
};
export function createMarkdownCompiler(options?: MarkdownCompilerOptions): MarkdownCompiler {
let mdx: ReturnType<typeof createMdxCompiler> | undefined;
let md: ReturnType<typeof createMdCompiler> | undefined;
function createMdCompiler() {
const mdOptions = options?.mdOptions ?? {};
return remark()
.use(
plugins(
remarkGfm,
plugin(remarkHeading, { generateToc: false }),
plugin(remarkNpm, { persist: { id: 'package-manager' } }),
remarkCodeTab,
remarkStructure,
...(mdOptions.remarkPlugins ?? []),
),
)
.use(remarkRehype, {
passThrough: ['mdxJsxFlowElement', 'mdxJsxTextElement'],
...mdOptions.remarkRehypeOptions,
})
.use([
plugin(rehypeCode, { lazy: true, fallbackLanguage: 'text' }),
plugin(rehypeToc, { exportToc: { as: 'data' } }),
...(mdOptions.rehypePlugins ?? []),
]);
}
function createMdxCompiler() {
const mdxOptions = options?.mdxOptions ?? {};
return Mdx.createProcessor({
...mdxOptions,
outputFormat: 'function-body',
development: false,
remarkPlugins: plugins(
remarkGfm,
plugin(remarkHeading, { generateToc: false }),
plugin(remarkNpm, { persist: { id: 'package-manager' } }),
remarkCodeTab,
remarkStructure,
...(mdxOptions.remarkPlugins ?? []),
),
rehypePlugins: [
plugin(rehypeCode, { lazy: true, fallbackLanguage: 'text' }),
plugin(rehypeToc, { exportToc: { as: 'esm', name: 'toc' } }),
...(mdxOptions.rehypePlugins ?? []),
],
});
}
return {
async compile(input) {
// inherit vfile
const file = input instanceof VFile ? input : new VFile(input);
const tree = await processor.run(processor.parse(file), file);
const file = new VFile(input);
if (file.extname === '.mdx') {
mdx ??= createMdxCompiler();
const out = await mdx.process(file);
return {
type: 'js',
file,
code: String(out.value),
};
}
md ??= createMdCompiler();
const tree = await md.run(md.parse(file), file);
return {
type: 'ast',
tree,
file,
};
},
};
}
export function plugin<
PluginParameters extends unknown[],
Input extends string | import('unist').Node | undefined,
Output,
>(plugin: Plugin<PluginParameters, Input, Output>, ...params: NoInfer<PluginParameters>) {
return [plugin, ...params] as Pluggable;
}
export function plugins(...plugins: (Pluggable | false | null | undefined)[]): Pluggable[] {
return plugins.filter((v) => v !== false && v != null);
}
+26
View File
@@ -0,0 +1,26 @@
interface Options {
scope?: Record<string, unknown>;
baseUrl?: string | URL;
jsxRuntime: object;
}
const AsyncFunction: new (...args: string[]) => (...args: unknown[]) => Promise<unknown> =
Object.getPrototypeOf(executeMdx).constructor;
/**
* Note: unsafe by design
*/
export async function executeMdx(compiled: string, options: Options) {
const { opts: scopeOpts, ...scope } = options.scope ?? {};
const fullScope = {
opts: {
...(scopeOpts as object),
...options.jsxRuntime,
baseUrl: options.baseUrl,
},
...scope,
};
const hydrateFn = new AsyncFunction(...Object.keys(fullScope), compiled);
return await hydrateFn.apply(hydrateFn, Object.values(fullScope));
}
+65 -44
View File
@@ -1,4 +1,3 @@
import type { CompileResult, BaseCompiler } from './compiler';
import type { TOCItemType } from 'fumadocs-core/toc';
import type { StructuredData } from 'fumadocs-core/mdx-plugins';
import type { ReactNode } from 'react';
@@ -8,27 +7,39 @@ import * as JsxRuntime from 'react/jsx-runtime';
import { type Components, toJsxRuntime } from 'hast-util-to-jsx-runtime';
import { Root } from 'hast';
import { VFile } from 'vfile';
import type { JSExecutor } from '@/js/executor';
import { executorVirtual } from '@/js/executor-virtual';
import type { JSExecutor, JSExecutorConfig } from '@/js/executor';
import type { CompileResult, MarkdownCompiler } from './compiler';
import { executeMdx } from './execute-js';
import { pathToFileURL } from 'node:url';
export interface PageRenderer {
structuredData: StructuredData;
render: (components?: Components) => Promise<{
exports: Record<string, unknown>;
toc?: TOCItemType[];
toc: TOCItemType[];
body: ReactNode;
}>;
}
export interface MarkdownRendererOptions {
executor?: (ctx: { jsx: typeof JsxRuntime }) => JSExecutor;
/**
* the engine to execute JavaScript (given estree with JSX)
*
* by default, it uses a virtual JS engine with limited
*/
executor?: (ctx: JSExecutorConfig) => JSExecutor | Promise<JSExecutor>;
}
export function createMarkdownRenderer(
compiler: BaseCompiler,
compiler: MarkdownCompiler,
options: MarkdownRendererOptions = {},
) {
const { executor: getExecutor = executorVirtual } = options;
const {
executor: getExecutor = async (config) => {
const { executorVirtual } = await import('@/js/executor-virtual');
return executorVirtual(config);
},
} = options;
const cache = new Map<string, Promise<CompileResult>>();
function render(
@@ -56,26 +67,16 @@ export function createMarkdownRenderer(
});
}
function getExports(
tree: Root,
sync: JSExecutor,
context: Record<string, unknown>,
): Record<string, unknown> {
for (const node of tree.children) {
if (node.type !== 'mdxjsEsm' || !node.data?.estree) continue;
sync.program(node.data.estree, context);
}
return sync.getExports();
}
return {
async compile<V>(page: RawPage<V>): Promise<PageRenderer> {
const cacheKey = stableHash({ path: page.absolutePath, value: page.content, compiler });
const cacheKey = stableHash([page.absolutePath, page.content, page.frontmatter, compiler]);
let promise = cache.get(cacheKey);
if (!promise) {
promise = compiler.compile({ path: page.absolutePath, value: page.content });
promise = compiler.compile({
path: page.absolutePath,
value: page.content,
data: { frontmatter: page.frontmatter },
});
cache.set(cacheKey, promise);
}
@@ -91,30 +92,50 @@ export function createMarkdownRenderer(
);
},
async render(components?: Components) {
const executor = getExecutor({ jsx: JsxRuntime });
const context: Record<string, unknown> = { ...components };
const exports = getExports(compiled.tree, executor, context);
const executor = await getExecutor({
jsx: JsxRuntime,
filePath: page.absolutePath,
});
const toc = compiled.file.data.rehypeToc?.map(
(item): TOCItemType => ({
...item,
title: render(
{
type: 'root',
children: item.title.children,
},
compiled.file,
executor,
components,
context,
),
}),
);
if (compiled.type === 'ast') {
const context: Record<string, unknown> = { ...components };
const toc =
compiled.file.data.rehypeToc?.map(
(item): TOCItemType => ({
...item,
title: render(
{
type: 'root',
children: item.title.children,
},
compiled.file,
executor,
components,
context,
),
}),
) ?? [];
return {
toc,
body: render(compiled.tree, compiled.file, executor, components, context),
exports: executor.getExports(),
};
}
const _out = await executeMdx(compiled.code, {
baseUrl: pathToFileURL(page.absolutePath),
jsxRuntime: JsxRuntime,
});
const out = _out as {
toc: TOCItemType[];
default: (props: { components?: Components }) => ReactNode;
};
return {
toc,
body: render(compiled.tree, compiled.file, executor, components, context),
exports,
toc: out.toc,
body: JsxRuntime.jsx(out.default, { components }),
exports: out,
};
},
};
+13
View File
@@ -0,0 +1,13 @@
import type { Pluggable, Plugin } from 'unified';
export function plugin<
PluginParameters extends unknown[],
Input extends string | import('unist').Node | undefined,
Output,
>(plugin: Plugin<PluginParameters, Input, Output>, ...params: NoInfer<PluginParameters>) {
return [plugin, ...params] as Pluggable;
}
export function plugins(...plugins: (Pluggable | false | null | undefined)[]): Pluggable[] {
return plugins.filter((v) => v !== false && v != null);
}
+2 -738
View File
@@ -1,704 +1,11 @@
{
"tree": {
"type": "root",
"children": [
{
"type": "element",
"tagName": "h1",
"properties": {
"id": "mdx-expressions"
},
"children": [
{
"type": "text",
"value": "MDX expressions",
"position": {
"start": {
"line": 1,
"column": 3,
"offset": 2
},
"end": {
"line": 1,
"column": 18,
"offset": 17
}
}
}
],
"position": {
"start": {
"line": 1,
"column": 1,
"offset": 0
},
"end": {
"line": 1,
"column": 18,
"offset": 17
}
}
},
{
"type": "text",
"value": "\n"
},
{
"type": "mdxJsxFlowElement",
"name": "div",
"attributes": [
{
"type": "mdxJsxAttribute",
"name": "data-sum",
"value": {
"type": "mdxJsxAttributeValueExpression",
"value": "1 + 2",
"data": {
"estree": {
"type": "Program",
"start": 34,
"end": 39,
"body": [
{
"type": "ExpressionStatement",
"expression": {
"type": "BinaryExpression",
"start": 34,
"end": 39,
"loc": {
"start": {
"line": 3,
"column": 15,
"offset": 34
},
"end": {
"line": 3,
"column": 20,
"offset": 39
}
},
"left": {
"type": "Literal",
"start": 34,
"end": 35,
"loc": {
"start": {
"line": 3,
"column": 15,
"offset": 34
},
"end": {
"line": 3,
"column": 16,
"offset": 35
}
},
"value": 1,
"raw": "1",
"range": [
34,
35
]
},
"operator": "+",
"right": {
"type": "Literal",
"start": 38,
"end": 39,
"loc": {
"start": {
"line": 3,
"column": 19,
"offset": 38
},
"end": {
"line": 3,
"column": 20,
"offset": 39
}
},
"value": 2,
"raw": "2",
"range": [
38,
39
]
},
"range": [
34,
39
]
},
"start": 34,
"end": 39,
"loc": {
"start": {
"line": 3,
"column": 15,
"offset": 34
},
"end": {
"line": 3,
"column": 20,
"offset": 39
}
},
"range": [
34,
39
]
}
],
"sourceType": "module",
"comments": [],
"loc": {
"start": {
"line": 3,
"column": 15,
"offset": 34
},
"end": {
"line": 3,
"column": 20,
"offset": 39
}
},
"range": [
34,
39
]
}
}
},
"position": {
"start": {
"line": 3,
"column": 6,
"offset": 24
},
"end": {
"line": 3,
"column": 22,
"offset": 40
}
}
},
{
"type": "mdxJsxAttribute",
"name": "data-product",
"value": {
"type": "mdxJsxAttributeValueExpression",
"value": "2 * 3",
"data": {
"estree": {
"type": "Program",
"start": 55,
"end": 60,
"body": [
{
"type": "ExpressionStatement",
"expression": {
"type": "BinaryExpression",
"start": 55,
"end": 60,
"loc": {
"start": {
"line": 3,
"column": 36,
"offset": 55
},
"end": {
"line": 3,
"column": 41,
"offset": 60
}
},
"left": {
"type": "Literal",
"start": 55,
"end": 56,
"loc": {
"start": {
"line": 3,
"column": 36,
"offset": 55
},
"end": {
"line": 3,
"column": 37,
"offset": 56
}
},
"value": 2,
"raw": "2",
"range": [
55,
56
]
},
"operator": "*",
"right": {
"type": "Literal",
"start": 59,
"end": 60,
"loc": {
"start": {
"line": 3,
"column": 40,
"offset": 59
},
"end": {
"line": 3,
"column": 41,
"offset": 60
}
},
"value": 3,
"raw": "3",
"range": [
59,
60
]
},
"range": [
55,
60
]
},
"start": 55,
"end": 60,
"loc": {
"start": {
"line": 3,
"column": 36,
"offset": 55
},
"end": {
"line": 3,
"column": 41,
"offset": 60
}
},
"range": [
55,
60
]
}
],
"sourceType": "module",
"comments": [],
"loc": {
"start": {
"line": 3,
"column": 36,
"offset": 55
},
"end": {
"line": 3,
"column": 41,
"offset": 60
}
},
"range": [
55,
60
]
}
}
},
"position": {
"start": {
"line": 3,
"column": 23,
"offset": 41
},
"end": {
"line": 3,
"column": 43,
"offset": 61
}
}
},
{
"type": "mdxJsxAttribute",
"name": "id",
"value": "sum-box",
"position": {
"start": {
"line": 3,
"column": 44,
"offset": 62
},
"end": {
"line": 3,
"column": 56,
"offset": 74
}
}
}
],
"position": {
"start": {
"line": 3,
"column": 1,
"offset": 19
},
"end": {
"line": 5,
"column": 7,
"offset": 96
}
},
"children": [
{
"type": "element",
"tagName": "p",
"properties": {},
"children": [
{
"type": "text",
"value": "Static body",
"position": {
"start": {
"line": 4,
"column": 3,
"offset": 78
},
"end": {
"line": 4,
"column": 14,
"offset": 89
}
}
}
],
"position": {
"start": {
"line": 4,
"column": 3,
"offset": 78
},
"end": {
"line": 4,
"column": 14,
"offset": 89
}
}
}
]
},
{
"type": "text",
"value": "\n"
},
{
"type": "element",
"tagName": "p",
"properties": {},
"children": [
{
"type": "mdxJsxTextElement",
"name": "abbr",
"attributes": [
{
"type": "mdxJsxAttribute",
"name": "title",
"value": {
"type": "mdxJsxAttributeValueExpression",
"value": "['a', 'b'].join('-')",
"data": {
"estree": {
"type": "Program",
"start": 111,
"end": 131,
"body": [
{
"type": "ExpressionStatement",
"expression": {
"type": "CallExpression",
"start": 111,
"end": 131,
"loc": {
"start": {
"line": 7,
"column": 13,
"offset": 111
},
"end": {
"line": 7,
"column": 33,
"offset": 131
}
},
"callee": {
"type": "MemberExpression",
"start": 111,
"end": 126,
"loc": {
"start": {
"line": 7,
"column": 13,
"offset": 111
},
"end": {
"line": 7,
"column": 28,
"offset": 126
}
},
"object": {
"type": "ArrayExpression",
"start": 111,
"end": 121,
"loc": {
"start": {
"line": 7,
"column": 13,
"offset": 111
},
"end": {
"line": 7,
"column": 23,
"offset": 121
}
},
"elements": [
{
"type": "Literal",
"start": 112,
"end": 115,
"loc": {
"start": {
"line": 7,
"column": 14,
"offset": 112
},
"end": {
"line": 7,
"column": 17,
"offset": 115
}
},
"value": "a",
"raw": "'a'",
"range": [
112,
115
]
},
{
"type": "Literal",
"start": 117,
"end": 120,
"loc": {
"start": {
"line": 7,
"column": 19,
"offset": 117
},
"end": {
"line": 7,
"column": 22,
"offset": 120
}
},
"value": "b",
"raw": "'b'",
"range": [
117,
120
]
}
],
"range": [
111,
121
]
},
"property": {
"type": "Identifier",
"start": 122,
"end": 126,
"loc": {
"start": {
"line": 7,
"column": 24,
"offset": 122
},
"end": {
"line": 7,
"column": 28,
"offset": 126
}
},
"name": "join",
"range": [
122,
126
]
},
"computed": false,
"optional": false,
"range": [
111,
126
]
},
"arguments": [
{
"type": "Literal",
"start": 127,
"end": 130,
"loc": {
"start": {
"line": 7,
"column": 29,
"offset": 127
},
"end": {
"line": 7,
"column": 32,
"offset": 130
}
},
"value": "-",
"raw": "'-'",
"range": [
127,
130
]
}
],
"optional": false,
"range": [
111,
131
]
},
"start": 111,
"end": 131,
"loc": {
"start": {
"line": 7,
"column": 13,
"offset": 111
},
"end": {
"line": 7,
"column": 33,
"offset": 131
}
},
"range": [
111,
131
]
}
],
"sourceType": "module",
"comments": [],
"loc": {
"start": {
"line": 7,
"column": 13,
"offset": 111
},
"end": {
"line": 7,
"column": 33,
"offset": 131
}
},
"range": [
111,
131
]
}
}
},
"position": {
"start": {
"line": 7,
"column": 7,
"offset": 104
},
"end": {
"line": 7,
"column": 35,
"offset": 132
}
}
}
],
"position": {
"start": {
"line": 7,
"column": 1,
"offset": 98
},
"end": {
"line": 7,
"column": 49,
"offset": 146
}
},
"children": [
{
"type": "text",
"value": "Joined",
"position": {
"start": {
"line": 7,
"column": 36,
"offset": 133
},
"end": {
"line": 7,
"column": 42,
"offset": 139
}
}
}
]
}
],
"position": {
"start": {
"line": 7,
"column": 1,
"offset": 98
},
"end": {
"line": 7,
"column": 49,
"offset": 146
}
}
}
],
"position": {
"start": {
"line": 1,
"column": 1,
"offset": 0
},
"end": {
"line": 8,
"column": 1,
"offset": 147
}
}
},
"code": "\"use strict\";\nconst {Fragment: _Fragment, jsx: _jsx, jsxs: _jsxs} = arguments[0];\nlet toc = [{\n depth: 1,\n url: \"#mdx-expressions\",\n title: _jsx(_Fragment, {\n children: \"MDX expressions\"\n })\n}];\nfunction _createMdxContent(props) {\n const _components = {\n h1: \"h1\",\n p: \"p\",\n ...props.components\n };\n return _jsxs(_Fragment, {\n children: [_jsx(_components.h1, {\n id: \"mdx-expressions\",\n children: \"MDX expressions\"\n }), \"\\n\", _jsx(\"div\", {\n \"data-sum\": 1 + 2,\n \"data-product\": 2 * 3,\n id: \"sum-box\",\n children: _jsx(_components.p, {\n children: \"Static body\"\n })\n }), \"\\n\", _jsx(\"abbr\", {\n title: ['a', 'b'].join('-'),\n children: \"Joined\"\n })]\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = props.components || ({});\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n toc,\n default: MDXContent\n};\n",
"data": {
"structuredData": {
"contents": [
{
"heading": "mdx-expressions",
"content": "Static body"
},
{
"heading": "mdx-expressions",
"content": "Joined"
}
],
"headings": [
@@ -707,49 +14,6 @@
"content": "MDX expressions"
}
]
},
"rehypeToc": [
{
"title": {
"type": "element",
"tagName": "h1",
"properties": {
"id": "mdx-expressions"
},
"children": [
{
"type": "text",
"value": "MDX expressions",
"position": {
"start": {
"line": 1,
"column": 3,
"offset": 2
},
"end": {
"line": 1,
"column": 18,
"offset": 17
}
}
}
],
"position": {
"start": {
"line": 1,
"column": 1,
"offset": 0
},
"end": {
"line": 1,
"column": 18,
"offset": 17
}
}
},
"depth": 1,
"url": "#mdx-expressions"
}
]
}
}
}
+1 -5
View File
@@ -4,10 +4,6 @@
{
"heading": "mdx-expressions",
"content": "Static body"
},
{
"heading": "mdx-expressions",
"content": "Joined"
}
],
"headings": [
@@ -17,7 +13,7 @@
}
]
},
"bodyHtml": "<h1 id=\"mdx-expressions\">MDX expressions</h1>\n<div data-sum=\"3\" data-product=\"6\" id=\"sum-box\"><p>Static body</p></div>\n<p><abbr title=\"a-b\">Joined</abbr></p>",
"bodyHtml": "<h1 id=\"mdx-expressions\">MDX expressions</h1>\n<div data-sum=\"3\" data-product=\"6\" id=\"sum-box\"><p>Static body</p></div>\n<abbr title=\"a-b\">Joined</abbr>",
"toc": [
{
"url": "#mdx-expressions",
+3 -308
View File
@@ -1,319 +1,14 @@
{
"tree": {
"type": "root",
"children": [
{
"type": "element",
"tagName": "h1",
"properties": {
"id": "jsx-expressions"
},
"children": [
{
"type": "text",
"value": "JSX expressions",
"position": {
"start": {
"line": 1,
"column": 3,
"offset": 2
},
"end": {
"line": 1,
"column": 18,
"offset": 17
}
}
}
],
"position": {
"start": {
"line": 1,
"column": 1,
"offset": 0
},
"end": {
"line": 1,
"column": 18,
"offset": 17
}
}
},
{
"type": "text",
"value": "\n"
},
{
"type": "text",
"value": "export const ignored = <span>Ignored export</span>",
"position": {
"start": {
"line": 3,
"column": 1,
"offset": 19
},
"end": {
"line": 3,
"column": 51,
"offset": 69
}
}
},
{
"type": "text",
"value": "\n"
},
{
"type": "text",
"value": "<div id=\"native-jsx\">Native JSX child</div>",
"position": {
"start": {
"line": 5,
"column": 1,
"offset": 71
},
"end": {
"line": 5,
"column": 46,
"offset": 116
}
}
},
{
"type": "text",
"value": "\n"
},
{
"type": "mdxJsxFlowElement",
"name": null,
"attributes": [],
"position": {
"start": {
"line": 7,
"column": 1,
"offset": 118
},
"end": {
"line": 10,
"column": 4,
"offset": 194
}
},
"children": [
{
"type": "element",
"tagName": "p",
"properties": {},
"children": [
{
"type": "mdxJsxTextElement",
"name": "span",
"attributes": [
{
"type": "mdxJsxAttribute",
"name": "data-inline",
"value": "one",
"position": {
"start": {
"line": 8,
"column": 9,
"offset": 129
},
"end": {
"line": 8,
"column": 26,
"offset": 146
}
}
}
],
"position": {
"start": {
"line": 8,
"column": 3,
"offset": 123
},
"end": {
"line": 8,
"column": 35,
"offset": 155
}
},
"children": [
{
"type": "text",
"value": "A",
"position": {
"start": {
"line": 8,
"column": 27,
"offset": 147
},
"end": {
"line": 8,
"column": 28,
"offset": 148
}
}
}
]
},
{
"type": "text",
"value": "\n",
"position": {
"start": {
"line": 8,
"column": 35,
"offset": 155
},
"end": {
"line": 9,
"column": 1,
"offset": 156
}
}
},
{
"type": "mdxJsxTextElement",
"name": "span",
"attributes": [
{
"type": "mdxJsxAttribute",
"name": "data-inline",
"value": "two",
"position": {
"start": {
"line": 9,
"column": 9,
"offset": 164
},
"end": {
"line": 9,
"column": 26,
"offset": 181
}
}
}
],
"position": {
"start": {
"line": 9,
"column": 3,
"offset": 158
},
"end": {
"line": 9,
"column": 35,
"offset": 190
}
},
"children": [
{
"type": "text",
"value": "B",
"position": {
"start": {
"line": 9,
"column": 27,
"offset": 182
},
"end": {
"line": 9,
"column": 28,
"offset": 183
}
}
}
]
}
],
"position": {
"start": {
"line": 8,
"column": 3,
"offset": 123
},
"end": {
"line": 9,
"column": 35,
"offset": 190
}
}
}
]
}
],
"position": {
"start": {
"line": 1,
"column": 1,
"offset": 0
},
"end": {
"line": 11,
"column": 1,
"offset": 195
}
}
},
"code": "\"use strict\";\nconst {Fragment: _Fragment, jsx: _jsx, jsxs: _jsxs} = arguments[0];\nconst ignored = _jsx(\"span\", {\n children: \"Ignored export\"\n});\nlet toc = [{\n depth: 1,\n url: \"#jsx-expressions\",\n title: _jsx(_Fragment, {\n children: \"JSX expressions\"\n })\n}];\nfunction _createMdxContent(props) {\n const _components = {\n h1: \"h1\",\n ...props.components\n };\n return _jsxs(_Fragment, {\n children: [_jsx(_components.h1, {\n id: \"jsx-expressions\",\n children: \"JSX expressions\"\n }), \"\\n\", \"\\n\", _jsx(\"div\", {\n id: \"native-jsx\",\n children: \"Native JSX child\"\n }), \"\\n\", _jsxs(_Fragment, {\n children: [_jsx(\"span\", {\n \"data-inline\": \"one\",\n children: \"A\"\n }), _jsx(\"span\", {\n \"data-inline\": \"two\",\n children: \"B\"\n })]\n })]\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = props.components || ({});\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n ignored,\n toc,\n default: MDXContent\n};\n",
"data": {
"structuredData": {
"contents": [
{
"heading": "jsx-expressions",
"content": "A\nB"
}
],
"contents": [],
"headings": [
{
"id": "jsx-expressions",
"content": "JSX expressions"
}
]
},
"rehypeToc": [
{
"title": {
"type": "element",
"tagName": "h1",
"properties": {
"id": "jsx-expressions"
},
"children": [
{
"type": "text",
"value": "JSX expressions",
"position": {
"start": {
"line": 1,
"column": 3,
"offset": 2
},
"end": {
"line": 1,
"column": 18,
"offset": 17
}
}
}
],
"position": {
"start": {
"line": 1,
"column": 1,
"offset": 0
},
"end": {
"line": 1,
"column": 18,
"offset": 17
}
}
},
"depth": 1,
"url": "#jsx-expressions"
}
]
}
}
}
+2 -7
View File
@@ -1,11 +1,6 @@
{
"structuredData": {
"contents": [
{
"heading": "jsx-expressions",
"content": "A\nB"
}
],
"contents": [],
"headings": [
{
"id": "jsx-expressions",
@@ -13,7 +8,7 @@
}
]
},
"bodyHtml": "<h1 id=\"jsx-expressions\">JSX expressions</h1>\nexport const ignored = &lt;span&gt;Ignored export&lt;/span&gt;\n&lt;div id=&quot;native-jsx&quot;&gt;Native JSX child&lt;/div&gt;\n<p><span data-inline=\"one\">A</span>\n<span data-inline=\"two\">B</span></p>",
"bodyHtml": "<h1 id=\"jsx-expressions\">JSX expressions</h1>\n\n<div id=\"native-jsx\">Native JSX child</div>\n<span data-inline=\"one\">A</span><span data-inline=\"two\">B</span>",
"toc": [
{
"url": "#jsx-expressions",
+12 -9
View File
@@ -3,7 +3,7 @@ import fs from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { renderToStaticMarkup } from 'react-dom/server';
import { createMarkdownCompiler, MarkdownCompiler } from '@/md/compiler-full';
import { createMarkdownCompiler, MarkdownCompiler } from '@/md/compiler';
import { createMarkdownRenderer } from '@/md/renderer';
import type { RawPage } from '@/storage';
import type { TOCItemType } from 'fumadocs-core/toc';
@@ -43,15 +43,18 @@ for (const { name, file } of cases) {
test(`compiler: ${name}`, async () => {
const { filePath, content } = await readFixture(file);
const compiler = createMarkdownCompiler();
const { tree, file: vfile } = await compiler.compile({ path: filePath, value: content });
const out = await compiler.compile({ path: filePath, value: content });
const payload = {
tree,
data: {
structuredData: vfile.data.structuredData,
rehypeToc: vfile.data.rehypeToc,
},
};
const payload =
out.type === 'ast'
? {
tree: out.tree,
data: out.file.data,
}
: {
code: out.code,
data: out.file.data,
};
await expect(JSON.stringify(payload, null, 2)).toMatchFileSnapshot(
path.join(fixturesDir, `${name}.compiler.json`),
+1 -1
View File
@@ -4,7 +4,7 @@ export default defineConfig({
dts: true,
fixedExtension: false,
target: 'es2023',
entry: ['./src/index.ts', './src/dev/index.ts'],
entry: ['./src/index.ts', './src/js/*', './src/dev/index.ts'],
format: 'esm',
exports: true,
deps: {
+32 -36
View File
@@ -1798,7 +1798,7 @@ importers:
version: link:../tsconfig
tsdown:
specifier: 0.21.8
version: 0.21.8(@tsdown/[email protected])([email protected](@emnapi/[email protected])(@emnapi/[email protected]))([email protected])
version: 0.21.8(@tsdown/[email protected])([email protected])([email protected])
unified:
specifier: ^11.0.5
version: 11.0.5
@@ -1832,7 +1832,7 @@ importers:
version: link:../tsconfig
tsdown:
specifier: 0.21.8
version: 0.21.8(@tsdown/[email protected])([email protected](@emnapi/[email protected])(@emnapi/[email protected]))([email protected])
version: 0.21.8(@tsdown/[email protected])([email protected])([email protected])
packages/content:
dependencies:
@@ -1857,7 +1857,7 @@ importers:
version: link:../tsconfig
tsdown:
specifier: 0.21.8
version: 0.21.8(@tsdown/[email protected])([email protected](@emnapi/[email protected])(@emnapi/[email protected]))([email protected])
version: 0.21.8(@tsdown/[email protected])([email protected])([email protected])
packages/content-collections:
dependencies:
@@ -1885,7 +1885,7 @@ importers:
version: link:../tsconfig
tsdown:
specifier: 0.21.8
version: 0.21.8(@tsdown/[email protected])([email protected](@emnapi/[email protected])(@emnapi/[email protected]))([email protected])
version: 0.21.8(@tsdown/[email protected])([email protected])([email protected])
packages/core:
dependencies:
@@ -2033,7 +2033,7 @@ importers:
version: link:../tsconfig
tsdown:
specifier: 0.21.8
version: 0.21.8(@tsdown/[email protected])([email protected](@emnapi/[email protected])(@emnapi/[email protected]))([email protected])
version: 0.21.8(@tsdown/[email protected])([email protected])([email protected])
typescript:
specifier: ^6.0.2
version: 6.0.2
@@ -2085,7 +2085,7 @@ importers:
version: link:../tsconfig
tsdown:
specifier: 0.21.8
version: 0.21.8(@tsdown/[email protected])([email protected](@emnapi/[email protected])(@emnapi/[email protected]))([email protected])
version: 0.21.8(@tsdown/[email protected])([email protected])([email protected])
typescript:
specifier: ^6.0.2
version: 6.0.2
@@ -2176,7 +2176,7 @@ importers:
version: link:../tsconfig
tsdown:
specifier: 0.21.8
version: 0.21.8(@tsdown/[email protected])([email protected](@emnapi/[email protected])(@emnapi/[email protected]))([email protected])
version: 0.21.8(@tsdown/[email protected])([email protected])([email protected])
typescript:
specifier: ^6.0.2
version: 6.0.2
@@ -2222,7 +2222,7 @@ importers:
version: link:../tsconfig
tsdown:
specifier: 0.21.8
version: 0.21.8(@tsdown/[email protected])([email protected](@emnapi/[email protected])(@emnapi/[email protected]))([email protected])
version: 0.21.8(@tsdown/[email protected])([email protected])([email protected])
typescript:
specifier: ^6.0.2
version: 6.0.2
@@ -2232,6 +2232,9 @@ importers:
packages/local-md:
dependencies:
'@mdx-js/mdx':
specifier: ^3.1.1
version: 3.1.1
'@standard-schema/spec':
specifier: ^1.1.0
version: 1.1.0
@@ -2247,9 +2250,6 @@ importers:
remark:
specifier: ^15.0.1
version: 15.0.1
remark-mdx:
specifier: ^3.1.1
version: 3.1.1
remark-rehype:
specifier: ^11.1.2
version: 11.1.2
@@ -2272,9 +2272,6 @@ importers:
'@types/hast':
specifier: ^3.0.4
version: 3.0.4
'@types/mdx':
specifier: ^2.0.13
version: 2.0.13
'@types/node':
specifier: 25.6.0
version: 25.6.0
@@ -2307,7 +2304,7 @@ importers:
version: link:../tsconfig
tsdown:
specifier: 0.21.8
version: 0.21.8(@tsdown/[email protected])([email protected](@emnapi/[email protected])(@emnapi/[email protected]))([email protected])
version: 0.21.8(@tsdown/[email protected])([email protected])([email protected])
packages/mdx:
dependencies:
@@ -2413,7 +2410,7 @@ importers:
version: link:../tsconfig
tsdown:
specifier: 0.21.8
version: 0.21.8(@tsdown/[email protected])([email protected](@emnapi/[email protected])(@emnapi/[email protected]))([email protected])
version: 0.21.8(@tsdown/[email protected])([email protected])([email protected])
vite:
specifier: ^8.0.8
version: 8.0.8(@types/[email protected])([email protected])([email protected])([email protected])([email protected])([email protected])
@@ -2462,7 +2459,7 @@ importers:
version: link:../tsconfig
tsdown:
specifier: 0.21.8
version: 0.21.8(@tsdown/[email protected])([email protected](@emnapi/[email protected])(@emnapi/[email protected]))([email protected])
version: 0.21.8(@tsdown/[email protected])([email protected])([email protected])
packages/obsidian:
dependencies:
@@ -2538,7 +2535,7 @@ importers:
version: link:../tsconfig
tsdown:
specifier: 0.21.8
version: 0.21.8(@tsdown/[email protected])([email protected](@emnapi/[email protected])(@emnapi/[email protected]))([email protected])
version: 0.21.8(@tsdown/[email protected])([email protected])([email protected])
typescript:
specifier: ^6.0.2
version: 6.0.2
@@ -2650,7 +2647,7 @@ importers:
version: link:../tsconfig
tsdown:
specifier: 0.21.8
version: 0.21.8(@tsdown/[email protected])([email protected](@emnapi/[email protected])(@emnapi/[email protected]))([email protected])
version: 0.21.8(@tsdown/[email protected])([email protected])([email protected])
packages/press:
dependencies:
@@ -2789,7 +2786,7 @@ importers:
version: 4.2.2
tsdown:
specifier: 0.21.8
version: 0.21.8(@tsdown/[email protected])([email protected](@emnapi/[email protected])(@emnapi/[email protected]))([email protected])
version: 0.21.8(@tsdown/[email protected])([email protected])([email protected])
typescript:
specifier: ^6.0.2
version: 6.0.2
@@ -2841,7 +2838,7 @@ importers:
version: link:../tsconfig
tsdown:
specifier: 0.21.8
version: 0.21.8(@tsdown/[email protected])([email protected](@emnapi/[email protected])(@emnapi/[email protected]))([email protected])
version: 0.21.8(@tsdown/[email protected])([email protected])([email protected])
packages/radix-ui:
dependencies:
@@ -2962,7 +2959,7 @@ importers:
version: link:../tsconfig
tsdown:
specifier: 0.21.8
version: 0.21.8(@tsdown/[email protected])([email protected](@emnapi/[email protected])(@emnapi/[email protected]))([email protected])
version: 0.21.8(@tsdown/[email protected])([email protected])([email protected])
unified:
specifier: ^11.0.5
version: 11.0.5
@@ -3006,7 +3003,7 @@ importers:
version: link:../tsconfig
tsdown:
specifier: 0.21.8
version: 0.21.8(@tsdown/[email protected])([email protected](@emnapi/[email protected])(@emnapi/[email protected]))([email protected])
version: 0.21.8(@tsdown/[email protected])([email protected])([email protected])
packages/story:
dependencies:
@@ -3064,7 +3061,7 @@ importers:
version: link:../tsconfig
tsdown:
specifier: 0.21.8
version: 0.21.8(@tsdown/[email protected])([email protected](@emnapi/[email protected])(@emnapi/[email protected]))([email protected])
version: 0.21.8(@tsdown/[email protected])([email protected])([email protected])
packages/tailwind:
devDependencies:
@@ -3088,7 +3085,7 @@ importers:
version: link:../tsconfig
tsdown:
specifier: 0.21.8
version: 0.21.8(@tsdown/[email protected])([email protected](@emnapi/[email protected])(@emnapi/[email protected]))([email protected])
version: 0.21.8(@tsdown/[email protected])([email protected])([email protected])
packages/tsconfig: {}
@@ -3148,7 +3145,7 @@ importers:
version: link:../tsconfig
tsdown:
specifier: 0.21.8
version: 0.21.8(@tsdown/[email protected])([email protected](@emnapi/[email protected])(@emnapi/[email protected]))([email protected])
version: 0.21.8(@tsdown/[email protected])([email protected])([email protected])
typescript:
specifier: ^6.0.2
version: 6.0.2
@@ -3224,7 +3221,7 @@ importers:
version: link:../tsconfig
tsdown:
specifier: 0.21.8
version: 0.21.8(@tsdown/[email protected])([email protected](@emnapi/[email protected])(@emnapi/[email protected]))([email protected])
version: 0.21.8(@tsdown/[email protected])([email protected])([email protected])
typescript:
specifier: ^6.0.2
version: 6.0.2
@@ -7835,7 +7832,6 @@ packages:
[email protected]:
resolution: {integrity: sha512-KLwDUqs5WIny/94F4xZ4QfaAE6YWyjR+s79pt/ItQhk2CG+PJQ5xL6VuOWhiyN2eP3fryZK95vog9CTLCaYV2Q==}
cpu: [arm64, x64]
os: [darwin, linux, win32]
hasBin: true
@@ -16200,7 +16196,7 @@ snapshots:
react: 19.2.5
react-dom: 19.2.5([email protected])
optionalDependencies:
'@vitejs/plugin-rsc': 0.5.24([email protected]([email protected]))([email protected]([email protected]([email protected]))([email protected]))([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected])([email protected]))
'@vitejs/plugin-rsc': 0.5.24([email protected]([email protected]))([email protected]([email protected]([email protected]))([email protected])([email protected]([email protected])))([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected])([email protected]))
transitivePeerDependencies:
- '@rsbuild/core'
- crossws
@@ -16236,7 +16232,7 @@ snapshots:
react-dom: 19.2.5([email protected])
vite: 8.0.8(@types/[email protected])([email protected])([email protected])([email protected])([email protected])([email protected])
optionalDependencies:
'@vitejs/plugin-rsc': 0.5.24([email protected]([email protected]))([email protected]([email protected]([email protected]))([email protected]))([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected])([email protected]))
'@vitejs/plugin-rsc': 0.5.24([email protected]([email protected]))([email protected]([email protected]([email protected]))([email protected])([email protected]([email protected])))([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected])([email protected]))
transitivePeerDependencies:
- '@rsbuild/core'
- crossws
@@ -16407,7 +16403,7 @@ snapshots:
lightningcss: 1.32.0
postcss-load-config: 6.0.1([email protected])([email protected])([email protected])([email protected])
rolldown: 1.0.0-rc.15
tsdown: 0.21.8(@tsdown/[email protected])([email protected](@emnapi/[email protected])(@emnapi/[email protected]))([email protected])
tsdown: 0.21.8(@tsdown/[email protected])([email protected])([email protected])
optionalDependencies:
postcss: 8.5.9
transitivePeerDependencies:
@@ -18073,7 +18069,7 @@ snapshots:
[email protected]: {}
[email protected]([email protected](@emnapi/[email protected])(@emnapi/[email protected])):
[email protected]([email protected]):
optionalDependencies:
oxc-resolver: 11.19.1(@emnapi/[email protected])(@emnapi/[email protected])
@@ -21451,7 +21447,7 @@ snapshots:
[email protected]: {}
[email protected]([email protected](@emnapi/[email protected])(@emnapi/[email protected]))([email protected])([email protected]):
[email protected]([email protected])([email protected])([email protected]):
dependencies:
'@babel/generator': 8.0.0-rc.3
'@babel/helper-validator-identifier': 8.0.0-rc.3
@@ -21459,7 +21455,7 @@ snapshots:
'@babel/types': 8.0.0-rc.3
ast-kit: 3.0.0-beta.1
birpc: 4.0.0
dts-resolver: 2.1.3([email protected](@emnapi/[email protected])(@emnapi/[email protected]))
dts-resolver: 2.1.3([email protected])
get-tsconfig: 4.14.0
obug: 2.1.1
picomatch: 4.0.4
@@ -22098,7 +22094,7 @@ snapshots:
minimist: 1.2.8
strip-bom: 3.0.0
[email protected](@tsdown/[email protected])([email protected](@emnapi/[email protected])(@emnapi/[email protected]))([email protected]):
[email protected](@tsdown/[email protected])([email protected])([email protected]):
dependencies:
ansis: 4.2.0
cac: 7.0.0
@@ -22109,7 +22105,7 @@ snapshots:
obug: 2.1.1
picomatch: 4.0.4
rolldown: 1.0.0-rc.15
rolldown-plugin-dts: 0.23.2([email protected](@emnapi/[email protected])(@emnapi/[email protected]))([email protected])([email protected])
rolldown-plugin-dts: 0.23.2([email protected])([email protected])([email protected])
semver: 7.7.4
tinyexec: 1.1.1
tinyglobby: 0.2.16