module-tsx 0.0.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.
- package/dist/index.d.mts +8 -0
- package/dist/index.mjs +282 -0
- package/dist/index.umd.js +449 -0
- package/package.json +20 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
//#region src/op.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Given a source URL and source code, transform the module and return a blob URL,
|
|
4
|
+
* where the blob URL's content is the transformed module code.
|
|
5
|
+
*/
|
|
6
|
+
declare function transformSourceModule(sourceUrl: string, sourceCode: string): Promise<string>;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { transformSourceModule };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
|
|
3
|
+
//#region \0@oxc-project+runtime@0.110.0/helpers/asyncToGenerator.js
|
|
4
|
+
function asyncGeneratorStep(n, t, e, r, o, a, c) {
|
|
5
|
+
try {
|
|
6
|
+
var i = n[a](c), u = i.value;
|
|
7
|
+
} catch (n) {
|
|
8
|
+
e(n);
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
i.done ? t(u) : Promise.resolve(u).then(r, o);
|
|
12
|
+
}
|
|
13
|
+
function _asyncToGenerator(n) {
|
|
14
|
+
return function() {
|
|
15
|
+
var t = this, e = arguments;
|
|
16
|
+
return new Promise(function(r, o) {
|
|
17
|
+
var a = n.apply(t, e);
|
|
18
|
+
function _next(n) {
|
|
19
|
+
asyncGeneratorStep(a, r, o, _next, _throw, "next", n);
|
|
20
|
+
}
|
|
21
|
+
function _throw(n) {
|
|
22
|
+
asyncGeneratorStep(a, r, o, _next, _throw, "throw", n);
|
|
23
|
+
}
|
|
24
|
+
_next(void 0);
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region src/network.ts
|
|
31
|
+
function fetchModule(_x, _x2) {
|
|
32
|
+
return _fetchModule.apply(this, arguments);
|
|
33
|
+
}
|
|
34
|
+
function _fetchModule() {
|
|
35
|
+
_fetchModule = _asyncToGenerator(function* (input, init) {
|
|
36
|
+
const res = yield fetch(input, init);
|
|
37
|
+
if (!res.ok) throw new Error(`Failed to fetch module ${res.url}: ${res.status}`);
|
|
38
|
+
return res.text();
|
|
39
|
+
});
|
|
40
|
+
return _fetchModule.apply(this, arguments);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
//#endregion
|
|
44
|
+
//#region src/ts.ts
|
|
45
|
+
const FILE_NAME = "temp.tsx";
|
|
46
|
+
function createSourceFile(code, fileName = FILE_NAME) {
|
|
47
|
+
return ts.createSourceFile(fileName, code, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
|
|
48
|
+
}
|
|
49
|
+
function printSourceFile(sourceFile) {
|
|
50
|
+
const code = ts.createPrinter({
|
|
51
|
+
newLine: ts.NewLineKind.LineFeed,
|
|
52
|
+
removeComments: false
|
|
53
|
+
}).printFile(sourceFile);
|
|
54
|
+
return ts.transpile(code, {
|
|
55
|
+
target: ts.ScriptTarget.Latest,
|
|
56
|
+
module: ts.ModuleKind.ESNext,
|
|
57
|
+
noCheck: true,
|
|
58
|
+
declaration: false,
|
|
59
|
+
jsx: ts.JsxEmit.React
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
function transform(sourceFile, transformers) {
|
|
63
|
+
const result = ts.transform(sourceFile, transformers);
|
|
64
|
+
const transformedFile = result.transformed[0];
|
|
65
|
+
result.dispose();
|
|
66
|
+
return transformedFile;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
//#endregion
|
|
70
|
+
//#region src/react.ts
|
|
71
|
+
/**
|
|
72
|
+
* Check if code uses JSX but missing React import
|
|
73
|
+
*/
|
|
74
|
+
function needsReactImport(sourceFile) {
|
|
75
|
+
let hasJSX = false;
|
|
76
|
+
let hasReactVariable = false;
|
|
77
|
+
function visitNode(node) {
|
|
78
|
+
if (ts.isJsxElement(node) || ts.isJsxSelfClosingElement(node) || ts.isJsxFragment(node)) hasJSX = true;
|
|
79
|
+
if (ts.isImportDeclaration(node) && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {
|
|
80
|
+
if (node.importClause) {
|
|
81
|
+
var _node$importClause$na;
|
|
82
|
+
if (((_node$importClause$na = node.importClause.name) === null || _node$importClause$na === void 0 ? void 0 : _node$importClause$na.text) === "React") hasReactVariable = true;
|
|
83
|
+
if (node.importClause.namedBindings && ts.isNamespaceImport(node.importClause.namedBindings)) {
|
|
84
|
+
if (node.importClause.namedBindings.name.text === "React") hasReactVariable = true;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (ts.isVariableDeclaration(node) && node.name && ts.isIdentifier(node.name)) {
|
|
89
|
+
if (node.name.text === "React") hasReactVariable = true;
|
|
90
|
+
}
|
|
91
|
+
ts.forEachChild(node, visitNode);
|
|
92
|
+
}
|
|
93
|
+
visitNode(sourceFile);
|
|
94
|
+
return hasJSX && !hasReactVariable;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Add React import statement at the top if missing
|
|
98
|
+
*/
|
|
99
|
+
function addReactImport(sourceFile) {
|
|
100
|
+
let reactSpecifier = "react";
|
|
101
|
+
function findReactSpecifier(node) {
|
|
102
|
+
if (ts.isImportDeclaration(node) && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {
|
|
103
|
+
const specifier = node.moduleSpecifier.text;
|
|
104
|
+
if (specifier === "react" || /^react@/.test(specifier) || specifier.endsWith("/react") || /\/react@/.test(specifier)) {
|
|
105
|
+
reactSpecifier = specifier;
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
ts.forEachChild(node, findReactSpecifier);
|
|
110
|
+
}
|
|
111
|
+
findReactSpecifier(sourceFile);
|
|
112
|
+
const statements = [ts.factory.createImportDeclaration(void 0, ts.factory.createImportClause(false, ts.factory.createIdentifier("React"), void 0), ts.factory.createStringLiteral(reactSpecifier), void 0), ...sourceFile.statements];
|
|
113
|
+
return ts.factory.updateSourceFile(sourceFile, statements, sourceFile.isDeclarationFile, sourceFile.referencedFiles, sourceFile.typeReferenceDirectives, sourceFile.hasNoDefaultLib, sourceFile.libReferenceDirectives);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
//#endregion
|
|
117
|
+
//#region src/op.ts
|
|
118
|
+
/**
|
|
119
|
+
* track blob URLs to their original source URLs
|
|
120
|
+
*/
|
|
121
|
+
const blobMap = /* @__PURE__ */ new Map();
|
|
122
|
+
/**
|
|
123
|
+
* track original source URLs to their transformed blob URLs
|
|
124
|
+
*/
|
|
125
|
+
const sourceMap = /* @__PURE__ */ new Map();
|
|
126
|
+
function track(sourceUrl, blobUrl) {
|
|
127
|
+
sourceMap.set(sourceUrl, blobUrl);
|
|
128
|
+
blobMap.set(blobUrl, sourceUrl);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Given a source URL and source code, transform the module and return a blob URL,
|
|
132
|
+
* where the blob URL's content is the transformed module code.
|
|
133
|
+
*/
|
|
134
|
+
function transformSourceModule(_x, _x2) {
|
|
135
|
+
return _transformSourceModule.apply(this, arguments);
|
|
136
|
+
}
|
|
137
|
+
function _transformSourceModule() {
|
|
138
|
+
_transformSourceModule = _asyncToGenerator(function* (sourceUrl, sourceCode) {
|
|
139
|
+
if (sourceMap.has(sourceUrl)) return sourceMap.get(sourceUrl);
|
|
140
|
+
const code = `import.meta.url=${JSON.stringify(sourceUrl)};\n` + (yield rewriteModuleImport(sourceUrl, sourceCode));
|
|
141
|
+
const blob = new Blob([code], { type: "text/javascript" });
|
|
142
|
+
const blobUrl = URL.createObjectURL(blob);
|
|
143
|
+
track(sourceUrl, blobUrl);
|
|
144
|
+
return blobUrl;
|
|
145
|
+
});
|
|
146
|
+
return _transformSourceModule.apply(this, arguments);
|
|
147
|
+
}
|
|
148
|
+
function getFileName(sourceUrl) {
|
|
149
|
+
try {
|
|
150
|
+
return new URL(sourceUrl).pathname;
|
|
151
|
+
} catch (_unused) {
|
|
152
|
+
return "temp.tsx";
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
function rewriteModuleImport(_x3, _x4) {
|
|
156
|
+
return _rewriteModuleImport.apply(this, arguments);
|
|
157
|
+
}
|
|
158
|
+
function _rewriteModuleImport() {
|
|
159
|
+
_rewriteModuleImport = _asyncToGenerator(function* (sourceUrl, sourceCode) {
|
|
160
|
+
const sourceFile = createSourceFile(sourceCode, getFileName(sourceUrl));
|
|
161
|
+
const rewrittenSpecifiers = yield resolveRelativeSpecifiers(collectRelativeSpecifiers(sourceFile), sourceUrl);
|
|
162
|
+
let workingSourceFile = sourceFile;
|
|
163
|
+
if (needsReactImport(workingSourceFile)) workingSourceFile = addReactImport(workingSourceFile);
|
|
164
|
+
const transformers = [createRewriteImportTransformer(rewrittenSpecifiers)];
|
|
165
|
+
return printSourceFile(transform(workingSourceFile, transformers));
|
|
166
|
+
});
|
|
167
|
+
return _rewriteModuleImport.apply(this, arguments);
|
|
168
|
+
}
|
|
169
|
+
function isBareSpecifier(specifier) {
|
|
170
|
+
if (specifier.match(/^\.*\//)) return false;
|
|
171
|
+
try {
|
|
172
|
+
new URL(specifier);
|
|
173
|
+
return false;
|
|
174
|
+
} catch (_unused2) {
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
function isRelativeSpecifier(specifier) {
|
|
179
|
+
return specifier.startsWith(".") || specifier.startsWith("/");
|
|
180
|
+
}
|
|
181
|
+
function collectRelativeSpecifiers(sourceFile) {
|
|
182
|
+
const set = /* @__PURE__ */ new Set();
|
|
183
|
+
const visit = (node) => {
|
|
184
|
+
const addIfRelative = (literal) => {
|
|
185
|
+
if (literal && isRelativeSpecifier(literal.text)) set.add(literal.text);
|
|
186
|
+
};
|
|
187
|
+
if (ts.isImportDeclaration(node) && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) addIfRelative(node.moduleSpecifier);
|
|
188
|
+
if (ts.isCallExpression(node) && node.expression.kind === ts.SyntaxKind.ImportKeyword) {
|
|
189
|
+
const arg = node.arguments[0];
|
|
190
|
+
if (arg && ts.isStringLiteral(arg)) addIfRelative(arg);
|
|
191
|
+
}
|
|
192
|
+
if (ts.isExportDeclaration(node) && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) addIfRelative(node.moduleSpecifier);
|
|
193
|
+
ts.forEachChild(node, visit);
|
|
194
|
+
};
|
|
195
|
+
visit(sourceFile);
|
|
196
|
+
return set;
|
|
197
|
+
}
|
|
198
|
+
function resolveRelativeSpecifiers(_x6, _x7) {
|
|
199
|
+
return _resolveRelativeSpecifiers.apply(this, arguments);
|
|
200
|
+
}
|
|
201
|
+
function _resolveRelativeSpecifiers() {
|
|
202
|
+
_resolveRelativeSpecifiers = _asyncToGenerator(function* (specifiers, sourceUrl) {
|
|
203
|
+
const resolved = /* @__PURE__ */ new Map();
|
|
204
|
+
const tasks = Array.from(specifiers).map(function() {
|
|
205
|
+
var _ref = _asyncToGenerator(function* (specifier) {
|
|
206
|
+
const targetUrl = new URL(specifier, sourceUrl).toString();
|
|
207
|
+
const blobUrl = yield transformSourceModule(targetUrl, yield fetchModule(targetUrl));
|
|
208
|
+
resolved.set(specifier, blobUrl);
|
|
209
|
+
});
|
|
210
|
+
return function(_x5) {
|
|
211
|
+
return _ref.apply(this, arguments);
|
|
212
|
+
};
|
|
213
|
+
}());
|
|
214
|
+
yield Promise.all(tasks);
|
|
215
|
+
return resolved;
|
|
216
|
+
});
|
|
217
|
+
return _resolveRelativeSpecifiers.apply(this, arguments);
|
|
218
|
+
}
|
|
219
|
+
function createRewriteImportTransformer(replacements) {
|
|
220
|
+
const rewriteSpecifier = (specifier) => {
|
|
221
|
+
if (replacements.has(specifier)) return replacements.get(specifier);
|
|
222
|
+
if (specifier.startsWith("npm:")) return specifier.replace(/^npm:/, "https://esm.sh/");
|
|
223
|
+
if (specifier.startsWith("node:")) return `https://raw.esm.sh/@jspm/core/nodelibs/browser/${specifier.slice(5)}.js`;
|
|
224
|
+
if (isBareSpecifier(specifier)) return new URL(specifier, "https://esm.sh/").toString();
|
|
225
|
+
if (isRelativeSpecifier(specifier)) throw new Error("Unreachable");
|
|
226
|
+
return specifier;
|
|
227
|
+
};
|
|
228
|
+
const transformer = (context) => {
|
|
229
|
+
const visitNode = (node) => {
|
|
230
|
+
if (ts.isImportDeclaration(node) && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {
|
|
231
|
+
const next = rewriteSpecifier(node.moduleSpecifier.text);
|
|
232
|
+
if (next !== node.moduleSpecifier.text) return ts.factory.updateImportDeclaration(node, node.modifiers, node.importClause, ts.factory.createStringLiteral(next), node.assertClause);
|
|
233
|
+
}
|
|
234
|
+
if (ts.isCallExpression(node) && node.expression.kind === ts.SyntaxKind.ImportKeyword) {
|
|
235
|
+
const arg = node.arguments[0];
|
|
236
|
+
if (arg && ts.isStringLiteral(arg)) {
|
|
237
|
+
const next = rewriteSpecifier(arg.text);
|
|
238
|
+
if (next !== arg.text) return ts.factory.updateCallExpression(node, node.expression, node.typeArguments, [ts.factory.createStringLiteral(next), ...node.arguments.slice(1)]);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
if (ts.isExportDeclaration(node) && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {
|
|
242
|
+
const next = rewriteSpecifier(node.moduleSpecifier.text);
|
|
243
|
+
if (next !== node.moduleSpecifier.text) return ts.factory.updateExportDeclaration(node, node.modifiers, node.isTypeOnly, node.exportClause, ts.factory.createStringLiteral(next), node.assertClause);
|
|
244
|
+
}
|
|
245
|
+
return ts.visitEachChild(node, visitNode, context);
|
|
246
|
+
};
|
|
247
|
+
return (sf) => ts.visitNode(sf, visitNode);
|
|
248
|
+
};
|
|
249
|
+
return transformer;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
//#endregion
|
|
253
|
+
//#region src/index.ts
|
|
254
|
+
const TYPE_ATTRIBUTE_VALUE = "module-tsx";
|
|
255
|
+
function runScript(_x) {
|
|
256
|
+
return _runScript.apply(this, arguments);
|
|
257
|
+
}
|
|
258
|
+
function _runScript() {
|
|
259
|
+
_runScript = _asyncToGenerator(function* (script) {
|
|
260
|
+
return script.src ? import(yield transformSourceModule(script.src, yield fetchModule(script.src, { priority: script.fetchPriority }))) : import(yield transformSourceModule(location.href, script.innerHTML));
|
|
261
|
+
});
|
|
262
|
+
return _runScript.apply(this, arguments);
|
|
263
|
+
}
|
|
264
|
+
function sideEffect() {
|
|
265
|
+
return _sideEffect.apply(this, arguments);
|
|
266
|
+
}
|
|
267
|
+
function _sideEffect() {
|
|
268
|
+
_sideEffect = _asyncToGenerator(function* () {
|
|
269
|
+
for (const s of Array.from(document.querySelectorAll(`script[type="${TYPE_ATTRIBUTE_VALUE}"]`))) {
|
|
270
|
+
const script = s;
|
|
271
|
+
if (!script.async && script.defer) console.warn(`script with type="${TYPE_ATTRIBUTE_VALUE}" does not support defer attribute. Use async or no attribute instead.`);
|
|
272
|
+
for (const key in ["integrity", "crossorigin"]) if (script[key]) console.warn(`script with type="${TYPE_ATTRIBUTE_VALUE}" does not support ${key} attribute.`);
|
|
273
|
+
if (script.async) runScript(script);
|
|
274
|
+
else yield runScript(script);
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
return _sideEffect.apply(this, arguments);
|
|
278
|
+
}
|
|
279
|
+
document.addEventListener("DOMContentLoaded", sideEffect);
|
|
280
|
+
|
|
281
|
+
//#endregion
|
|
282
|
+
export { transformSourceModule };
|