|
1 | 1 | /**
|
| 2 | + * @typedef {import('astring').State} State |
| 3 | + * @typedef {import('estree-jsx').Node} Nodes |
2 | 4 | * @typedef {import('estree-jsx').Program} Program
|
3 | 5 | * @typedef {typeof import('source-map').SourceMapGenerator} SourceMapGenerator
|
4 | 6 | * @typedef {import('source-map').RawSourceMap} Map
|
5 |
| - * @typedef {import('./types.js').Handlers} Handlers |
6 | 7 | */
|
7 | 8 |
|
8 | 9 | /**
|
9 |
| - * @typedef BaseFields |
| 10 | + * @typedef {Record<Nodes['type'], Handler>} Generator |
| 11 | + * |
| 12 | + * @callback Handler |
| 13 | + * Handle a particular node. |
| 14 | + * @param {Generator} this |
| 15 | + * `astring` generator. |
| 16 | + * @param {any} node |
| 17 | + * Node to serialize. |
| 18 | + * @param {State} state |
| 19 | + * Info passed around. |
| 20 | + * @returns {undefined} |
| 21 | + * Nothing. |
| 22 | + * |
| 23 | + * @typedef {Partial<import('astring').Generator>} Handlers |
| 24 | + */ |
| 25 | + |
| 26 | +/** |
| 27 | + * @typedef {OptionsWithMaybeMapGenerator} Options |
| 28 | + * Configuration. |
| 29 | + * |
| 30 | + * @typedef OptionsFieldsBase |
| 31 | + * Base shared option fields. |
10 | 32 | * @property {Handlers | null | undefined} [handlers]
|
11 | 33 | * Object mapping node types to functions handling the corresponding nodes.
|
12 | 34 | *
|
13 |
| - * @typedef SourceMapFieldsWithoutSourceMapGenerator |
| 35 | + * @typedef OptionsFieldsWithoutSourceMapGenerator |
| 36 | + * Extra option fields where there’s definitely no source map generator. |
14 | 37 | * @property {null | undefined} [SourceMapGenerator]
|
15 | 38 | * Generate a source map by passing a `SourceMapGenerator` from `source-map`
|
16 |
| - * in. |
17 |
| - * This works if there is positional info on nodes. |
| 39 | + * in; this works if there is positional info on nodes. |
18 | 40 | * @property {null | undefined} [filePath]
|
19 |
| - * Path to input file. |
20 |
| - * Only used in source map. |
| 41 | + * Path to input file; only used in source map. |
21 | 42 | *
|
22 |
| - * @typedef SourceMapFieldsWithSourceMapGenerator |
| 43 | + * @typedef OptionsFieldsWithSourceMapGenerator |
| 44 | + * Extra option fields where there’s definitely a source map generator. |
23 | 45 | * @property {SourceMapGenerator} SourceMapGenerator
|
24 | 46 | * Generate a source map by passing a `SourceMapGenerator` from `source-map`
|
25 |
| - * in. |
26 |
| - * This works if there is positional info on nodes. |
| 47 | + * in; this works if there is positional info on nodes. |
27 | 48 | * @property {string | null | undefined} [filePath]
|
28 |
| - * Path to input file. |
29 |
| - * Only used in source map. |
| 49 | + * Path to input file; only used in source map. |
30 | 50 | *
|
31 |
| - * @typedef SourceMapFieldsMaybeSourceMapGenerator |
32 |
| - * @property {SourceMapGenerator | null | undefined} SourceMapGenerator |
| 51 | + * @typedef OptionsFieldsMaybeSourceMapGenerator |
| 52 | + * Extra option fields where there may or may not be a source map generator. |
| 53 | + * @property {SourceMapGenerator | null | undefined} [SourceMapGenerator] |
33 | 54 | * Generate a source map by passing a `SourceMapGenerator` from `source-map`
|
34 |
| - * in. |
35 |
| - * This works if there is positional info on nodes. |
| 55 | + * in; this works if there is positional info on nodes. |
36 | 56 | * @property {string | null | undefined} [filePath]
|
37 |
| - * Path to input file. |
38 |
| - * Only used in source map. |
| 57 | + * Path to input file; only used in source map. |
39 | 58 | *
|
40 |
| - * @typedef {BaseFields & SourceMapFieldsWithoutSourceMapGenerator} OptionsWithoutSourceMapGenerator |
41 |
| - * @typedef {BaseFields & SourceMapFieldsWithSourceMapGenerator} OptionsWithSourceMapGenerator |
42 |
| - * @typedef {BaseFields & SourceMapFieldsMaybeSourceMapGenerator} OptionsWithMaybeMapGenerator |
| 59 | + * @typedef {OptionsFieldsBase & OptionsFieldsWithoutSourceMapGenerator} OptionsWithoutSourceMapGenerator |
| 60 | + * Options where there’s definitely no source map generator. |
| 61 | + * @typedef {OptionsFieldsBase & OptionsFieldsWithSourceMapGenerator} OptionsWithSourceMapGenerator |
| 62 | + * Options where there’s definitely a source map generator. |
| 63 | + * @typedef {OptionsFieldsBase & OptionsFieldsMaybeSourceMapGenerator} OptionsWithMaybeMapGenerator |
| 64 | + * Options where there may or may not be a source map generator. |
43 | 65 | *
|
44 |
| - * @typedef {OptionsWithMaybeMapGenerator} Options |
45 |
| - * Configuration (optional). |
| 66 | + * @typedef {ResultWithMaybeSourceMapGenerator} Result |
| 67 | + * Result. |
46 | 68 | *
|
47 |
| - * @typedef BaseResultFields |
| 69 | + * @typedef ResultFieldsBase |
| 70 | + * Base shared result fields. |
48 | 71 | * @property {string} value
|
49 | 72 | * Serialized JavaScript.
|
50 | 73 | *
|
51 | 74 | * @typedef ResultFieldsWithoutSourceMapGenerator
|
| 75 | + * Extra result fields where there’s definitely no source map generator. |
52 | 76 | * @property {undefined} map
|
53 | 77 | * Source map as (parsed) JSON, if `SourceMapGenerator` is passed.
|
54 | 78 | *
|
55 | 79 | * @typedef ResultFieldsWithSourceMapGenerator
|
| 80 | + * Extra result fields where there’s definitely a source map generator. |
56 | 81 | * @property {Map} map
|
57 | 82 | * Source map as (parsed) JSON, if `SourceMapGenerator` is not passed.
|
58 | 83 | *
|
59 | 84 | * @typedef ResultFieldsMaybeSourceMapGenerator
|
| 85 | + * Extra result fields where there may or may not be a source map generator. |
60 | 86 | * @property {Map | undefined} map
|
61 | 87 | * Source map as (parsed) JSON, if `SourceMapGenerator` might be passed.
|
62 | 88 | *
|
63 |
| - * @typedef {BaseResultFields & ResultFieldsWithoutSourceMapGenerator} ResultWithoutSourceMapGenerator |
64 |
| - * @typedef {BaseResultFields & ResultFieldsWithSourceMapGenerator} ResultWithSourceMapGenerator |
65 |
| - * @typedef {BaseResultFields & ResultFieldsMaybeSourceMapGenerator} ResultMaybeSourceMapGenerator |
66 |
| - * |
67 |
| - * @typedef {ResultMaybeSourceMapGenerator} Result |
| 89 | + * @typedef {ResultFieldsBase & ResultFieldsWithoutSourceMapGenerator} ResultWithoutSourceMapGenerator |
| 90 | + * Result where there’s definitely no source map generator. |
| 91 | + * @typedef {ResultFieldsBase & ResultFieldsWithSourceMapGenerator} ResultWithSourceMapGenerator |
| 92 | + * Result where there’s definitely a source map generator. |
| 93 | + * @typedef {ResultFieldsBase & ResultFieldsMaybeSourceMapGenerator} ResultWithMaybeSourceMapGenerator |
| 94 | + * Result where there may or may not be a source map generator. |
68 | 95 | */
|
69 | 96 |
|
70 |
| -import * as astring from 'astring' |
| 97 | +import {GENERATOR, generate} from 'astring' |
71 | 98 |
|
72 |
| -/** @type {Handlers} */ |
73 |
| -const GENERATOR = astring.GENERATOR |
74 |
| - |
75 |
| -const generate = astring.generate |
| 99 | +/** @type {Options} */ |
| 100 | +const emptyOptions = {} |
76 | 101 |
|
77 | 102 | /**
|
78 | 103 | * Serialize an estree as JavaScript.
|
79 | 104 | *
|
80 |
| - * @param tree |
| 105 | + * @overload |
| 106 | + * @param {Program} tree |
| 107 | + * @param {OptionsWithSourceMapGenerator} options |
| 108 | + * @returns {ResultWithSourceMapGenerator} |
| 109 | + * |
| 110 | + * @overload |
| 111 | + * @param {Program} tree |
| 112 | + * @param {OptionsWithMaybeMapGenerator} options |
| 113 | + * @returns {ResultWithMaybeSourceMapGenerator} |
| 114 | + * |
| 115 | + * @overload |
| 116 | + * @param {Program} tree |
| 117 | + * @param {OptionsWithoutSourceMapGenerator | null | undefined} [options] |
| 118 | + * @returns {ResultWithoutSourceMapGenerator} |
| 119 | + * |
| 120 | + * @param {Program} tree |
81 | 121 | * Estree (esast).
|
82 |
| - * @param options |
| 122 | + * @param {Options | null | undefined} [options] |
83 | 123 | * Configuration (optional).
|
84 |
| - * @returns |
| 124 | + * @returns {Result} |
85 | 125 | * Result, optionally with source map.
|
86 | 126 | */
|
87 |
| -export const toJs = |
88 |
| - /** |
89 |
| - * @type {( |
90 |
| - * ((value: Program, options: OptionsWithSourceMapGenerator) => ResultWithSourceMapGenerator) & |
91 |
| - * ((value: Program, options: OptionsWithMaybeMapGenerator) => ResultMaybeSourceMapGenerator) & |
92 |
| - * ((value: Program, options?: OptionsWithoutSourceMapGenerator | null | undefined) => ResultWithoutSourceMapGenerator) |
93 |
| - * )} |
94 |
| - */ |
95 |
| - ( |
96 |
| - /** |
97 |
| - * @param {Program} tree |
98 |
| - * @param {Options | null | undefined} [options] |
99 |
| - * @returns {Result} |
100 |
| - */ |
101 |
| - function (tree, options) { |
102 |
| - const {SourceMapGenerator, filePath, handlers} = options || {} |
103 |
| - const sourceMap = SourceMapGenerator |
104 |
| - ? new SourceMapGenerator({file: filePath || '<unknown>.js'}) |
105 |
| - : undefined |
| 127 | +export function toJs(tree, options) { |
| 128 | + const {SourceMapGenerator, filePath, handlers} = options || emptyOptions |
| 129 | + const sourceMap = SourceMapGenerator |
| 130 | + ? new SourceMapGenerator({file: filePath || '<unknown>.js'}) |
| 131 | + : undefined |
106 | 132 |
|
107 |
| - const value = generate(tree, { |
108 |
| - comments: true, |
109 |
| - // @ts-expect-error: assume all handlers are defined. |
110 |
| - generator: {...GENERATOR, ...handlers}, |
111 |
| - sourceMap |
112 |
| - }) |
113 |
| - const map = sourceMap ? sourceMap.toJSON() : undefined |
114 |
| - |
115 |
| - return {value, map} |
| 133 | + const value = generate( |
| 134 | + tree, |
| 135 | + // @ts-expect-error: `sourceMap` can be undefined, `astring` types are buggy. |
| 136 | + { |
| 137 | + comments: true, |
| 138 | + generator: {...GENERATOR, ...handlers}, |
| 139 | + sourceMap: sourceMap || undefined |
116 | 140 | }
|
117 | 141 | )
|
| 142 | + const map = sourceMap ? sourceMap.toJSON() : undefined |
| 143 | + |
| 144 | + return {value, map} |
| 145 | +} |
0 commit comments