@opentf/web 0.4.0 → 0.6.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/README.md +30 -28
- package/components/Link.jsx +43 -0
- package/core/errors.js +48 -0
- package/core/reactive.js +190 -0
- package/core/signals.js +207 -0
- package/index.js +13 -0
- package/package.json +27 -18
- package/runtime/clipboard.js +47 -0
- package/runtime/code-block.js +47 -0
- package/runtime/context.js +99 -0
- package/runtime/dom.js +368 -0
- package/runtime/error-boundary.js +109 -0
- package/runtime/events.js +17 -0
- package/runtime/hydrate.js +121 -0
- package/runtime/index.js +22 -0
- package/runtime/lifecycle.js +9 -0
- package/runtime/mount.js +49 -0
- package/runtime/portal.js +59 -0
- package/runtime/raw-html.js +33 -0
- package/runtime/router.js +392 -0
- package/server/builtins.js +16 -0
- package/server/head.js +191 -0
- package/server/index.js +8 -0
- package/server/render.js +98 -0
- package/server/ssg-runtime.js +112 -0
- package/dist/CHANGELOG.md +0 -49
- package/dist/README.md +0 -41
- package/dist/babel.config.cjs +0 -6
- package/dist/compiler/babel-plugin.cjs +0 -798
- package/dist/core/mount.js +0 -32
- package/dist/index.js +0 -7
- package/dist/node_modules/@babel/core/LICENSE +0 -22
- package/dist/node_modules/@babel/core/README.md +0 -19
- package/dist/node_modules/@babel/core/lib/config/cache-contexts.js +0 -5
- package/dist/node_modules/@babel/core/lib/config/cache-contexts.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/config/caching.js +0 -261
- package/dist/node_modules/@babel/core/lib/config/caching.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/config/config-chain.js +0 -469
- package/dist/node_modules/@babel/core/lib/config/config-chain.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/config/config-descriptors.js +0 -190
- package/dist/node_modules/@babel/core/lib/config/config-descriptors.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/config/files/configuration.js +0 -290
- package/dist/node_modules/@babel/core/lib/config/files/configuration.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/config/files/import.cjs +0 -6
- package/dist/node_modules/@babel/core/lib/config/files/import.cjs.map +0 -1
- package/dist/node_modules/@babel/core/lib/config/files/index-browser.js +0 -58
- package/dist/node_modules/@babel/core/lib/config/files/index-browser.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/config/files/index.js +0 -78
- package/dist/node_modules/@babel/core/lib/config/files/index.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/config/files/module-types.js +0 -203
- package/dist/node_modules/@babel/core/lib/config/files/module-types.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/config/files/package.js +0 -61
- package/dist/node_modules/@babel/core/lib/config/files/package.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/config/files/plugins.js +0 -220
- package/dist/node_modules/@babel/core/lib/config/files/plugins.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/config/files/types.js +0 -5
- package/dist/node_modules/@babel/core/lib/config/files/types.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/config/files/utils.js +0 -36
- package/dist/node_modules/@babel/core/lib/config/files/utils.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/config/full.js +0 -312
- package/dist/node_modules/@babel/core/lib/config/full.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/config/helpers/config-api.js +0 -85
- package/dist/node_modules/@babel/core/lib/config/helpers/config-api.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/config/helpers/deep-array.js +0 -23
- package/dist/node_modules/@babel/core/lib/config/helpers/deep-array.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/config/helpers/environment.js +0 -12
- package/dist/node_modules/@babel/core/lib/config/helpers/environment.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/config/index.js +0 -87
- package/dist/node_modules/@babel/core/lib/config/index.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/config/item.js +0 -67
- package/dist/node_modules/@babel/core/lib/config/item.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/config/partial.js +0 -158
- package/dist/node_modules/@babel/core/lib/config/partial.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/config/pattern-to-regex.js +0 -38
- package/dist/node_modules/@babel/core/lib/config/pattern-to-regex.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/config/plugin.js +0 -33
- package/dist/node_modules/@babel/core/lib/config/plugin.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/config/printer.js +0 -113
- package/dist/node_modules/@babel/core/lib/config/printer.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/config/resolve-targets-browser.js +0 -41
- package/dist/node_modules/@babel/core/lib/config/resolve-targets-browser.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/config/resolve-targets.js +0 -61
- package/dist/node_modules/@babel/core/lib/config/resolve-targets.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/config/util.js +0 -31
- package/dist/node_modules/@babel/core/lib/config/util.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/config/validation/option-assertions.js +0 -277
- package/dist/node_modules/@babel/core/lib/config/validation/option-assertions.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/config/validation/options.js +0 -187
- package/dist/node_modules/@babel/core/lib/config/validation/options.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/config/validation/plugins.js +0 -67
- package/dist/node_modules/@babel/core/lib/config/validation/plugins.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/config/validation/removed.js +0 -68
- package/dist/node_modules/@babel/core/lib/config/validation/removed.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/errors/config-error.js +0 -18
- package/dist/node_modules/@babel/core/lib/errors/config-error.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/errors/rewrite-stack-trace.js +0 -98
- package/dist/node_modules/@babel/core/lib/errors/rewrite-stack-trace.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/gensync-utils/async.js +0 -90
- package/dist/node_modules/@babel/core/lib/gensync-utils/async.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/gensync-utils/fs.js +0 -31
- package/dist/node_modules/@babel/core/lib/gensync-utils/fs.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/gensync-utils/functional.js +0 -58
- package/dist/node_modules/@babel/core/lib/gensync-utils/functional.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/index.js +0 -230
- package/dist/node_modules/@babel/core/lib/index.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/parse.js +0 -45
- package/dist/node_modules/@babel/core/lib/parse.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/parser/index.js +0 -85
- package/dist/node_modules/@babel/core/lib/parser/index.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/parser/util/missing-plugin-helper.js +0 -337
- package/dist/node_modules/@babel/core/lib/parser/util/missing-plugin-helper.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/tools/build-external-helpers.js +0 -144
- package/dist/node_modules/@babel/core/lib/tools/build-external-helpers.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/transform-ast.js +0 -48
- package/dist/node_modules/@babel/core/lib/transform-ast.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/transform-file-browser.js +0 -23
- package/dist/node_modules/@babel/core/lib/transform-file-browser.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/transform-file.js +0 -40
- package/dist/node_modules/@babel/core/lib/transform-file.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/transform.js +0 -47
- package/dist/node_modules/@babel/core/lib/transform.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/transformation/block-hoist-plugin.js +0 -84
- package/dist/node_modules/@babel/core/lib/transformation/block-hoist-plugin.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/transformation/file/babel-7-helpers.cjs +0 -4
- package/dist/node_modules/@babel/core/lib/transformation/file/babel-7-helpers.cjs.map +0 -1
- package/dist/node_modules/@babel/core/lib/transformation/file/file.js +0 -204
- package/dist/node_modules/@babel/core/lib/transformation/file/file.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/transformation/file/generate.js +0 -84
- package/dist/node_modules/@babel/core/lib/transformation/file/generate.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/transformation/file/merge-map.js +0 -37
- package/dist/node_modules/@babel/core/lib/transformation/file/merge-map.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/transformation/index.js +0 -90
- package/dist/node_modules/@babel/core/lib/transformation/index.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/transformation/normalize-file.js +0 -127
- package/dist/node_modules/@babel/core/lib/transformation/normalize-file.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/transformation/normalize-opts.js +0 -59
- package/dist/node_modules/@babel/core/lib/transformation/normalize-opts.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/transformation/plugin-pass.js +0 -48
- package/dist/node_modules/@babel/core/lib/transformation/plugin-pass.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/transformation/util/clone-deep.js +0 -54
- package/dist/node_modules/@babel/core/lib/transformation/util/clone-deep.js.map +0 -1
- package/dist/node_modules/@babel/core/lib/vendor/import-meta-resolve.js +0 -1042
- package/dist/node_modules/@babel/core/lib/vendor/import-meta-resolve.js.map +0 -1
- package/dist/node_modules/@babel/core/package.json +0 -82
- package/dist/node_modules/@babel/core/src/config/files/index-browser.ts +0 -115
- package/dist/node_modules/@babel/core/src/config/files/index.ts +0 -30
- package/dist/node_modules/@babel/core/src/config/resolve-targets-browser.ts +0 -42
- package/dist/node_modules/@babel/core/src/config/resolve-targets.ts +0 -54
- package/dist/node_modules/@babel/core/src/transform-file-browser.ts +0 -33
- package/dist/node_modules/@babel/core/src/transform-file.ts +0 -56
- package/dist/node_modules/@babel/helper-module-imports/LICENSE +0 -22
- package/dist/node_modules/@babel/helper-module-imports/README.md +0 -19
- package/dist/node_modules/@babel/helper-module-imports/lib/import-builder.js +0 -122
- package/dist/node_modules/@babel/helper-module-imports/lib/import-builder.js.map +0 -1
- package/dist/node_modules/@babel/helper-module-imports/lib/import-injector.js +0 -304
- package/dist/node_modules/@babel/helper-module-imports/lib/import-injector.js.map +0 -1
- package/dist/node_modules/@babel/helper-module-imports/lib/index.js +0 -37
- package/dist/node_modules/@babel/helper-module-imports/lib/index.js.map +0 -1
- package/dist/node_modules/@babel/helper-module-imports/lib/is-module.js +0 -11
- package/dist/node_modules/@babel/helper-module-imports/lib/is-module.js.map +0 -1
- package/dist/node_modules/@babel/helper-module-imports/package.json +0 -28
- package/dist/node_modules/@babel/plugin-syntax-jsx/LICENSE +0 -22
- package/dist/node_modules/@babel/plugin-syntax-jsx/README.md +0 -19
- package/dist/node_modules/@babel/plugin-syntax-jsx/lib/index.js +0 -21
- package/dist/node_modules/@babel/plugin-syntax-jsx/lib/index.js.map +0 -1
- package/dist/node_modules/@babel/plugin-syntax-jsx/package.json +0 -33
- package/dist/node_modules/@preact/signals-core/CHANGELOG.md +0 -331
- package/dist/node_modules/@preact/signals-core/LICENSE +0 -21
- package/dist/node_modules/@preact/signals-core/README.md +0 -258
- package/dist/node_modules/@preact/signals-core/dist/signals-core.d.ts +0 -149
- package/dist/node_modules/@preact/signals-core/dist/signals-core.js +0 -1
- package/dist/node_modules/@preact/signals-core/dist/signals-core.js.map +0 -1
- package/dist/node_modules/@preact/signals-core/dist/signals-core.min.js +0 -1
- package/dist/node_modules/@preact/signals-core/dist/signals-core.min.js.map +0 -1
- package/dist/node_modules/@preact/signals-core/dist/signals-core.mjs +0 -1
- package/dist/node_modules/@preact/signals-core/dist/signals-core.mjs.map +0 -1
- package/dist/node_modules/@preact/signals-core/dist/signals-core.module.js +0 -1
- package/dist/node_modules/@preact/signals-core/dist/signals-core.module.js.map +0 -1
- package/dist/node_modules/@preact/signals-core/package.json +0 -48
- package/dist/node_modules/@preact/signals-core/src/index.ts +0 -1121
- package/dist/package.json +0 -30
- package/dist/router/Link.js +0 -73
- package/dist/router/index.js +0 -216
- package/dist/runtime/For.js +0 -16
- package/dist/runtime/dom.js +0 -73
- package/dist/runtime/lifecycle.js +0 -25
- package/dist/runtime/props.js +0 -103
package/server/render.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
//! Server render for SSG (ARCHITECTURE.md §6) — composes a route's HTML by
|
|
2
|
+
//! calling the SSG render functions the compiler emits (page/layout factories
|
|
3
|
+
//! that return strings, components registered in the SSG registry). No DOM: this
|
|
4
|
+
//! runs in plain Bun/Node at build time.
|
|
5
|
+
//
|
|
6
|
+
// The route table (registerRoutes/matchRoute/layoutChain) is shared with the
|
|
7
|
+
// client router; here we resolve a route's page + layout chain to string
|
|
8
|
+
// renderers and concatenate them, passing `children` as an HTML string.
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
layoutChain,
|
|
12
|
+
matchRoute,
|
|
13
|
+
resolveFactory,
|
|
14
|
+
routes,
|
|
15
|
+
setRouteState,
|
|
16
|
+
} from "../runtime/router.js";
|
|
17
|
+
import { resolveMetadata } from "./head.js";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Render `pathname` to `{ html, metadata, status }`: the markup for inside `#app`,
|
|
21
|
+
* the resolved SEO metadata (for the `<head>`), and an HTTP `status` (200 when the
|
|
22
|
+
* path matched a real route, 404 when it fell back to the registered 404 page — the
|
|
23
|
+
* SSR server uses it; SSG ignores it). `params` (from `getStaticPaths`) override the
|
|
24
|
+
* matched route's params for dynamic routes. Returns `null` if there's no match and
|
|
25
|
+
* no 404 page.
|
|
26
|
+
*/
|
|
27
|
+
export async function renderRoute(pathname, params = null, search = "") {
|
|
28
|
+
const real = matchRoute(pathname);
|
|
29
|
+
const match =
|
|
30
|
+
real || (routes.notFound ? { entry: routes.notFound, params: {}, route: null } : null);
|
|
31
|
+
if (!match) return null;
|
|
32
|
+
if (params) match.params = params;
|
|
33
|
+
|
|
34
|
+
// Let a page reading `router.params`/`pathname`/`query` resolve to this route.
|
|
35
|
+
setRouteState({ pathname, search, params: match.params });
|
|
36
|
+
|
|
37
|
+
const query = Object.fromEntries(new URLSearchParams(search));
|
|
38
|
+
const props = { params: match.params, query };
|
|
39
|
+
let html = (await resolveFactory(match.entry))(props);
|
|
40
|
+
|
|
41
|
+
// Wrap with layouts, most-specific inward to root outermost.
|
|
42
|
+
const chain = layoutChain(match.route);
|
|
43
|
+
for (let i = chain.length - 1; i >= 0; i--) {
|
|
44
|
+
const layout = await resolveFactory(chain[i]);
|
|
45
|
+
html = layout({ ...props, children: html });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const metadata = await resolveMetadata({
|
|
49
|
+
route: match.route,
|
|
50
|
+
entry: match.entry,
|
|
51
|
+
params: match.params,
|
|
52
|
+
query,
|
|
53
|
+
});
|
|
54
|
+
return { html, metadata, status: real ? 200 : 404 };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Back-compat / convenience: render just the `#app` markup for `pathname`. */
|
|
58
|
+
export async function renderToString(pathname, search = "") {
|
|
59
|
+
const result = await renderRoute(pathname, null, search);
|
|
60
|
+
return result ? result.html : null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Substitute `[param]` / `[...rest]` in a route with concrete values. */
|
|
64
|
+
function fillRoute(route, params) {
|
|
65
|
+
return route
|
|
66
|
+
.replace(/\[\.\.\.([^\]]+)\]/g, (_, k) => [].concat(params[k] ?? []).join("/"))
|
|
67
|
+
.replace(/\[([^\]]+)\]/g, (_, k) => String(params[k] ?? ""));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Enumerate the concrete paths to pre-render as `{ path, params }`. Static routes
|
|
72
|
+
* are taken as-is (`params: {}`); dynamic routes (`[param]`) are expanded via the
|
|
73
|
+
* page module's optional `getStaticPaths()` (returning `[{ params }]`), carrying the
|
|
74
|
+
* params forward so the renderer/`generateMetadata` see them. Dynamic routes without
|
|
75
|
+
* `getStaticPaths` are collected as `skipped`.
|
|
76
|
+
*/
|
|
77
|
+
export async function collectRoutePaths() {
|
|
78
|
+
const paths = [];
|
|
79
|
+
const skipped = [];
|
|
80
|
+
for (const route in routes.pages) {
|
|
81
|
+
if (!route.includes("[")) {
|
|
82
|
+
paths.push({ path: route, params: {} });
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
const ns = routes.pages[route];
|
|
86
|
+
const getStaticPaths =
|
|
87
|
+
ns && (ns.getStaticPaths || (ns.default && ns.default.getStaticPaths));
|
|
88
|
+
if (typeof getStaticPaths === "function") {
|
|
89
|
+
for (const entry of (await getStaticPaths()) || []) {
|
|
90
|
+
const params = entry.params || entry;
|
|
91
|
+
paths.push({ path: fillRoute(route, params), params });
|
|
92
|
+
}
|
|
93
|
+
} else {
|
|
94
|
+
skipped.push(route);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return { paths, skipped };
|
|
98
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
//! SSG runtime helpers — the string-building primitives the SSG codegen emits
|
|
2
|
+
//! (ARCHITECTURE.md §6). No DOM: these run in plain Bun/Node at build time and
|
|
3
|
+
//! return HTML strings. Component output is composed via a tag→renderer registry,
|
|
4
|
+
//! mirroring how CSR composes by Custom Element tag.
|
|
5
|
+
|
|
6
|
+
const VOID = new Set([
|
|
7
|
+
"area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta",
|
|
8
|
+
"param", "source", "track", "wbr",
|
|
9
|
+
]);
|
|
10
|
+
|
|
11
|
+
const UNITLESS = new Set([
|
|
12
|
+
"opacity", "zIndex", "fontWeight", "lineHeight", "flex", "flexGrow", "flexShrink",
|
|
13
|
+
"order", "zoom", "tabSize", "columnCount", "fillOpacity", "strokeOpacity",
|
|
14
|
+
]);
|
|
15
|
+
|
|
16
|
+
const registry = {};
|
|
17
|
+
|
|
18
|
+
/** Register a component's SSG renderer under its Custom Element tag. */
|
|
19
|
+
export function defineSSG(tag, render) {
|
|
20
|
+
registry[tag] = render;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Escape text content for HTML. */
|
|
24
|
+
export function escapeHtml(s) {
|
|
25
|
+
return String(s).replace(/[&<>]/g, (c) => (c === "&" ? "&" : c === "<" ? "<" : ">"));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Escape an attribute value. */
|
|
29
|
+
export function escapeAttr(s) {
|
|
30
|
+
return String(s).replace(/[&"]/g, (c) => (c === "&" ? "&" : """));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** clsx-style class normalization (mirrors runtime/dom.js). */
|
|
34
|
+
export function clsx(value) {
|
|
35
|
+
if (!value) return "";
|
|
36
|
+
if (typeof value === "string") return value;
|
|
37
|
+
if (typeof value === "number") return String(value);
|
|
38
|
+
if (Array.isArray(value)) {
|
|
39
|
+
const parts = [];
|
|
40
|
+
for (const v of value) {
|
|
41
|
+
const s = clsx(v);
|
|
42
|
+
if (s) parts.push(s);
|
|
43
|
+
}
|
|
44
|
+
return parts.join(" ");
|
|
45
|
+
}
|
|
46
|
+
if (typeof value === "object") {
|
|
47
|
+
const parts = [];
|
|
48
|
+
for (const k in value) if (value[k]) parts.push(k);
|
|
49
|
+
return parts.join(" ");
|
|
50
|
+
}
|
|
51
|
+
return "";
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Serialize a style value (string passthrough, or object → `prop:val;`). */
|
|
55
|
+
export function styleString(value) {
|
|
56
|
+
if (!value) return "";
|
|
57
|
+
if (typeof value === "string") return value;
|
|
58
|
+
let s = "";
|
|
59
|
+
for (const k in value) {
|
|
60
|
+
const v = value[k];
|
|
61
|
+
if (v == null) continue;
|
|
62
|
+
const prop = k.startsWith("--") ? k : k.replace(/[A-Z]/g, (m) => "-" + m.toLowerCase());
|
|
63
|
+
const val = typeof v === "number" && !UNITLESS.has(k) ? `${v}px` : v;
|
|
64
|
+
s += `${prop}:${val};`;
|
|
65
|
+
}
|
|
66
|
+
return s;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Render one attribute: ` name="value"`, ` name` (true), or "" (null/false). */
|
|
70
|
+
export function attr(name, value) {
|
|
71
|
+
if (name === "class") value = clsx(value);
|
|
72
|
+
else if (name === "style") value = styleString(value);
|
|
73
|
+
if (value == null || value === false) return "";
|
|
74
|
+
if (value === true) return ` ${name}`;
|
|
75
|
+
return ` ${name}="${escapeAttr(String(value))}"`;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** A dynamic hole's value → HTML: trusted `{__html}` raw, else escaped text. */
|
|
79
|
+
export function ssgText(v) {
|
|
80
|
+
if (v == null || v === false || v === true) return "";
|
|
81
|
+
if (typeof v === "object" && v.__html != null) return v.__html;
|
|
82
|
+
return escapeHtml(String(v));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Render an array.map list to concatenated HTML. */
|
|
86
|
+
export function ssgList(arr, fn) {
|
|
87
|
+
return (Array.isArray(arr) ? arr : []).map(fn).join("");
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Render a child component `<tag>inner</tag>` via the registry. Props are passed to
|
|
92
|
+
* the renderer (which decides where they land — declared props become properties /
|
|
93
|
+
* forward into the view), so the host tag carries no reflected attributes — exactly
|
|
94
|
+
* as CSR composes a component (props go through `setProp`, declared ones as
|
|
95
|
+
* properties, not host attributes). Avoids duplicating e.g. `class` on both the
|
|
96
|
+
* host and the element the component renders.
|
|
97
|
+
*/
|
|
98
|
+
export function ssgComponent(tag, props, children) {
|
|
99
|
+
const render = registry[tag];
|
|
100
|
+
let inner;
|
|
101
|
+
try {
|
|
102
|
+
inner = render ? render(props || {}, children ?? "") : (children ?? "");
|
|
103
|
+
} catch {
|
|
104
|
+
inner = ""; // fail soft (client renders/handles it)
|
|
105
|
+
}
|
|
106
|
+
// Stamp the stable styling hook on the host (mirrors CSR's `classList.add`) so
|
|
107
|
+
// tag-hashed components are still styleable by a readable class name.
|
|
108
|
+
const cls = render && render.hostClass;
|
|
109
|
+
return cls ? `<${tag} class="${cls}">${inner}</${tag}>` : `<${tag}>${inner}</${tag}>`;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export { VOID };
|
package/dist/CHANGELOG.md
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
# @opentf/web
|
|
2
|
-
|
|
3
|
-
## 0.4.0
|
|
4
|
-
|
|
5
|
-
### Minor Changes
|
|
6
|
-
|
|
7
|
-
- ba984c2: Here is a summary of the changes for your changelog:
|
|
8
|
-
|
|
9
|
-
### 🚀 Features
|
|
10
|
-
|
|
11
|
-
- **Compiler:** Added comprehensive support for **SVG camelCase attributes** (e.g., `viewBox`, `strokeWidth`, `strokeLinecap`). The compiler now preserves the original casing for these attributes, ensuring icons and SVGs render correctly in the browser.
|
|
12
|
-
- **Router:** Improved route matching to support **optional trailing slashes** (e.g., `/about` and `/about/` now match the same route).
|
|
13
|
-
- **Playground:** Added a new **SVG Icons Showcase** page to demonstrate seamless integration with icon libraries like Lucide and Heroicons.
|
|
14
|
-
|
|
15
|
-
### 🐞 Bug Fixes
|
|
16
|
-
|
|
17
|
-
- **Compiler:** Fixed a critical bug where **imported components** were incorrectly compiled as dynamic variables (e.g., `document.createElement(Link)`) instead of using their registered custom element tag names (e.g., `document.createElement("web-link")`).
|
|
18
|
-
- **Playground:** Resolved a build failure in the Icons page by correcting an illegal `const` reassignment of a reactive state variable.
|
|
19
|
-
- **Performance:** Reduced the simulated network delay in `routeGuard.js` from 800ms to 100ms for a snappier development experience.
|
|
20
|
-
|
|
21
|
-
### 🏠 Internal & Maintenance
|
|
22
|
-
|
|
23
|
-
- **Refactoring:** Optimized the Babel plugin by moving large static lists (SVG tags, properties, etc.) to the top-level scope, improving compilation speed.
|
|
24
|
-
- **Testing:** Expanded the test suite with new cases for **icon libraries** and **complex React patterns** (dynamic tags, render props, spread overrides).
|
|
25
|
-
|
|
26
|
-
***
|
|
27
|
-
|
|
28
|
-
## 0.3.0
|
|
29
|
-
|
|
30
|
-
### Minor Changes
|
|
31
|
-
|
|
32
|
-
- 476d65a: Fix reactivity issues by re-exporting all signals from the core package and updating the compiler to use a unified reactivity instance. This prevents state-update failures in complex project structures.
|
|
33
|
-
|
|
34
|
-
## 0.2.0
|
|
35
|
-
|
|
36
|
-
### Minor Changes
|
|
37
|
-
|
|
38
|
-
- a56fdfe: Fix the core components to prebuilt before publishing
|
|
39
|
-
|
|
40
|
-
## 0.1.0
|
|
41
|
-
|
|
42
|
-
### Minor Changes
|
|
43
|
-
|
|
44
|
-
- Global rebranding to Web App Framework and monorepo restructuring.
|
|
45
|
-
- Renamed all packages from `@opentf/mwaf-*` to `@opentf/web-*`.
|
|
46
|
-
- Updated Custom Element prefix from `mwaf-` to `web-`.
|
|
47
|
-
- Restructured the repository into a scoped monorepo.
|
|
48
|
-
- Updated scaffolding tool `@opentf/create-web` with new templates.
|
|
49
|
-
- Aligned all package versions to 0.1.0-alpha.1.
|
package/dist/README.md
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
# @opentf/web
|
|
2
|
-
|
|
3
|
-
The core engine of the **Web App Framework**, a lightweight, high-performance SPA framework designed for the modern web.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- 🚀 **Zero-VDOM**: Compiles JSX directly to imperative DOM operations for maximum speed.
|
|
8
|
-
- ⚡ **Signal-Based Reactivity**: Powered by `@preact/signals-core` for fine-grained, surgical updates.
|
|
9
|
-
- 📦 **Web Component Native**: Every component is a standard Custom Element, ensuring perfect encapsulation and interoperability.
|
|
10
|
-
- 🛠️ **Convention-over-Configuration**: File-based routing and automatic component registration.
|
|
11
|
-
- 📏 **Ultra-Lightweight**: Minimal runtime footprint.
|
|
12
|
-
|
|
13
|
-
## Installation
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
npm install @opentf/web
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## Basic Usage
|
|
20
|
-
|
|
21
|
-
```jsx
|
|
22
|
-
export default function Counter() {
|
|
23
|
-
let count = $state(0);
|
|
24
|
-
|
|
25
|
-
return (
|
|
26
|
-
<div className="counter">
|
|
27
|
-
<button onclick={() => count--}>-</button>
|
|
28
|
-
<span>{count}</span>
|
|
29
|
-
<button onclick={() => count++}>+</button>
|
|
30
|
-
</div>
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
## Documentation
|
|
36
|
-
|
|
37
|
-
Visit [web.opentf.workers.dev](https://web.opentf.workers.dev) for full documentation and guides.
|
|
38
|
-
|
|
39
|
-
## License
|
|
40
|
-
|
|
41
|
-
MIT © [Open Tech Foundation](https://github.com/Open-Tech-Foundation)
|