@knighted/jsx 1.6.3 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/cjs/loader/dom-template-builder.cjs +217 -0
  2. package/dist/cjs/loader/dom-template-builder.d.cts +12 -0
  3. package/dist/cjs/loader/helpers/dom-snippets.cjs +149 -0
  4. package/dist/cjs/loader/helpers/dom-snippets.d.cts +2 -0
  5. package/dist/cjs/loader/helpers/format-import-specifier.cjs +30 -0
  6. package/dist/cjs/loader/helpers/format-import-specifier.d.cts +13 -0
  7. package/dist/cjs/loader/helpers/materialize-slice.cjs +37 -0
  8. package/dist/cjs/loader/helpers/materialize-slice.d.cts +1 -0
  9. package/dist/cjs/loader/helpers/parse-range-key.cjs +14 -0
  10. package/dist/cjs/loader/helpers/parse-range-key.d.cts +1 -0
  11. package/dist/cjs/loader/helpers/rewrite-imports-without-tags.cjs +62 -0
  12. package/dist/cjs/loader/helpers/rewrite-imports-without-tags.d.cts +3 -0
  13. package/dist/cjs/loader/jsx.cjs +32 -33
  14. package/dist/cjs/loader/jsx.d.cts +1 -1
  15. package/dist/cjs/loader/modes.cjs +17 -0
  16. package/dist/cjs/loader/modes.d.cts +3 -0
  17. package/dist/cjs/runtime/shared.cjs +3 -13
  18. package/dist/cjs/shared/normalize-text.cjs +22 -0
  19. package/dist/cjs/shared/normalize-text.d.cts +1 -0
  20. package/dist/lite/debug/index.js +7 -7
  21. package/dist/lite/index.js +7 -7
  22. package/dist/lite/node/debug/index.js +7 -7
  23. package/dist/lite/node/index.js +7 -7
  24. package/dist/lite/node/react/index.js +5 -5
  25. package/dist/lite/react/index.js +5 -5
  26. package/dist/loader/dom-template-builder.d.ts +12 -0
  27. package/dist/loader/dom-template-builder.js +213 -0
  28. package/dist/loader/helpers/dom-snippets.d.ts +2 -0
  29. package/dist/loader/helpers/dom-snippets.js +146 -0
  30. package/dist/loader/helpers/format-import-specifier.d.ts +13 -0
  31. package/dist/loader/helpers/format-import-specifier.js +26 -0
  32. package/dist/loader/helpers/materialize-slice.d.ts +1 -0
  33. package/dist/loader/helpers/materialize-slice.js +33 -0
  34. package/dist/loader/helpers/parse-range-key.d.ts +1 -0
  35. package/dist/loader/helpers/parse-range-key.js +10 -0
  36. package/dist/loader/helpers/rewrite-imports-without-tags.d.ts +3 -0
  37. package/dist/loader/helpers/rewrite-imports-without-tags.js +58 -0
  38. package/dist/loader/jsx.d.ts +1 -1
  39. package/dist/loader/jsx.js +28 -29
  40. package/dist/loader/modes.d.ts +3 -0
  41. package/dist/loader/modes.js +13 -0
  42. package/dist/runtime/shared.js +3 -13
  43. package/dist/shared/normalize-text.d.ts +1 -0
  44. package/dist/shared/normalize-text.js +18 -0
  45. package/package.json +2 -2
@@ -0,0 +1,217 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DOM_HELPER_SNIPPETS = exports.compileDomTemplate = void 0;
4
+ const oxc_parser_1 = require("oxc-parser");
5
+ const template_diagnostics_js_1 = require("../internal/template-diagnostics.cjs");
6
+ const dom_snippets_js_1 = require("./helpers/dom-snippets.cjs");
7
+ Object.defineProperty(exports, "DOM_HELPER_SNIPPETS", { enumerable: true, get: function () { return dom_snippets_js_1.DOM_HELPER_SNIPPETS; } });
8
+ const normalize_text_js_1 = require("../shared/normalize-text.cjs");
9
+ const TEMPLATE_PARSER_OPTIONS = {
10
+ lang: 'tsx',
11
+ sourceType: 'module',
12
+ range: true,
13
+ preserveParens: true,
14
+ };
15
+ const NAMESPACE_URIS = {
16
+ html: 'http://www.w3.org/1999/xhtml',
17
+ svg: 'http://www.w3.org/2000/svg',
18
+ math: 'http://www.w3.org/1998/Math/MathML',
19
+ };
20
+ const createPlaceholderMap = (placeholders) => new Map(placeholders.map(entry => [entry.marker, entry.code]));
21
+ const isLoaderPlaceholderIdentifier = (node) => {
22
+ const name = node.name;
23
+ return typeof name === 'string' && name.startsWith('__JSX_LOADER');
24
+ };
25
+ class DomTemplateBuilder {
26
+ placeholderMap;
27
+ helpers;
28
+ id = 0;
29
+ constructor(placeholderSource) {
30
+ this.placeholderMap = createPlaceholderMap(placeholderSource);
31
+ this.helpers = new Set();
32
+ }
33
+ compile(root) {
34
+ const code = this.compileNode(root, 'html');
35
+ return { code, helpers: this.helpers };
36
+ }
37
+ nextId(prefix) {
38
+ return `__jsxDom_${prefix}_${this.id++}`;
39
+ }
40
+ compileNode(node, namespace) {
41
+ if (node.type === 'JSXFragment') {
42
+ const fragVar = this.nextId('frag');
43
+ const lines = [`const ${fragVar} = document.createDocumentFragment()`];
44
+ node.children.forEach(child => {
45
+ const childExpr = this.compileChild(child, namespace);
46
+ if (childExpr) {
47
+ this.helpers.add('dom');
48
+ lines.push(`__jsxDomAppend(${fragVar}, ${childExpr})`);
49
+ }
50
+ });
51
+ lines.push(`return ${fragVar}`);
52
+ return `(() => { ${lines.join('; ')} })()`;
53
+ }
54
+ const { tagExpr, namespace: tagNs } = this.compileTagName(node.openingElement.name);
55
+ const resolvedNs = tagNs ?? namespace;
56
+ const creator = resolvedNs === 'html'
57
+ ? `document.createElement(${tagExpr})`
58
+ : `document.createElementNS('${NAMESPACE_URIS[resolvedNs]}', ${tagExpr})`;
59
+ const elVar = this.nextId('el');
60
+ const lines = [`const ${elVar} = ${creator}`];
61
+ node.openingElement.attributes.forEach(attr => {
62
+ if (attr.type === 'JSXSpreadAttribute') {
63
+ this.helpers.add('dom');
64
+ const value = this.compileExpression(attr.argument);
65
+ lines.push(`__jsxDomAssignProps(${elVar}, ${value}, '${resolvedNs}')`);
66
+ return;
67
+ }
68
+ const name = this.compileAttributeName(attr.name);
69
+ const valueExpr = this.compileAttributeValue(attr);
70
+ if (!valueExpr) {
71
+ /* c8 ignore next */
72
+ return;
73
+ }
74
+ this.helpers.add('dom');
75
+ lines.push(`__jsxDomSetProp(${elVar}, ${name}, ${valueExpr}, '${resolvedNs}')`);
76
+ });
77
+ node.children.forEach(child => {
78
+ const childExpr = this.compileChild(child, resolvedNs);
79
+ if (childExpr) {
80
+ this.helpers.add('dom');
81
+ lines.push(`__jsxDomAppend(${elVar}, ${childExpr})`);
82
+ }
83
+ });
84
+ lines.push(`return ${elVar}`);
85
+ return `(() => { ${lines.join('; ')} })()`;
86
+ }
87
+ compileAttributeValue(attr) {
88
+ if (!attr.value) {
89
+ return 'true';
90
+ }
91
+ if (attr.value.type === 'Literal') {
92
+ return JSON.stringify(attr.value.value);
93
+ }
94
+ if (attr.value.type === 'JSXExpressionContainer') {
95
+ const expr = attr.value.expression;
96
+ if (expr.type === 'JSXEmptyExpression') {
97
+ /* c8 ignore next */
98
+ return null;
99
+ }
100
+ return this.compileExpression(expr);
101
+ }
102
+ /* c8 ignore next */
103
+ return 'undefined';
104
+ }
105
+ compileAttributeName(name) {
106
+ if (name.type === 'JSXIdentifier') {
107
+ return JSON.stringify(name.name);
108
+ }
109
+ if (name.type === 'JSXNamespacedName') {
110
+ return JSON.stringify(`${name.namespace.name}:${name.name.name}`);
111
+ }
112
+ if (name.type === 'JSXMemberExpression') {
113
+ return JSON.stringify(`${this.compileAttributeName(name.object).replace(/"/g, '')}.${name.property.name}`);
114
+ }
115
+ /* c8 ignore next */
116
+ return '""';
117
+ }
118
+ compileChild(child, namespace) {
119
+ switch (child.type) {
120
+ case 'JSXText': {
121
+ const text = (0, normalize_text_js_1.normalizeJsxText)(child.value);
122
+ if (!text)
123
+ return null;
124
+ return JSON.stringify(text);
125
+ }
126
+ case 'JSXExpressionContainer': {
127
+ if (child.expression.type === 'JSXEmptyExpression')
128
+ return null;
129
+ return this.compileExpression(child.expression);
130
+ }
131
+ case 'JSXSpreadChild': {
132
+ return this.compileExpression(child.expression);
133
+ }
134
+ case 'JSXElement':
135
+ case 'JSXFragment': {
136
+ return this.compileNode(child, namespace);
137
+ }
138
+ default:
139
+ /* c8 ignore next */
140
+ return null;
141
+ }
142
+ }
143
+ compileTagName(name) {
144
+ if (!name) {
145
+ /* c8 ignore next */
146
+ throw new Error('[jsx-loader] Encountered JSX element without a tag name.');
147
+ }
148
+ if (name.type === 'JSXIdentifier') {
149
+ if (isLoaderPlaceholderIdentifier(name)) {
150
+ const resolved = this.placeholderMap.get(name.name);
151
+ if (!resolved) {
152
+ throw new Error('[jsx-loader] Unable to resolve placeholder for tag expression.');
153
+ }
154
+ return { tagExpr: resolved, namespace: null };
155
+ }
156
+ const tagName = name.name;
157
+ const lower = tagName.toLowerCase();
158
+ if (lower === 'svg')
159
+ return { tagExpr: JSON.stringify(tagName), namespace: 'svg' };
160
+ if (lower === 'math')
161
+ return { tagExpr: JSON.stringify(tagName), namespace: 'math' };
162
+ return { tagExpr: JSON.stringify(tagName), namespace: null };
163
+ }
164
+ if (name.type === 'JSXMemberExpression') {
165
+ const tagExpr = `${this.compileAttributeName(name.object).replace(/"/g, '')}.${name.property.name}`;
166
+ return { tagExpr: JSON.stringify(tagExpr), namespace: null };
167
+ }
168
+ if (name.type === 'JSXNamespacedName') {
169
+ const tagExpr = `${name.namespace.name}:${name.name.name}`;
170
+ return { tagExpr: JSON.stringify(tagExpr), namespace: null };
171
+ }
172
+ /* c8 ignore next */
173
+ throw new Error('[jsx-loader] Unsupported tag expression in dom mode.');
174
+ }
175
+ compileExpression(node) {
176
+ if (node.type === 'JSXElement' || node.type === 'JSXFragment') {
177
+ return this.compileNode(node, 'html');
178
+ }
179
+ if (node.type === 'Identifier') {
180
+ const resolved = this.placeholderMap.get(node.name);
181
+ if (resolved)
182
+ return resolved;
183
+ return node.name;
184
+ }
185
+ if (node.type === 'Literal') {
186
+ return JSON.stringify(node.value);
187
+ }
188
+ if ('range' in node && Array.isArray(node.range)) {
189
+ throw new Error('[jsx-loader] Unable to inline complex expressions in dom mode.');
190
+ }
191
+ /* c8 ignore next */
192
+ throw new Error('[jsx-loader] Unable to compile expression for dom mode.');
193
+ }
194
+ }
195
+ const compileDomTemplate = (templateSource, placeholders, resourcePath, tagName, templates, diagnostics) => {
196
+ const parsed = (0, oxc_parser_1.parseSync)(`${resourcePath}?jsx-dom-template`, templateSource, TEMPLATE_PARSER_OPTIONS);
197
+ if (parsed.errors.length > 0) {
198
+ throw new Error((0, template_diagnostics_js_1.formatTaggedTemplateParserError)(tagName, templates, diagnostics, parsed.errors[0], {
199
+ label: 'jsx-loader',
200
+ }));
201
+ }
202
+ const root = extractJsxRoot(parsed.program);
203
+ const builder = new DomTemplateBuilder(placeholders);
204
+ return builder.compile(root);
205
+ };
206
+ exports.compileDomTemplate = compileDomTemplate;
207
+ const extractJsxRoot = (program) => {
208
+ for (const statement of program.body) {
209
+ if (statement.type === 'ExpressionStatement') {
210
+ const expression = statement.expression;
211
+ if (expression.type === 'JSXElement' || expression.type === 'JSXFragment') {
212
+ return expression;
213
+ }
214
+ }
215
+ }
216
+ throw new Error('[jsx-loader] Expected the template to contain a single JSX root node.');
217
+ };
@@ -0,0 +1,12 @@
1
+ import { type TemplateDiagnostics } from '../internal/template-diagnostics.cjs';
2
+ import { DOM_HELPER_SNIPPETS, type DomHelperKind } from './helpers/dom-snippets.cjs';
3
+ export type TemplatePlaceholder = {
4
+ marker: string;
5
+ code: string;
6
+ };
7
+ type DomCompileResult = {
8
+ code: string;
9
+ helpers: Set<DomHelperKind>;
10
+ };
11
+ export declare const compileDomTemplate: (templateSource: string, placeholders: TemplatePlaceholder[], resourcePath: string, tagName: string, templates: TemplateStringsArray, diagnostics: TemplateDiagnostics) => DomCompileResult;
12
+ export { DOM_HELPER_SNIPPETS };
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DOM_HELPER_SNIPPETS = void 0;
4
+ exports.DOM_HELPER_SNIPPETS = {
5
+ dom: `const __jsxDomAppend = (parent, child) => {
6
+ if (child === null || child === undefined || typeof child === 'boolean') return
7
+ if (Array.isArray(child)) { child.forEach(entry => __jsxDomAppend(parent, entry)); return }
8
+ if (typeof child === 'object' && typeof child[Symbol.iterator] === 'function') {
9
+ for (const entry of child) __jsxDomAppend(parent, entry); return
10
+ }
11
+ if (child instanceof Node) { parent.appendChild(child); return }
12
+ parent.appendChild(document.createTextNode(String(child)))
13
+ }
14
+
15
+ const __jsxDomClass = (el, value) => {
16
+ if (value === null || value === undefined || value === false) return
17
+ if (typeof value === 'string' || typeof value === 'number') { el.classList.add(...String(value).trim().split(/\\s+/u).filter(Boolean)); return }
18
+ if (Array.isArray(value)) { value.forEach(entry => __jsxDomClass(el, entry)); return }
19
+ if (typeof value === 'object') {
20
+ Object.entries(value).forEach(([key, active]) => {
21
+ if (active) el.classList.add(key)
22
+ else el.classList.remove(key)
23
+ })
24
+ }
25
+ }
26
+
27
+ const __jsxDomStyle = (el, value) => {
28
+ if (value === null || value === undefined || value === false) return
29
+ const style = el.style
30
+ if (!style) return
31
+ if (typeof value === 'string') { style.cssText += value; return }
32
+ if (typeof value === 'object') {
33
+ Object.entries(value).forEach(([key, v]) => {
34
+ if (v === null || v === undefined) return
35
+ if (key.startsWith('--')) { style.setProperty(key, String(v)); return }
36
+ style[key] = v
37
+ })
38
+ }
39
+ }
40
+
41
+ const __jsxDomResolveHandler = (propName, value) => {
42
+ if (typeof value === 'function' || (value && typeof value === 'object' && typeof value.handleEvent === 'function')) {
43
+ return { listener: value }
44
+ }
45
+ if (!value || typeof value !== 'object' || !('handler' in value)) {
46
+ return null
47
+ }
48
+ const handler = value.handler
49
+ if (typeof handler !== 'function' && !(handler && typeof handler === 'object' && typeof handler.handleEvent === 'function')) {
50
+ return null
51
+ }
52
+ const options = value.options ? { ...value.options } : undefined
53
+ const assign = (key, v) => {
54
+ if (v === undefined || v === null) return
55
+ if (!options) options = {}
56
+ options[key] = v
57
+ }
58
+ assign('capture', value.capture)
59
+ assign('once', value.once)
60
+ assign('passive', value.passive)
61
+ assign('signal', value.signal ?? undefined)
62
+ return { listener: handler, options }
63
+ }
64
+
65
+ const __jsxDomParseEventName = raw => {
66
+ if (!raw.startsWith('on')) return null
67
+ if (raw.startsWith('on:')) {
68
+ const name = raw.slice(3)
69
+ if (!name) return null
70
+ const capture = name.endsWith('Capture')
71
+ const eventName = capture ? name.slice(0, -7) : name
72
+ if (!eventName) return null
73
+ return { eventName, capture }
74
+ }
75
+ const name = raw.slice(2)
76
+ if (!name) return null
77
+ const capture = name.endsWith('Capture')
78
+ const eventName = (capture ? name.slice(0, -7) : name).toLowerCase()
79
+ if (!eventName) return null
80
+ return { eventName, capture }
81
+ }
82
+
83
+ const __jsxDomEvent = (el, propName, value) => {
84
+ const parsed = __jsxDomParseEventName(propName)
85
+ if (!parsed) return false
86
+ const resolved = __jsxDomResolveHandler(propName, value)
87
+ if (!resolved) return true
88
+ let options = resolved.options ? { ...resolved.options } : undefined
89
+ if (parsed.capture) {
90
+ if (!options) options = { capture: true }
91
+ else options.capture = true
92
+ }
93
+ el.addEventListener(parsed.eventName, resolved.listener, options)
94
+ return true
95
+ }
96
+
97
+ const __jsxDomNamespaceForAttr = (raw, namespace) => {
98
+ if (!raw.includes(':')) return null
99
+ const prefix = raw.split(':', 1)[0]
100
+ if (prefix === 'xml') return 'http://www.w3.org/XML/1998/namespace'
101
+ if (prefix === 'xlink') return 'http://www.w3.org/1999/xlink'
102
+ if (namespace === 'svg') return 'http://www.w3.org/2000/svg'
103
+ if (namespace === 'math') return 'http://www.w3.org/1998/Math/MathML'
104
+ return null
105
+ }
106
+
107
+ const __jsxDomSetProp = (el, name, value, namespace) => {
108
+ if (value === null || value === undefined) return
109
+ if (name === 'dangerouslySetInnerHTML' && value && typeof value === 'object' && '__html' in value) {
110
+ el.innerHTML = String(value.__html ?? '')
111
+ return
112
+ }
113
+ const ns = __jsxDomNamespaceForAttr(name, namespace)
114
+ if (name === 'ref') {
115
+ if (typeof value === 'function') { value(el); return }
116
+ if (value && typeof value === 'object') { value.current = el; return }
117
+ }
118
+ if (name === 'class' || name === 'className') { __jsxDomClass(el, value); return }
119
+ if (name === 'style') { __jsxDomStyle(el, value); return }
120
+ if (__jsxDomEvent(el, name, value)) return
121
+ if (typeof value === 'boolean') {
122
+ if (value) {
123
+ if (ns) el.setAttributeNS(ns, name, '')
124
+ else el.setAttribute(name, '')
125
+ } else {
126
+ if (ns) el.removeAttributeNS(ns, name)
127
+ else el.removeAttribute(name)
128
+ }
129
+ if (name in el) { try { el[name] = value } catch {}
130
+ }
131
+ return
132
+ }
133
+ if (name.startsWith('data-')) { el.setAttribute(name, value as any); return }
134
+ if (name in el && name !== 'list') {
135
+ try { (el as any)[name] = value } catch {}
136
+ return
137
+ }
138
+ if (ns) el.setAttributeNS(ns, name, value as any)
139
+ else el.setAttribute(name, value as any)
140
+ }
141
+
142
+ const __jsxDomAssignProps = (el, props, namespace) => {
143
+ if (!props) return
144
+ Object.entries(props).forEach(([name, value]) => {
145
+ __jsxDomSetProp(el, name, value, namespace)
146
+ })
147
+ }
148
+ `,
149
+ };
@@ -0,0 +1,2 @@
1
+ export type DomHelperKind = 'dom';
2
+ export declare const DOM_HELPER_SNIPPETS: Record<DomHelperKind, string>;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatImportSpecifier = void 0;
4
+ const formatImportSpecifier = (spec) => {
5
+ const node = spec;
6
+ if (node.type === 'ImportDefaultSpecifier') {
7
+ const name = node.local?.name;
8
+ if (!name) {
9
+ throw new Error('[jsx-loader] Encountered default import without a local name.');
10
+ }
11
+ return name;
12
+ }
13
+ if (node.type === 'ImportNamespaceSpecifier') {
14
+ const name = node.local?.name;
15
+ if (!name) {
16
+ throw new Error('[jsx-loader] Encountered namespace import without a local name.');
17
+ }
18
+ return `* as ${name}`;
19
+ }
20
+ if (node.type === 'ImportSpecifier') {
21
+ const imported = node.imported?.name;
22
+ if (!imported) {
23
+ throw new Error('[jsx-loader] Encountered named import without an imported name.');
24
+ }
25
+ const local = node.local?.name ?? imported;
26
+ return imported === local ? imported : `${imported} as ${local}`;
27
+ }
28
+ return '';
29
+ };
30
+ exports.formatImportSpecifier = formatImportSpecifier;
@@ -0,0 +1,13 @@
1
+ type AnyNode = {
2
+ type: string;
3
+ local?: {
4
+ name?: string;
5
+ };
6
+ imported?: {
7
+ name?: string;
8
+ value?: string;
9
+ };
10
+ [key: string]: unknown;
11
+ };
12
+ export declare const formatImportSpecifier: (spec: AnyNode) => string;
13
+ export {};
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.materializeSlice = void 0;
4
+ const parse_range_key_js_1 = require("./parse-range-key.cjs");
5
+ const materializeSlice = (start, end, source, replacements) => {
6
+ const exact = replacements.get(`${start}:${end}`);
7
+ if (exact !== undefined) {
8
+ return exact;
9
+ }
10
+ const nested = [];
11
+ replacements.forEach((code, key) => {
12
+ const range = (0, parse_range_key_js_1.parseRangeKey)(key);
13
+ if (!range)
14
+ return;
15
+ const [rStart, rEnd] = range;
16
+ if (rStart >= start && rEnd <= end) {
17
+ nested.push({ start: rStart, end: rEnd, code });
18
+ }
19
+ });
20
+ if (!nested.length) {
21
+ return source.slice(start, end);
22
+ }
23
+ nested.sort((a, b) => a.start - b.start);
24
+ let cursor = start;
25
+ let output = '';
26
+ nested.forEach(entry => {
27
+ if (entry.start < cursor) {
28
+ throw new Error(`[jsx-loader] Overlapping replacement ranges detected (${entry.start}:${entry.end}) within ${start}:${end}. Nested replacements must not overlap.`);
29
+ }
30
+ output += source.slice(cursor, entry.start);
31
+ output += entry.code;
32
+ cursor = entry.end;
33
+ });
34
+ output += source.slice(cursor, end);
35
+ return output;
36
+ };
37
+ exports.materializeSlice = materializeSlice;
@@ -0,0 +1 @@
1
+ export declare const materializeSlice: (start: number, end: number, source: string, replacements: Map<string, string>) => string;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseRangeKey = void 0;
4
+ const parseRangeKey = (key) => {
5
+ const [start, end] = key.split(':').map(entry => Number.parseInt(entry, 10));
6
+ if (!Number.isFinite(start) || !Number.isFinite(end)) {
7
+ return null;
8
+ }
9
+ if (end < start) {
10
+ return null;
11
+ }
12
+ return [start, end];
13
+ };
14
+ exports.parseRangeKey = parseRangeKey;
@@ -0,0 +1 @@
1
+ export declare const parseRangeKey: (key: string) => [number, number] | null;
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.rewriteImportsWithoutTags = void 0;
4
+ const format_import_specifier_js_1 = require("./format-import-specifier.cjs");
5
+ const rewriteImportsWithoutTags = (program, magic, inlineTagNames, originalSource) => {
6
+ if (!inlineTagNames.size) {
7
+ return false;
8
+ }
9
+ let mutated = false;
10
+ program.body.forEach(node => {
11
+ if (node.type !== 'ImportDeclaration') {
12
+ return;
13
+ }
14
+ const specifiers = node.specifiers;
15
+ const kept = [];
16
+ let removed = false;
17
+ specifiers.forEach(spec => {
18
+ const localName = spec.local?.name;
19
+ if (!localName) {
20
+ kept.push(spec);
21
+ return;
22
+ }
23
+ const shouldDrop = inlineTagNames.has(localName);
24
+ if (shouldDrop) {
25
+ removed = true;
26
+ return;
27
+ }
28
+ kept.push(spec);
29
+ });
30
+ if (!removed) {
31
+ return;
32
+ }
33
+ if (!kept.length) {
34
+ magic.remove(node.start, node.end);
35
+ mutated = true;
36
+ return;
37
+ }
38
+ const keyword = node.importKind === 'type' ? 'import type' : 'import';
39
+ const bindings = [];
40
+ const defaultSpec = kept.find(spec => spec.type === 'ImportDefaultSpecifier');
41
+ const namespaceSpec = kept.find(spec => spec.type === 'ImportNamespaceSpecifier');
42
+ const namedSpecs = kept.filter(spec => spec.type === 'ImportSpecifier');
43
+ if (defaultSpec) {
44
+ bindings.push((0, format_import_specifier_js_1.formatImportSpecifier)(defaultSpec));
45
+ }
46
+ if (namespaceSpec) {
47
+ bindings.push((0, format_import_specifier_js_1.formatImportSpecifier)(namespaceSpec));
48
+ }
49
+ if (namedSpecs.length) {
50
+ bindings.push(`{ ${namedSpecs.map(format_import_specifier_js_1.formatImportSpecifier).join(', ')} }`);
51
+ }
52
+ const sourceLiteral = node.source;
53
+ const sourceText = sourceLiteral.raw
54
+ ? sourceLiteral.raw
55
+ : originalSource.slice(sourceLiteral.start ?? 0, sourceLiteral.end ?? 0);
56
+ const rewritten = `${keyword} ${bindings.join(', ')} from ${sourceText}`;
57
+ magic.overwrite(node.start, node.end, rewritten);
58
+ mutated = true;
59
+ });
60
+ return mutated;
61
+ };
62
+ exports.rewriteImportsWithoutTags = rewriteImportsWithoutTags;
@@ -0,0 +1,3 @@
1
+ import type MagicString from 'magic-string';
2
+ import type { Program } from '@oxc-project/types';
3
+ export declare const rewriteImportsWithoutTags: (program: Program, magic: MagicString, inlineTagNames: Set<string>, originalSource: string) => boolean;