@fluixi/compiler 1.0.0-alpha.83 → 1.0.0-alpha.84
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/analyze/expr-shape.cjs +62 -1
- package/dist/analyze/expr-shape.d.cts +14 -0
- package/dist/analyze/expr-shape.mjs +41 -1
- package/dist/analyze/intrinsics.cjs +80 -1
- package/dist/analyze/intrinsics.d.cts +66 -0
- package/dist/analyze/intrinsics.mjs +59 -1
- package/dist/analyze/paren.cjs +134 -0
- package/dist/analyze/paren.d.cts +23 -0
- package/dist/analyze/paren.d.ts +24 -0
- package/dist/analyze/paren.d.ts.map +1 -0
- package/dist/analyze/paren.js +168 -0
- package/dist/analyze/paren.mjs +113 -0
- package/dist/analyze/props-destructure.cjs +226 -1
- package/dist/analyze/props-destructure.d.cts +83 -0
- package/dist/analyze/props-destructure.mjs +205 -1
- package/dist/analyze/reactive-bindings.cjs +190 -1
- package/dist/analyze/reactive-bindings.d.cts +42 -0
- package/dist/analyze/reactive-bindings.mjs +167 -1
- package/dist/analyze/reactive-expr.cjs +38 -1
- package/dist/analyze/reactive-expr.d.cts +38 -0
- package/dist/analyze/reactive-expr.mjs +17 -1
- package/dist/analyze/static-graph.cjs +811 -1
- package/dist/analyze/static-graph.d.cts +102 -0
- package/dist/analyze/static-graph.mjs +793 -1
- package/dist/babel-NRW4EFTG.mjs +636 -0
- package/dist/chunk-3YKZ4GNH.mjs +11 -0
- package/dist/chunk-EZR7NZOY.mjs +1718 -0
- package/dist/chunk-FSSWUXUR.mjs +16 -0
- package/dist/chunk-MJV3UXIL.mjs +158 -0
- package/dist/chunk-R2VHAZAX.mjs +1078 -0
- package/dist/codegen/backend.cjs +18 -1
- package/dist/codegen/backend.d.cts +35 -0
- package/dist/codegen/backends/imperative.cjs +542 -1
- package/dist/codegen/backends/imperative.d.cts +11 -0
- package/dist/codegen/backends/imperative.d.ts.map +1 -1
- package/dist/codegen/backends/imperative.js +12 -8
- package/dist/codegen/backends/imperative.mjs +519 -1
- package/dist/codegen/contract.cjs +52 -1
- package/dist/codegen/contract.d.cts +24 -0
- package/dist/codegen/contract.mjs +31 -1
- package/dist/codegen/partial-template.cjs +176 -1
- package/dist/codegen/partial-template.d.cts +61 -0
- package/dist/codegen/partial-template.mjs +153 -1
- package/dist/codegen/serialize-static.cjs +125 -1
- package/dist/codegen/serialize-static.d.cts +38 -0
- package/dist/codegen/serialize-static.mjs +104 -1
- package/dist/frontend/babel/build-ir-lit.cjs +1509 -1
- package/dist/frontend/babel/build-ir-lit.d.cts +26 -0
- package/dist/frontend/babel/build-ir-lit.mjs +1478 -1
- package/dist/frontend/babel/build-ir.cjs +1524 -1
- package/dist/frontend/babel/build-ir.d.cts +35 -0
- package/dist/frontend/babel/build-ir.mjs +1495 -1
- package/dist/frontend/babel/index.cjs +2186 -1
- package/dist/frontend/babel/index.d.cts +33 -0
- package/dist/frontend/babel/index.mjs +2156 -1
- package/dist/frontend/babel/lower-template.cjs +1507 -1
- package/dist/frontend/babel/lower-template.d.cts +23 -0
- package/dist/frontend/babel/lower-template.mjs +1478 -1
- package/dist/frontend/babel/plugin.cjs +2132 -1
- package/dist/frontend/babel/plugin.d.cts +95 -0
- package/dist/frontend/babel/plugin.mjs +2103 -1
- package/dist/frontend/babel/server-functions.cjs +110 -1
- package/dist/frontend/babel/server-functions.d.cts +10 -0
- package/dist/frontend/babel/server-functions.mjs +89 -1
- package/dist/frontend/babel/types.cjs +18 -1
- package/dist/frontend/babel/types.d.cts +33 -0
- package/dist/frontend/types.cjs +18 -1
- package/dist/frontend/types.d.cts +25 -0
- package/dist/frontend/vocabulary.cjs +98 -0
- package/dist/frontend/vocabulary.d.cts +79 -0
- package/dist/frontend/vocabulary.d.ts +80 -0
- package/dist/frontend/vocabulary.d.ts.map +1 -0
- package/dist/frontend/vocabulary.js +124 -0
- package/dist/frontend/vocabulary.mjs +77 -0
- package/dist/index.cjs +1594 -13
- package/dist/index.d.cts +27 -0
- package/dist/index.mjs +1574 -13
- package/dist/integrations.cjs +4307 -25
- package/dist/integrations.d.cts +215 -0
- package/dist/integrations.mjs +531 -17
- package/dist/ir/nodes.cjs +18 -1
- package/dist/ir/nodes.d.cts +168 -0
- package/dist/lower/compile-template.cjs +1356 -1
- package/dist/lower/compile-template.d.cts +69 -0
- package/dist/lower/compile-template.mjs +1336 -1
- package/dist/lower/jsx.cjs +529 -1
- package/dist/lower/jsx.d.cts +25 -0
- package/dist/lower/jsx.d.ts.map +1 -1
- package/dist/lower/jsx.js +2 -1
- package/dist/lower/jsx.mjs +506 -1
- package/dist/lower/template.cjs +1061 -1
- package/dist/lower/template.d.cts +53 -0
- package/dist/lower/template.d.ts.map +1 -1
- package/dist/lower/template.js +5 -4
- package/dist/lower/template.mjs +1042 -1
- package/dist/lower/text.cjs +42 -1
- package/dist/lower/text.d.cts +10 -0
- package/dist/lower/text.mjs +21 -1
- package/dist/optimize/analyze-static.cjs +112 -1
- package/dist/optimize/analyze-static.d.cts +39 -0
- package/dist/optimize/analyze-static.mjs +91 -1
- package/dist/optimize/collapse-strategies.cjs +90 -1
- package/dist/optimize/collapse-strategies.d.cts +30 -0
- package/dist/optimize/collapse-strategies.mjs +67 -1
- package/dist/options.cjs +33 -1
- package/dist/options.d.cts +39 -0
- package/dist/options.mjs +12 -1
- package/dist/resolve/builtins.cjs +73 -1
- package/dist/resolve/builtins.d.cts +68 -0
- package/dist/resolve/builtins.mjs +53 -1
- package/dist/resolve/component-globals.cjs +233 -13
- package/dist/resolve/component-globals.d.cts +80 -0
- package/dist/resolve/component-globals.mjs +210 -13
- package/dist/resolve/component-resolver.cjs +80 -1
- package/dist/resolve/component-resolver.d.cts +68 -0
- package/dist/resolve/component-resolver.mjs +59 -1
- package/dist/resolve/load-directive.cjs +93 -1
- package/dist/resolve/load-directive.d.cts +53 -0
- package/dist/resolve/load-directive.mjs +72 -1
- package/dist/resolve/resolve-ir.cjs +108 -1
- package/dist/resolve/resolve-ir.d.cts +53 -0
- package/dist/resolve/resolve-ir.mjs +85 -1
- package/dist/resolve/write-globals.cjs +318 -13
- package/dist/resolve/write-globals.d.cts +30 -0
- package/dist/resolve/write-globals.mjs +297 -13
- package/dist/server-fns-4ZXN6DYU.mjs +78 -0
- package/dist/server-functions-V6D6DRIA.mjs +82 -0
- package/dist/transform/bindings.cjs +71 -1
- package/dist/transform/bindings.d.cts +16 -0
- package/dist/transform/bindings.mjs +50 -1
- package/dist/transform/index.cjs +2732 -8
- package/dist/transform/index.d.cts +15 -0
- package/dist/transform/index.mjs +3773 -17
- package/dist/transform/intrinsics.cjs +216 -3
- package/dist/transform/intrinsics.d.cts +21 -0
- package/dist/transform/intrinsics.mjs +193 -3
- package/dist/transform/props.cjs +441 -3
- package/dist/transform/props.d.cts +45 -0
- package/dist/transform/props.mjs +1482 -12
- package/dist/transform/server-fn-id.cjs +35 -1
- package/dist/transform/server-fn-id.d.cts +9 -0
- package/dist/transform/server-fn-id.mjs +14 -1
- package/dist/transform/server-fns.cjs +114 -2
- package/dist/transform/server-fns.d.cts +12 -0
- package/dist/transform/server-fns.mjs +1155 -11
- package/dist/transform/source-locations.cjs +330 -1
- package/dist/transform/source-locations.d.cts +43 -0
- package/dist/transform/source-locations.mjs +307 -1
- package/dist/transform/templates.cjs +2701 -7
- package/dist/transform/templates.d.cts +69 -0
- package/dist/transform/templates.mjs +3743 -16
- package/dist/transform-BT4MMASR.mjs +893 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +6 -5
- package/dist/babel-VXKH6MRQ.mjs +0 -1
- package/dist/chunk-3SAEGOMQ.mjs +0 -1
- package/dist/chunk-5KMMN5QP.mjs +0 -1
- package/dist/chunk-IBRM4W7I.mjs +0 -10
- package/dist/chunk-OHHZCYIQ.mjs +0 -1
- package/dist/chunk-YKZ54NVE.mjs +0 -1
- package/dist/server-fns-6QM243HC.mjs +0 -2
- package/dist/server-functions-E3LKCZ4R.mjs +0 -1
- package/dist/transform-C4ZXRVGP.mjs +0 -8
|
@@ -1,22 +1,219 @@
|
|
|
1
|
-
|
|
1
|
+
// src/resolve/component-resolver.ts
|
|
2
|
+
var isMapRule = (rule) => "components" in rule;
|
|
3
|
+
function substitute(template, match) {
|
|
4
|
+
return template.replace(/\$(\d+)/g, (whole, index) => {
|
|
5
|
+
const group = match[Number(index)];
|
|
6
|
+
return group ?? whole;
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
function normalise(name, entry) {
|
|
10
|
+
return typeof entry === "string" ? { module: entry, export: name } : entry;
|
|
11
|
+
}
|
|
12
|
+
function createComponentResolver(rules = []) {
|
|
13
|
+
const exact = /* @__PURE__ */ new Map();
|
|
14
|
+
const conflicts = [];
|
|
15
|
+
const patterns = [];
|
|
16
|
+
for (const rule of rules) {
|
|
17
|
+
if (!isMapRule(rule)) {
|
|
18
|
+
patterns.push(rule);
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
for (const [name, entry] of Object.entries(rule.components)) {
|
|
22
|
+
const resolved = normalise(name, entry);
|
|
23
|
+
const existing = exact.get(name);
|
|
24
|
+
if (existing && existing.module !== resolved.module) {
|
|
25
|
+
const conflict = conflicts.find((c) => c.name === name);
|
|
26
|
+
if (conflict) conflict.modules.push(resolved.module);
|
|
27
|
+
else conflicts.push({ name, modules: [existing.module, resolved.module] });
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
exact.set(name, resolved);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const cache = /* @__PURE__ */ new Map();
|
|
34
|
+
const resolve = (name) => {
|
|
35
|
+
if (cache.has(name)) return cache.get(name);
|
|
36
|
+
let result = exact.get(name);
|
|
37
|
+
if (!result) {
|
|
38
|
+
for (const rule of patterns) {
|
|
39
|
+
const match = name.match(new RegExp(rule.match.source, rule.match.flags.replace("g", "")));
|
|
40
|
+
if (!match) continue;
|
|
41
|
+
result = {
|
|
42
|
+
module: substitute(rule.module, match),
|
|
43
|
+
export: rule.export ? substitute(rule.export, match) : name
|
|
44
|
+
};
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
cache.set(name, result);
|
|
49
|
+
return result;
|
|
50
|
+
};
|
|
51
|
+
return {
|
|
52
|
+
resolve,
|
|
53
|
+
names: () => [...exact.keys()],
|
|
54
|
+
conflicts: () => conflicts
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// src/resolve/builtins.ts
|
|
59
|
+
var DOM_CONTROL_FLOW = [
|
|
60
|
+
"Show",
|
|
61
|
+
"For",
|
|
62
|
+
"Index",
|
|
63
|
+
"Switch",
|
|
64
|
+
"Match",
|
|
65
|
+
"Portal",
|
|
66
|
+
"Dynamic",
|
|
67
|
+
"ErrorBoundary"
|
|
68
|
+
];
|
|
69
|
+
var CORE_CONTROL_FLOW = ["Suspense", "SuspenseList", "Await"];
|
|
70
|
+
var ROUTER_COMPONENTS = ["Router", "Outlet", "Redirect", "Link"];
|
|
71
|
+
var BUILTIN_COMPONENTS = [
|
|
72
|
+
...DOM_CONTROL_FLOW,
|
|
73
|
+
...CORE_CONTROL_FLOW,
|
|
74
|
+
...ROUTER_COMPONENTS
|
|
75
|
+
];
|
|
76
|
+
var RESERVED_COMPONENTS = /* @__PURE__ */ new Set([
|
|
77
|
+
...DOM_CONTROL_FLOW,
|
|
78
|
+
...CORE_CONTROL_FLOW
|
|
79
|
+
]);
|
|
80
|
+
function builtinComponentMap(modules = {}) {
|
|
81
|
+
const {
|
|
82
|
+
controlFlowModule = "@fluixi/dom",
|
|
83
|
+
coreModule = "@fluixi/core",
|
|
84
|
+
routerModule = "@fluixi/core/router"
|
|
85
|
+
} = modules;
|
|
86
|
+
const map = {};
|
|
87
|
+
for (const name of DOM_CONTROL_FLOW) map[name] = controlFlowModule;
|
|
88
|
+
for (const name of CORE_CONTROL_FLOW) map[name] = coreModule;
|
|
89
|
+
for (const name of ROUTER_COMPONENTS) map[name] = routerModule;
|
|
90
|
+
return map;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// src/analyze/intrinsics.ts
|
|
94
|
+
var REACTIVE_MODULE = "@fluixi/reactive/signal";
|
|
95
|
+
var INTRINSICS = {
|
|
96
|
+
$signal: { export: "signal", module: REACTIVE_MODULE, returns: "signal-handle" },
|
|
97
|
+
$memo: { export: "memo", module: REACTIVE_MODULE, returns: "memo-handle" },
|
|
98
|
+
$effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
|
|
99
|
+
$store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
|
|
100
|
+
$resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
|
|
101
|
+
// No short runtime form for these yet, so the intrinsic stands for the `create*`
|
|
102
|
+
// name. Still worth having — no import to write — and when a shorter form is
|
|
103
|
+
// designed, the change is this line rather than a compiler pass.
|
|
104
|
+
$selector: { export: "createSelector", module: REACTIVE_MODULE, returns: "memo-accessor" },
|
|
105
|
+
$deferred: { export: "createDeferred", module: REACTIVE_MODULE, returns: "memo-accessor" },
|
|
106
|
+
// Not value constructors, but the compiler has to know them: they change what a read
|
|
107
|
+
// does. `untrack` suppresses dependency collection, which is exactly the kind of thing
|
|
108
|
+
// dependency analysis must not guess at.
|
|
109
|
+
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
110
|
+
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" }
|
|
111
|
+
};
|
|
112
|
+
var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
|
|
113
|
+
|
|
114
|
+
// src/resolve/component-globals.ts
|
|
115
|
+
var DOM_GLOBALS = /* @__PURE__ */ new Set([
|
|
116
|
+
"Text",
|
|
117
|
+
"Image",
|
|
118
|
+
"Option",
|
|
119
|
+
"Audio",
|
|
120
|
+
"Comment",
|
|
121
|
+
"Range",
|
|
122
|
+
"Selection",
|
|
123
|
+
"Notification",
|
|
124
|
+
"Event",
|
|
125
|
+
"Document",
|
|
126
|
+
"Element",
|
|
127
|
+
"Node",
|
|
128
|
+
"Screen",
|
|
129
|
+
"Window",
|
|
130
|
+
"Location",
|
|
131
|
+
"History",
|
|
132
|
+
"Storage",
|
|
133
|
+
"Response",
|
|
134
|
+
"Request",
|
|
135
|
+
"Headers"
|
|
136
|
+
]);
|
|
137
|
+
function packageOf(specifier) {
|
|
138
|
+
if (specifier.startsWith(".") || specifier.startsWith("/")) return void 0;
|
|
139
|
+
if (/^[~@]\//.test(specifier)) return void 0;
|
|
140
|
+
const parts = specifier.split("/");
|
|
141
|
+
return specifier.startsWith("@") ? parts.slice(0, 2).join("/") : parts[0];
|
|
142
|
+
}
|
|
143
|
+
function namespaceAlias(module) {
|
|
144
|
+
return `_${module.replace(/[^A-Za-z0-9]/g, "_")}`;
|
|
145
|
+
}
|
|
146
|
+
function componentGlobals(rules, options = {}) {
|
|
147
|
+
const {
|
|
148
|
+
available: availableList,
|
|
149
|
+
builtins = true,
|
|
150
|
+
intrinsics = true,
|
|
151
|
+
generator = "@fluixi/compiler",
|
|
152
|
+
specifier = (module) => module
|
|
153
|
+
} = options;
|
|
154
|
+
const all = [...rules];
|
|
155
|
+
if (builtins) {
|
|
156
|
+
all.push({ components: builtinComponentMap() });
|
|
157
|
+
}
|
|
158
|
+
const resolver = createComponentResolver(all);
|
|
159
|
+
const available = availableList ? new Set(availableList) : void 0;
|
|
160
|
+
const declared = [];
|
|
161
|
+
const shadowedByDom = [];
|
|
162
|
+
const unavailable = [];
|
|
163
|
+
const resolved = /* @__PURE__ */ new Map();
|
|
164
|
+
for (const name of [...resolver.names()].sort()) {
|
|
165
|
+
const target = resolver.resolve(name);
|
|
166
|
+
if (!target) continue;
|
|
167
|
+
const pkg = packageOf(target.module);
|
|
168
|
+
if (DOM_GLOBALS.has(name)) shadowedByDom.push(name);
|
|
169
|
+
else if (available && pkg && !available.has(pkg)) unavailable.push(name);
|
|
170
|
+
else {
|
|
171
|
+
declared.push(name);
|
|
172
|
+
resolved.set(name, target);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
const intrinsicModules = intrinsics ? [...new Set(Object.values(INTRINSICS).map((i) => i.module))] : [];
|
|
176
|
+
const modules = [
|
|
177
|
+
.../* @__PURE__ */ new Set([...declared.map((name) => resolved.get(name).module), ...intrinsicModules])
|
|
178
|
+
].sort();
|
|
179
|
+
const imports = modules.map(
|
|
180
|
+
(m) => `import * as ${namespaceAlias(m)} from '${specifier(m)}';`
|
|
181
|
+
);
|
|
182
|
+
const lines = declared.map((name) => {
|
|
183
|
+
const target = resolved.get(name);
|
|
184
|
+
const ns = namespaceAlias(target.module);
|
|
185
|
+
return target.export === "default" ? ` const ${name}: typeof ${ns}.default;` : ` export import ${name} = ${ns}.${target.export};`;
|
|
186
|
+
});
|
|
187
|
+
const note = shadowedByDom.length > 0 ? `//
|
|
2
188
|
// Import these explicitly — lib.dom already declares the name, so an ambient
|
|
3
189
|
// declaration cannot win:
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
190
|
+
` + shadowedByDom.map((n) => {
|
|
191
|
+
const module = resolver.resolve(n)?.module;
|
|
192
|
+
return `// import { ${n} } from '${module ? specifier(module) : ""}';
|
|
193
|
+
`;
|
|
194
|
+
}).join("") : "";
|
|
195
|
+
const intrinsicLines = intrinsics ? Object.entries(INTRINSICS).map(
|
|
196
|
+
([name, intrinsic]) => ` const ${name}: typeof ${namespaceAlias(intrinsic.module)}.${intrinsic.export};`
|
|
197
|
+
) : [];
|
|
198
|
+
const patternRules = rules.filter((rule) => "match" in rule).length;
|
|
199
|
+
const patternNote = patternRules > 0 ? `//
|
|
200
|
+
// ${patternRules} pattern rule${patternRules === 1 ? "" : "s"} cannot be declared:
|
|
7
201
|
// a pattern matches unboundedly many names, so there is no list to emit. Those
|
|
8
202
|
// tags still resolve at build time; declare them by hand if the editor needs them.
|
|
9
|
-
|
|
203
|
+
` : "";
|
|
204
|
+
const source = `// GENERATED by ${generator} — do not edit.
|
|
10
205
|
//
|
|
11
206
|
// The components \`resolve\` supplies without an import. This describes what the
|
|
12
207
|
// compiler already does; it does not enable it.
|
|
13
|
-
|
|
14
|
-
${
|
|
15
|
-
`)
|
|
16
|
-
`:`
|
|
17
|
-
`)+`
|
|
208
|
+
` + note + patternNote + (imports.length > 0 ? `
|
|
209
|
+
${imports.join("\n")}
|
|
210
|
+
` : "\n") + `
|
|
18
211
|
declare global {
|
|
19
|
-
${[...
|
|
20
|
-
|
|
212
|
+
${[...lines, ...intrinsicLines].join("\n")}
|
|
213
|
+
}
|
|
214
|
+
`;
|
|
215
|
+
return { source, declared, shadowedByDom, unavailable, patternRules };
|
|
21
216
|
}
|
|
22
|
-
|
|
217
|
+
export {
|
|
218
|
+
componentGlobals
|
|
219
|
+
};
|
|
@@ -1 +1,80 @@
|
|
|
1
|
-
"use strict";
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/resolve/component-resolver.ts
|
|
21
|
+
var component_resolver_exports = {};
|
|
22
|
+
__export(component_resolver_exports, {
|
|
23
|
+
createComponentResolver: () => createComponentResolver
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(component_resolver_exports);
|
|
26
|
+
var isMapRule = (rule) => "components" in rule;
|
|
27
|
+
function substitute(template, match) {
|
|
28
|
+
return template.replace(/\$(\d+)/g, (whole, index) => {
|
|
29
|
+
const group = match[Number(index)];
|
|
30
|
+
return group ?? whole;
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
function normalise(name, entry) {
|
|
34
|
+
return typeof entry === "string" ? { module: entry, export: name } : entry;
|
|
35
|
+
}
|
|
36
|
+
function createComponentResolver(rules = []) {
|
|
37
|
+
const exact = /* @__PURE__ */ new Map();
|
|
38
|
+
const conflicts = [];
|
|
39
|
+
const patterns = [];
|
|
40
|
+
for (const rule of rules) {
|
|
41
|
+
if (!isMapRule(rule)) {
|
|
42
|
+
patterns.push(rule);
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
for (const [name, entry] of Object.entries(rule.components)) {
|
|
46
|
+
const resolved = normalise(name, entry);
|
|
47
|
+
const existing = exact.get(name);
|
|
48
|
+
if (existing && existing.module !== resolved.module) {
|
|
49
|
+
const conflict = conflicts.find((c) => c.name === name);
|
|
50
|
+
if (conflict) conflict.modules.push(resolved.module);
|
|
51
|
+
else conflicts.push({ name, modules: [existing.module, resolved.module] });
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
exact.set(name, resolved);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const cache = /* @__PURE__ */ new Map();
|
|
58
|
+
const resolve = (name) => {
|
|
59
|
+
if (cache.has(name)) return cache.get(name);
|
|
60
|
+
let result = exact.get(name);
|
|
61
|
+
if (!result) {
|
|
62
|
+
for (const rule of patterns) {
|
|
63
|
+
const match = name.match(new RegExp(rule.match.source, rule.match.flags.replace("g", "")));
|
|
64
|
+
if (!match) continue;
|
|
65
|
+
result = {
|
|
66
|
+
module: substitute(rule.module, match),
|
|
67
|
+
export: rule.export ? substitute(rule.export, match) : name
|
|
68
|
+
};
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
cache.set(name, result);
|
|
73
|
+
return result;
|
|
74
|
+
};
|
|
75
|
+
return {
|
|
76
|
+
resolve,
|
|
77
|
+
names: () => [...exact.keys()],
|
|
78
|
+
conflicts: () => conflicts
|
|
79
|
+
};
|
|
80
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compile-time component resolution.
|
|
3
|
+
*
|
|
4
|
+
* An unbound capitalised tag in a template is a name the compiler can resolve to a
|
|
5
|
+
* module, instead of an import the author has to write. The framework already does
|
|
6
|
+
* this for `Suspense`/`Portal`/`Router`, but through a hardcoded name set inside the
|
|
7
|
+
* Babel plugin — which cannot be extended by a UI library or an app, and cannot be
|
|
8
|
+
* configured per project.
|
|
9
|
+
*
|
|
10
|
+
* This is the configurable version of the same idea. It is deliberately a pure
|
|
11
|
+
* `name -> { module, export }` function with no filesystem access and no Babel
|
|
12
|
+
* dependency, because three separate consumers need exactly the same answer:
|
|
13
|
+
*
|
|
14
|
+
* - the compiler, to inject the import;
|
|
15
|
+
* - the TS plugin, to synthesise the import so hover/go-to-definition/rename work;
|
|
16
|
+
* - a codemod, to materialise imports back into source.
|
|
17
|
+
*
|
|
18
|
+
* Keeping resolution pure is what lets those three agree. Anything requiring the
|
|
19
|
+
* filesystem (directory conventions) belongs in a rule *builder* that produces a map,
|
|
20
|
+
* not in the resolver itself.
|
|
21
|
+
*/
|
|
22
|
+
/** Where a resolved component comes from. */
|
|
23
|
+
export interface ResolvedComponent {
|
|
24
|
+
module: string;
|
|
25
|
+
/** The export name, or `default`. */
|
|
26
|
+
export: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* An explicit name -> module map. This is what a component library ships
|
|
30
|
+
* (`Button -> @fluixi-ui/button`), generated from its own package list rather than
|
|
31
|
+
* hand-maintained.
|
|
32
|
+
*/
|
|
33
|
+
export interface ComponentMapRule {
|
|
34
|
+
components: Record<string, string | ResolvedComponent>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* A pattern rule. `$1`-style references in `module`/`export` are substituted from the
|
|
38
|
+
* match groups, so one rule can cover a family (`Icon(.+) -> @/icons/$1`).
|
|
39
|
+
*/
|
|
40
|
+
export interface ComponentPatternRule {
|
|
41
|
+
match: RegExp;
|
|
42
|
+
module: string;
|
|
43
|
+
/** Defaults to the tag name; use `'default'` for file-per-component layouts. */
|
|
44
|
+
export?: string;
|
|
45
|
+
}
|
|
46
|
+
export type ComponentResolverRule = ComponentMapRule | ComponentPatternRule;
|
|
47
|
+
/** Two rules claiming the same name — reported rather than silently first-wins. */
|
|
48
|
+
export interface ResolverConflict {
|
|
49
|
+
name: string;
|
|
50
|
+
modules: string[];
|
|
51
|
+
}
|
|
52
|
+
export interface ComponentResolver {
|
|
53
|
+
/** `undefined` when no rule claims the name. */
|
|
54
|
+
resolve: (name: string) => ResolvedComponent | undefined;
|
|
55
|
+
/** Every name the resolver can answer, for editor completion. */
|
|
56
|
+
names: () => string[];
|
|
57
|
+
/** Names claimed by more than one rule with different targets. */
|
|
58
|
+
conflicts: () => ResolverConflict[];
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Build a resolver from rules, in order.
|
|
62
|
+
*
|
|
63
|
+
* Map rules are flattened up front so lookup is a plain object read — resolution runs
|
|
64
|
+
* once per component reference per compile, so it sits on the hot path of every build.
|
|
65
|
+
* Pattern rules are tried afterwards, in declaration order, and only when no map rule
|
|
66
|
+
* matched: an explicit entry should always beat a pattern.
|
|
67
|
+
*/
|
|
68
|
+
export declare function createComponentResolver(rules?: readonly ComponentResolverRule[]): ComponentResolver;
|
|
@@ -1 +1,59 @@
|
|
|
1
|
-
|
|
1
|
+
// src/resolve/component-resolver.ts
|
|
2
|
+
var isMapRule = (rule) => "components" in rule;
|
|
3
|
+
function substitute(template, match) {
|
|
4
|
+
return template.replace(/\$(\d+)/g, (whole, index) => {
|
|
5
|
+
const group = match[Number(index)];
|
|
6
|
+
return group ?? whole;
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
function normalise(name, entry) {
|
|
10
|
+
return typeof entry === "string" ? { module: entry, export: name } : entry;
|
|
11
|
+
}
|
|
12
|
+
function createComponentResolver(rules = []) {
|
|
13
|
+
const exact = /* @__PURE__ */ new Map();
|
|
14
|
+
const conflicts = [];
|
|
15
|
+
const patterns = [];
|
|
16
|
+
for (const rule of rules) {
|
|
17
|
+
if (!isMapRule(rule)) {
|
|
18
|
+
patterns.push(rule);
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
for (const [name, entry] of Object.entries(rule.components)) {
|
|
22
|
+
const resolved = normalise(name, entry);
|
|
23
|
+
const existing = exact.get(name);
|
|
24
|
+
if (existing && existing.module !== resolved.module) {
|
|
25
|
+
const conflict = conflicts.find((c) => c.name === name);
|
|
26
|
+
if (conflict) conflict.modules.push(resolved.module);
|
|
27
|
+
else conflicts.push({ name, modules: [existing.module, resolved.module] });
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
exact.set(name, resolved);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const cache = /* @__PURE__ */ new Map();
|
|
34
|
+
const resolve = (name) => {
|
|
35
|
+
if (cache.has(name)) return cache.get(name);
|
|
36
|
+
let result = exact.get(name);
|
|
37
|
+
if (!result) {
|
|
38
|
+
for (const rule of patterns) {
|
|
39
|
+
const match = name.match(new RegExp(rule.match.source, rule.match.flags.replace("g", "")));
|
|
40
|
+
if (!match) continue;
|
|
41
|
+
result = {
|
|
42
|
+
module: substitute(rule.module, match),
|
|
43
|
+
export: rule.export ? substitute(rule.export, match) : name
|
|
44
|
+
};
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
cache.set(name, result);
|
|
49
|
+
return result;
|
|
50
|
+
};
|
|
51
|
+
return {
|
|
52
|
+
resolve,
|
|
53
|
+
names: () => [...exact.keys()],
|
|
54
|
+
conflicts: () => conflicts
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
export {
|
|
58
|
+
createComponentResolver
|
|
59
|
+
};
|
|
@@ -1 +1,93 @@
|
|
|
1
|
-
"use strict";
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/resolve/load-directive.ts
|
|
21
|
+
var load_directive_exports = {};
|
|
22
|
+
__export(load_directive_exports, {
|
|
23
|
+
DEFAULT_INTERACTION_EVENTS: () => DEFAULT_INTERACTION_EVENTS,
|
|
24
|
+
EAGER: () => EAGER,
|
|
25
|
+
LoadDirectiveError: () => LoadDirectiveError,
|
|
26
|
+
isDeferred: () => isDeferred,
|
|
27
|
+
isLoadDirective: () => isLoadDirective,
|
|
28
|
+
parseLoadDirective: () => parseLoadDirective,
|
|
29
|
+
strategyKey: () => strategyKey
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(load_directive_exports);
|
|
32
|
+
var EAGER = { kind: "eager" };
|
|
33
|
+
var DEFAULT_INTERACTION_EVENTS = ["pointerdown", "focusin", "keydown"];
|
|
34
|
+
var STRATEGIES = /* @__PURE__ */ new Set(["eager", "idle", "visible", "interaction", "media", "never"]);
|
|
35
|
+
var LoadDirectiveError = class extends Error {
|
|
36
|
+
};
|
|
37
|
+
function isLoadDirective(name) {
|
|
38
|
+
return name.startsWith("load:");
|
|
39
|
+
}
|
|
40
|
+
function parseLoadDirective(name, value) {
|
|
41
|
+
const strategy = name.slice("load:".length);
|
|
42
|
+
if (!STRATEGIES.has(strategy)) {
|
|
43
|
+
throw new LoadDirectiveError(
|
|
44
|
+
`Unknown load strategy 'load:${strategy}'. Expected one of ${[...STRATEGIES].join(", ")}.`
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
switch (strategy) {
|
|
48
|
+
case "eager":
|
|
49
|
+
return EAGER;
|
|
50
|
+
case "idle":
|
|
51
|
+
return { kind: "idle" };
|
|
52
|
+
case "never":
|
|
53
|
+
return { kind: "never" };
|
|
54
|
+
case "visible":
|
|
55
|
+
return value ? { kind: "visible", rootMargin: value } : { kind: "visible" };
|
|
56
|
+
case "interaction":
|
|
57
|
+
return {
|
|
58
|
+
kind: "interaction",
|
|
59
|
+
events: value ? splitEvents(value) : [...DEFAULT_INTERACTION_EVENTS]
|
|
60
|
+
};
|
|
61
|
+
case "media":
|
|
62
|
+
if (!value) {
|
|
63
|
+
throw new LoadDirectiveError(
|
|
64
|
+
`'load:media' needs a query, e.g. load:media="(min-width: 1024px)".`
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
return { kind: "media", query: value };
|
|
68
|
+
default:
|
|
69
|
+
throw new LoadDirectiveError(`Unhandled load strategy '${strategy}'.`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function splitEvents(value) {
|
|
73
|
+
const events = value.split(/[\s,]+/).map((e) => e.trim()).filter(Boolean);
|
|
74
|
+
if (events.length === 0) {
|
|
75
|
+
throw new LoadDirectiveError(`'load:interaction' was given no event names.`);
|
|
76
|
+
}
|
|
77
|
+
return events;
|
|
78
|
+
}
|
|
79
|
+
function isDeferred(strategy) {
|
|
80
|
+
return strategy.kind !== "eager" && strategy.kind !== "never";
|
|
81
|
+
}
|
|
82
|
+
function strategyKey(strategy) {
|
|
83
|
+
switch (strategy.kind) {
|
|
84
|
+
case "visible":
|
|
85
|
+
return `visible:${strategy.rootMargin ?? ""}`;
|
|
86
|
+
case "interaction":
|
|
87
|
+
return `interaction:${[...strategy.events].sort().join(",")}`;
|
|
88
|
+
case "media":
|
|
89
|
+
return `media:${strategy.query}`;
|
|
90
|
+
default:
|
|
91
|
+
return strategy.kind;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `load:` directive — when a component's code is fetched.
|
|
3
|
+
*
|
|
4
|
+
* Resolution decides *where* a component comes from; this decides *when*. They are
|
|
5
|
+
* separate because they vary independently: the location of `<RevenueChart>` is the
|
|
6
|
+
* same everywhere and belongs in config, while whether this particular usage should
|
|
7
|
+
* wait for the viewport is a property of the usage. Fusing them — `<Chart lazy="./Chart">`
|
|
8
|
+
* — was rejected for exactly that reason.
|
|
9
|
+
*
|
|
10
|
+
* `load:` joins the existing `use:`/`prop:`/`attr:`/`bool:` namespace, so it cannot
|
|
11
|
+
* collide with a real prop and the parser already has a directive taxonomy to hang it on.
|
|
12
|
+
*
|
|
13
|
+
* One parser for both frontends. `load:visible` is already a valid `JSXNamespacedName`,
|
|
14
|
+
* so JSX needs no parser change, and the html`` path produces a `LoadDirective` node —
|
|
15
|
+
* but both funnel through {@link parseLoadDirective}, so the two syntaxes cannot drift.
|
|
16
|
+
*/
|
|
17
|
+
/** When a component's module is fetched. */
|
|
18
|
+
export type IRLoadStrategy = {
|
|
19
|
+
kind: 'eager';
|
|
20
|
+
} | {
|
|
21
|
+
kind: 'idle';
|
|
22
|
+
} | {
|
|
23
|
+
kind: 'visible';
|
|
24
|
+
rootMargin?: string;
|
|
25
|
+
} | {
|
|
26
|
+
kind: 'interaction';
|
|
27
|
+
events: string[];
|
|
28
|
+
} | {
|
|
29
|
+
kind: 'media';
|
|
30
|
+
query: string;
|
|
31
|
+
} | {
|
|
32
|
+
kind: 'never';
|
|
33
|
+
};
|
|
34
|
+
/** Everything is eager unless a directive says otherwise. */
|
|
35
|
+
export declare const EAGER: IRLoadStrategy;
|
|
36
|
+
/** Events that trigger an `interaction` load when none are named. */
|
|
37
|
+
export declare const DEFAULT_INTERACTION_EVENTS: readonly ["pointerdown", "focusin", "keydown"];
|
|
38
|
+
export declare class LoadDirectiveError extends Error {
|
|
39
|
+
}
|
|
40
|
+
/** True for an attribute name in the `load:` namespace. */
|
|
41
|
+
export declare function isLoadDirective(name: string): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Parse `load:<strategy>` plus its optional value into a strategy.
|
|
44
|
+
*
|
|
45
|
+
* `value` is the attribute's literal text — `load:visible="200px"` — or null for a bare
|
|
46
|
+
* directive. A `${…}` hole is rejected: the strategy has to be known at compile time
|
|
47
|
+
* because it decides how the module is emitted, and a runtime value cannot.
|
|
48
|
+
*/
|
|
49
|
+
export declare function parseLoadDirective(name: string, value: string | null): IRLoadStrategy;
|
|
50
|
+
/** True when the strategy means "not in the parent chunk". */
|
|
51
|
+
export declare function isDeferred(strategy: IRLoadStrategy): boolean;
|
|
52
|
+
/** A stable key for grouping references that share a strategy. */
|
|
53
|
+
export declare function strategyKey(strategy: IRLoadStrategy): string;
|