diff --git a/.npmrc b/.npmrc index 9951b11..3757b30 100644 --- a/.npmrc +++ b/.npmrc @@ -1,2 +1,2 @@ -package-lock=false ignore-scripts=true +package-lock=false diff --git a/index.js b/index.js index 868069d..13dd598 100644 --- a/index.js +++ b/index.js @@ -1,9 +1,9 @@ /** - * @typedef {import('./lib/types.js').Handler} Handler - * @typedef {import('./lib/types.js').Handlers} Handlers + * @typedef {import('./lib/index.js').Handler} Handler + * @typedef {import('./lib/index.js').Handlers} Handlers * @typedef {import('./lib/index.js').Options} Options * @typedef {import('./lib/index.js').Result} Result - * @typedef {import('./lib/types.js').State} State + * @typedef {import('./lib/index.js').State} State */ export {toJs} from './lib/index.js' diff --git a/lib/index.js b/lib/index.js index 1c72ef2..09868e4 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,118 +1,145 @@ /** + * @typedef {import('astring').State} State + * @typedef {import('estree-jsx').Node} Nodes * @typedef {import('estree-jsx').Program} Program * @typedef {typeof import('source-map').SourceMapGenerator} SourceMapGenerator * @typedef {import('source-map').RawSourceMap} Map - * @typedef {import('./types.js').Handlers} Handlers */ /** - * @typedef BaseFields + * @typedef {Record} Generator + * + * @callback Handler + * Handle a particular node. + * @param {Generator} this + * `astring` generator. + * @param {any} node + * Node to serialize. + * @param {State} state + * Info passed around. + * @returns {undefined} + * Nothing. + * + * @typedef {Partial} Handlers + */ + +/** + * @typedef {OptionsWithMaybeMapGenerator} Options + * Configuration. + * + * @typedef OptionsFieldsBase + * Base shared option fields. * @property {Handlers | null | undefined} [handlers] * Object mapping node types to functions handling the corresponding nodes. * - * @typedef SourceMapFieldsWithoutSourceMapGenerator + * @typedef OptionsFieldsWithoutSourceMapGenerator + * Extra option fields where there’s definitely no source map generator. * @property {null | undefined} [SourceMapGenerator] * Generate a source map by passing a `SourceMapGenerator` from `source-map` - * in. - * This works if there is positional info on nodes. + * in; this works if there is positional info on nodes. * @property {null | undefined} [filePath] - * Path to input file. - * Only used in source map. + * Path to input file; only used in source map. * - * @typedef SourceMapFieldsWithSourceMapGenerator + * @typedef OptionsFieldsWithSourceMapGenerator + * Extra option fields where there’s definitely a source map generator. * @property {SourceMapGenerator} SourceMapGenerator * Generate a source map by passing a `SourceMapGenerator` from `source-map` - * in. - * This works if there is positional info on nodes. + * in; this works if there is positional info on nodes. * @property {string | null | undefined} [filePath] - * Path to input file. - * Only used in source map. + * Path to input file; only used in source map. * - * @typedef SourceMapFieldsMaybeSourceMapGenerator - * @property {SourceMapGenerator | null | undefined} SourceMapGenerator + * @typedef OptionsFieldsMaybeSourceMapGenerator + * Extra option fields where there may or may not be a source map generator. + * @property {SourceMapGenerator | null | undefined} [SourceMapGenerator] * Generate a source map by passing a `SourceMapGenerator` from `source-map` - * in. - * This works if there is positional info on nodes. + * in; this works if there is positional info on nodes. * @property {string | null | undefined} [filePath] - * Path to input file. - * Only used in source map. + * Path to input file; only used in source map. * - * @typedef {BaseFields & SourceMapFieldsWithoutSourceMapGenerator} OptionsWithoutSourceMapGenerator - * @typedef {BaseFields & SourceMapFieldsWithSourceMapGenerator} OptionsWithSourceMapGenerator - * @typedef {BaseFields & SourceMapFieldsMaybeSourceMapGenerator} OptionsWithMaybeMapGenerator + * @typedef {OptionsFieldsBase & OptionsFieldsWithoutSourceMapGenerator} OptionsWithoutSourceMapGenerator + * Options where there’s definitely no source map generator. + * @typedef {OptionsFieldsBase & OptionsFieldsWithSourceMapGenerator} OptionsWithSourceMapGenerator + * Options where there’s definitely a source map generator. + * @typedef {OptionsFieldsBase & OptionsFieldsMaybeSourceMapGenerator} OptionsWithMaybeMapGenerator + * Options where there may or may not be a source map generator. * - * @typedef {OptionsWithMaybeMapGenerator} Options - * Configuration (optional). + * @typedef {ResultWithMaybeSourceMapGenerator} Result + * Result. * - * @typedef BaseResultFields + * @typedef ResultFieldsBase + * Base shared result fields. * @property {string} value * Serialized JavaScript. * * @typedef ResultFieldsWithoutSourceMapGenerator + * Extra result fields where there’s definitely no source map generator. * @property {undefined} map * Source map as (parsed) JSON, if `SourceMapGenerator` is passed. * * @typedef ResultFieldsWithSourceMapGenerator + * Extra result fields where there’s definitely a source map generator. * @property {Map} map * Source map as (parsed) JSON, if `SourceMapGenerator` is not passed. * * @typedef ResultFieldsMaybeSourceMapGenerator + * Extra result fields where there may or may not be a source map generator. * @property {Map | undefined} map * Source map as (parsed) JSON, if `SourceMapGenerator` might be passed. * - * @typedef {BaseResultFields & ResultFieldsWithoutSourceMapGenerator} ResultWithoutSourceMapGenerator - * @typedef {BaseResultFields & ResultFieldsWithSourceMapGenerator} ResultWithSourceMapGenerator - * @typedef {BaseResultFields & ResultFieldsMaybeSourceMapGenerator} ResultMaybeSourceMapGenerator - * - * @typedef {ResultMaybeSourceMapGenerator} Result + * @typedef {ResultFieldsBase & ResultFieldsWithoutSourceMapGenerator} ResultWithoutSourceMapGenerator + * Result where there’s definitely no source map generator. + * @typedef {ResultFieldsBase & ResultFieldsWithSourceMapGenerator} ResultWithSourceMapGenerator + * Result where there’s definitely a source map generator. + * @typedef {ResultFieldsBase & ResultFieldsMaybeSourceMapGenerator} ResultWithMaybeSourceMapGenerator + * Result where there may or may not be a source map generator. */ -// @ts-expect-error: `astring` has broken types. -import * as astring from 'astring' +import {GENERATOR, generate} from 'astring' -/** @type {Handlers} */ -const GENERATOR = astring.GENERATOR - -/** @type {(node: Program, options: unknown) => string} */ -const generate = astring.generate +/** @type {Options} */ +const emptyOptions = {} /** * Serialize an estree as JavaScript. * - * @param tree + * @overload + * @param {Program} tree + * @param {OptionsWithSourceMapGenerator} options + * @returns {ResultWithSourceMapGenerator} + * + * @overload + * @param {Program} tree + * @param {OptionsWithMaybeMapGenerator} options + * @returns {ResultWithMaybeSourceMapGenerator} + * + * @overload + * @param {Program} tree + * @param {OptionsWithoutSourceMapGenerator | null | undefined} [options] + * @returns {ResultWithoutSourceMapGenerator} + * + * @param {Program} tree * Estree (esast). - * @param options + * @param {Options | null | undefined} [options] * Configuration (optional). - * @returns + * @returns {Result} * Result, optionally with source map. */ -export const toJs = - /** - * @type {( - * ((value: Program, options: OptionsWithSourceMapGenerator) => ResultWithSourceMapGenerator) & - * ((value: Program, options: OptionsWithMaybeMapGenerator) => ResultMaybeSourceMapGenerator) & - * ((value: Program, options?: OptionsWithoutSourceMapGenerator | null | undefined) => ResultWithoutSourceMapGenerator) - * )} - */ - ( - /** - * @param {Program} tree - * @param {Options | null | undefined} [options] - * @returns {Result} - */ - function (tree, options) { - const {SourceMapGenerator, filePath, handlers} = options || {} - const sourceMap = SourceMapGenerator - ? new SourceMapGenerator({file: filePath || '.js'}) - : undefined +export function toJs(tree, options) { + const {SourceMapGenerator, filePath, handlers} = options || emptyOptions + const sourceMap = SourceMapGenerator + ? new SourceMapGenerator({file: filePath || '.js'}) + : undefined - const value = generate(tree, { - comments: true, - generator: {...GENERATOR, ...handlers}, - sourceMap - }) - const map = sourceMap ? sourceMap.toJSON() : undefined - - return {value, map} + const value = generate( + tree, + // @ts-expect-error: `sourceMap` can be undefined, `astring` types are buggy. + { + comments: true, + generator: {...GENERATOR, ...handlers}, + sourceMap: sourceMap || undefined } ) + const map = sourceMap ? sourceMap.toJSON() : undefined + + return {value, map} +} diff --git a/lib/jsx.js b/lib/jsx.js index 448d6f6..47e567e 100644 --- a/lib/jsx.js +++ b/lib/jsx.js @@ -1,36 +1,37 @@ /** - * @typedef {import('estree-jsx').JSXAttribute} JSXAttribute - * @typedef {import('estree-jsx').JSXClosingElement} JSXClosingElement - * @typedef {import('estree-jsx').JSXClosingFragment} JSXClosingFragment - * @typedef {import('estree-jsx').JSXElement} JSXElement - * @typedef {import('estree-jsx').JSXExpressionContainer} JSXExpressionContainer - * @typedef {import('estree-jsx').JSXFragment} JSXFragment - * @typedef {import('estree-jsx').JSXIdentifier} JSXIdentifier - * @typedef {import('estree-jsx').JSXMemberExpression} JSXMemberExpression - * @typedef {import('estree-jsx').JSXNamespacedName} JSXNamespacedName - * @typedef {import('estree-jsx').JSXOpeningElement} JSXOpeningElement - * @typedef {import('estree-jsx').JSXOpeningFragment} JSXOpeningFragment - * @typedef {import('estree-jsx').JSXSpreadAttribute} JSXSpreadAttribute - * @typedef {import('estree-jsx').JSXText} JSXText - * @typedef {import('./types.js').Generator} Generator - * @typedef {import('./types.js').State} State + * @typedef {import('estree-jsx').JSXAttribute} JsxAttribute + * @typedef {import('estree-jsx').JSXClosingElement} JsxClosingElement + * @typedef {import('estree-jsx').JSXClosingFragment} JsxClosingFragment + * @typedef {import('estree-jsx').JSXElement} JsxElement + * @typedef {import('estree-jsx').JSXExpressionContainer} JsxExpressionContainer + * @typedef {import('estree-jsx').JSXFragment} JsxFragment + * @typedef {import('estree-jsx').JSXIdentifier} JsxIdentifier + * @typedef {import('estree-jsx').JSXMemberExpression} JsxMemberExpression + * @typedef {import('estree-jsx').JSXNamespacedName} JsxNamespacedName + * @typedef {import('estree-jsx').JSXOpeningElement} JsxOpeningElement + * @typedef {import('estree-jsx').JSXOpeningFragment} JsxOpeningFragment + * @typedef {import('estree-jsx').JSXSpreadAttribute} JsxSpreadAttribute + * @typedef {import('estree-jsx').JSXText} JsxText + * + * @typedef {import('./index.js').Generator} Generator + * @typedef {import('./index.js').State} State */ export const jsx = { - JSXAttribute, - JSXClosingElement, - JSXClosingFragment, - JSXElement, - JSXEmptyExpression, - JSXExpressionContainer, - JSXFragment, - JSXIdentifier, - JSXMemberExpression, - JSXNamespacedName, - JSXOpeningElement, - JSXOpeningFragment, - JSXSpreadAttribute, - JSXText + JSXAttribute: jsxAttribute, + JSXClosingElement: jsxClosingElement, + JSXClosingFragment: jsxClosingFragment, + JSXElement: jsxElement, + JSXEmptyExpression: jsxEmptyExpression, + JSXExpressionContainer: jsxExpressionContainer, + JSXFragment: jsxFragment, + JSXIdentifier: jsxIdentifier, + JSXMemberExpression: jsxMemberExpression, + JSXNamespacedName: jsxNamespacedName, + JSXOpeningElement: jsxOpeningElement, + JSXOpeningFragment: jsxOpeningFragment, + JSXSpreadAttribute: jsxSpreadAttribute, + JSXText: jsxText } /** @@ -40,17 +41,17 @@ export const jsx = { * * @this {Generator} * `astring` generator. - * @param {JSXAttribute} node + * @param {JsxAttribute} node * Node to serialize. * @param {State} state * Info passed around. - * @returns {void} + * @returns {undefined} * Nothing. */ -function JSXAttribute(node, state) { +function jsxAttribute(node, state) { this[node.name.type](node.name, state) - if (node.value !== undefined && node.value !== null) { + if (node.value !== null && node.value !== undefined) { state.write('=') // Encode double quotes in attribute values. @@ -70,14 +71,14 @@ function JSXAttribute(node, state) { * * @this {Generator} * `astring` generator. - * @param {JSXClosingElement} node + * @param {JsxClosingElement} node * Node to serialize. * @param {State} state * Info passed around. - * @returns {void} + * @returns {undefined} * Nothing. */ -function JSXClosingElement(node, state) { +function jsxClosingElement(node, state) { state.write('') @@ -88,14 +89,14 @@ function JSXClosingElement(node, state) { * * @this {Generator} * `astring` generator. - * @param {JSXClosingFragment} node + * @param {JsxClosingFragment} node * Node to serialize. * @param {State} state * Info passed around. - * @returns {void} + * @returns {undefined} * Nothing. */ -function JSXClosingFragment(node, state) { +function jsxClosingFragment(node, state) { state.write('', node) } @@ -105,14 +106,14 @@ function JSXClosingFragment(node, state) { * * @this {Generator} * `astring` generator. - * @param {JSXElement} node + * @param {JsxElement} node * Node to serialize. * @param {State} state * Info passed around. - * @returns {void} + * @returns {undefined} * Nothing. */ -function JSXElement(node, state) { +function jsxElement(node, state) { let index = -1 this[node.openingElement.type](node.openingElement, state) @@ -141,24 +142,24 @@ function JSXElement(node, state) { * * @this {Generator} * `astring` generator. - * @returns {void} + * @returns {undefined} * Nothing. */ -function JSXEmptyExpression() {} +function jsxEmptyExpression() {} /** * `{expression}` * * @this {Generator} * `astring` generator. - * @param {JSXExpressionContainer} node + * @param {JsxExpressionContainer} node * Node to serialize. * @param {State} state * Info passed around. - * @returns {void} + * @returns {undefined} * Nothing. */ -function JSXExpressionContainer(node, state) { +function jsxExpressionContainer(node, state) { state.write('{') this[node.expression.type](node.expression, state) state.write('}') @@ -169,14 +170,14 @@ function JSXExpressionContainer(node, state) { * * @this {Generator} * `astring` generator. - * @param {JSXFragment} node + * @param {JsxFragment} node * Node to serialize. * @param {State} state * Info passed around. - * @returns {void} + * @returns {undefined} * Nothing. */ -function JSXFragment(node, state) { +function jsxFragment(node, state) { let index = -1 this[node.openingFragment.type](node.openingFragment, state) @@ -203,14 +204,14 @@ function JSXFragment(node, state) { * * @this {Generator} * `astring` generator. - * @param {JSXIdentifier} node + * @param {JsxIdentifier} node * Node to serialize. * @param {State} state * Info passed around. - * @returns {void} + * @returns {undefined} * Nothing. */ -function JSXIdentifier(node, state) { +function jsxIdentifier(node, state) { state.write(node.name, node) } @@ -219,14 +220,14 @@ function JSXIdentifier(node, state) { * * @this {Generator} * `astring` generator. - * @param {JSXMemberExpression} node + * @param {JsxMemberExpression} node * Node to serialize. * @param {State} state * Info passed around. - * @returns {void} + * @returns {undefined} * Nothing. */ -function JSXMemberExpression(node, state) { +function jsxMemberExpression(node, state) { this[node.object.type](node.object, state) state.write('.') this[node.property.type](node.property, state) @@ -237,14 +238,14 @@ function JSXMemberExpression(node, state) { * * @this {Generator} * `astring` generator. - * @param {JSXNamespacedName} node + * @param {JsxNamespacedName} node * Node to serialize. * @param {State} state * Info passed around. - * @returns {void} + * @returns {undefined} * Nothing. */ -function JSXNamespacedName(node, state) { +function jsxNamespacedName(node, state) { this[node.namespace.type](node.namespace, state) state.write(':') this[node.name.type](node.name, state) @@ -255,14 +256,14 @@ function JSXNamespacedName(node, state) { * * @this {Generator} * `astring` generator. - * @param {JSXOpeningElement} node + * @param {JsxOpeningElement} node * Node to serialize. * @param {State} state * Info passed around. - * @returns {void} + * @returns {undefined} * Nothing. */ -function JSXOpeningElement(node, state) { +function jsxOpeningElement(node, state) { let index = -1 state.write('<') @@ -283,14 +284,14 @@ function JSXOpeningElement(node, state) { * * @this {Generator} * `astring` generator. - * @param {JSXOpeningFragment} node + * @param {JsxOpeningFragment} node * Node to serialize. * @param {State} state * Info passed around. - * @returns {void} + * @returns {undefined} * Nothing. */ -function JSXOpeningFragment(node, state) { +function jsxOpeningFragment(node, state) { state.write('<>', node) } @@ -299,14 +300,14 @@ function JSXOpeningFragment(node, state) { * * @this {Generator} * `astring` generator. - * @param {JSXSpreadAttribute} node + * @param {JsxSpreadAttribute} node * Node to serialize. * @param {State} state * Info passed around. - * @returns {void} + * @returns {undefined} * Nothing. */ -function JSXSpreadAttribute(node, state) { +function jsxSpreadAttribute(node, state) { state.write('{') // eslint-disable-next-line new-cap this.SpreadElement(node, state) @@ -318,26 +319,15 @@ function JSXSpreadAttribute(node, state) { * * @this {Generator} * `astring` generator. - * @param {JSXText} node + * @param {JsxText} node * Node to serialize. * @param {State} state * Info passed around. - * @returns {void} + * @returns {undefined} * Nothing. */ -function JSXText(node, state) { - state.write( - encodeJsx(node.value).replace(/[<>{}]/g, ($0) => - $0 === '<' - ? '<' - : $0 === '>' - ? '>' - : $0 === '{' - ? '{' - : '}' - ), - node - ) +function jsxText(node, state) { + state.write(encodeJsx(node.value).replace(/[<>{}]/g, replaceJsxChar), node) } /** @@ -358,3 +348,17 @@ function JSXText(node, state) { function encodeJsx(value) { return value.replace(/&(?=[#a-z])/gi, '&') } + +/** + * @param {string} $0 + * @returns {string} + */ +function replaceJsxChar($0) { + return $0 === '<' + ? '<' + : $0 === '>' + ? '>' + : $0 === '{' + ? '{' + : '}' +} diff --git a/lib/types.js b/lib/types.js deleted file mode 100644 index a67204a..0000000 --- a/lib/types.js +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @typedef {import('estree-jsx').Node} Node - * @typedef {import('source-map').Mapping} Mapping - */ - -// To do: `astring` types are broken. -// Either `import('astring').State` if everything is fixed, or: -// `Omit & {write: ((code: string, node?: Node) => void)}` -/** - * @typedef State - * @property {string} output - * @property {(code: string, node?: Node) => void} write - * @property {boolean} writeComments - * @property {string} indent - * @property {string} lineEnd - * @property {number} indentLevel - * @property {number | undefined} [line] - * @property {number | undefined} [column] - * @property {number | undefined} [lineEndSize] - * @property {Mapping | undefined} [mapping] - */ - -/** - * @typedef {Record} Generator - * @typedef {Partial} Handlers - * Handlers for different nodes. - * - * @callback Handler - * Handle a particular node. - * @param {Generator} this - * `astring` generator. - * @param {any} node - * Node to serialize. - * @param {State} state - * Info passed around. - * @returns {void} - * Nothing. - */ - -export {} diff --git a/package.json b/package.json index 06f19aa..781eae0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "estree-util-to-js", - "version": "1.2.0", + "version": "2.0.0", "description": "estree (and esast) utility to serialize to JavaScript", "license": "MIT", "keywords": [ @@ -29,8 +29,7 @@ ], "sideEffects": false, "type": "module", - "main": "index.js", - "types": "index.d.ts", + "exports": "./index.js", "files": [ "lib/", "index.d.ts", @@ -42,45 +41,50 @@ "source-map": "^0.7.0" }, "devDependencies": { - "@types/node": "^18.0.0", - "c8": "^7.0.0", - "prettier": "^2.0.0", + "@types/node": "^20.0.0", + "c8": "^8.0.0", + "prettier": "^3.0.0", "remark-cli": "^11.0.0", "remark-preset-wooorm": "^9.0.0", "type-coverage": "^2.0.0", - "typescript": "^4.0.0", - "xo": "^0.53.0" + "typescript": "^5.0.0", + "xo": "^0.55.0" }, "scripts": { "prepack": "npm run build && npm run format", "build": "tsc --build --clean && tsc --build && type-coverage", - "format": "remark . -qfo && prettier . -w --loglevel warn && xo --fix", + "format": "remark . -qfo && prettier . -w --log-level warn && xo --fix", "test-api": "node --conditions development test/index.js", - "test-coverage": "c8 --check-coverage --100 --reporter lcov npm run test-api", + "test-coverage": "c8 --100 --reporter lcov npm run test-api", "test": "npm run build && npm run format && npm run test-coverage" }, "prettier": { - "tabWidth": 2, - "useTabs": false, - "singleQuote": true, "bracketSpacing": false, "semi": false, - "trailingComma": "none" - }, - "xo": { - "prettier": true + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "none", + "useTabs": false }, "remarkConfig": { "plugins": [ - "preset-wooorm" + "remark-preset-wooorm" ] }, "typeCoverage": { "atLeast": 100, "detail": true, - "strict": true, + "ignoreCatch": true, + "#": "needed `any`s", "ignoreFiles": [ - "lib/types.d.ts" - ] + "lib/index.d.ts" + ], + "strict": true + }, + "xo": { + "prettier": true, + "rules": { + "unicorn/prefer-string-replace-all": "off" + } } } diff --git a/readme.md b/readme.md index 8997d38..39f9a59 100644 --- a/readme.md +++ b/readme.md @@ -56,7 +56,7 @@ It turns JS into esast. ## Install This package is [ESM only][esm]. -In Node.js (version 14.14+ and 16.0+), install with [npm][]: +In Node.js (version 16+), install with [npm][]: ```sh npm install estree-util-to-js @@ -65,14 +65,14 @@ npm install estree-util-to-js In Deno with [`esm.sh`][esmsh]: ```js -import {toJs} from 'https://esm.sh/estree-util-to-js@1' +import {toJs} from 'https://esm.sh/estree-util-to-js@2' ``` In browsers with [`esm.sh`][esmsh]: ```html ``` @@ -140,7 +140,7 @@ Handle a particular node (TypeScript type). ###### Returns -Nothing (`void`). +Nothing (`undefined`). ### `Handlers` @@ -287,7 +287,7 @@ Modified example from § Use above: -import {toJs} from 'estree-util-to-js' +import {Parser} from 'acorn' +import acornJsx from 'acorn-jsx' -+import {toJs, jsx} from 'estree-util-to-js' ++import {jsx, toJs} from 'estree-util-to-js' -const file = String(await fs.readFile('index.js')) +const file = '<>{1 + 1}' @@ -322,10 +322,13 @@ It exports the additional types [`Handler`][api-handler], ## Compatibility -Projects maintained by the unified collective are compatible with all maintained +Projects maintained by the unified collective are compatible with maintained versions of Node.js. -As of now, that is Node.js 14.14+, 16.0+, and 18.0+. -Our projects sometimes work with older versions, but this is not guaranteed. + +When we cut a new major release, we drop support for unmaintained versions of +Node. +This means we try to keep the current release line, `estree-util-to-js@^2`, +compatible with Node.js 16. ## Contribute @@ -355,9 +358,9 @@ abide by its terms. [downloads]: https://www.npmjs.com/package/estree-util-to-js -[size-badge]: https://img.shields.io/bundlephobia/minzip/estree-util-to-js.svg +[size-badge]: https://img.shields.io/badge/dynamic/json?label=minzipped%20size&query=$.size.compressedSize&url=https://deno.bundlejs.com/?q=estree-util-to-js -[size]: https://bundlephobia.com/result?p=estree-util-to-js +[size]: https://bundlejs.com/?q=estree-util-to-js [sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg diff --git a/test/index.js b/test/index.js index 6283b74..c089613 100644 --- a/test/index.js +++ b/test/index.js @@ -6,26 +6,26 @@ import assert from 'node:assert/strict' import test from 'node:test' import {Parser} from 'acorn' import acornJsx from 'acorn-jsx' +import {jsx, toJs} from 'estree-util-to-js' import {SourceMapGenerator} from 'source-map' -import {toJs, jsx} from '../index.js' -import * as mod from '../index.js' -test('toJs', () => { - assert.deepEqual( - Object.keys(mod).sort(), - ['jsx', 'toJs'], - 'should expose the public api' - ) +test('toJs', async function (t) { + await t.test('should expose the public api', async function () { + assert.deepEqual(Object.keys(await import('estree-util-to-js')).sort(), [ + 'jsx', + 'toJs' + ]) + }) - assert.deepEqual( - toJs(fromJs('const a = 1')), - {value: 'const a = 1;\n', map: undefined}, - 'should serialize js' - ) + await t.test('should serialize js', async function () { + assert.deepEqual(toJs(fromJs('const a = 1')), { + value: 'const a = 1;\n', + map: undefined + }) + }) - assert.deepEqual( - toJs(fromJs('const a = 1'), {SourceMapGenerator}), - { + await t.test('should serialize js w/ a source map', async function () { + assert.deepEqual(toJs(fromJs('const a = 1'), {SourceMapGenerator}), { value: 'const a = 1;\n', map: { version: 3, @@ -34,84 +34,107 @@ test('toJs', () => { mappings: 'MAAMA,IAAI', file: '.js' } - }, - 'should serialize js w/ a source map' - ) + }) + }) - assert.deepEqual( - toJs(fromJs('const a = 1'), {SourceMapGenerator, filePath: 'example.js'}), - { - value: 'const a = 1;\n', - map: { - version: 3, - sources: ['example.js'], - names: ['a'], - mappings: 'MAAMA,IAAI', - file: 'example.js' - } - }, - 'should serialize js w/ a source map and a file path' + await t.test( + 'should serialize js w/ a source map and a file path', + async function () { + assert.deepEqual( + toJs(fromJs('const a = 1'), { + SourceMapGenerator, + filePath: 'example.js' + }), + { + value: 'const a = 1;\n', + map: { + version: 3, + sources: ['example.js'], + names: ['a'], + mappings: 'MAAMA,IAAI', + file: 'example.js' + } + } + ) + } ) - assert.equal( - toJs(fromJs('1', true), {handlers: jsx}).value, - '1;\n', - 'should supports jsx (opening and closing tag)' + await t.test( + 'should supports jsx (opening and closing tag)', + async function () { + assert.equal( + toJs(fromJs('1', true), {handlers: jsx}).value, + '1;\n' + ) + } ) - assert.equal( - toJs(fromJs('<>1', true), {handlers: jsx}).value, - '<>1;\n', - 'should supports jsx (opening and closing fragment)' + await t.test( + 'should supports jsx (opening and closing fragment)', + async function () { + assert.equal( + toJs(fromJs('<>1', true), {handlers: jsx}).value, + '<>1;\n' + ) + } ) - assert.equal( - toJs(fromJs('', true), {handlers: jsx}).value, - ';\n', - 'should supports jsx (member name)' - ) + await t.test('should supports jsx (member name)', async function () { + assert.equal( + toJs(fromJs('', true), {handlers: jsx}).value, + ';\n' + ) + }) - assert.equal( - toJs(fromJs('', true), {handlers: jsx}).value, - ';\n', - 'should supports jsx (namespaced name)' - ) + await t.test('should supports jsx (namespaced name)', async function () { + assert.equal( + toJs(fromJs('', true), {handlers: jsx}).value, + ';\n' + ) + }) - assert.equal( - toJs(fromJs('', true), {handlers: jsx}).value, - ';\n', - 'should supports jsx (attributes)' - ) + await t.test('should supports jsx (attributes)', async function () { + assert.equal( + toJs(fromJs('', true), {handlers: jsx}).value, + ';\n' + ) + }) - assert.equal( - toJs(fromJs('', true), {handlers: jsx}).value, - ';\n', - 'should supports jsx (namespaced attribute)' - ) + await t.test('should supports jsx (namespaced attribute)', async function () { + assert.equal( + toJs(fromJs('', true), {handlers: jsx}).value, + ';\n' + ) + }) - assert.equal( - toJs(fromJs('empty: {}, comment: {/*b*/}, value: {1}', true), { - handlers: jsx - }).value, - 'empty: {}, comment: {}, value: {1};\n', - 'should supports jsx (expressions)' - ) + await t.test('should supports jsx (expressions)', async function () { + assert.equal( + toJs(fromJs('empty: {}, comment: {/*b*/}, value: {1}', true), { + handlers: jsx + }).value, + 'empty: {}, comment: {}, value: {1};\n' + ) + }) - assert.equal( - toJs(fromJs('1 < 2 > 3 { 4 } 5', true), { - handlers: jsx - }).value, - '1 < 2 > 3 { 4 } 5;\n', - 'should supports jsx (text)' - ) + await t.test('should supports jsx (text)', async function () { + assert.equal( + toJs(fromJs('1 < 2 > 3 { 4 } 5', true), { + handlers: jsx + }).value, + '1 < 2 > 3 { 4 } 5;\n' + ) + }) }) /** * @param {string} value - * @param {boolean} [jsx=false] + * JavaScript. + * @param {boolean | null | undefined} [jsx=false] + * Whether to parse as JSX (default: `false`). * @returns {Program} + * ESTree program. */ -function fromJs(value, jsx = false) { +function fromJs(value, jsx) { const parser = jsx ? Parser.extend(acornJsx()) : Parser // @ts-expect-error: fine. return parser.parse(value, { diff --git a/tsconfig.json b/tsconfig.json index 1bc9e99..82cc749 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,17 +1,15 @@ { - "include": ["**/**.js"], - "exclude": ["coverage/", "node_modules/"], "compilerOptions": { "checkJs": true, + "customConditions": ["development"], "declaration": true, "emitDeclarationOnly": true, "exactOptionalPropertyTypes": true, - "forceConsistentCasingInFileNames": true, - "lib": ["es2020"], + "lib": ["es2022"], "module": "node16", - "newLine": "lf", - "skipLibCheck": true, "strict": true, - "target": "es2020" - } + "target": "es2022" + }, + "exclude": ["coverage/", "node_modules/"], + "include": ["**/*.js"] } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy