From 3ee1560ea9f81ed73cf8af187a94063470bad2d3 Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Tue, 17 Jan 2023 14:40:39 +0100 Subject: [PATCH 01/13] Update dev-dependencies --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index f47948c..fafe0bf 100644 --- a/package.json +++ b/package.json @@ -61,11 +61,11 @@ "remark-preset-wooorm": "^9.0.0", "rimraf": "^3.0.0", "tape": "^5.0.0", - "tsd": "^0.23.0", + "tsd": "^0.25.0", "type-coverage": "^2.0.0", "typescript": "^4.0.0", "unist-builder": "^3.0.0", - "xo": "^0.52.0" + "xo": "^0.53.0" }, "scripts": { "prepack": "npm run build && npm run format", From 27917c46f89d495e3d17aeaf98d48c6567c30eeb Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Tue, 17 Jan 2023 14:40:45 +0100 Subject: [PATCH 02/13] Update Actions --- .github/workflows/main.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 69924a4..89dc06c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -7,13 +7,13 @@ jobs: name: ${{matrix.node}} runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: dcodeIO/setup-node-nvm@master + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 with: node-version: ${{matrix.node}} - run: npm install - run: npm test - - uses: codecov/codecov-action@v1 + - uses: codecov/codecov-action@v3 strategy: matrix: node: From 31ab7f770c0b29a2435aa8611b4e6dbcc3b6b7c3 Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Tue, 17 Jan 2023 14:53:08 +0100 Subject: [PATCH 03/13] Update `tsconfig.json` --- index.js | 4 ++-- jsx-dev-runtime.js | 2 +- lib/index.js | 25 ++++++++++++++----------- lib/runtime.js | 8 ++++---- package.json | 9 ++++----- readme.md | 2 +- test/jsx.jsx | 6 ++++++ tsconfig.json | 29 ++++++++++++++--------------- 8 files changed, 46 insertions(+), 39 deletions(-) diff --git a/index.js b/index.js index f33ac57..d224b3c 100644 --- a/index.js +++ b/index.js @@ -1,7 +1,7 @@ /** - * @typedef {import('./lib/index.js').XChild}} Child + * @typedef {import('./lib/index.js').XChild} Child * Acceptable child value - * @typedef {import('./lib/index.js').XAttributes}} Attributes + * @typedef {import('./lib/index.js').XAttributes} Attributes * Acceptable attributes value. */ diff --git a/jsx-dev-runtime.js b/jsx-dev-runtime.js index dccba61..dcbe50c 100644 --- a/jsx-dev-runtime.js +++ b/jsx-dev-runtime.js @@ -13,7 +13,7 @@ export {Fragment} from './jsx-runtime.js' export const jsxDEV = /** * @type {{ - * (name: null|undefined, props: {children?: XChild}, ...unused: unknown[]): Root + * (name: null | undefined, props: {children?: XChild}, ...unused: unknown[]): Root * (name: string, props: JSXProps, ...unused: unknown[]): Element * }} */ diff --git a/lib/index.js b/lib/index.js index 71cdc57..f71096e 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,15 +1,18 @@ /** * @typedef {import('xast').Root} Root * @typedef {import('xast').Element} Element + */ + +/** * @typedef {Root['children'][number]} Child - * @typedef {Child|Root} Node - * @typedef {Root|Element} XResult - * @typedef {string|number|boolean|null|undefined} XValue + * @typedef {Child | Root} Node + * @typedef {Root | Element} XResult + * @typedef {string | number | boolean | null | undefined} XValue * @typedef {{[attribute: string]: XValue}} XAttributes Attributes to support JS primitive types * - * @typedef {string|number|null|undefined} XPrimitiveChild - * @typedef {Array} XArrayChild - * @typedef {Node|XPrimitiveChild|XArrayChild} XChild + * @typedef {string | number | null | undefined} XPrimitiveChild + * @typedef {Array} XArrayChild + * @typedef {Node | XPrimitiveChild | XArrayChild} XChild * @typedef {import('./jsx-classic.js').Element} x.JSX.Element * @typedef {import('./jsx-classic.js').IntrinsicAttributes} x.JSX.IntrinsicAttributes * @typedef {import('./jsx-classic.js').IntrinsicElements} x.JSX.IntrinsicElements @@ -19,7 +22,7 @@ /** * Create XML trees in xast. * - * @param name Qualified name. Case sensitive and can contain a namespace prefix (such as `rdf:RDF`). Pass `null|undefined` to build a root. + * @param name Qualified name. Case sensitive and can contain a namespace prefix (such as `rdf:RDF`). Pass `null | undefined` to build a root. * @param attributes Map of attributes. Nullish (null or undefined) or NaN values are ignored, other values (strings, booleans) are cast to strings. * @param children (Lists of) child nodes. When strings are encountered, they are mapped to Text nodes. */ @@ -27,7 +30,7 @@ export const x = /** * @type {{ * (): Root - * (name: null|undefined, ...children: Array): Root + * (name: null | undefined, ...children: Array): Root * (name: string, attributes: XAttributes, ...children: Array): Element * (name: string, ...children: Array): Element * }} @@ -36,8 +39,8 @@ export const x = /** * Hyperscript compatible DSL for creating virtual xast trees. * - * @param {string|null} [name] - * @param {XAttributes|XChild} [attributes] + * @param {string | null} [name] + * @param {XAttributes | XChild} [attributes] * @param {Array} children * @returns {XResult} */ @@ -112,7 +115,7 @@ function addChild(nodes, value) { } /** - * @param {XAttributes|XChild} value + * @param {XAttributes | XChild} value * @returns {value is XAttributes} */ function isAttributes(value) { diff --git a/lib/runtime.js b/lib/runtime.js index 51a71a8..522a15c 100644 --- a/lib/runtime.js +++ b/lib/runtime.js @@ -6,7 +6,7 @@ * @typedef {import('./index.js').XAttributes} XAttributes * @typedef {import('./index.js').XValue} XValue * - * @typedef {{[x: string]: XValue|XChild}} JSXProps + * @typedef {{[x: string]: XValue | XChild}} JSXProps */ import {x} from './index.js' @@ -17,19 +17,19 @@ export * from './jsx-automatic.js' /** * Create XML trees in xast through JSX. * - * @param name Qualified name. Case sensitive and can contain a namespace prefix (such as `rdf:RDF`). Pass `null|undefined` to build a root. + * @param name Qualified name. Case sensitive and can contain a namespace prefix (such as `rdf:RDF`). Pass `null | undefined` to build a root. * @param props Map of attributes. Nullish (null or undefined) or NaN values are ignored, other values (strings, booleans) are cast to strings. `children` can contain one child or a list of children. When strings are encountered, they are mapped to text nodes. */ export const jsx = /** * @type {{ - * (name: null|undefined, props: {children?: XChild}, key?: string): Root + * (name: null | undefined, props: {children?: XChild}, key?: string): Root * (name: string, props: JSXProps, key?: string): Element * }} */ ( /** - * @param {string|null} name + * @param {string | null} name * @param {XAttributes & {children?: XChild}} props * @returns {XResult} */ diff --git a/package.json b/package.json index fafe0bf..2eb52ce 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,6 @@ "prettier": "^2.0.0", "remark-cli": "^11.0.0", "remark-preset-wooorm": "^9.0.0", - "rimraf": "^3.0.0", "tape": "^5.0.0", "tsd": "^0.25.0", "type-coverage": "^2.0.0", @@ -69,11 +68,11 @@ }, "scripts": { "prepack": "npm run build && npm run format", - "build": "rimraf \"{script/**,test/**,}*.d.ts\" \"lib/{index,runtime}.d.ts\" && tsc && tsd && type-coverage", - "generate": "node script/generate-jsx", + "generate": "node script/generate-jsx.js", + "build": "tsc --build --clean && tsc --build && tsd && type-coverage", "format": "remark . -qfo && prettier . -w --loglevel warn && xo --fix", - "test-api": "node test/index.js", - "test-coverage": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 --reporter lcov node test/index.js", + "test-api": "node --conditions development test.js", + "test-coverage": "c8 --check-coverage --100 --reporter lcov npm run test-api", "test": "npm run generate && npm run build && npm run format && npm run test-coverage" }, "prettier": { diff --git a/readme.md b/readme.md index c0d62db..481885d 100644 --- a/readme.md +++ b/readme.md @@ -215,7 +215,7 @@ When nullish, a [`Root`][root] is built instead. ###### `attributes` -Map of attributes (`Record`, +Map of attributes (`Record`, optional). Nullish (`null` or `undefined`) or `NaN` values are ignored, other values are turned to strings. diff --git a/test/jsx.jsx b/test/jsx.jsx index 3b3397f..ee9c5a9 100644 --- a/test/jsx.jsx +++ b/test/jsx.jsx @@ -1,3 +1,5 @@ +/** @jsxImportSource xastscript */ + import test from 'tape' import {u} from 'unist-builder' import {x} from '../index.js' @@ -9,6 +11,8 @@ test('name', (t) => { const A = 'a' + // Note: this file is a template, generated with different runtimes. + // @ts-ignore: TS (depending on this build) sometimes doesn’t understand. t.deepEqual(, x(A), 'should support an uppercase tag name') t.deepEqual( @@ -42,6 +46,8 @@ test('name', (t) => { const com = {acme: {a: 'A', b: 'B'}} t.deepEqual( + // Note: this file is a template, generated with different runtimes. + // @ts-ignore: TS (depending on this build) sometimes doesn’t understand. , x(com.acme.a), 'should support members as names (`a.b`)' diff --git a/tsconfig.json b/tsconfig.json index ab14bdd..6250214 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,24 +1,23 @@ { - "include": [ - "*.js", - "script/**/*.js", - "test/**/*.js", - "lib/index.js", - "lib/runtime.js", - "lib/jsx-automatic.d.ts", - "lib/jsx-classic.d.ts" + "include": ["**/**.js", "**/**.jsx"], + "exclude": [ + "coverage/", + "node_modules/", + "lib/jsx-automatic.js", + "lib/jsx-classic.js" ], "compilerOptions": { - "target": "ES2020", - "lib": ["ES2020"], - "module": "Node16", - "allowJs": true, "checkJs": true, "declaration": true, "emitDeclarationOnly": true, - "allowSyntheticDefaultImports": true, + "exactOptionalPropertyTypes": true, + "forceConsistentCasingInFileNames": true, + "lib": ["es2020"], + "module": "node16", + "newLine": "lf", "skipLibCheck": true, - "strictNullChecks": true, - "strict": true + "strict": true, + "target": "es2020", + "jsx": "preserve" } } From 6703df6224ef9891c7e99759d79e50c4bfbdc977 Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Tue, 17 Jan 2023 14:55:30 +0100 Subject: [PATCH 04/13] Add export of `Result` type --- index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/index.js b/index.js index d224b3c..ea7b8c2 100644 --- a/index.js +++ b/index.js @@ -3,6 +3,7 @@ * Acceptable child value * @typedef {import('./lib/index.js').XAttributes} Attributes * Acceptable attributes value. + * @typedef {import('./lib/index.js').XResult} Result */ export {x} from './lib/index.js' From 752f368664b6d7ac7bd042b2b2b5e839115166cd Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Tue, 17 Jan 2023 14:55:33 +0100 Subject: [PATCH 05/13] Fix typo --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2eb52ce..59f9031 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "generate": "node script/generate-jsx.js", "build": "tsc --build --clean && tsc --build && tsd && type-coverage", "format": "remark . -qfo && prettier . -w --loglevel warn && xo --fix", - "test-api": "node --conditions development test.js", + "test-api": "node --conditions development test/index.js", "test-coverage": "c8 --check-coverage --100 --reporter lcov npm run test-api", "test": "npm run generate && npm run build && npm run format && npm run test-coverage" }, From 88315af50f30ee75443f9e11c4ca2a8407a52373 Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Tue, 17 Jan 2023 14:56:40 +0100 Subject: [PATCH 06/13] Remove classic Babel test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Babel no longer supports `null` as a pragma as a keyword, instead it forces that as a string (`'null'`), which we can’t handle. --- script/generate-jsx.js | 10 ---------- test/index.js | 1 - 2 files changed, 11 deletions(-) diff --git a/script/generate-jsx.js b/script/generate-jsx.js index 4411102..9cdc310 100644 --- a/script/generate-jsx.js +++ b/script/generate-jsx.js @@ -60,16 +60,6 @@ fs.writeFileSync( ).value ) -fs.writeFileSync( - path.join('test', 'jsx-babel-classic.js'), - // @ts-expect-error Result always given. - babel.transform(doc.replace(/'name'/, "'jsx (babel, classic)'"), { - plugins: [ - ['@babel/plugin-transform-react-jsx', {pragma: 'x', pragmaFrag: 'null'}] - ] - }).code -) - fs.writeFileSync( path.join('test', 'jsx-babel-automatic.js'), // @ts-expect-error Result always given. diff --git a/test/index.js b/test/index.js index b6b160d..11265e1 100644 --- a/test/index.js +++ b/test/index.js @@ -1,6 +1,5 @@ /* eslint-disable import/no-unassigned-import */ import './core.js' -import './jsx-babel-classic.js' import './jsx-babel-automatic.js' import './jsx-build-jsx-classic.js' import './jsx-build-jsx-automatic.js' From d0c8e885629af52a40a98eb9f0c5ff625145998b Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Tue, 17 Jan 2023 15:01:32 +0100 Subject: [PATCH 07/13] Remove superfluous dev-dependencies --- package.json | 5 +-- script/generate-jsx.js | 73 +++++++++++------------------------------- test/index.js | 2 +- 3 files changed, 20 insertions(+), 60 deletions(-) diff --git a/package.json b/package.json index 59f9031..0aa41cf 100644 --- a/package.json +++ b/package.json @@ -48,12 +48,9 @@ "@types/xast": "^1.0.0" }, "devDependencies": { - "@babel/core": "^7.0.0", - "@babel/plugin-syntax-jsx": "^7.0.0", - "@babel/plugin-transform-react-jsx": "^7.0.0", - "@types/babel__core": "^7.0.0", "@types/tape": "^4.0.0", "c8": "^7.0.0", + "esast-util-from-js": "^1.0.0", "estree-util-build-jsx": "^2.0.0", "estree-util-to-js": "^1.0.0", "prettier": "^2.0.0", diff --git a/script/generate-jsx.js b/script/generate-jsx.js index 9cdc310..3222744 100644 --- a/script/generate-jsx.js +++ b/script/generate-jsx.js @@ -1,87 +1,50 @@ -import fs from 'node:fs' +import fs from 'node:fs/promises' import path from 'node:path' -import babel from '@babel/core' -import {Parser} from 'acorn' import acornJsx from 'acorn-jsx' +import {fromJs} from 'esast-util-from-js' import {toJs} from 'estree-util-to-js' import {buildJsx} from 'estree-util-build-jsx' -const doc = String(fs.readFileSync(path.join('test', 'jsx.jsx'))) +const doc = String(await fs.readFile(path.join('test', 'jsx.jsx'))) -fs.writeFileSync( +await fs.writeFile( path.join('test', 'jsx-build-jsx-classic.js'), toJs( - // @ts-expect-error it’s a program. buildJsx( - // @ts-expect-error Acorn nodes are assignable to ESTree nodes. - Parser.extend(acornJsx()).parse( - doc.replace(/'name'/, "'jsx (estree-util-build-jsx, classic)'"), - // Note: different npms resolve this differently, so it may break or work, hence the ignore. - // @ts-ignore Hush, `2021` is fine. - {sourceType: 'module', ecmaVersion: 2021} - ), + fromJs(doc.replace(/'name'/, "'jsx (estree-util-build-jsx, classic)'"), { + plugins: [acornJsx()], + module: true + }), {pragma: 'x', pragmaFrag: 'null'} ) - // @ts-expect-error Some bug in `to-js` ).value ) -fs.writeFileSync( +await fs.writeFile( path.join('test', 'jsx-build-jsx-automatic.js'), toJs( - // @ts-expect-error it’s a program. buildJsx( - // @ts-expect-error Acorn nodes are assignable to ESTree nodes. - Parser.extend(acornJsx()).parse( + fromJs( doc.replace(/'name'/, "'jsx (estree-util-build-jsx, automatic)'"), - // Note: different npms resolve this differently, so it may break or work, hence the ignore. - // @ts-ignore Hush, `2021` is fine. - {sourceType: 'module', ecmaVersion: 2021} + {plugins: [acornJsx()], module: true} ), {runtime: 'automatic', importSource: 'xastscript'} ) - // @ts-expect-error Some bug in `to-js` ).value ) -fs.writeFileSync( +await fs.writeFile( path.join('test', 'jsx-build-jsx-automatic-development.js'), toJs( - // @ts-expect-error it’s a program. buildJsx( - // @ts-expect-error Acorn nodes are assignable to ESTree nodes. - Parser.extend(acornJsx()).parse( - doc.replace(/'name'/, "'jsx (estree-util-build-jsx, automatic)'"), - {sourceType: 'module', ecmaVersion: 2021} + fromJs( + doc.replace( + /'name'/, + "'jsx (estree-util-build-jsx, automatic, development)'" + ), + {plugins: [acornJsx()], module: true} ), {runtime: 'automatic', importSource: 'xastscript', development: true} ) - // @ts-expect-error Some bug in `to-js` ).value ) - -fs.writeFileSync( - path.join('test', 'jsx-babel-automatic.js'), - // @ts-expect-error Result always given. - babel.transformSync(doc.replace(/'name'/, "'jsx (babel, automatic)'"), { - plugins: [ - [ - '@babel/plugin-transform-react-jsx', - {runtime: 'automatic', importSource: 'xastscript'} - ] - ] - }).code -) - -fs.writeFileSync( - path.join('test', 'jsx-babel-automatic-development.js'), - // @ts-expect-error Result always given. - babel.transformSync(doc.replace(/'name'/, "'jsx (babel, automatic)'"), { - plugins: [ - [ - '@babel/plugin-transform-react-jsx', - {runtime: 'automatic', importSource: 'xastscript', development: true} - ] - ] - }).code -) diff --git a/test/index.js b/test/index.js index 11265e1..04e777f 100644 --- a/test/index.js +++ b/test/index.js @@ -1,6 +1,6 @@ /* eslint-disable import/no-unassigned-import */ import './core.js' -import './jsx-babel-automatic.js' import './jsx-build-jsx-classic.js' import './jsx-build-jsx-automatic.js' +import './jsx-build-jsx-automatic-development.js' /* eslint-enable import/no-unassigned-import */ From 30b06793cfddad37ac21cc6908ad34501cadcb0f Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Tue, 17 Jan 2023 15:04:34 +0100 Subject: [PATCH 08/13] Replace paths with URLs --- script/generate-jsx.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/script/generate-jsx.js b/script/generate-jsx.js index 3222744..48c34a6 100644 --- a/script/generate-jsx.js +++ b/script/generate-jsx.js @@ -1,14 +1,15 @@ import fs from 'node:fs/promises' -import path from 'node:path' import acornJsx from 'acorn-jsx' import {fromJs} from 'esast-util-from-js' import {toJs} from 'estree-util-to-js' import {buildJsx} from 'estree-util-build-jsx' -const doc = String(await fs.readFile(path.join('test', 'jsx.jsx'))) +const doc = String( + await fs.readFile(new URL('../test/jsx.jsx', import.meta.url)) +) await fs.writeFile( - path.join('test', 'jsx-build-jsx-classic.js'), + new URL('../test/jsx-build-jsx-classic.js', import.meta.url), toJs( buildJsx( fromJs(doc.replace(/'name'/, "'jsx (estree-util-build-jsx, classic)'"), { @@ -21,7 +22,7 @@ await fs.writeFile( ) await fs.writeFile( - path.join('test', 'jsx-build-jsx-automatic.js'), + new URL('../test/jsx-build-jsx-automatic.js', import.meta.url), toJs( buildJsx( fromJs( @@ -34,7 +35,7 @@ await fs.writeFile( ) await fs.writeFile( - path.join('test', 'jsx-build-jsx-automatic-development.js'), + new URL('../test/jsx-build-jsx-automatic-development.js', import.meta.url), toJs( buildJsx( fromJs( From e4654eb3934058f7ba793064e0a6fe627c412b97 Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Tue, 17 Jan 2023 15:30:43 +0100 Subject: [PATCH 09/13] Refactor code-style * Refactor a bunch of code * Add more JSDoc --- index.js | 8 ++-- jsx-dev-runtime.js | 11 ++++-- jsx-runtime.js | 5 ++- lib/index.js | 85 ++++++++++++++++++++++++++++++------------ lib/jsx-automatic.d.ts | 8 ++-- lib/jsx-classic.d.ts | 8 ++-- lib/runtime.js | 37 +++++++++++------- readme.md | 1 + 8 files changed, 107 insertions(+), 56 deletions(-) diff --git a/index.js b/index.js index ea7b8c2..bc5922f 100644 --- a/index.js +++ b/index.js @@ -1,9 +1,7 @@ /** - * @typedef {import('./lib/index.js').XChild} Child - * Acceptable child value - * @typedef {import('./lib/index.js').XAttributes} Attributes - * Acceptable attributes value. - * @typedef {import('./lib/index.js').XResult} Result + * @typedef {import('./lib/index.js').Child} Child + * @typedef {import('./lib/index.js').Attributes} Attributes + * @typedef {import('./lib/index.js').Result} Result */ export {x} from './lib/index.js' diff --git a/jsx-dev-runtime.js b/jsx-dev-runtime.js index dcbe50c..9dc055c 100644 --- a/jsx-dev-runtime.js +++ b/jsx-dev-runtime.js @@ -1,11 +1,14 @@ /** * @typedef {import('xast').Element} Element * @typedef {import('xast').Root} Root - * @typedef {import('./lib/index.js').XChild} XChild + * @typedef {import('./lib/index.js').Child} Child * @typedef {import('./lib/runtime.js').JSXProps} JSXProps */ -import {jsx} from './jsx-runtime.js' +import {jsx} from './lib/runtime.js' + +// Export `JSX` as a global for TypeScript. +export * from './lib/jsx-automatic.js' export {Fragment} from './jsx-runtime.js' @@ -13,8 +16,8 @@ export {Fragment} from './jsx-runtime.js' export const jsxDEV = /** * @type {{ - * (name: null | undefined, props: {children?: XChild}, ...unused: unknown[]): Root - * (name: string, props: JSXProps, ...unused: unknown[]): Element + * (name: null | undefined, props: {children?: Child}, key?: string, ...unused: Array): Root + * (name: string, props: JSXProps, key?: string, ...unused: Array): Element * }} */ (jsx) diff --git a/jsx-runtime.js b/jsx-runtime.js index 8049d04..6ce9428 100644 --- a/jsx-runtime.js +++ b/jsx-runtime.js @@ -2,4 +2,7 @@ * @typedef {import('./lib/runtime.js').JSXProps}} JSXProps */ -export * from './lib/runtime.js' +// Export `JSX` as a global for TypeScript. +export * from './lib/jsx-automatic.js' + +export {jsx, jsxs, Fragment} from './lib/runtime.js' diff --git a/lib/index.js b/lib/index.js index f71096e..78a37e3 100644 --- a/lib/index.js +++ b/lib/index.js @@ -4,15 +4,25 @@ */ /** - * @typedef {Root['children'][number]} Child - * @typedef {Child | Root} Node - * @typedef {Root | Element} XResult - * @typedef {string | number | boolean | null | undefined} XValue - * @typedef {{[attribute: string]: XValue}} XAttributes Attributes to support JS primitive types + * @typedef {Root['children'][number]} Content + * @typedef {Content | Root} Node + * Any concrete `xast` node. + * + * @typedef {Root | Element} Result + * Result from a `x` call. + * + * @typedef {string | number | boolean | null | undefined} Value + * Attribute value + * @typedef {{[attribute: string]: Value}} Attributes + * Acceptable value for element properties. + * + * @typedef {string | number | null | undefined} PrimitiveChild + * Primitive children, either ignored (nullish), or turned into text nodes. + * @typedef {Array} ArrayChild + * List of children. + * @typedef {Node | PrimitiveChild | ArrayChild} Child + * Acceptable child value. * - * @typedef {string | number | null | undefined} XPrimitiveChild - * @typedef {Array} XArrayChild - * @typedef {Node | XPrimitiveChild | XArrayChild} XChild * @typedef {import('./jsx-classic.js').Element} x.JSX.Element * @typedef {import('./jsx-classic.js').IntrinsicAttributes} x.JSX.IntrinsicAttributes * @typedef {import('./jsx-classic.js').IntrinsicElements} x.JSX.IntrinsicElements @@ -22,31 +32,48 @@ /** * Create XML trees in xast. * - * @param name Qualified name. Case sensitive and can contain a namespace prefix (such as `rdf:RDF`). Pass `null | undefined` to build a root. - * @param attributes Map of attributes. Nullish (null or undefined) or NaN values are ignored, other values (strings, booleans) are cast to strings. - * @param children (Lists of) child nodes. When strings are encountered, they are mapped to Text nodes. + * @param name + * Qualified name. + * + * Case sensitive and can contain a namespace prefix (such as `rdf:RDF`). + * When string, an `Element` is built. + * When nullish, a `Root` is built instead. + * @param attributes + * Map of attributes. + * + * Nullish (`null` or `undefined`) or `NaN` values are ignored, other values + * are turned to strings. + * + * Cannot be given if building a `Root`. + * Cannot be omitted when building an `Element` if the first child is a + * `Node`. + * @param children + * (Lists of) children. + * + * When strings or numbers are encountered, they are mapped to `Text` nodes. + * If a `Root` node is encountered, its children are used instead. + * @returns + * `Element` or `Root`. */ export const x = /** * @type {{ * (): Root - * (name: null | undefined, ...children: Array): Root - * (name: string, attributes: XAttributes, ...children: Array): Element - * (name: string, ...children: Array): Element + * (name: null | undefined, ...children: Array): Root + * (name: string, attributes?: Attributes, ...children: Array): Element + * (name: string, ...children: Array): Element * }} */ ( /** - * Hyperscript compatible DSL for creating virtual xast trees. - * - * @param {string | null} [name] - * @param {XAttributes | XChild} [attributes] - * @param {Array} children - * @returns {XResult} + * @param {string | null | undefined} [name] + * @param {Attributes | Child | null | undefined} [attributes] + * @param {Array} children + * @returns {Result} */ function (name, attributes, ...children) { let index = -1 - /** @type {XResult} */ + /** @type {Result} */ let node if (name === undefined || name === null) { @@ -89,8 +116,14 @@ export const x = ) /** + * Add children. + * * @param {Array} nodes - * @param {XChild} value + * List of nodes. + * @param {Child} value + * Child. + * @returns {void} + * Nothing. */ function addChild(nodes, value) { let index = -1 @@ -115,8 +148,12 @@ function addChild(nodes, value) { } /** - * @param {XAttributes | XChild} value - * @returns {value is XAttributes} + * Check if `value` is `Attributes`. + * + * @param {Attributes | Child} value + * Value. + * @returns {value is Attributes} + * Whether `value` is `Attributes`. */ function isAttributes(value) { if ( diff --git a/lib/jsx-automatic.d.ts b/lib/jsx-automatic.d.ts index ac742b3..c18f132 100644 --- a/lib/jsx-automatic.d.ts +++ b/lib/jsx-automatic.d.ts @@ -1,11 +1,11 @@ /* eslint-disable-next-line @typescript-eslint/consistent-type-imports -- fix in major */ -import {XAttributes, XChild, XResult} from './index.js' +import {Attributes, Child, Result} from './index.js' export namespace JSX { /** * This defines the return value of JSX syntax. */ - type Element = XResult + type Element = Result /** * This disallows the use of functional components. @@ -24,12 +24,12 @@ export namespace JSX { // eslint-disable-next-line @typescript-eslint/consistent-indexed-object-style interface IntrinsicElements { [name: string]: - | XAttributes + | Attributes | { /** * The prop that matches `ElementChildrenAttribute` key defines the type of JSX children, defines the children type. */ - children?: XChild + children?: Child } } diff --git a/lib/jsx-classic.d.ts b/lib/jsx-classic.d.ts index 53de7ad..fd2721d 100644 --- a/lib/jsx-classic.d.ts +++ b/lib/jsx-classic.d.ts @@ -1,5 +1,5 @@ /* eslint-disable-next-line @typescript-eslint/consistent-type-imports -- fix in major */ -import {XAttributes, XChild, XResult} from './index.js' +import {Attributes, Child, Result} from './index.js' /** * This unique symbol is declared to specify the key on which JSX children are passed, without conflicting @@ -10,7 +10,7 @@ declare const children: unique symbol /** * This defines the return value of JSX syntax. */ -export type Element = XResult +export type Element = Result /** * This disallows the use of functional components. @@ -29,12 +29,12 @@ export type IntrinsicAttributes = never // eslint-disable-next-line @typescript-eslint/consistent-indexed-object-style export interface IntrinsicElements { [name: string]: - | XAttributes + | Attributes | { /** * The prop that matches `ElementChildrenAttribute` key defines the type of JSX children, defines the children type. */ - [children]?: XChild + [children]?: Child } } diff --git a/lib/runtime.js b/lib/runtime.js index 522a15c..6df8e5b 100644 --- a/lib/runtime.js +++ b/lib/runtime.js @@ -1,37 +1,47 @@ /** * @typedef {import('./index.js').Element} Element * @typedef {import('./index.js').Root} Root - * @typedef {import('./index.js').XResult} XResult - * @typedef {import('./index.js').XChild} XChild - * @typedef {import('./index.js').XAttributes} XAttributes - * @typedef {import('./index.js').XValue} XValue + * @typedef {import('./index.js').Result} Result + * @typedef {import('./index.js').Child} Child + * @typedef {import('./index.js').Attributes} Attributes + * @typedef {import('./index.js').Value} Value * - * @typedef {{[x: string]: XValue | XChild}} JSXProps + * @typedef {{[x: string]: Value | Child}} JSXProps */ import {x} from './index.js' -// Export `JSX` as a global for TypeScript. -export * from './jsx-automatic.js' - /** * Create XML trees in xast through JSX. * - * @param name Qualified name. Case sensitive and can contain a namespace prefix (such as `rdf:RDF`). Pass `null | undefined` to build a root. - * @param props Map of attributes. Nullish (null or undefined) or NaN values are ignored, other values (strings, booleans) are cast to strings. `children` can contain one child or a list of children. When strings are encountered, they are mapped to text nodes. + * @param name + * Qualified name. + * + * Case sensitive and can contain a namespace prefix (such as `rdf:RDF`). + * When string, an `Element` is built. + * When nullish, a `Root` is built instead. + * @param props + * Map of attributes. + * + * Nullish (`null` or `undefined`) or `NaN` values are ignored, other values + * are turned to strings. + * + * Cannot be given if building a `Root`. + * Cannot be omitted when building an `Element` if the first child is a + * `Node`. */ export const jsx = /** * @type {{ - * (name: null | undefined, props: {children?: XChild}, key?: string): Root + * (name: null | undefined, props: {children?: Child}, key?: string): Root * (name: string, props: JSXProps, key?: string): Element * }} */ ( /** * @param {string | null} name - * @param {XAttributes & {children?: XChild}} props - * @returns {XResult} + * @param {Attributes & {children?: Child}} props + * @returns {Result} */ function (name, props) { const {children, ...properties} = props @@ -41,5 +51,4 @@ export const jsx = export const jsxs = jsx -/** @type {null} */ export const Fragment = null diff --git a/readme.md b/readme.md index 481885d..c8b6c49 100644 --- a/readme.md +++ b/readme.md @@ -209,6 +209,7 @@ Create [xast][] trees. ###### `name` Qualified name (`string`, optional). + Case sensitive and can contain a namespace prefix (such as `rdf:RDF`). When string, an [`Element`][element] is built. When nullish, a [`Root`][root] is built instead. From b886ed29ed6b67276bdba8a82f230232a530f8a8 Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Tue, 17 Jan 2023 15:33:10 +0100 Subject: [PATCH 10/13] Use Node test runner --- .github/workflows/main.yml | 2 +- package.json | 3 +-- test/core.js | 49 +++++++++++++++++++------------------- test/jsx.jsx | 41 ++++++++++++++++--------------- 4 files changed, 46 insertions(+), 49 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 89dc06c..fb63387 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -17,5 +17,5 @@ jobs: strategy: matrix: node: - - lts/fermium + - lts/gallium - node diff --git a/package.json b/package.json index 0aa41cf..b4dff5c 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "@types/xast": "^1.0.0" }, "devDependencies": { - "@types/tape": "^4.0.0", + "@types/node": "^18.0.0", "c8": "^7.0.0", "esast-util-from-js": "^1.0.0", "estree-util-build-jsx": "^2.0.0", @@ -56,7 +56,6 @@ "prettier": "^2.0.0", "remark-cli": "^11.0.0", "remark-preset-wooorm": "^9.0.0", - "tape": "^5.0.0", "tsd": "^0.25.0", "type-coverage": "^2.0.0", "typescript": "^4.0.0", diff --git a/test/core.js b/test/core.js index 4c1225c..ef9db37 100644 --- a/test/core.js +++ b/test/core.js @@ -1,16 +1,17 @@ -import test from 'tape' +import assert from 'node:assert/strict' +import test from 'node:test' import {x} from '../index.js' -test('xastscript', (t) => { - t.equal(typeof x, 'function', 'should expose a function') +test('xastscript', () => { + assert.equal(typeof x, 'function', 'should expose a function') - t.deepEqual( + assert.deepEqual( x(), {type: 'root', children: []}, 'should create a root when w/o `name`' ) - t.throws( + assert.throws( () => { // @ts-expect-error runtime. x(1) @@ -19,31 +20,31 @@ test('xastscript', (t) => { 'should throw w/ incorrect `name`' ) - t.deepEqual( + assert.deepEqual( x('y'), {type: 'element', name: 'y', attributes: {}, children: []}, 'should create an element when given `name`' ) - t.deepEqual( + assert.deepEqual( x('Y'), {type: 'element', name: 'Y', attributes: {}, children: []}, 'should treat `name` case-sensitive' ) - t.deepEqual( + assert.deepEqual( x('y', {a: 'b'}), {type: 'element', name: 'y', attributes: {a: 'b'}, children: []}, 'should create an element with given attributes' ) - t.deepEqual( + assert.deepEqual( x('y', {a: null, b: undefined, c: Number.NaN}), {type: 'element', name: 'y', attributes: {}, children: []}, 'should ignore null, undefined, and NaN attribute values' ) - t.deepEqual( + assert.deepEqual( x('y', {}, x('z')), { type: 'element', @@ -54,7 +55,7 @@ test('xastscript', (t) => { 'should add a child' ) - t.deepEqual( + assert.deepEqual( x('y', {}, [x('a'), x('b')]), { type: 'element', @@ -68,7 +69,7 @@ test('xastscript', (t) => { 'should add children as an array' ) - t.deepEqual( + assert.deepEqual( // @ts-expect-error Deeply nested children are not typed. x('y', {}, [[[x('a')]], [[[[x('b')]], x('c')]]]), { @@ -84,7 +85,7 @@ test('xastscript', (t) => { 'should add children in a deeply nested array' ) - t.deepEqual( + assert.deepEqual( x('y', {}, x('a'), x('b')), { type: 'element', @@ -98,7 +99,7 @@ test('xastscript', (t) => { 'should add children as arguments' ) - t.deepEqual( + assert.deepEqual( x('y', {}, 'a', 1), { type: 'element', @@ -112,13 +113,13 @@ test('xastscript', (t) => { 'should add strings and numbers as literals' ) - t.deepEqual( + assert.deepEqual( x('y', {}, null, undefined), {type: 'element', name: 'y', attributes: {}, children: []}, 'should ignore null and undefined children' ) - t.throws( + assert.throws( () => { // @ts-expect-error runtime. x('y', {}, {}) @@ -127,7 +128,7 @@ test('xastscript', (t) => { 'should throw on invalid children' ) - t.deepEqual( + assert.deepEqual( x('y', 'z'), { type: 'element', @@ -138,7 +139,7 @@ test('xastscript', (t) => { 'should support omitting attributes when given a string for a child' ) - t.deepEqual( + assert.deepEqual( x('y', 1), { type: 'element', @@ -149,7 +150,7 @@ test('xastscript', (t) => { 'should support omitting attributes when given a number for a child' ) - t.deepEqual( + assert.deepEqual( x('y', ['a', 1]), { type: 'element', @@ -163,19 +164,19 @@ test('xastscript', (t) => { 'should support omitting attributes when given an array for a child' ) - t.deepEqual( + assert.deepEqual( x(null, '1'), {type: 'root', children: [{type: 'text', value: '1'}]}, 'should create a root with a textual child' ) - t.deepEqual( + assert.deepEqual( x(null, 1), {type: 'root', children: [{type: 'text', value: '1'}]}, 'should create a root with a numerical child' ) - t.deepEqual( + assert.deepEqual( x(null, x('a')), { type: 'root', @@ -184,7 +185,7 @@ test('xastscript', (t) => { 'should create a root with a node child' ) - t.deepEqual( + assert.deepEqual( x('a', {}, [x(null, x('b'))]), { type: 'element', @@ -194,6 +195,4 @@ test('xastscript', (t) => { }, 'should create a node w/ by unraveling roots' ) - - t.end() }) diff --git a/test/jsx.jsx b/test/jsx.jsx index ee9c5a9..5d7ccb7 100644 --- a/test/jsx.jsx +++ b/test/jsx.jsx @@ -1,35 +1,36 @@ /** @jsxImportSource xastscript */ -import test from 'tape' +import assert from 'node:assert/strict' +import test from 'node:test' import {u} from 'unist-builder' import {x} from '../index.js' -test('name', (t) => { - t.deepEqual(, x('a'), 'should support a self-closing element') +test('name', () => { + assert.deepEqual(, x('a'), 'should support a self-closing element') - t.deepEqual(b, x('a', 'b'), 'should support a value as a child') + assert.deepEqual(b, x('a', 'b'), 'should support a value as a child') const A = 'a' // Note: this file is a template, generated with different runtimes. // @ts-ignore: TS (depending on this build) sometimes doesn’t understand. - t.deepEqual(, x(A), 'should support an uppercase tag name') + assert.deepEqual(, x(A), 'should support an uppercase tag name') - t.deepEqual( + assert.deepEqual( {1 + 1}, x('a', '2'), 'should support expressions as children' ) - t.deepEqual(<>, u('root', []), 'should support a fragment') + assert.deepEqual(<>, u('root', []), 'should support a fragment') - t.deepEqual( + assert.deepEqual( <>a, u('root', [u('text', 'a')]), 'should support a fragment with text' ) - t.deepEqual( + assert.deepEqual( <> , @@ -37,7 +38,7 @@ test('name', (t) => { 'should support a fragment with an element' ) - t.deepEqual( + assert.deepEqual( <>{-1}, u('root', [u('text', '-1')]), 'should support a fragment with an expression' @@ -45,7 +46,7 @@ test('name', (t) => { const com = {acme: {a: 'A', b: 'B'}} - t.deepEqual( + assert.deepEqual( // Note: this file is a template, generated with different runtimes. // @ts-ignore: TS (depending on this build) sometimes doesn’t understand. , @@ -53,25 +54,25 @@ test('name', (t) => { 'should support members as names (`a.b`)' ) - t.deepEqual( + assert.deepEqual( , x('a', {b: 'true'}), 'should support a boolean attribute' ) - t.deepEqual( + assert.deepEqual( , x('a', {b: ''}), 'should support a double quoted attribute' ) - t.deepEqual( + assert.deepEqual( , x('a', {b: '"'}), 'should support a single quoted attribute' ) - t.deepEqual( + assert.deepEqual( , x('a', {b: '2'}), 'should support expression value attributes' @@ -79,13 +80,13 @@ test('name', (t) => { const props = {a: 1, b: 2} - t.deepEqual( + assert.deepEqual( , x('a', props), 'should support expression spread attributes' ) - t.deepEqual( + assert.deepEqual( ce {1 + 1} @@ -94,7 +95,7 @@ test('name', (t) => { 'should support text, elements, and expressions in JSX' ) - t.deepEqual( + assert.deepEqual( <>{1} , @@ -107,7 +108,7 @@ test('name', (t) => { ['Chrome', 'A chemical element.'] ] - t.deepEqual( + assert.deepEqual(
{dl.map(([title, definition]) => ( <> @@ -124,6 +125,4 @@ test('name', (t) => { ]), 'should support a fragment in an element (#2)' ) - - t.end() }) From 0bcd5cec9572ac18fb687b76530fe2e3a4e45262 Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Tue, 17 Jan 2023 15:37:28 +0100 Subject: [PATCH 11/13] Add tests for exposed identifiers --- test/core.js | 21 +++++++++++++++++++-- test/jsx.jsx | 2 +- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/test/core.js b/test/core.js index ef9db37..6beec97 100644 --- a/test/core.js +++ b/test/core.js @@ -1,9 +1,26 @@ import assert from 'node:assert/strict' import test from 'node:test' -import {x} from '../index.js' +import {x} from 'xastscript' +import * as coreMod from 'xastscript' +import * as jsxCoreMod from 'xastscript/jsx-runtime' +import * as jsxDevMod from 'xastscript/jsx-dev-runtime' test('xastscript', () => { - assert.equal(typeof x, 'function', 'should expose a function') + assert.deepEqual( + Object.keys(coreMod).sort(), + ['x'], + 'should expose the public api (`/`)' + ) + assert.deepEqual( + Object.keys(jsxCoreMod).sort(), + ['Fragment', 'jsx', 'jsxs'], + 'should expose the public api (`/jsx-runtime`)' + ) + assert.deepEqual( + Object.keys(jsxDevMod).sort(), + ['Fragment', 'jsxDEV'], + 'should expose the public api (`/jsx-dev-runtime`)' + ) assert.deepEqual( x(), diff --git a/test/jsx.jsx b/test/jsx.jsx index 5d7ccb7..437ea5f 100644 --- a/test/jsx.jsx +++ b/test/jsx.jsx @@ -3,7 +3,7 @@ import assert from 'node:assert/strict' import test from 'node:test' import {u} from 'unist-builder' -import {x} from '../index.js' +import {x} from 'xastscript' test('name', () => { assert.deepEqual(, x('a'), 'should support a self-closing element') From e170d2c4585272b6cb53a7b1d26e8c3e125131cf Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Tue, 17 Jan 2023 15:51:44 +0100 Subject: [PATCH 12/13] Add improved docs --- lib/index.js | 14 +----- readme.md | 124 +++++++++++++++++++++++++++++++-------------------- 2 files changed, 77 insertions(+), 61 deletions(-) diff --git a/lib/index.js b/lib/index.js index 78a37e3..cb36f7e 100644 --- a/lib/index.js +++ b/lib/index.js @@ -39,19 +39,9 @@ * When string, an `Element` is built. * When nullish, a `Root` is built instead. * @param attributes - * Map of attributes. - * - * Nullish (`null` or `undefined`) or `NaN` values are ignored, other values - * are turned to strings. - * - * Cannot be given if building a `Root`. - * Cannot be omitted when building an `Element` if the first child is a - * `Node`. + * Attributes of the element. * @param children - * (Lists of) children. - * - * When strings or numbers are encountered, they are mapped to `Text` nodes. - * If a `Root` node is encountered, its children are used instead. + * Children of the node. * @returns * `Element` or `Root`. */ diff --git a/readme.md b/readme.md index c8b6c49..4d7eb8d 100644 --- a/readme.md +++ b/readme.md @@ -18,6 +18,10 @@ * [Use](#use) * [API](#api) * [`x(name?[, attributes][, …children])`](#xname-attributes-children) + * [`Attributes`](#attributes-1) + * [`Child`](#child) + * [`Result`](#result) +* [Syntax tree](#syntax-tree) * [JSX](#jsx) * [Types](#types) * [Compatibility](#compatibility) @@ -44,7 +48,7 @@ You can instead use [`unist-builder`][u] when creating any unist nodes and ## Install This package is [ESM only][esm]. -In Node.js (version 12.20+, 14.14+, 16.0+, 18.0+), install with [npm][]: +In Node.js (version 14.14+ and 16.0+), install with [npm][]: ```sh npm install xastscript @@ -187,12 +191,12 @@ Yields: ## API -This package exports the identifier `x`. +This package exports the identifier [`x`][x]. There is no default export. The export map supports the automatic JSX runtime. -You can pass `xastscript` to your build tool (TypeScript, Babel, SWC) as with -an `importSource` option or similar. +You can pass `xastscript` to your build tool (TypeScript, Babel, SWC) with an +`importSource` option or similar. ### `x(name?[, attributes][, …children])` @@ -216,36 +220,81 @@ When nullish, a [`Root`][root] is built instead. ###### `attributes` -Map of attributes (`Record`, -optional). +Attributes of the element ([`Attributes`][attributes], optional). + +###### `children` + +Children of the node ([`Child`][child] or `Array`, optional). + +##### Returns + +Created tree ([`Result`][result]). + +[`Element`][element] when a `name` is passed, otherwise [`Root`][root]. + +### `Attributes` + +Map of attributes (TypeScript type). + Nullish (`null` or `undefined`) or `NaN` values are ignored, other values are turned to strings. -Cannot be given if building a [`Root`][root]. -Cannot be omitted when building an [`Element`][element] if the first child is a -[`Node`][node]. +###### Type -###### `children` +```ts +type Attributes = Record +``` -(Lists of) children (`string`, `number`, `Node`, `Array`, optional). -When strings or numbers are encountered, they are mapped to [`Text`][text] +### `Child` + +(Lists of) children (TypeScript type). + +When strings or numbers are encountered, they are turned into [`Text`][text] nodes. -If a [`Root`][root] node is encountered, its children are used instead. +[`Root`][root] nodes are treated as “fragments”, meaning that their children +are used instead. + +###### Type + +```ts +type Child = + | string + | number + | null + | undefined + | Node + | Array +``` -##### Returns +### `Result` -[`Element`][element] or [`Root`][root]. +Result from a `x` call (TypeScript type). + +###### Type + +```ts +type Result = Root | Element +``` + +## Syntax tree + +The syntax tree is [xast][]. ## JSX -`xastscript` can be used with JSX. -Either use the automatic runtime set to `xastscript` or import `x` yourself and -define it as the pragma (plus set the fragment to `null`). +This package can be used with JSX. +You should use the automatic JSX runtime set to `xastscript`. + +> 🪦 **Legacy**: you can also use the classic JSX runtime, but this is not +> recommended. +> To do so, import `x` yourself and define it as the pragma (plus set the +> fragment to `null`). -The example above (omitting the second) can then be written like so: +The Use example above (omitting the second) can then be written like so: ```jsx /** @jsxImportSource x */ + import {u} from 'unist-builder' console.log( @@ -268,38 +317,17 @@ console.log( ) ``` -You can use [`estree-util-build-jsx`][estree-util-build-jsx] to compile JSX -away. - -For [Babel][], use [`@babel/plugin-transform-react-jsx`][babel-jsx] and either -pass `pragma: 'x'` and `pragmaFrag: 'null'`, or pass `importSource: -'xastscript'`. -Alternatively, Babel also lets you configure this with a comment: -Babel also lets you configure this from code: - -```jsx -/** @jsx x @jsxFrag null */ -import {x} from 'xastscript' - -console.log() -``` - -For [TypeScript][], this can be done by setting `"jsx": "react"`, -`"jsxFactory": "x"`, and `"jsxFragmentFactory": "null"` in the compiler options. -For more details on configuring JSX for TypeScript, see the -[TypeScript JSX handbook page][typescript-jsx]. -TypeScript also lets you configure this from code as shown with Babel above. - ## Types This package is fully typed with [TypeScript][]. -It exports the additional types `Child` and `Attributes`. +It exports the additional types [`Attributes`][attributes], [`Child`][child], +and [`Result`][result]. ## Compatibility Projects maintained by the unified collective are compatible with all maintained versions of Node.js. -As of now, that is Node.js 12.20+, 14.14+, 16.0+, and 18.0+. +As of now, that is Node.js 14.14+ and 16.0+. Our projects sometimes work with older versions, but this is not guaranteed. ## Security @@ -383,8 +411,6 @@ abide by its terms. [xast]: https://github.com/syntax-tree/xast -[node]: https://github.com/syntax-tree/unist#node - [root]: https://github.com/syntax-tree/xast#root [element]: https://github.com/syntax-tree/xast#element @@ -395,10 +421,10 @@ abide by its terms. [h]: https://github.com/syntax-tree/hastscript -[babel]: https://github.com/babel/babel +[x]: #xname-attributes-children -[babel-jsx]: https://github.com/babel/babel/tree/main/packages/babel-plugin-transform-react-jsx +[attributes]: #attributes-1 -[typescript-jsx]: https://www.typescriptlang.org/docs/handbook/jsx.html +[child]: #child -[estree-util-build-jsx]: https://github.com/syntax-tree/estree-util-build-jsx +[result]: #result From 22c43df451961c513764a3d744bf45f6b4bb753a Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Tue, 17 Jan 2023 15:53:32 +0100 Subject: [PATCH 13/13] 3.1.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b4dff5c..741740b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "xastscript", - "version": "3.1.0", + "version": "3.1.1", "description": "xast utility to create trees", "license": "MIT", "keywords": [