@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.
@@ -0,0 +1,87 @@
1
+ //#region src/loaders/types.d.ts
2
+ declare enum LoaderType {
3
+ ESModule = "esmodule",
4
+ Style = "style",
5
+ Script = "script",
6
+ Asset = "asset",
7
+ }
8
+ interface BaseLoaderOutput<T extends LoaderType> {
9
+ type: T;
10
+ content: string;
11
+ }
12
+ interface ESModuleLoaderOutput extends BaseLoaderOutput<LoaderType.ESModule> {
13
+ dependencies: Record<string, string>;
14
+ externals: {
15
+ name: string;
16
+ imported: string[];
17
+ }[];
18
+ }
19
+ interface StyleLoaderOutput extends BaseLoaderOutput<LoaderType.Style> {
20
+ imports: string[];
21
+ href?: string;
22
+ attributes?: Record<string, string>;
23
+ }
24
+ interface ScriptLoaderOutput extends BaseLoaderOutput<LoaderType.Script> {
25
+ src?: string;
26
+ attributes?: Record<string, string>;
27
+ }
28
+ type AssetLoaderOutput = BaseLoaderOutput<LoaderType.Asset>;
29
+ type LoaderOutput<T extends LoaderType> = Extract<ESModuleLoaderOutput | StyleLoaderOutput | ScriptLoaderOutput | AssetLoaderOutput, {
30
+ type: T;
31
+ }>;
32
+ interface LoaderContext {
33
+ resourcePath: string;
34
+ getSource: (path: string) => string | undefined;
35
+ resolve: (source: string) => string | null;
36
+ }
37
+ interface Loader<T extends LoaderType> {
38
+ readonly name: string;
39
+ readonly test: RegExp;
40
+ transform(source: string, ctx?: LoaderContext): LoaderOutput<T>;
41
+ }
42
+ //#endregion
43
+ //#region src/loaders/css-loader.d.ts
44
+ declare class CSSLoader implements Loader<LoaderType.Style> {
45
+ private config?;
46
+ readonly name = "css-loader";
47
+ readonly test: RegExp;
48
+ constructor(config?: {
49
+ tailwind?: {
50
+ enabled?: boolean;
51
+ match?: RegExp;
52
+ };
53
+ } | undefined);
54
+ transform(source: string, ctx: LoaderContext): StyleLoaderOutput;
55
+ }
56
+ //#endregion
57
+ //#region src/loaders/es-loader.d.ts
58
+ interface ESLoaderOptions {
59
+ /** JSX preset, e.g. [availablePresets.react, { runtime: 'automatic' }] */
60
+ jsxPreset?: [unknown, Record<string, unknown>];
61
+ /** Whether to enable TSX support, default false */
62
+ isTSX?: boolean;
63
+ }
64
+ declare class ESLoader implements Loader<LoaderType.ESModule> {
65
+ readonly name = "es-loader";
66
+ readonly test: RegExp;
67
+ private jsxPreset;
68
+ private isTSX;
69
+ constructor(options?: ESLoaderOptions);
70
+ transform(source: string, ctx: LoaderContext): ESModuleLoaderOutput;
71
+ }
72
+ //#endregion
73
+ //#region src/loaders/json-loader.d.ts
74
+ declare class JSONLoader implements Loader<LoaderType.ESModule> {
75
+ readonly name = "json-loader";
76
+ readonly test: RegExp;
77
+ transform(source: string): ESModuleLoaderOutput;
78
+ }
79
+ //#endregion
80
+ //#region src/loaders/markdown-loader.d.ts
81
+ declare class MarkdownLoader implements Loader<LoaderType.Asset> {
82
+ readonly name = "markdown-loader";
83
+ readonly test: RegExp;
84
+ transform(source: string): AssetLoaderOutput;
85
+ }
86
+ //#endregion
87
+ export { AssetLoaderOutput, CSSLoader, ESLoader, ESLoaderOptions, ESModuleLoaderOutput, JSONLoader, Loader, LoaderContext, LoaderOutput, LoaderType, MarkdownLoader, ScriptLoaderOutput, StyleLoaderOutput };
@@ -0,0 +1,175 @@
1
+ import { parse } from "@babel/parser";
2
+ import { availablePresets, transform } from "@babel/standalone";
3
+ import DOMPurify from "dompurify";
4
+ import { marked } from "marked";
5
+
6
+ //#region src/loaders/types.ts
7
+ let LoaderType = /* @__PURE__ */ function(LoaderType$1) {
8
+ LoaderType$1["ESModule"] = "esmodule";
9
+ LoaderType$1["Style"] = "style";
10
+ LoaderType$1["Script"] = "script";
11
+ LoaderType$1["Asset"] = "asset";
12
+ return LoaderType$1;
13
+ }({});
14
+
15
+ //#endregion
16
+ //#region src/loaders/css-loader.ts
17
+ var CSSLoader = class {
18
+ name = "css-loader";
19
+ test = /\.css$/;
20
+ constructor(config) {
21
+ this.config = config;
22
+ }
23
+ transform(source, ctx) {
24
+ const { enabled = true, match } = this.config?.tailwind || {};
25
+ const isTailwind = match ? match.test(ctx.resourcePath) : ctx.resourcePath.endsWith(".tw.css");
26
+ const imports = [];
27
+ const content = source.replace(/@import\s+(?:url\()?['"]?([^'")]+)['"]?\)?\s*;?/g, (_, importPath) => {
28
+ const resolved = ctx.resolve(importPath);
29
+ if (resolved) imports.push(resolved);
30
+ return "";
31
+ });
32
+ return {
33
+ type: LoaderType.Style,
34
+ content,
35
+ imports,
36
+ attributes: enabled && isTailwind ? { type: "text/tailwindcss" } : {}
37
+ };
38
+ }
39
+ };
40
+
41
+ //#endregion
42
+ //#region src/loaders/es-loader.ts
43
+ const parseCode = (code) => parse(code, {
44
+ sourceType: "module",
45
+ plugins: ["jsx", "typescript"]
46
+ }).program.body;
47
+ const collectIdentifiers = (ast) => {
48
+ const ids = /* @__PURE__ */ new Set();
49
+ const walk = (node) => {
50
+ if (!node || typeof node !== "object") return;
51
+ if (node.type === "Identifier" || node.type === "JSXIdentifier") ids.add(node.name);
52
+ for (const k of Object.keys(node)) {
53
+ if (k === "loc" || k === "range") continue;
54
+ const val = node[k];
55
+ if (Array.isArray(val)) val.forEach(walk);
56
+ else if (val && typeof val === "object") walk(val);
57
+ }
58
+ };
59
+ ast.forEach(walk);
60
+ return ids;
61
+ };
62
+ const analyzeImports = (ast) => {
63
+ const imports = ast.filter((node) => node.type === "ImportDeclaration");
64
+ const usedIds = collectIdentifiers(ast.filter((node) => node.type !== "ImportDeclaration"));
65
+ const importMap = /* @__PURE__ */ new Map();
66
+ imports.forEach((imp) => {
67
+ if (imp.importKind === "type") return;
68
+ imp.specifiers.forEach((spec) => {
69
+ if (spec.type === "ImportSpecifier" && spec.importKind === "type") return;
70
+ importMap.set(spec.local.name, imp.source.value);
71
+ });
72
+ });
73
+ const usedSources = /* @__PURE__ */ new Set();
74
+ usedIds.forEach((id) => {
75
+ if (importMap.has(id)) usedSources.add(importMap.get(id));
76
+ });
77
+ return {
78
+ imports,
79
+ usedSources
80
+ };
81
+ };
82
+ const buildExternalDeps = (imports, usedSources) => {
83
+ const externals = /* @__PURE__ */ new Map();
84
+ imports.forEach((imp) => {
85
+ if (imp.importKind === "type") return;
86
+ const source = imp.source.value;
87
+ if (!usedSources.has(source) || source.startsWith(".") || source.startsWith("/")) return;
88
+ const namedImports = imp.specifiers.filter((spec) => spec.type === "ImportSpecifier" && spec.importKind !== "type").map((spec) => spec.imported.name);
89
+ const existing = externals.get(source);
90
+ if (existing) namedImports.forEach((name) => existing.imported.add(name));
91
+ else externals.set(source, {
92
+ name: source,
93
+ imported: new Set(namedImports)
94
+ });
95
+ });
96
+ return [...externals.values()].map((dep) => ({
97
+ ...dep,
98
+ imported: [...dep.imported]
99
+ }));
100
+ };
101
+ var ESLoader = class {
102
+ name = "es-loader";
103
+ test = /\.(tsx?|jsx?)$/;
104
+ jsxPreset;
105
+ isTSX;
106
+ constructor(options) {
107
+ const { jsxPreset, isTSX = false } = options || {};
108
+ this.jsxPreset = jsxPreset;
109
+ this.isTSX = isTSX;
110
+ }
111
+ transform(source, ctx) {
112
+ const { imports, usedSources } = analyzeImports(parseCode(source));
113
+ const externals = buildExternalDeps(imports, usedSources);
114
+ const dependencies = {};
115
+ for (const imp of imports) {
116
+ if (imp.importKind === "type") continue;
117
+ const importPath = imp.source.value;
118
+ if (imp.specifiers.length === 0) {
119
+ const resolved$1 = ctx.resolve(importPath);
120
+ if (resolved$1) dependencies[importPath] = resolved$1;
121
+ continue;
122
+ }
123
+ if (!usedSources.has(importPath)) continue;
124
+ const resolved = ctx.resolve(importPath);
125
+ if (resolved) dependencies[importPath] = resolved;
126
+ }
127
+ const { typescript } = availablePresets;
128
+ const defaultPresets = [typescript, {
129
+ isTSX: this.isTSX,
130
+ allExtensions: true
131
+ }];
132
+ const { code } = transform(source, {
133
+ filename: ctx.resourcePath,
134
+ presets: this.jsxPreset ? [this.jsxPreset, defaultPresets] : [defaultPresets]
135
+ });
136
+ return {
137
+ type: LoaderType.ESModule,
138
+ content: code || "",
139
+ dependencies,
140
+ externals
141
+ };
142
+ }
143
+ };
144
+
145
+ //#endregion
146
+ //#region src/loaders/json-loader.ts
147
+ var JSONLoader = class {
148
+ name = "json-loader";
149
+ test = /\.json$/;
150
+ transform(source) {
151
+ return {
152
+ type: LoaderType.ESModule,
153
+ content: `export default ${source};`,
154
+ dependencies: {},
155
+ externals: []
156
+ };
157
+ }
158
+ };
159
+
160
+ //#endregion
161
+ //#region src/loaders/markdown-loader.ts
162
+ var MarkdownLoader = class {
163
+ name = "markdown-loader";
164
+ test = /\.md$/;
165
+ transform(source) {
166
+ const html = DOMPurify.sanitize(marked.parse(source, { async: false }));
167
+ return {
168
+ type: LoaderType.Asset,
169
+ content: html
170
+ };
171
+ }
172
+ };
173
+
174
+ //#endregion
175
+ export { CSSLoader, ESLoader, JSONLoader, LoaderType, MarkdownLoader };
@@ -0,0 +1,52 @@
1
+ import { Framework as Framework$1 } from "@codespark/framework";
2
+ import "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/markdown/index.d.ts
43
+ declare class Framework extends Framework$1 {
44
+ readonly name = "markdown";
45
+ readonly imports: {};
46
+ outputs: Outputs;
47
+ analyze(entry: string, files: Record<string, string>): void;
48
+ compile(): any;
49
+ }
50
+ declare const markdown: Framework;
51
+ //#endregion
52
+ export { Framework, markdown };
@@ -0,0 +1,75 @@
1
+ import { Framework as Framework$1 } from "@codespark/framework";
2
+ import DOMPurify from "dompurify";
3
+ import { marked } from "marked";
4
+
5
+ //#region src/loaders/types.ts
6
+ let LoaderType = /* @__PURE__ */ function(LoaderType$1) {
7
+ LoaderType$1["ESModule"] = "esmodule";
8
+ LoaderType$1["Style"] = "style";
9
+ LoaderType$1["Script"] = "script";
10
+ LoaderType$1["Asset"] = "asset";
11
+ return LoaderType$1;
12
+ }({});
13
+
14
+ //#endregion
15
+ //#region src/loaders/markdown-loader.ts
16
+ var MarkdownLoader = class {
17
+ name = "markdown-loader";
18
+ test = /\.md$/;
19
+ transform(source) {
20
+ const html = DOMPurify.sanitize(marked.parse(source, { async: false }));
21
+ return {
22
+ type: LoaderType.Asset,
23
+ content: html
24
+ };
25
+ }
26
+ };
27
+
28
+ //#endregion
29
+ //#region src/markdown/analyze.ts
30
+ const LOADERS = [new MarkdownLoader()];
31
+ function matchLoader(path) {
32
+ return LOADERS.find((l) => l.test.test(path)) ?? null;
33
+ }
34
+ function processFile(path, files, outputs = /* @__PURE__ */ new Map(), visited = /* @__PURE__ */ new Set()) {
35
+ if (visited.has(path)) return;
36
+ visited.add(path);
37
+ const source = files[path];
38
+ if (source === void 0) return;
39
+ const loader = matchLoader(path);
40
+ if (!loader) return;
41
+ const output = loader.transform(source);
42
+ const result = {
43
+ path,
44
+ content: output.content
45
+ };
46
+ outputs.get(output.type).push(result);
47
+ }
48
+ function analyze(entry, files) {
49
+ const outputs = /* @__PURE__ */ new Map();
50
+ outputs.set(LoaderType.ESModule, []);
51
+ outputs.set(LoaderType.Style, []);
52
+ outputs.set(LoaderType.Script, []);
53
+ outputs.set(LoaderType.Asset, []);
54
+ processFile(entry, files, outputs);
55
+ return outputs;
56
+ }
57
+
58
+ //#endregion
59
+ //#region src/markdown/index.ts
60
+ var Framework = class extends Framework$1 {
61
+ name = "markdown";
62
+ imports = {};
63
+ outputs = /* @__PURE__ */ new Map();
64
+ analyze(entry, files) {
65
+ this.outputs = analyze(entry, files);
66
+ }
67
+ compile() {
68
+ const assets = this.getOutput(LoaderType.Asset);
69
+ return this.createBuilder().setHTML(JSON.stringify(assets.map(({ content }) => content).join(""))).done();
70
+ }
71
+ };
72
+ const markdown = new Framework();
73
+
74
+ //#endregion
75
+ export { Framework, markdown };
@@ -0,0 +1,59 @@
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/react/index.d.ts
43
+ declare class Framework extends Framework$1 {
44
+ readonly name = "react";
45
+ readonly imports: {
46
+ react: string;
47
+ 'react/jsx-runtime': string;
48
+ 'react-dom/client': string;
49
+ };
50
+ outputs: Outputs;
51
+ private blobUrlMap;
52
+ analyze(entry: string, files: Record<string, string>): void;
53
+ compile(): any;
54
+ private transformModulesToBlob;
55
+ private transformCodeWithBlobUrls;
56
+ }
57
+ declare const react: Framework;
58
+ //#endregion
59
+ export { Framework, react };