@codespark/framework 1.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/html.d.ts ADDED
@@ -0,0 +1,66 @@
1
+ import { Framework as Framework$1 } from "@codespark/framework";
2
+ import MagicString from "magic-string";
3
+
4
+ //#region src/loaders/types.d.ts
5
+ declare enum LoaderType {
6
+ ESModule = "esmodule",
7
+ Style = "style",
8
+ Script = "script",
9
+ Asset = "asset",
10
+ }
11
+ interface BaseLoaderOutput<T extends LoaderType> {
12
+ type: T;
13
+ content: string;
14
+ }
15
+ interface ESModuleLoaderOutput extends BaseLoaderOutput<LoaderType.ESModule> {
16
+ dependencies: Record<string, string>;
17
+ externals: {
18
+ name: string;
19
+ imported: string[];
20
+ }[];
21
+ }
22
+ interface StyleLoaderOutput extends BaseLoaderOutput<LoaderType.Style> {
23
+ imports: string[];
24
+ href?: string;
25
+ attributes?: Record<string, string>;
26
+ }
27
+ interface ScriptLoaderOutput extends BaseLoaderOutput<LoaderType.Script> {
28
+ src?: string;
29
+ attributes?: Record<string, string>;
30
+ }
31
+ type AssetLoaderOutput = BaseLoaderOutput<LoaderType.Asset>;
32
+ type LoaderOutput<T extends LoaderType> = Extract<ESModuleLoaderOutput | StyleLoaderOutput | ScriptLoaderOutput | AssetLoaderOutput, {
33
+ type: T;
34
+ }>;
35
+ //#endregion
36
+ //#region src/registry.d.ts
37
+ type Output<T extends LoaderType = LoaderType> = Omit<LoaderOutput<T>, 'type'> & {
38
+ path: string;
39
+ };
40
+ type Outputs = Map<LoaderType, Output[]>;
41
+ //#endregion
42
+ //#region src/html/index.d.ts
43
+ interface FrameworkConfig {
44
+ liteMode?: {
45
+ enabled?: boolean;
46
+ htmlEntry?: string;
47
+ scriptEntry?: string;
48
+ styleEntry?: string;
49
+ };
50
+ }
51
+ declare class Framework extends Framework$1 {
52
+ private config?;
53
+ readonly name = "html";
54
+ readonly imports: {};
55
+ outputs: Outputs;
56
+ private blobUrlMap;
57
+ constructor(config?: FrameworkConfig | undefined);
58
+ analyze(entry: string, files: Record<string, string>): void;
59
+ compile(): string;
60
+ private wrapInLiteModeTemplate;
61
+ private transformModulesToBlob;
62
+ private transformCodeWithBlobUrls;
63
+ }
64
+ declare const html: Framework;
65
+ //#endregion
66
+ export { Framework, FrameworkConfig, html };
package/dist/html.js ADDED
@@ -0,0 +1,442 @@
1
+ import { parse } from "@babel/parser";
2
+ import { Framework as Framework$1 } from "@codespark/framework";
3
+ import MagicString from "magic-string";
4
+ import { render } from "dom-serializer";
5
+ import { DomUtils, parseDocument } from "htmlparser2";
6
+ import { availablePresets, transform } from "@babel/standalone";
7
+
8
+ //#region src/loaders/types.ts
9
+ let LoaderType = /* @__PURE__ */ function(LoaderType$1) {
10
+ LoaderType$1["ESModule"] = "esmodule";
11
+ LoaderType$1["Style"] = "style";
12
+ LoaderType$1["Script"] = "script";
13
+ LoaderType$1["Asset"] = "asset";
14
+ return LoaderType$1;
15
+ }({});
16
+
17
+ //#endregion
18
+ //#region src/loaders/css-loader.ts
19
+ var CSSLoader = class {
20
+ name = "css-loader";
21
+ test = /\.css$/;
22
+ constructor(config) {
23
+ this.config = config;
24
+ }
25
+ transform(source, ctx) {
26
+ const { enabled = true, match } = this.config?.tailwind || {};
27
+ const isTailwind = match ? match.test(ctx.resourcePath) : ctx.resourcePath.endsWith(".tw.css");
28
+ const imports = [];
29
+ const content = source.replace(/@import\s+(?:url\()?['"]?([^'")]+)['"]?\)?\s*;?/g, (_, importPath) => {
30
+ const resolved = ctx.resolve(importPath);
31
+ if (resolved) imports.push(resolved);
32
+ return "";
33
+ });
34
+ return {
35
+ type: LoaderType.Style,
36
+ content,
37
+ imports,
38
+ attributes: enabled && isTailwind ? { type: "text/tailwindcss" } : {}
39
+ };
40
+ }
41
+ };
42
+
43
+ //#endregion
44
+ //#region src/loaders/es-loader.ts
45
+ const parseCode = (code) => parse(code, {
46
+ sourceType: "module",
47
+ plugins: ["jsx", "typescript"]
48
+ }).program.body;
49
+ const collectIdentifiers = (ast) => {
50
+ const ids = /* @__PURE__ */ new Set();
51
+ const walk = (node) => {
52
+ if (!node || typeof node !== "object") return;
53
+ if (node.type === "Identifier" || node.type === "JSXIdentifier") ids.add(node.name);
54
+ for (const k of Object.keys(node)) {
55
+ if (k === "loc" || k === "range") continue;
56
+ const val = node[k];
57
+ if (Array.isArray(val)) val.forEach(walk);
58
+ else if (val && typeof val === "object") walk(val);
59
+ }
60
+ };
61
+ ast.forEach(walk);
62
+ return ids;
63
+ };
64
+ const analyzeImports = (ast) => {
65
+ const imports = ast.filter((node) => node.type === "ImportDeclaration");
66
+ const usedIds = collectIdentifiers(ast.filter((node) => node.type !== "ImportDeclaration"));
67
+ const importMap = /* @__PURE__ */ new Map();
68
+ imports.forEach((imp) => {
69
+ if (imp.importKind === "type") return;
70
+ imp.specifiers.forEach((spec) => {
71
+ if (spec.type === "ImportSpecifier" && spec.importKind === "type") return;
72
+ importMap.set(spec.local.name, imp.source.value);
73
+ });
74
+ });
75
+ const usedSources = /* @__PURE__ */ new Set();
76
+ usedIds.forEach((id) => {
77
+ if (importMap.has(id)) usedSources.add(importMap.get(id));
78
+ });
79
+ return {
80
+ imports,
81
+ usedSources
82
+ };
83
+ };
84
+ const buildExternalDeps = (imports, usedSources) => {
85
+ const externals = /* @__PURE__ */ new Map();
86
+ imports.forEach((imp) => {
87
+ if (imp.importKind === "type") return;
88
+ const source = imp.source.value;
89
+ if (!usedSources.has(source) || source.startsWith(".") || source.startsWith("/")) return;
90
+ const namedImports = imp.specifiers.filter((spec) => spec.type === "ImportSpecifier" && spec.importKind !== "type").map((spec) => spec.imported.name);
91
+ const existing = externals.get(source);
92
+ if (existing) namedImports.forEach((name) => existing.imported.add(name));
93
+ else externals.set(source, {
94
+ name: source,
95
+ imported: new Set(namedImports)
96
+ });
97
+ });
98
+ return [...externals.values()].map((dep) => ({
99
+ ...dep,
100
+ imported: [...dep.imported]
101
+ }));
102
+ };
103
+ var ESLoader = class {
104
+ name = "es-loader";
105
+ test = /\.(tsx?|jsx?)$/;
106
+ jsxPreset;
107
+ isTSX;
108
+ constructor(options) {
109
+ const { jsxPreset, isTSX = false } = options || {};
110
+ this.jsxPreset = jsxPreset;
111
+ this.isTSX = isTSX;
112
+ }
113
+ transform(source, ctx) {
114
+ const { imports, usedSources } = analyzeImports(parseCode(source));
115
+ const externals = buildExternalDeps(imports, usedSources);
116
+ const dependencies = {};
117
+ for (const imp of imports) {
118
+ if (imp.importKind === "type") continue;
119
+ const importPath = imp.source.value;
120
+ if (imp.specifiers.length === 0) {
121
+ const resolved$1 = ctx.resolve(importPath);
122
+ if (resolved$1) dependencies[importPath] = resolved$1;
123
+ continue;
124
+ }
125
+ if (!usedSources.has(importPath)) continue;
126
+ const resolved = ctx.resolve(importPath);
127
+ if (resolved) dependencies[importPath] = resolved;
128
+ }
129
+ const { typescript } = availablePresets;
130
+ const defaultPresets = [typescript, {
131
+ isTSX: this.isTSX,
132
+ allExtensions: true
133
+ }];
134
+ const { code } = transform(source, {
135
+ filename: ctx.resourcePath,
136
+ presets: this.jsxPreset ? [this.jsxPreset, defaultPresets] : [defaultPresets]
137
+ });
138
+ return {
139
+ type: LoaderType.ESModule,
140
+ content: code || "",
141
+ dependencies,
142
+ externals
143
+ };
144
+ }
145
+ };
146
+
147
+ //#endregion
148
+ //#region src/html/analyze.ts
149
+ const LOADERS = {
150
+ es: new ESLoader(),
151
+ css: new CSSLoader()
152
+ };
153
+ function isExternalUrl(url) {
154
+ return url.startsWith("http://") || url.startsWith("https://") || url.startsWith("//");
155
+ }
156
+ function getTextContent(element) {
157
+ return element.children.filter((child) => child.type === "text").map((child) => child.data).join("").trim();
158
+ }
159
+ function extractAttributes(attribs, excludeKeys) {
160
+ const filtered = Object.fromEntries(Object.entries(attribs).filter(([key]) => !excludeKeys.includes(key)));
161
+ return Object.keys(filtered).length > 0 ? filtered : void 0;
162
+ }
163
+ function createLoaderContext(files) {
164
+ return {
165
+ getSource: (path) => files[path],
166
+ resolve: (src) => files[src] !== void 0 ? src : null
167
+ };
168
+ }
169
+ function parseHTML(html$1) {
170
+ const doc = parseDocument(html$1);
171
+ const elements = [];
172
+ const scripts = DomUtils.getElementsByTagName("script", doc);
173
+ for (const script of scripts) {
174
+ const src = script.attribs.src;
175
+ elements.push({
176
+ type: "script",
177
+ isModule: script.attribs.type === "module",
178
+ src,
179
+ content: src ? void 0 : getTextContent(script),
180
+ attributes: extractAttributes(script.attribs, ["src", "type"])
181
+ });
182
+ }
183
+ const styles = DomUtils.getElementsByTagName("style", doc);
184
+ for (const style of styles) elements.push({
185
+ type: "style",
186
+ content: getTextContent(style),
187
+ attributes: extractAttributes(style.attribs, [])
188
+ });
189
+ const links = DomUtils.getElementsByTagName("link", doc);
190
+ for (const link of links) {
191
+ if (link.attribs.rel !== "stylesheet" || !link.attribs.href) continue;
192
+ elements.push({
193
+ type: "link",
194
+ href: link.attribs.href,
195
+ attributes: extractAttributes(link.attribs, ["href", "rel"])
196
+ });
197
+ }
198
+ const bodies = DomUtils.getElementsByTagName("body", doc);
199
+ const container = bodies.length > 0 ? bodies[0] : doc;
200
+ const tagsToRemove = [
201
+ ...DomUtils.getElementsByTagName("script", container),
202
+ ...DomUtils.getElementsByTagName("style", container),
203
+ ...DomUtils.getElementsByTagName("link", container)
204
+ ];
205
+ for (const tag of tagsToRemove) DomUtils.removeElement(tag);
206
+ return {
207
+ elements,
208
+ bodyContent: render(DomUtils.getChildren(container)).trim()
209
+ };
210
+ }
211
+ function processESModule(path, files, outputs, visited = /* @__PURE__ */ new Set()) {
212
+ if (visited.has(path)) return;
213
+ visited.add(path);
214
+ const source = files[path];
215
+ if (source === void 0) return;
216
+ const ctx = createLoaderContext(files);
217
+ const output = LOADERS.es.transform(source, {
218
+ resourcePath: path,
219
+ ...ctx
220
+ });
221
+ getOutputArray(outputs, LoaderType.ESModule).push({
222
+ path,
223
+ content: output.content,
224
+ dependencies: output.dependencies,
225
+ externals: output.externals
226
+ });
227
+ for (const depPath of Object.values(output.dependencies)) processESModule(depPath, files, outputs, visited);
228
+ }
229
+ function processStylesheet(path, files, outputs, visited = /* @__PURE__ */ new Set()) {
230
+ if (visited.has(path)) return;
231
+ visited.add(path);
232
+ const source = files[path];
233
+ if (source === void 0) return;
234
+ const ctx = createLoaderContext(files);
235
+ const output = LOADERS.css.transform(source, {
236
+ resourcePath: path,
237
+ ...ctx
238
+ });
239
+ getOutputArray(outputs, LoaderType.Style).push({
240
+ path,
241
+ content: output.content,
242
+ imports: output.imports,
243
+ attributes: output.attributes
244
+ });
245
+ for (const depPath of output.imports) processStylesheet(depPath, files, outputs, visited);
246
+ }
247
+ function getOutputArray(outputs, type) {
248
+ return outputs.get(type);
249
+ }
250
+ function createOutputs() {
251
+ const outputs = /* @__PURE__ */ new Map();
252
+ outputs.set(LoaderType.ESModule, []);
253
+ outputs.set(LoaderType.Style, []);
254
+ outputs.set(LoaderType.Script, []);
255
+ outputs.set(LoaderType.Asset, []);
256
+ return outputs;
257
+ }
258
+ function processScriptElement(el, entry, files, outputs, visited = /* @__PURE__ */ new Set()) {
259
+ if (el.isModule) processModuleScript(el, entry, files, outputs, visited);
260
+ else processRegularScript(el, entry, files, outputs);
261
+ }
262
+ function processModuleScript(el, entry, files, outputs, visited = /* @__PURE__ */ new Set()) {
263
+ if (el.src) {
264
+ if (isExternalUrl(el.src)) getOutputArray(outputs, LoaderType.Script).push({
265
+ path: el.src,
266
+ content: "",
267
+ src: el.src,
268
+ attributes: {
269
+ ...el.attributes,
270
+ type: "module"
271
+ }
272
+ });
273
+ else if (files[el.src] !== void 0) processESModule(el.src, files, outputs, visited);
274
+ return;
275
+ }
276
+ if (!el.content) return;
277
+ const virtualPath = `${entry}#inline-module-${getOutputArray(outputs, LoaderType.ESModule).length}`;
278
+ const ctx = createLoaderContext(files);
279
+ const output = LOADERS.es.transform(el.content, {
280
+ resourcePath: virtualPath,
281
+ ...ctx
282
+ });
283
+ getOutputArray(outputs, LoaderType.ESModule).push({
284
+ path: virtualPath,
285
+ content: output.content,
286
+ dependencies: output.dependencies,
287
+ externals: output.externals
288
+ });
289
+ for (const depPath of Object.values(output.dependencies)) processESModule(depPath, files, outputs, visited);
290
+ }
291
+ function processRegularScript(el, entry, files, outputs) {
292
+ if (el.src) {
293
+ if (isExternalUrl(el.src)) getOutputArray(outputs, LoaderType.Script).push({
294
+ path: el.src,
295
+ content: "",
296
+ src: el.src,
297
+ attributes: el.attributes
298
+ });
299
+ else if (files[el.src] !== void 0) getOutputArray(outputs, LoaderType.Script).push({
300
+ path: el.src,
301
+ content: files[el.src],
302
+ attributes: el.attributes
303
+ });
304
+ return;
305
+ }
306
+ if (!el.content) return;
307
+ const virtualPath = `${entry}#inline-script-${getOutputArray(outputs, LoaderType.Script).length}`;
308
+ getOutputArray(outputs, LoaderType.Script).push({
309
+ path: virtualPath,
310
+ content: el.content,
311
+ attributes: el.attributes
312
+ });
313
+ }
314
+ function processStyleElement(el, entry, outputs) {
315
+ if (!el.content) return;
316
+ const virtualPath = `${entry}#inline-style-${getOutputArray(outputs, LoaderType.Style).length}`;
317
+ getOutputArray(outputs, LoaderType.Style).push({
318
+ path: virtualPath,
319
+ content: el.content,
320
+ imports: [],
321
+ attributes: el.attributes
322
+ });
323
+ }
324
+ function processLinkElement(el, files, outputs, visited = /* @__PURE__ */ new Set()) {
325
+ if (!el.href) return;
326
+ if (isExternalUrl(el.href)) getOutputArray(outputs, LoaderType.Style).push({
327
+ path: el.href,
328
+ content: "",
329
+ imports: [],
330
+ href: el.href,
331
+ attributes: el.attributes
332
+ });
333
+ else if (files[el.href] !== void 0) processStylesheet(el.href, files, outputs, visited);
334
+ }
335
+ function analyze(entry, files) {
336
+ const outputs = createOutputs();
337
+ const html$1 = files[entry];
338
+ if (!html$1) return outputs;
339
+ const { elements, bodyContent } = parseHTML(html$1);
340
+ for (const el of elements) if (el.type === "script") processScriptElement(el, entry, files, outputs);
341
+ else if (el.type === "style") processStyleElement(el, entry, outputs);
342
+ else if (el.type === "link") processLinkElement(el, files, outputs);
343
+ if (bodyContent) getOutputArray(outputs, LoaderType.Asset).push({
344
+ path: entry,
345
+ content: bodyContent
346
+ });
347
+ return outputs;
348
+ }
349
+
350
+ //#endregion
351
+ //#region src/html/index.ts
352
+ function serializeAttributes(attrs) {
353
+ if (!attrs || Object.keys(attrs).length === 0) return "";
354
+ return Object.entries(attrs).map(([key, value]) => value === "" ? ` ${key}` : ` ${key}="${value}"`).join("");
355
+ }
356
+ var Framework = class extends Framework$1 {
357
+ name = "html";
358
+ imports = {};
359
+ outputs = /* @__PURE__ */ new Map();
360
+ blobUrlMap = /* @__PURE__ */ new Map();
361
+ constructor(config) {
362
+ super();
363
+ this.config = config;
364
+ }
365
+ analyze(entry, files) {
366
+ const { enabled, htmlEntry = entry } = this.config?.liteMode ?? {};
367
+ if (enabled) this.outputs = analyze(entry, {
368
+ ...files,
369
+ [htmlEntry]: this.wrapInLiteModeTemplate(files[htmlEntry] ?? "")
370
+ });
371
+ else this.outputs = analyze(entry, files);
372
+ }
373
+ compile() {
374
+ const builder = this.createBuilder();
375
+ const assets = this.getOutput(LoaderType.Asset);
376
+ const styles = this.getOutput(LoaderType.Style);
377
+ const scripts = this.getOutput(LoaderType.Script);
378
+ const modules = this.getOutput(LoaderType.ESModule);
379
+ let htmlContent = assets.map((a) => a.content).join("");
380
+ for (const style of styles) if (style.href) htmlContent += `<link${serializeAttributes(style.attributes)} rel="stylesheet" href="${style.href}">`;
381
+ else htmlContent += `<style${serializeAttributes(style.attributes)}>${style.content}</style>`;
382
+ for (const script of scripts) if (script.src) htmlContent += `<script${serializeAttributes(script.attributes)} src="${script.src}"><\/script>`;
383
+ else htmlContent += `<script${serializeAttributes(script.attributes)}>${script.content}<\/script>`;
384
+ if (modules.length > 0) {
385
+ const entryCode = this.transformModulesToBlob([...modules].reverse());
386
+ if (entryCode) htmlContent += `<script type="module">${entryCode}<\/script>`;
387
+ }
388
+ this.outputs.set(LoaderType.Style, []);
389
+ this.outputs.set(LoaderType.Script, []);
390
+ return builder.setHTML(JSON.stringify(htmlContent), {
391
+ target: "body",
392
+ activateScripts: scripts.length > 0 || modules.length > 0
393
+ }).done();
394
+ }
395
+ wrapInLiteModeTemplate(htmlFragment) {
396
+ const { scriptEntry = "./index.js", styleEntry = "./index.css" } = this.config?.liteMode ?? {};
397
+ return `<!DOCTYPE html>
398
+ <html>
399
+ <head>
400
+ <link rel="stylesheet" href="${styleEntry}">
401
+ <script type="module" src="${scriptEntry}"><\/script>
402
+ </head>
403
+ <body>
404
+ ${htmlFragment}
405
+ </body>
406
+ </html>`;
407
+ }
408
+ transformModulesToBlob(modules) {
409
+ let entryCode = "";
410
+ for (let index = 0; index < modules.length; index++) {
411
+ const mod = modules[index];
412
+ const isEntry = index === modules.length - 1;
413
+ const code = this.transformCodeWithBlobUrls(mod);
414
+ if (isEntry) entryCode = code;
415
+ else {
416
+ const blob = new Blob([code], { type: "application/javascript" });
417
+ this.blobUrlMap.set(mod.path, URL.createObjectURL(blob));
418
+ }
419
+ }
420
+ return entryCode;
421
+ }
422
+ transformCodeWithBlobUrls(mod) {
423
+ const s = new MagicString(mod.content);
424
+ const ast = parse(mod.content, {
425
+ sourceType: "module",
426
+ plugins: ["jsx", "typescript"]
427
+ }).program.body;
428
+ for (const node of ast) {
429
+ if (node.type !== "ImportDeclaration") continue;
430
+ const resolved = mod.dependencies[node.source.value];
431
+ if (!resolved) continue;
432
+ const blobUrl = this.blobUrlMap.get(resolved);
433
+ if (blobUrl) s.update(node.source.start + 1, node.source.end - 1, blobUrl);
434
+ else s.remove(node.start, node.end);
435
+ }
436
+ return s.toString();
437
+ }
438
+ };
439
+ const html = new Framework();
440
+
441
+ //#endregion
442
+ export { Framework, html };
@@ -0,0 +1,76 @@
1
+ import MagicString from "magic-string";
2
+
3
+ //#region src/builder.d.ts
4
+ declare class RuntimeBuilder {
5
+ private s;
6
+ root: string;
7
+ constructor(code?: string | MagicString);
8
+ toString(): string;
9
+ update(start: number, end: number, content: string): this;
10
+ remove(start: number, end: number): this;
11
+ setHTML(content: string, options?: {
12
+ target?: 'root' | 'body';
13
+ activateScripts?: boolean;
14
+ }): this;
15
+ append(code: string): this;
16
+ prepend(code: string): this;
17
+ done(): string;
18
+ async(code: string): this;
19
+ }
20
+ //#endregion
21
+ //#region src/loaders/types.d.ts
22
+ declare enum LoaderType {
23
+ ESModule = "esmodule",
24
+ Style = "style",
25
+ Script = "script",
26
+ Asset = "asset",
27
+ }
28
+ interface BaseLoaderOutput<T extends LoaderType> {
29
+ type: T;
30
+ content: string;
31
+ }
32
+ interface ESModuleLoaderOutput extends BaseLoaderOutput<LoaderType.ESModule> {
33
+ dependencies: Record<string, string>;
34
+ externals: {
35
+ name: string;
36
+ imported: string[];
37
+ }[];
38
+ }
39
+ interface StyleLoaderOutput extends BaseLoaderOutput<LoaderType.Style> {
40
+ imports: string[];
41
+ href?: string;
42
+ attributes?: Record<string, string>;
43
+ }
44
+ interface ScriptLoaderOutput extends BaseLoaderOutput<LoaderType.Script> {
45
+ src?: string;
46
+ attributes?: Record<string, string>;
47
+ }
48
+ type AssetLoaderOutput = BaseLoaderOutput<LoaderType.Asset>;
49
+ type LoaderOutput<T extends LoaderType> = Extract<ESModuleLoaderOutput | StyleLoaderOutput | ScriptLoaderOutput | AssetLoaderOutput, {
50
+ type: T;
51
+ }>;
52
+ //#endregion
53
+ //#region src/registry.d.ts
54
+ type Output<T extends LoaderType = LoaderType> = Omit<LoaderOutput<T>, 'type'> & {
55
+ path: string;
56
+ };
57
+ type Outputs = Map<LoaderType, Output[]>;
58
+ declare abstract class Framework {
59
+ abstract readonly name: string;
60
+ abstract readonly imports: Record<string, string>;
61
+ abstract outputs: Outputs;
62
+ abstract analyze(entry: string, files: Record<string, string>): void;
63
+ abstract compile(): string;
64
+ protected createBuilder(init?: string): RuntimeBuilder;
65
+ getOutput<T extends LoaderType>(type: T): Output<T>[];
66
+ }
67
+ declare class FrameworkRegistry {
68
+ private frameworks;
69
+ register(framework: Framework, name?: string): void;
70
+ get(name: string): Framework | undefined;
71
+ list(): string[];
72
+ }
73
+ declare const registry: FrameworkRegistry;
74
+ declare function registerFramework(framework: Framework, name?: string): void;
75
+ //#endregion
76
+ export { Framework, type Output, type Outputs, registerFramework, registry };
package/dist/index.js ADDED
@@ -0,0 +1,87 @@
1
+ import MagicString from "magic-string";
2
+
3
+ //#region src/builder.ts
4
+ var RuntimeBuilder = class {
5
+ s;
6
+ root = `document.getElementById('root')`;
7
+ constructor(code = "") {
8
+ this.s = typeof code === "string" ? new MagicString(code) : code;
9
+ }
10
+ toString() {
11
+ return this.s.toString();
12
+ }
13
+ update(start, end, content) {
14
+ this.s.update(start, end, content);
15
+ return this;
16
+ }
17
+ remove(start, end) {
18
+ this.s.remove(start, end);
19
+ return this;
20
+ }
21
+ setHTML(content, options) {
22
+ const container = options?.target === "body" ? "document.body" : `document.getElementById('root')`;
23
+ this.s.append(`${container}.innerHTML = ${content};`);
24
+ if (options?.activateScripts) this.s.append(`
25
+ ${container}.querySelectorAll('script').forEach(old => {
26
+ const el = document.createElement('script');
27
+ [...old.attributes].forEach(a => el.setAttribute(a.name, a.value));
28
+ el.textContent = old.textContent;
29
+ old.replaceWith(el);
30
+ });`);
31
+ return this;
32
+ }
33
+ append(code) {
34
+ this.s.append(code);
35
+ return this;
36
+ }
37
+ prepend(code) {
38
+ this.s.prepend(code);
39
+ return this;
40
+ }
41
+ done() {
42
+ this.s.append("window.__render_complete__?.();\nwindow.__next__?.();");
43
+ return this.s.toString();
44
+ }
45
+ async(code) {
46
+ this.s.append(`
47
+ ;(async () => {
48
+ try {
49
+ ${code}
50
+ window.__render_complete__?.();
51
+ } finally {
52
+ window.__next__?.();
53
+ }
54
+ })();`);
55
+ return this;
56
+ }
57
+ };
58
+
59
+ //#endregion
60
+ //#region src/registry.ts
61
+ var Framework = class {
62
+ createBuilder(init) {
63
+ return new RuntimeBuilder(init);
64
+ }
65
+ getOutput(type) {
66
+ return this.outputs.get(type) ?? [];
67
+ }
68
+ };
69
+ var FrameworkRegistry = class {
70
+ frameworks = /* @__PURE__ */ new Map();
71
+ register(framework, name) {
72
+ this.frameworks.set(name ?? framework.name, framework);
73
+ }
74
+ get(name) {
75
+ return this.frameworks.get(name);
76
+ }
77
+ list() {
78
+ return Array.from(this.frameworks.keys());
79
+ }
80
+ };
81
+ const registry = new FrameworkRegistry();
82
+ function registerFramework(framework, name) {
83
+ registry.register(framework, name);
84
+ }
85
+
86
+ //#endregion
87
+ export { Framework, registerFramework, registry };