diff --git a/docs/.eslintrc.json b/docs/.eslintrc.json index e5a34aec6..e2cc698fb 100644 --- a/docs/.eslintrc.json +++ b/docs/.eslintrc.json @@ -1,4 +1,7 @@ { + "resolve": { + "extensions": [".js", ".jsx"] + }, "env": { "browser": true } diff --git a/docs/components/Card.jsx b/docs/components/Card.jsx new file mode 100644 index 000000000..03e0fb8e3 --- /dev/null +++ b/docs/components/Card.jsx @@ -0,0 +1,8 @@ +export function Card({title, children} = {}) { + return ( +
+ {title ?

{title}

: null} + {children} +
+ ); +} diff --git a/docs/jsx.md b/docs/jsx.md new file mode 100644 index 000000000..df61f4814 --- /dev/null +++ b/docs/jsx.md @@ -0,0 +1,137 @@ +# JSX + +[React](https://react.dev/) is a popular and powerful library for building interactive interfaces. React is typically written in [JSX](https://react.dev/learn/writing-markup-with-jsx), an extension of JavaScript that allows HTML-like markup. To use JSX and React, declare a JSX fenced code block (```jsx). For example, to define a `Greeting` component that accepts a `subject` prop: + +````md +```jsx +function Greeting({subject}) { + return
Hello, {subject}!
+} +``` +```` + +```jsx +function Greeting({subject}) { + return
Hello, {subject}!
+} +``` + +Then call the built-in display function to render content: + +```jsx echo +display(); +``` + +You can combine React with Framework’s built-in [reactivity](./reactivity) by passing reactive values as props. Try changing the `name` below. + +```jsx echo +display(); +``` + +```js echo +const name = view(Inputs.text({label: "Name", placeholder: "Anonymous"})); +``` + +You can use hooks such as [`useState`](https://react.dev/reference/react/useState), [`useEffect`](https://react.dev/reference/react/useEffect), and [`useRef`](https://react.dev/reference/react/useRef). The `Counter` component below counts the number of times you click the button. + +```jsx echo +function Counter() { + const [count, setCount] = React.useState(0); + return ( + + ); +} +``` + +```jsx echo +display(); +``` + +React is available by default as `React` in Markdown, but you can import it explicitly like so: + +```js run=false +import * as React from "npm:react"; +``` + +If you prefer, you can import specific symbols, such as hooks: + +```js run=false +import {useState} from "npm:react"; +``` + +React DOM is also available as `ReactDOM` in Markdown, or can be imported as: + +```js run=false +import * as ReactDOM from "npm:react-dom"; +``` + +You can define components in JSX modules. For example, if this were `components/Card.jsx`: + +```jsx run=false +export function Card({title, children} = {}) { + return ( +
+ {title ?

{title}

: null} + {children} +
+ ); +} +``` + +You could then import the `Card` component as: + +```js echo +import {Card} from "./components/Card.js"; +``` + +
+ +Use the `.js` file extension when importing JSX (`.jsx`) modules; JSX is transpiled to JavaScript during build. + +
+ +And, as before, you can render a card using the display function: + +```jsx echo +display(If you can read this, success!); +``` + +Within a JSX fenced code block, the [display function](./javascript#explicit-display) behaves a bit differently from a JavaScript fenced code block or inline expression: +it replaces the previously-displayed content, if any. In addition, JSX fenced code blocks do not support implicit display; content can only be displayed explicitly. + +
+ +In the future we intend to support other JSX-compatible frameworks, such as Preact. We are also working on server-side rendering with client-side hydration; please upvote [#931](https://github.com/observablehq/framework/issues/931) if you are interested in this feature. + +
+ +## Inline expressions + +JSX is not currently supported in inline expression `${…}`; only JavaScript is allowed in inline expressions. However, you can declare a detached root using [`createRoot`](https://react.dev/reference/react-dom/client/createRoot): + +```js echo +const node = document.createElement("SPAN"); +const root = ReactDOM.createRoot(node); +``` + +Then use a JSX code block to render the desired content into the root: + +```jsx echo +root.render(<>Hello, {name || "anonymous"}!); +``` + +Lastly, interpolate the root into the desired location with an inline expression: + +
+

Rendering into an inline expression

+ ${node} +
+ +```md run=false +
+

Rendering into an inline expression

+ ${node} +
+``` diff --git a/observablehq.config.ts b/observablehq.config.ts index 906cb9900..c9e611411 100644 --- a/observablehq.config.ts +++ b/observablehq.config.ts @@ -22,6 +22,7 @@ export default { {name: "Markdown", path: "/markdown"}, {name: "JavaScript", path: "/javascript"}, {name: "Reactivity", path: "/reactivity"}, + {name: "JSX", path: "/jsx"}, {name: "Imports", path: "/imports"}, {name: "Data loaders", path: "/loaders"}, {name: "Files", path: "/files"}, diff --git a/package.json b/package.json index 3994ac21b..da900fea1 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "observable": "dist/bin/observable.js" }, "scripts": { - "dev": "rimraf --glob docs/themes.md docs/theme/*.md && (tsx watch docs/theme/generate-themes.ts & tsx watch --no-warnings=ExperimentalWarning ./src/bin/observable.ts preview --no-open)", + "dev": "rimraf --glob docs/themes.md docs/theme/*.md && (tsx watch docs/theme/generate-themes.ts & tsx watch --ignore docs --no-warnings=ExperimentalWarning ./src/bin/observable.ts preview --no-open)", "docs:themes": "rimraf --glob docs/themes.md docs/theme/*.md && tsx docs/theme/generate-themes.ts", "docs:build": "yarn docs:themes && rimraf docs/.observablehq/dist && tsx --no-warnings=ExperimentalWarning ./src/bin/observable.ts build", "docs:deploy": "yarn docs:themes && tsx --no-warnings=ExperimentalWarning ./src/bin/observable.ts deploy", diff --git a/src/client/main.js b/src/client/main.js index 60ab42de4..a75d47af5 100644 --- a/src/client/main.js +++ b/src/client/main.js @@ -23,7 +23,7 @@ const cellsById = new Map(); const rootsById = findRoots(document.body); export function define(cell) { - const {id, inline, inputs = [], outputs = [], body} = cell; + const {id, mode, inputs = [], outputs = [], body} = cell; const variables = []; cellsById.set(id, {cell, variables}); const root = rootsById.get(id); @@ -35,7 +35,8 @@ export function define(cell) { const v = main.variable({_node: root.parentNode, pending, rejected}, {shadow: {}}); // _node for visibility promise if (inputs.includes("display") || inputs.includes("view")) { let displayVersion = -1; // the variable._version of currently-displayed values - const display = inline ? displayInline : displayBlock; + const predisplay = mode === "jsx" ? noop : clear; // jsx replaces previous display naturally + const display = mode === "inline" ? displayInline : mode === "jsx" ? displayJsx : displayBlock; const vd = new v.constructor(2, v._module); vd.define( inputs.filter((i) => i !== "display" && i !== "view"), @@ -43,7 +44,7 @@ export function define(cell) { let version = v._version; // capture version on input change return (value) => { if (version < displayVersion) throw new Error("stale display"); - else if (version > displayVersion) clear(root); + else if (version > displayVersion) predisplay(root); displayVersion = version; display(root, value); return value; @@ -63,6 +64,13 @@ export function define(cell) { for (const o of outputs) variables.push(main.variable(true).define(o, [`cell ${id}`], (exports) => exports[o])); } +function noop() {} + +function clear(root) { + for (const v of root._nodes) v.remove(); + root._nodes.length = 0; +} + // If the variable previously rejected, it will show an error even if it doesn’t // normally display; we can’t rely on a subsequent display clearing the error, // so we clear the error when the variable is pending. We also restore the @@ -83,6 +91,19 @@ function reject(root, error) { displayNode(root, inspectError(error)); } +function displayJsx(root, value) { + return (root._root ??= import("npm:react-dom/client").then(({createRoot}) => { + const node = document.createElement("DIV"); + return [node, createRoot(node)]; + })).then(([node, client]) => { + if (!node.parentNode) { + root._nodes.push(node); + root.parentNode.insertBefore(node, root); + } + client.render(value); + }); +} + function displayNode(root, node) { if (node.nodeType === 11) { let child; @@ -96,11 +117,6 @@ function displayNode(root, node) { } } -function clear(root) { - for (const v of root._nodes) v.remove(); - root._nodes.length = 0; -} - function displayInline(root, value) { if (isNode(value)) { displayNode(root, value); diff --git a/src/client/stdlib/recommendedLibraries.js b/src/client/stdlib/recommendedLibraries.js index d700673c7..ebe5dea81 100644 --- a/src/client/stdlib/recommendedLibraries.js +++ b/src/client/stdlib/recommendedLibraries.js @@ -14,6 +14,8 @@ export const L = () => import("npm:leaflet"); export const mapboxgl = () => import("npm:mapbox-gl").then((module) => module.default); export const mermaid = () => import("observablehq:stdlib/mermaid").then((mermaid) => mermaid.default); export const Plot = () => import("npm:@observablehq/plot"); +export const React = () => import("npm:react"); +export const ReactDOM = () => import("npm:react-dom"); export const sql = () => import("observablehq:stdlib/duckdb").then((duckdb) => duckdb.sql); export const SQLite = () => import("observablehq:stdlib/sqlite").then((sqlite) => sqlite.default); export const SQLiteDatabaseClient = () => import("observablehq:stdlib/sqlite").then((sqlite) => sqlite.SQLiteDatabaseClient); // prettier-ignore diff --git a/src/dataloader.ts b/src/dataloader.ts index e0f3ce9b5..dc86d95a2 100644 --- a/src/dataloader.ts +++ b/src/dataloader.ts @@ -125,7 +125,12 @@ export class LoaderResolver { getWatchPath(path: string): string | undefined { const exactPath = join(this.root, path); - return existsSync(exactPath) ? exactPath : this.find(path)?.path; + if (existsSync(exactPath)) return exactPath; + if (exactPath.endsWith(".js")) { + const jsxPath = exactPath + "x"; + if (existsSync(jsxPath)) return jsxPath; + } + return this.find(path)?.path; } watchFiles(path: string, watchPaths: Iterable, callback: (name: string) => void) { diff --git a/src/javascript/module.ts b/src/javascript/module.ts index a1af2417c..bf84f555e 100644 --- a/src/javascript/module.ts +++ b/src/javascript/module.ts @@ -1,7 +1,9 @@ import {createHash} from "node:crypto"; -import {accessSync, constants, readFileSync, statSync} from "node:fs"; +import {accessSync, constants, existsSync, readFileSync, statSync} from "node:fs"; +import {readFile} from "node:fs/promises"; import {join} from "node:path/posix"; import type {Program} from "acorn"; +import {transform, transformSync} from "esbuild"; import {resolvePath} from "../path.js"; import {findFiles} from "./files.js"; import {findImports} from "./imports.js"; @@ -73,7 +75,7 @@ export function getModuleInfo(root: string, path: string): ModuleInfo | undefine const key = join(root, path); let mtimeMs: number; try { - ({mtimeMs} = statSync(key)); + ({mtimeMs} = statSync(resolveJsx(key) ?? key)); } catch { moduleInfoCache.delete(key); // delete stale entry return; // ignore missing file @@ -83,7 +85,7 @@ export function getModuleInfo(root: string, path: string): ModuleInfo | undefine let source: string; let body: Program; try { - source = readFileSync(key, "utf-8"); + source = readJavaScriptSync(key); body = parseProgram(source); } catch { moduleInfoCache.delete(key); // delete stale entry @@ -157,3 +159,37 @@ export function getFileInfo(root: string, path: string): FileInfo | undefined { } return entry; } + +function resolveJsx(path: string): string | null { + return !existsSync(path) && path.endsWith(".js") && existsSync((path += "x")) ? path : null; +} + +export async function readJavaScript(path: string): Promise { + const jsxPath = resolveJsx(path); + if (jsxPath !== null) { + const source = await readFile(jsxPath, "utf-8"); + const {code} = await transform(source, { + loader: "jsx", + jsx: "automatic", + jsxImportSource: "npm:react", + sourcefile: jsxPath + }); + return code; + } + return await readFile(path, "utf-8"); +} + +export function readJavaScriptSync(path: string): string { + const jsxPath = resolveJsx(path); + if (jsxPath !== null) { + const source = readFileSync(jsxPath, "utf-8"); + const {code} = transformSync(source, { + loader: "jsx", + jsx: "automatic", + jsxImportSource: "npm:react", + sourcefile: jsxPath + }); + return code; + } + return readFileSync(path, "utf-8"); +} diff --git a/src/javascript/parse.ts b/src/javascript/parse.ts index d93f2b8bd..5e16c68de 100644 --- a/src/javascript/parse.ts +++ b/src/javascript/parse.ts @@ -13,7 +13,7 @@ import {syntaxError} from "./syntaxError.js"; export interface ParseOptions { /** The path to the source within the source root. */ path: string; - /** If true, treat the input as an inline expression instead of a fenced code block. */ + /** If true, require the input to be an expresssion. */ inline?: boolean; } @@ -30,7 +30,6 @@ export interface JavaScriptNode { imports: ImportReference[]; expression: boolean; // is this an expression or a program cell? async: boolean; // does this use top-level await? - inline: boolean; input: string; } @@ -57,7 +56,6 @@ export function parseJavaScript(input: string, options: ParseOptions): JavaScrip imports: findImports(body, path, input), expression: !!expression, async: findAwaits(body).length > 0, - inline, input }; } diff --git a/src/javascript/transpile.ts b/src/javascript/transpile.ts index d54a1af55..b264ca94f 100644 --- a/src/javascript/transpile.ts +++ b/src/javascript/transpile.ts @@ -17,10 +17,11 @@ import {getStringLiteralValue, isStringLiteral} from "./source.js"; export interface TranspileOptions { id: string; path: string; + mode?: string; resolveImport?: (specifier: string) => string; } -export function transpileJavaScript(node: JavaScriptNode, {id, path, resolveImport}: TranspileOptions): string { +export function transpileJavaScript(node: JavaScriptNode, {id, path, mode, resolveImport}: TranspileOptions): string { let async = node.async; const inputs = Array.from(new Set(node.references.map((r) => r.name))); const outputs = Array.from(new Set(node.declarations?.map((r) => r.name))); @@ -35,7 +36,7 @@ export function transpileJavaScript(node: JavaScriptNode, {id, path, resolveImpo output.insertLeft(0, `, body: ${async ? "async " : ""}(${inputs}) => {\n`); if (outputs.length) output.insertLeft(0, `, outputs: ${JSON.stringify(outputs)}`); if (inputs.length) output.insertLeft(0, `, inputs: ${JSON.stringify(inputs)}`); - if (node.inline) output.insertLeft(0, ", inline: true"); + if (mode && mode !== "block") output.insertLeft(0, `, mode: ${JSON.stringify(mode)}`); output.insertLeft(0, `define({id: ${JSON.stringify(id)}`); if (outputs.length) output.insertRight(node.input.length, `\nreturn {${outputs}};`); output.insertRight(node.input.length, "\n}});\n"); diff --git a/src/markdown.ts b/src/markdown.ts index a4819ea38..ca182fccb 100644 --- a/src/markdown.ts +++ b/src/markdown.ts @@ -1,5 +1,6 @@ /* eslint-disable import/no-named-as-default-member */ import {createHash} from "node:crypto"; +import {transformSync} from "esbuild"; import he from "he"; import MarkdownIt from "markdown-it"; import type {Token} from "markdown-it"; @@ -25,6 +26,7 @@ import {red} from "./tty.js"; export interface MarkdownCode { id: string; node: JavaScriptNode; + mode: "inline" | "block" | "jsx"; } export interface MarkdownPage { @@ -57,9 +59,19 @@ function isFalse(attribute: string | undefined): boolean { return attribute?.toLowerCase() === "false"; } +function transformJsx(content: string): string { + try { + return transformSync(content, {loader: "jsx", jsx: "automatic", jsxImportSource: "npm:react"}).code; + } catch (error: any) { + throw new SyntaxError(error.message); + } +} + function getLiveSource(content: string, tag: string, attributes: Record): string | undefined { return tag === "js" ? content + : tag === "jsx" + ? transformJsx(content) : tag === "tex" ? transpileTag(content, "tex.block", true) : tag === "html" @@ -107,7 +119,7 @@ function makeFenceRenderer(baseRenderer: RenderRule): RenderRule { const id = uniqueCodeId(context, source); // TODO const sourceLine = context.startLine + context.currentLine; const node = parseJavaScript(source, {path}); - context.code.push({id, node}); + context.code.push({id, node, mode: tag === "jsx" ? "jsx" : "block"}); html += `
${ node.expression ? "" : "" }
\n`; @@ -173,7 +185,7 @@ function makePlaceholderRenderer(): RenderRule { try { // TODO sourceLine: context.startLine + context.currentLine const node = parseJavaScript(token.content, {path, inline: true}); - context.code.push({id, node}); + context.code.push({id, node, mode: "inline"}); return ``; } catch (error) { if (!(error instanceof SyntaxError)) throw error; diff --git a/src/preview.ts b/src/preview.ts index 092454bed..336834fd0 100644 --- a/src/preview.ts +++ b/src/preview.ts @@ -21,6 +21,7 @@ import {HttpError, isEnoent, isHttpError, isSystemError} from "./error.js"; import {getClientPath} from "./files.js"; import type {FileWatchers} from "./fileWatchers.js"; import {isComment, isElement, isText, parseHtml, rewriteHtml} from "./html.js"; +import {readJavaScript} from "./javascript/module.js"; import {transpileJavaScript, transpileModule} from "./javascript/transpile.js"; import {parseMarkdown} from "./markdown.js"; import type {MarkdownCode, MarkdownPage} from "./markdown.js"; @@ -142,7 +143,7 @@ export class PreviewServer { end(req, res, await bundleStyles({path: filepath}), "text/css"); return; } else if (pathname.endsWith(".js")) { - const input = await readFile(join(root, path), "utf-8"); + const input = await readJavaScript(join(root, path)); const output = await transpileModule(input, {root, path}); end(req, res, output, "text/javascript"); return; @@ -188,19 +189,14 @@ export class PreviewServer { // If this path ends with a slash, then add an implicit /index to the // end of the path. Otherwise, remove the .html extension (we use clean // paths as the internal canonical representation; see normalizePage). - let path = join(root, pathname); - if (pathname.endsWith("/")) { - pathname = join(pathname, "index"); - path = join(path, "index"); - } else { - pathname = pathname.replace(/\.html$/, ""); - } + if (pathname.endsWith("/")) pathname = join(pathname, "index"); + else pathname = pathname.replace(/\.html$/, ""); // Lastly, serve the corresponding Markdown file, if it exists. // Anything else should 404; static files should be matched above. try { - const options = {path: pathname, ...config, preview: true}; - const source = await readFile(join(dirname(path), basename(path, ".html") + ".md"), "utf8"); + const options = {...config, path: pathname, preview: true}; + const source = await readFile(join(root, pathname + ".md"), "utf8"); const parse = parseMarkdown(source, options); const html = await renderPage(parse, options); end(req, res, html, "text/html"); @@ -218,7 +214,7 @@ export class PreviewServer { } if (req.method === "GET" && res.statusCode === 404) { try { - const options = {path: "/404", ...config, preview: true}; + const options = {...config, path: "/404", preview: true}; const source = await readFile(join(root, "404.md"), "utf8"); const parse = parseMarkdown(source, options); const html = await renderPage(parse, options); @@ -459,10 +455,10 @@ function getCode({code}: MarkdownPage, resolvers: Resolvers): Map { diff --git a/src/render.ts b/src/render.ts index 8e9e0b129..6367cd811 100644 --- a/src/render.ts +++ b/src/render.ts @@ -73,7 +73,7 @@ import ${preview || page.code.length ? `{${preview ? "open, " : ""}define} from : "" }${data?.sql ? `\n${registerTables(data.sql, options)}` : ""} ${preview ? `\nopen({hash: ${JSON.stringify(resolvers.hash)}, eval: (body) => eval(body)});\n` : ""}${page.code - .map(({node, id}) => `\n${transpileJavaScript(node, {id, path, resolveImport})}`) + .map(({node, id, mode}) => `\n${transpileJavaScript(node, {id, path, mode, resolveImport})}`) .join("")}`)} ${sidebar ? html`\n${await renderSidebar(options, resolvers.resolveLink)}` : ""}${ toc.show ? html`\n${renderToc(findHeaders(page), toc.label)}` : "" diff --git a/src/resolvers.ts b/src/resolvers.ts index 9ca7abd7c..31dd09d50 100644 --- a/src/resolvers.ts +++ b/src/resolvers.ts @@ -170,6 +170,12 @@ export async function getResolvers( globalImports.add(i); } + // Add React for JSX blocks. + if (page.code.some((c) => c.mode === "jsx")) { + staticImports.add("npm:react-dom/client"); + globalImports.add("npm:react-dom/client"); + } + // Add transitive imports for built-in libraries. for (const i of getImplicitDependencies(staticImports)) { staticImports.add(i); diff --git a/test/input/jsx.md b/test/input/jsx.md new file mode 100644 index 000000000..f44c03183 --- /dev/null +++ b/test/input/jsx.md @@ -0,0 +1,9 @@ +```jsx +function Greeting({subject}) { + return
Hello, {subject}!
+} +``` + +```jsx +display(); +``` diff --git a/test/mocks/jsdelivr.ts b/test/mocks/jsdelivr.ts index 09e836d65..26835db76 100644 --- a/test/mocks/jsdelivr.ts +++ b/test/mocks/jsdelivr.ts @@ -21,6 +21,8 @@ const packages: [name: string, {version: string; dependencies?: Record B [style=dashed]\n A -> C\n A -> D [penwidth=5, arrowhead=none]\n\n}`" - } + }, + "mode": "block" } ] } \ No newline at end of file diff --git a/test/output/double-quote-expression.md.json b/test/output/double-quote-expression.md.json index e1a95a2a3..a128cea86 100644 --- a/test/output/double-quote-expression.md.json +++ b/test/output/double-quote-expression.md.json @@ -19,9 +19,9 @@ "imports": [], "expression": true, "async": false, - "inline": true, "input": "\"}'\"" - } + }, + "mode": "inline" } ] } \ No newline at end of file diff --git a/test/output/dynamic-import-noent.js.json b/test/output/dynamic-import-noent.js.json index 5598a4384..a63f87a4b 100644 --- a/test/output/dynamic-import-noent.js.json +++ b/test/output/dynamic-import-noent.js.json @@ -61,6 +61,5 @@ } ], "expression": false, - "async": true, - "inline": false + "async": true } \ No newline at end of file diff --git a/test/output/embedded-expression.md.json b/test/output/embedded-expression.md.json index 66b79d2fc..cd8ebe9fa 100644 --- a/test/output/embedded-expression.md.json +++ b/test/output/embedded-expression.md.json @@ -32,9 +32,9 @@ "imports": [], "expression": true, "async": false, - "inline": true, "input": "1 + 2" - } + }, + "mode": "inline" } ] } \ No newline at end of file diff --git a/test/output/empty.js.json b/test/output/empty.js.json index 1beeabf95..95997a867 100644 --- a/test/output/empty.js.json +++ b/test/output/empty.js.json @@ -11,6 +11,5 @@ "files": [], "imports": [], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/escaped-expression.md.json b/test/output/escaped-expression.md.json index dfd4a6708..c1cc6ae7b 100644 --- a/test/output/escaped-expression.md.json +++ b/test/output/escaped-expression.md.json @@ -19,9 +19,9 @@ "imports": [], "expression": true, "async": false, - "inline": true, "input": "1" - } + }, + "mode": "inline" }, { "id": "4e074085", @@ -39,9 +39,9 @@ "imports": [], "expression": true, "async": false, - "inline": true, "input": "3" - } + }, + "mode": "inline" }, { "id": "ef2d127d", @@ -59,9 +59,9 @@ "imports": [], "expression": true, "async": false, - "inline": true, "input": "5" - } + }, + "mode": "inline" }, { "id": "4523540f", @@ -79,9 +79,9 @@ "imports": [], "expression": true, "async": false, - "inline": true, "input": "17" - } + }, + "mode": "inline" }, { "id": "6f4b6612", @@ -99,9 +99,9 @@ "imports": [], "expression": true, "async": false, - "inline": true, "input": "21" - } + }, + "mode": "inline" }, { "id": "535fa30d", @@ -119,9 +119,9 @@ "imports": [], "expression": true, "async": false, - "inline": true, "input": "23" - } + }, + "mode": "inline" }, { "id": "b7a56873", @@ -139,9 +139,9 @@ "imports": [], "expression": true, "async": false, - "inline": true, "input": "25" - } + }, + "mode": "inline" }, { "id": "35135aaa", @@ -159,9 +159,9 @@ "imports": [], "expression": true, "async": false, - "inline": true, "input": "29" - } + }, + "mode": "inline" } ] } \ No newline at end of file diff --git a/test/output/expression-leading-comment.js.json b/test/output/expression-leading-comment.js.json index feb8d606a..817a6b2d9 100644 --- a/test/output/expression-leading-comment.js.json +++ b/test/output/expression-leading-comment.js.json @@ -11,6 +11,5 @@ "files": [], "imports": [], "expression": true, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/expression-statement.js.json b/test/output/expression-statement.js.json index 08e4cf818..d3183c041 100644 --- a/test/output/expression-statement.js.json +++ b/test/output/expression-statement.js.json @@ -37,6 +37,5 @@ "files": [], "imports": [], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/expression-trailing-comment.js.json b/test/output/expression-trailing-comment.js.json index 1c58ff83b..a39cda056 100644 --- a/test/output/expression-trailing-comment.js.json +++ b/test/output/expression-trailing-comment.js.json @@ -11,6 +11,5 @@ "files": [], "imports": [], "expression": true, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/expression.js.json b/test/output/expression.js.json index 3349da5ae..aedeb2dd4 100644 --- a/test/output/expression.js.json +++ b/test/output/expression.js.json @@ -24,6 +24,5 @@ "files": [], "imports": [], "expression": true, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/fenced-code-options.md.json b/test/output/fenced-code-options.md.json index b8a908216..ba1497bb5 100644 --- a/test/output/fenced-code-options.md.json +++ b/test/output/fenced-code-options.md.json @@ -85,9 +85,9 @@ "imports": [], "expression": false, "async": false, - "inline": false, "input": "function add(a, b) {\n return a + b;\n}\n" - } + }, + "mode": "block" }, { "id": "4bf815ab", @@ -147,9 +147,9 @@ "imports": [], "expression": false, "async": false, - "inline": false, "input": "function bareJs() {\n return 1;\n}\n" - } + }, + "mode": "block" }, { "id": "d41a5631", @@ -209,9 +209,9 @@ "imports": [], "expression": false, "async": false, - "inline": false, "input": "function langOutside() {\n return 1;\n}\n" - } + }, + "mode": "block" }, { "id": "2f4eff36", @@ -271,9 +271,9 @@ "imports": [], "expression": false, "async": false, - "inline": false, "input": "function langAndAttributes() {\n return 1;\n}\n" - } + }, + "mode": "block" } ] } \ No newline at end of file diff --git a/test/output/fenced-code.md.json b/test/output/fenced-code.md.json index 6ac043d03..39b32715a 100644 --- a/test/output/fenced-code.md.json +++ b/test/output/fenced-code.md.json @@ -85,9 +85,9 @@ "imports": [], "expression": false, "async": false, - "inline": false, "input": "function add(a, b) {\n return a + b;\n}\n" - } + }, + "mode": "block" } ] } \ No newline at end of file diff --git a/test/output/fetch-parent-dir.md.json b/test/output/fetch-parent-dir.md.json index ed3d7424b..7d93502a1 100644 --- a/test/output/fetch-parent-dir.md.json +++ b/test/output/fetch-parent-dir.md.json @@ -120,9 +120,9 @@ "imports": [], "expression": false, "async": false, - "inline": false, "input": "const fail3 = FileAttachment(\"./NOENT.md\").text()\n" - } + }, + "mode": "block" }, { "id": "d306f60f", @@ -241,9 +241,9 @@ "imports": [], "expression": false, "async": false, - "inline": false, "input": "const ok1 = FileAttachment(\"./tex-expression.md\").text()\n" - } + }, + "mode": "block" } ] } \ No newline at end of file diff --git a/test/output/for-await-of.js.json b/test/output/for-await-of.js.json index 2fa4d84e5..50496aa4f 100644 --- a/test/output/for-await-of.js.json +++ b/test/output/for-await-of.js.json @@ -128,6 +128,5 @@ "files": [], "imports": [], "expression": false, - "async": true, - "inline": false + "async": true } \ No newline at end of file diff --git a/test/output/for-of-array-pattern.js.json b/test/output/for-of-array-pattern.js.json index 67a36c0de..d4c78c26b 100644 --- a/test/output/for-of-array-pattern.js.json +++ b/test/output/for-of-array-pattern.js.json @@ -115,6 +115,5 @@ "files": [], "imports": [], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/for-of-object-pattern.js.json b/test/output/for-of-object-pattern.js.json index d46abcbe4..30f08e2d0 100644 --- a/test/output/for-of-object-pattern.js.json +++ b/test/output/for-of-object-pattern.js.json @@ -175,6 +175,5 @@ "files": [], "imports": [], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/function.js.json b/test/output/function.js.json index 2b9729c06..9d445ef83 100644 --- a/test/output/function.js.json +++ b/test/output/function.js.json @@ -77,6 +77,5 @@ "files": [], "imports": [], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/functions.js.json b/test/output/functions.js.json index cd061c492..50d924946 100644 --- a/test/output/functions.js.json +++ b/test/output/functions.js.json @@ -141,6 +141,5 @@ "files": [], "imports": [], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/generator-function.js.json b/test/output/generator-function.js.json index 154c7d577..46aedc91e 100644 --- a/test/output/generator-function.js.json +++ b/test/output/generator-function.js.json @@ -59,6 +59,5 @@ "files": [], "imports": [], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/generator.js.json b/test/output/generator.js.json index fed2c6815..bfcb734d6 100644 --- a/test/output/generator.js.json +++ b/test/output/generator.js.json @@ -149,6 +149,5 @@ "files": [], "imports": [], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/heading-expression.md.json b/test/output/heading-expression.md.json index 0734646fb..1fb8ce160 100644 --- a/test/output/heading-expression.md.json +++ b/test/output/heading-expression.md.json @@ -32,9 +32,9 @@ "imports": [], "expression": true, "async": false, - "inline": true, "input": "1 + 2" - } + }, + "mode": "inline" } ] } \ No newline at end of file diff --git a/test/output/identifier.js.json b/test/output/identifier.js.json index 4296f6de6..7be3a1779 100644 --- a/test/output/identifier.js.json +++ b/test/output/identifier.js.json @@ -17,6 +17,5 @@ "files": [], "imports": [], "expression": true, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/imports/alias-import.js.json b/test/output/imports/alias-import.js.json index 71c219004..f5a2f77e7 100644 --- a/test/output/imports/alias-import.js.json +++ b/test/output/imports/alias-import.js.json @@ -88,6 +88,5 @@ } ], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/imports/dynamic-import.js.json b/test/output/imports/dynamic-import.js.json index 6b261aae2..bc83e0f25 100644 --- a/test/output/imports/dynamic-import.js.json +++ b/test/output/imports/dynamic-import.js.json @@ -61,6 +61,5 @@ } ], "expression": false, - "async": true, - "inline": false + "async": true } \ No newline at end of file diff --git a/test/output/imports/dynamic-npm-import.js.json b/test/output/imports/dynamic-npm-import.js.json index 165c23a9f..e02444f5d 100644 --- a/test/output/imports/dynamic-npm-import.js.json +++ b/test/output/imports/dynamic-npm-import.js.json @@ -101,6 +101,5 @@ } ], "expression": false, - "async": true, - "inline": false + "async": true } \ No newline at end of file diff --git a/test/output/imports/empty-import.js.json b/test/output/imports/empty-import.js.json index c5d033601..f4c3ca1ae 100644 --- a/test/output/imports/empty-import.js.json +++ b/test/output/imports/empty-import.js.json @@ -31,6 +31,5 @@ } ], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/imports/local-fetch-from-import.js.json b/test/output/imports/local-fetch-from-import.js.json index d531a169e..c94805a7f 100644 --- a/test/output/imports/local-fetch-from-import.js.json +++ b/test/output/imports/local-fetch-from-import.js.json @@ -88,6 +88,5 @@ } ], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/imports/namespace-import.js.json b/test/output/imports/namespace-import.js.json index 3e1334384..4af92d263 100644 --- a/test/output/imports/namespace-import.js.json +++ b/test/output/imports/namespace-import.js.json @@ -82,6 +82,5 @@ } ], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/imports/npm-meta-resolve-import.js.json b/test/output/imports/npm-meta-resolve-import.js.json index b5ac6ac47..b49c8e045 100644 --- a/test/output/imports/npm-meta-resolve-import.js.json +++ b/test/output/imports/npm-meta-resolve-import.js.json @@ -89,6 +89,5 @@ } ], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/imports/static-all-import.js.json b/test/output/imports/static-all-import.js.json index c92b853ea..3c8269044 100644 --- a/test/output/imports/static-all-import.js.json +++ b/test/output/imports/static-all-import.js.json @@ -135,6 +135,5 @@ } ], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/imports/static-hoisted-import.js.json b/test/output/imports/static-hoisted-import.js.json index 5968a480d..bd46876d7 100644 --- a/test/output/imports/static-hoisted-import.js.json +++ b/test/output/imports/static-hoisted-import.js.json @@ -68,6 +68,5 @@ } ], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/imports/static-import.js.json b/test/output/imports/static-import.js.json index f81ea31d9..8b61c5dcc 100644 --- a/test/output/imports/static-import.js.json +++ b/test/output/imports/static-import.js.json @@ -88,6 +88,5 @@ } ], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/imports/static-npm-import.js.json b/test/output/imports/static-npm-import.js.json index 72865604e..e1b18817e 100644 --- a/test/output/imports/static-npm-import.js.json +++ b/test/output/imports/static-npm-import.js.json @@ -68,6 +68,5 @@ } ], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/imports/transitive-dynamic-import.js.json b/test/output/imports/transitive-dynamic-import.js.json index 0377ded93..0b81bedbf 100644 --- a/test/output/imports/transitive-dynamic-import.js.json +++ b/test/output/imports/transitive-dynamic-import.js.json @@ -61,6 +61,5 @@ } ], "expression": false, - "async": true, - "inline": false + "async": true } \ No newline at end of file diff --git a/test/output/imports/transitive-static-import.js.json b/test/output/imports/transitive-static-import.js.json index 92cce33e2..8260b0f62 100644 --- a/test/output/imports/transitive-static-import.js.json +++ b/test/output/imports/transitive-static-import.js.json @@ -56,6 +56,5 @@ } ], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/indented-inline.md.json b/test/output/indented-inline.md.json index 7da6c88ed..e17517e59 100644 --- a/test/output/indented-inline.md.json +++ b/test/output/indented-inline.md.json @@ -19,9 +19,9 @@ "imports": [], "expression": true, "async": false, - "inline": true, "input": "\"hello\"" - } + }, + "mode": "inline" } ] } \ No newline at end of file diff --git a/test/output/inline-expression.md.json b/test/output/inline-expression.md.json index 0734646fb..1fb8ce160 100644 --- a/test/output/inline-expression.md.json +++ b/test/output/inline-expression.md.json @@ -32,9 +32,9 @@ "imports": [], "expression": true, "async": false, - "inline": true, "input": "1 + 2" - } + }, + "mode": "inline" } ] } \ No newline at end of file diff --git a/test/output/inline-following-backticks.md.json b/test/output/inline-following-backticks.md.json index c315bc199..20ae2b276 100644 --- a/test/output/inline-following-backticks.md.json +++ b/test/output/inline-following-backticks.md.json @@ -30,9 +30,9 @@ "imports": [], "expression": true, "async": false, - "inline": true, "input": "`1`" - } + }, + "mode": "inline" } ] } \ No newline at end of file diff --git a/test/output/inline-within-lists.md.json b/test/output/inline-within-lists.md.json index 0734646fb..1fb8ce160 100644 --- a/test/output/inline-within-lists.md.json +++ b/test/output/inline-within-lists.md.json @@ -32,9 +32,9 @@ "imports": [], "expression": true, "async": false, - "inline": true, "input": "1 + 2" - } + }, + "mode": "inline" } ] } \ No newline at end of file diff --git a/test/output/input.js.json b/test/output/input.js.json index a5d5f6361..92a53db56 100644 --- a/test/output/input.js.json +++ b/test/output/input.js.json @@ -121,6 +121,5 @@ "files": [], "imports": [], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/jsx.html b/test/output/jsx.html new file mode 100644 index 000000000..5f7ad0744 --- /dev/null +++ b/test/output/jsx.html @@ -0,0 +1,2 @@ +
+
diff --git a/test/output/jsx.md.json b/test/output/jsx.md.json new file mode 100644 index 000000000..e8ab80d09 --- /dev/null +++ b/test/output/jsx.md.json @@ -0,0 +1,416 @@ +{ + "data": {}, + "title": null, + "style": null, + "code": [ + { + "id": "e9f5e6dc", + "node": { + "body": { + "type": "Program", + "start": 0, + "end": 221, + "body": [ + { + "type": "ImportDeclaration", + "start": 0, + "end": 50, + "specifiers": [ + { + "type": "ImportSpecifier", + "start": 9, + "end": 12, + "imported": { + "type": "Identifier", + "start": 9, + "end": 12, + "name": "jsx" + }, + "local": { + "type": "Identifier", + "start": 9, + "end": 12, + "name": "jsx" + } + }, + { + "type": "ImportSpecifier", + "start": 14, + "end": 18, + "imported": { + "type": "Identifier", + "start": 14, + "end": 18, + "name": "jsxs" + }, + "local": { + "type": "Identifier", + "start": 14, + "end": 18, + "name": "jsxs" + } + } + ], + "source": { + "type": "Literal", + "start": 26, + "end": 49, + "value": "npm:react/jsx-runtime", + "raw": "\"npm:react/jsx-runtime\"" + } + }, + { + "type": "FunctionDeclaration", + "start": 51, + "end": 220, + "id": { + "type": "Identifier", + "start": 60, + "end": 68, + "name": "Greeting" + }, + "expression": false, + "generator": false, + "async": false, + "params": [ + { + "type": "ObjectPattern", + "start": 69, + "end": 80, + "properties": [ + { + "type": "Property", + "start": 71, + "end": 78, + "method": false, + "shorthand": true, + "computed": false, + "key": { + "type": "Identifier", + "start": 71, + "end": 78, + "name": "subject" + }, + "kind": "init", + "value": { + "type": "Identifier", + "start": 71, + "end": 78, + "name": "subject" + } + } + ] + } + ], + "body": { + "type": "BlockStatement", + "start": 82, + "end": 220, + "body": [ + { + "type": "ReturnStatement", + "start": 86, + "end": 218, + "argument": { + "type": "CallExpression", + "start": 109, + "end": 217, + "callee": { + "type": "Identifier", + "start": 109, + "end": 113, + "name": "jsxs" + }, + "arguments": [ + { + "type": "Literal", + "start": 114, + "end": 119, + "value": "div", + "raw": "\"div\"" + }, + { + "type": "ObjectExpression", + "start": 121, + "end": 216, + "properties": [ + { + "type": "Property", + "start": 123, + "end": 214, + "method": false, + "shorthand": false, + "computed": false, + "key": { + "type": "Identifier", + "start": 123, + "end": 131, + "name": "children" + }, + "value": { + "type": "ArrayExpression", + "start": 133, + "end": 214, + "elements": [ + { + "type": "Literal", + "start": 139, + "end": 148, + "value": "Hello, ", + "raw": "\"Hello, \"" + }, + { + "type": "CallExpression", + "start": 170, + "end": 201, + "callee": { + "type": "Identifier", + "start": 170, + "end": 173, + "name": "jsx" + }, + "arguments": [ + { + "type": "Literal", + "start": 174, + "end": 177, + "value": "b", + "raw": "\"b\"" + }, + { + "type": "ObjectExpression", + "start": 179, + "end": 200, + "properties": [ + { + "type": "Property", + "start": 181, + "end": 198, + "method": false, + "shorthand": false, + "computed": false, + "key": { + "type": "Identifier", + "start": 181, + "end": 189, + "name": "children" + }, + "value": { + "type": "Identifier", + "start": 191, + "end": 198, + "name": "subject" + }, + "kind": "init" + } + ] + } + ], + "optional": false + }, + { + "type": "Literal", + "start": 207, + "end": 210, + "value": "!", + "raw": "\"!\"" + } + ] + }, + "kind": "init" + } + ] + } + ], + "optional": false + } + } + ] + } + } + ], + "sourceType": "module" + }, + "declarations": [ + { + "type": "Identifier", + "start": 9, + "end": 12, + "name": "jsx" + }, + { + "type": "Identifier", + "start": 14, + "end": 18, + "name": "jsxs" + }, + { + "type": "Identifier", + "start": 60, + "end": 68, + "name": "Greeting" + } + ], + "references": [], + "files": [], + "imports": [ + { + "name": "npm:react/jsx-runtime", + "type": "global", + "method": "static" + } + ], + "expression": false, + "async": false, + "input": "import { jsx, jsxs } from \"npm:react/jsx-runtime\";\nfunction Greeting({ subject }) {\n return /* @__PURE__ */ jsxs(\"div\", { children: [\n \"Hello, \",\n /* @__PURE__ */ jsx(\"b\", { children: subject }),\n \"!\"\n ] });\n}\n" + }, + "mode": "jsx" + }, + { + "id": "2fb46873", + "node": { + "body": { + "type": "Program", + "start": 0, + "end": 105, + "body": [ + { + "type": "ImportDeclaration", + "start": 0, + "end": 44, + "specifiers": [ + { + "type": "ImportSpecifier", + "start": 9, + "end": 12, + "imported": { + "type": "Identifier", + "start": 9, + "end": 12, + "name": "jsx" + }, + "local": { + "type": "Identifier", + "start": 9, + "end": 12, + "name": "jsx" + } + } + ], + "source": { + "type": "Literal", + "start": 20, + "end": 43, + "value": "npm:react/jsx-runtime", + "raw": "\"npm:react/jsx-runtime\"" + } + }, + { + "type": "ExpressionStatement", + "start": 45, + "end": 104, + "expression": { + "type": "CallExpression", + "start": 45, + "end": 103, + "callee": { + "type": "Identifier", + "start": 45, + "end": 52, + "name": "display" + }, + "arguments": [ + { + "type": "CallExpression", + "start": 69, + "end": 102, + "callee": { + "type": "Identifier", + "start": 69, + "end": 72, + "name": "jsx" + }, + "arguments": [ + { + "type": "Identifier", + "start": 73, + "end": 81, + "name": "Greeting" + }, + { + "type": "ObjectExpression", + "start": 83, + "end": 101, + "properties": [ + { + "type": "Property", + "start": 85, + "end": 99, + "method": false, + "shorthand": false, + "computed": false, + "key": { + "type": "Identifier", + "start": 85, + "end": 92, + "name": "subject" + }, + "value": { + "type": "Literal", + "start": 94, + "end": 99, + "value": "JSX", + "raw": "\"JSX\"" + }, + "kind": "init" + } + ] + } + ], + "optional": false + } + ], + "optional": false + } + } + ], + "sourceType": "module" + }, + "declarations": [ + { + "type": "Identifier", + "start": 9, + "end": 12, + "name": "jsx" + } + ], + "references": [ + { + "type": "Identifier", + "start": 45, + "end": 52, + "name": "display" + }, + { + "type": "Identifier", + "start": 73, + "end": 81, + "name": "Greeting" + } + ], + "files": [], + "imports": [ + { + "name": "npm:react/jsx-runtime", + "type": "global", + "method": "static" + } + ], + "expression": false, + "async": false, + "input": "import { jsx } from \"npm:react/jsx-runtime\";\ndisplay(/* @__PURE__ */ jsx(Greeting, { subject: \"JSX\" }));\n" + }, + "mode": "jsx" + } + ] +} \ No newline at end of file diff --git a/test/output/legal-arguments.js.json b/test/output/legal-arguments.js.json index de52efd20..b86f76e80 100644 --- a/test/output/legal-arguments.js.json +++ b/test/output/legal-arguments.js.json @@ -65,6 +65,5 @@ "files": [], "imports": [], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/let-assign.js.json b/test/output/let-assign.js.json index 0861b11a2..77efc4692 100644 --- a/test/output/let-assign.js.json +++ b/test/output/let-assign.js.json @@ -87,6 +87,5 @@ "files": [], "imports": [], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/let-increment.js.json b/test/output/let-increment.js.json index 87116b81a..05985353d 100644 --- a/test/output/let-increment.js.json +++ b/test/output/let-increment.js.json @@ -81,6 +81,5 @@ "files": [], "imports": [], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/let.js.json b/test/output/let.js.json index 367a23380..0eb51b9fb 100644 --- a/test/output/let.js.json +++ b/test/output/let.js.json @@ -45,6 +45,5 @@ "files": [], "imports": [], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/lets.js.json b/test/output/lets.js.json index ec452856a..bc83c3368 100644 --- a/test/output/lets.js.json +++ b/test/output/lets.js.json @@ -69,6 +69,5 @@ "files": [], "imports": [], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/local-const.js.json b/test/output/local-const.js.json index ff5938ce6..db269c203 100644 --- a/test/output/local-const.js.json +++ b/test/output/local-const.js.json @@ -45,6 +45,5 @@ "files": [], "imports": [], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/local-fetch.md.json b/test/output/local-fetch.md.json index 14217c8d7..2afe8aa03 100644 --- a/test/output/local-fetch.md.json +++ b/test/output/local-fetch.md.json @@ -65,9 +65,9 @@ "imports": [], "expression": true, "async": false, - "inline": false, "input": "FileAttachment(\"./local-fetch.md\")\n" - } + }, + "mode": "block" } ] } \ No newline at end of file diff --git a/test/output/logical-assignment.js.json b/test/output/logical-assignment.js.json index ef65879de..23e96dba1 100644 --- a/test/output/logical-assignment.js.json +++ b/test/output/logical-assignment.js.json @@ -100,6 +100,5 @@ "files": [], "imports": [], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/mermaid.md.json b/test/output/mermaid.md.json index b01e6649c..fbc4ca5c8 100644 --- a/test/output/mermaid.md.json +++ b/test/output/mermaid.md.json @@ -53,9 +53,9 @@ "imports": [], "expression": true, "async": true, - "inline": false, "input": "await mermaid`graph TD;\n A-->B;\n A-->C;\n B-->D;\n C-->D;`" - } + }, + "mode": "block" } ] } \ No newline at end of file diff --git a/test/output/nullish-coalescing.js.json b/test/output/nullish-coalescing.js.json index ed4341517..e4ef98328 100644 --- a/test/output/nullish-coalescing.js.json +++ b/test/output/nullish-coalescing.js.json @@ -58,6 +58,5 @@ "files": [], "imports": [], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/object-literal.js.json b/test/output/object-literal.js.json index 1c3a9cdac..2d58610be 100644 --- a/test/output/object-literal.js.json +++ b/test/output/object-literal.js.json @@ -33,6 +33,5 @@ "files": [], "imports": [], "expression": true, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/object-pattern-rest.js.json b/test/output/object-pattern-rest.js.json index 682fb34c4..78003bf24 100644 --- a/test/output/object-pattern-rest.js.json +++ b/test/output/object-pattern-rest.js.json @@ -177,6 +177,5 @@ "files": [], "imports": [], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/object-pattern.js.json b/test/output/object-pattern.js.json index b4b065b17..5bf74cd75 100644 --- a/test/output/object-pattern.js.json +++ b/test/output/object-pattern.js.json @@ -138,6 +138,5 @@ "files": [], "imports": [], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/optional-chaining.js.json b/test/output/optional-chaining.js.json index 9d76495be..d75ee9416 100644 --- a/test/output/optional-chaining.js.json +++ b/test/output/optional-chaining.js.json @@ -82,6 +82,5 @@ "files": [], "imports": [], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/semicolon.js.json b/test/output/semicolon.js.json index 7034f0fa3..6fd1032ee 100644 --- a/test/output/semicolon.js.json +++ b/test/output/semicolon.js.json @@ -17,6 +17,5 @@ "files": [], "imports": [], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/semicolons.js.json b/test/output/semicolons.js.json index 27c905d62..1e8261778 100644 --- a/test/output/semicolons.js.json +++ b/test/output/semicolons.js.json @@ -22,6 +22,5 @@ "files": [], "imports": [], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/setext.md.json b/test/output/setext.md.json index 0734646fb..1fb8ce160 100644 --- a/test/output/setext.md.json +++ b/test/output/setext.md.json @@ -32,9 +32,9 @@ "imports": [], "expression": true, "async": false, - "inline": true, "input": "1 + 2" - } + }, + "mode": "inline" } ] } \ No newline at end of file diff --git a/test/output/single-quote-expression.md.json b/test/output/single-quote-expression.md.json index 3296daaae..0a0726ccf 100644 --- a/test/output/single-quote-expression.md.json +++ b/test/output/single-quote-expression.md.json @@ -19,9 +19,9 @@ "imports": [], "expression": true, "async": false, - "inline": true, "input": "'}\"'" - } + }, + "mode": "inline" } ] } \ No newline at end of file diff --git a/test/output/static-import-noent.js.json b/test/output/static-import-noent.js.json index e6889660b..5049df28b 100644 --- a/test/output/static-import-noent.js.json +++ b/test/output/static-import-noent.js.json @@ -88,6 +88,5 @@ } ], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/svg-placeholder.md.json b/test/output/svg-placeholder.md.json index 7da6c88ed..e17517e59 100644 --- a/test/output/svg-placeholder.md.json +++ b/test/output/svg-placeholder.md.json @@ -19,9 +19,9 @@ "imports": [], "expression": true, "async": false, - "inline": true, "input": "\"hello\"" - } + }, + "mode": "inline" } ] } \ No newline at end of file diff --git a/test/output/template-expression.md.json b/test/output/template-expression.md.json index fffdd181b..1c1980b1b 100644 --- a/test/output/template-expression.md.json +++ b/test/output/template-expression.md.json @@ -30,9 +30,9 @@ "imports": [], "expression": true, "async": false, - "inline": true, "input": "`}'\"`" - } + }, + "mode": "inline" } ] } \ No newline at end of file diff --git a/test/output/template-file-attachment.js.json b/test/output/template-file-attachment.js.json index eba3042c9..53b1ac026 100644 --- a/test/output/template-file-attachment.js.json +++ b/test/output/template-file-attachment.js.json @@ -92,6 +92,5 @@ ], "imports": [], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/tex-block.md.json b/test/output/tex-block.md.json index c46459a02..e6ae7abf6 100644 --- a/test/output/tex-block.md.json +++ b/test/output/tex-block.md.json @@ -61,9 +61,9 @@ "imports": [], "expression": true, "async": false, - "inline": false, "input": "tex.block`\\int_0^1 (x + y)dx`" - } + }, + "mode": "block" } ] } \ No newline at end of file diff --git a/test/output/tex-expression.md.json b/test/output/tex-expression.md.json index d4c07ef28..73ef2a851 100644 --- a/test/output/tex-expression.md.json +++ b/test/output/tex-expression.md.json @@ -48,9 +48,9 @@ "imports": [], "expression": true, "async": false, - "inline": true, "input": "tex`\\KaTeX`" - } + }, + "mode": "inline" }, { "id": "828eccc1", @@ -97,9 +97,9 @@ "imports": [], "expression": true, "async": false, - "inline": true, "input": "tex`E = mc^2`" - } + }, + "mode": "inline" } ] } \ No newline at end of file diff --git a/test/output/this.js.json b/test/output/this.js.json index c40a5eb48..db89f6b21 100644 --- a/test/output/this.js.json +++ b/test/output/this.js.json @@ -9,6 +9,5 @@ "files": [], "imports": [], "expression": true, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/triple-backtick-inline.md.json b/test/output/triple-backtick-inline.md.json index 0734646fb..1fb8ce160 100644 --- a/test/output/triple-backtick-inline.md.json +++ b/test/output/triple-backtick-inline.md.json @@ -32,9 +32,9 @@ "imports": [], "expression": true, "async": false, - "inline": true, "input": "1 + 2" - } + }, + "mode": "inline" } ] } \ No newline at end of file diff --git a/test/output/try-catch.js.json b/test/output/try-catch.js.json index 3c631e7e4..9341b957f 100644 --- a/test/output/try-catch.js.json +++ b/test/output/try-catch.js.json @@ -162,6 +162,5 @@ "files": [], "imports": [], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/var-undefined.js.json b/test/output/var-undefined.js.json index abdde48e1..70e36d344 100644 --- a/test/output/var-undefined.js.json +++ b/test/output/var-undefined.js.json @@ -45,6 +45,5 @@ "files": [], "imports": [], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file diff --git a/test/output/var.js.json b/test/output/var.js.json index 387a9a0af..aa7d21b45 100644 --- a/test/output/var.js.json +++ b/test/output/var.js.json @@ -45,6 +45,5 @@ "files": [], "imports": [], "expression": false, - "async": false, - "inline": false + "async": false } \ No newline at end of file