@homepages/template-kit 0.3.0 → 0.4.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/CHANGELOG.md +71 -0
- package/README.md +39 -4
- package/dist/asset-modules.d.ts +81 -0
- package/dist/cli/check/config.js +5 -1
- package/dist/cli/check/css.js +27 -13
- package/dist/cli/check/loader.js +4 -0
- package/dist/cli/check/section-assets.js +58 -0
- package/dist/cli/check/stages/size.js +124 -8
- package/dist/cli/check/stages/tree.js +26 -27
- package/dist/cli/dev/build-css.js +91 -0
- package/dist/cli/dev/catalog.js +35 -0
- package/dist/cli/dev/compose-template.js +38 -0
- package/dist/cli/dev/content-override.js +58 -0
- package/dist/cli/dev/discover.js +35 -0
- package/dist/cli/dev/fill-state.js +75 -0
- package/dist/cli/dev/index.js +32 -0
- package/dist/cli/dev/inspect.js +38 -0
- package/dist/cli/dev/island-bootstrap.js +38 -0
- package/dist/cli/dev/island-map.js +35 -0
- package/dist/cli/dev/island-transform.js +31 -0
- package/dist/cli/dev/manifest-instances.js +31 -0
- package/dist/cli/dev/render-section.js +24 -0
- package/dist/cli/dev/screenshot-target.js +24 -0
- package/dist/cli/dev/section-page.js +54 -0
- package/dist/cli/dev/server.js +480 -0
- package/dist/cli/dev/slot-schema.js +12 -0
- package/dist/cli/dev/structure-summary.js +118 -0
- package/dist/cli/dev/tailwind.js +32 -0
- package/dist/cli/dev/vite-server.js +33 -0
- package/dist/cli/dev/workspace.js +63 -0
- package/dist/cli/link/index.js +74 -0
- package/dist/cli/link/overlay.js +59 -0
- package/dist/cli/link/watch.js +25 -0
- package/dist/cli/new/emit.js +48 -0
- package/dist/cli/new/index.js +69 -0
- package/dist/cli/new/scaffold/section/_Renderer.tsx +20 -0
- package/dist/cli/new/scaffold/section/_fill-spec.ts +18 -0
- package/dist/cli/new/scaffold/section/_fixtures.ts +13 -0
- package/dist/cli/new/scaffold/section/_schema.ts +24 -0
- package/dist/cli/new/scaffold/template/_manifest.json +9 -0
- package/dist/cli/new/scaffold/template/sections/hero/ExpandableText.tsx +45 -0
- package/dist/cli/new/scaffold/template/sections/hero/Renderer.tsx +40 -0
- package/dist/cli/new/scaffold/template/sections/hero/components/Feature.tsx +14 -0
- package/dist/cli/new/scaffold/template/sections/hero/fill-spec.ts +29 -0
- package/dist/cli/new/scaffold/template/sections/hero/fixtures.ts +41 -0
- package/dist/cli/new/scaffold/template/sections/hero/schema.ts +60 -0
- package/dist/cli/new/scaffold/template/theme.css +24 -0
- package/dist/cli/new/scaffold/template/theme.ts +27 -0
- package/dist/cli/new/scaffold-assets.js +20 -0
- package/dist/cli/pack/collect.js +44 -0
- package/dist/cli/pack/guards.js +57 -0
- package/dist/cli/pack/index.js +66 -0
- package/dist/cli/pack/manifest.js +15 -0
- package/dist/cli/pack/zip.js +86 -0
- package/dist/cli.js +80 -14
- package/dist/dev-client/assets/index-DfEfrp6P.css +1 -0
- package/dist/dev-client/assets/index-bpMP0b0W.js +50 -0
- package/dist/dev-client/index.html +13 -0
- package/dist/eslint/is-client-file.d.ts +4 -0
- package/dist/index.d.ts +1 -0
- package/dist/islands/detect.d.ts +16 -0
- package/dist/islands/detect.js +22 -0
- package/dist/islands/discover.d.ts +5 -0
- package/dist/islands/discover.js +19 -0
- package/dist/islands/esbuild-plugin.d.ts +13 -0
- package/dist/islands/esbuild-plugin.js +39 -0
- package/dist/islands/wrap.d.ts +11 -0
- package/dist/islands/wrap.js +48 -0
- package/dist/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.js +77 -0
- package/dist/node_modules/magic-string/dist/magic-string.es.js +939 -0
- package/dist/package.js +1 -1
- package/dist/ssr.d.ts +31 -0
- package/dist/ssr.js +46 -0
- package/docs/INDEX.md +9 -1
- package/docs/assets.md +128 -0
- package/docs/check.md +6 -3
- package/docs/dev.md +187 -0
- package/docs/islands.md +5 -2
- package/docs/llms.txt +41 -3
- package/docs/new.md +27 -0
- package/docs/overview.md +57 -0
- package/docs/pack.md +46 -0
- package/docs/primitives.md +5 -6
- package/docs/quickstart.md +102 -0
- package/docs/recipes/INDEX.md +27 -0
- package/docs/recipes/bind-property-fact.md +58 -0
- package/docs/recipes/collection-slot.md +100 -0
- package/docs/recipes/fill-spec-decision.md +66 -0
- package/docs/recipes/fixture-states.md +68 -0
- package/docs/recipes/image-slot-crop.md +98 -0
- package/docs/recipes/interactive-island.md +100 -0
- package/docs/recipes/organize-section-folder.md +72 -0
- package/docs/recipes/prepare-submission.md +55 -0
- package/docs/recipes/second-template.md +49 -0
- package/docs/recipes/select-slot.md +59 -0
- package/docs/recipes/static-asset.md +103 -0
- package/docs/recipes/third-party-package.md +90 -0
- package/docs/rules/INDEX.md +4 -2
- package/docs/rules/bundle-binary-asset.md +33 -52
- package/docs/rules/bundle-incomplete.md +2 -2
- package/docs/rules/css-reason.md +3 -3
- package/docs/rules/no-bare-css-import.md +8 -8
- package/docs/rules/no-css-import-from-render-path.md +7 -8
- package/docs/rules/size-assets.md +88 -0
- package/docs/rules/size-island-bundle.md +123 -0
- package/docs/rules/size-section-css.md +19 -14
- package/docs/schema-system.md +28 -28
- package/docs/theme-and-css.md +2 -2
- package/docs/vocabulary.md +98 -0
- package/package.json +11 -3
- package/tsconfig.json +1 -1
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>template-kit dev</title>
|
|
7
|
+
<script type="module" crossorigin src="/dev-client/assets/index-bpMP0b0W.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="/dev-client/assets/index-DfEfrp6P.css">
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<div id="root"></div>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ResponsiveImage, ResponsiveSource } from "./contracts/image-descriptor.js";
|
|
2
2
|
import { Coordinates, FloorplanAssignment, PropertyFacts, UnitRow } from "./schema/property-facts.js";
|
|
3
|
+
import "./asset-modules.js";
|
|
3
4
|
import { COLLECTIONS, CONTENT_SLOT_TYPES, CollectionField, CollectionIdKey, CollectionOwnership, ContentSlotType, DECISION_TYPES, DERIVED_INPUT_FIELDS, DecisionType, DerivedInputName, FORMATTER_NAMES, FormatterName, REFERRAL_FIELDS, REFERRAL_IMAGE_FIELDS, REF_SLOT_TYPES, RefSlotType, ReferralField, ReferralImageField, SLOT_TYPES, SOURCE_FIELDS, SlotType, SourceFieldContainer, SourceFieldDescriptor, SourceFieldName, SourceFieldValueType, WritebackTarget, collectionForSlot } from "./contracts/slot-catalog.js";
|
|
4
5
|
import { AddressParts, TRANSFORMS, TRANSFORM_NAMES, TransformDescriptor, TransformFn, TransformInput, TransformName, TransformUnit } from "./contracts/transforms.js";
|
|
5
6
|
import { VariantSelectorFn, VariantsMeta, makeResolveVariants } from "./schema/resolve-variants.js";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { hasClientDirective } from "../eslint/is-client-file.js";
|
|
2
|
+
//#region src/islands/detect.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* True iff `file` is a client component — an on-disk source file whose directive
|
|
5
|
+
* prologue is `"use client"`. Returns false for an unreadable or absent path.
|
|
6
|
+
*/
|
|
7
|
+
declare function isClientComponentFile(file: string): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Compose an island key: `<sectionKey>:<componentName>` (e.g.
|
|
10
|
+
* `spw-essential/floorplan:UnitFilter`). The key is what a marker in the DOM
|
|
11
|
+
* carries and what the browser loader resolves the client module by, so the
|
|
12
|
+
* emitter and the loader must derive it identically.
|
|
13
|
+
*/
|
|
14
|
+
declare function islandKey(sectionKey: string, componentName: string): string;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { hasClientDirective, isClientComponentFile, islandKey };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { hasClientDirective, isClientFile } from "../eslint/is-client-file.js";
|
|
2
|
+
|
|
3
|
+
//#region src/islands/detect.ts
|
|
4
|
+
/**
|
|
5
|
+
* True iff `file` is a client component — an on-disk source file whose directive
|
|
6
|
+
* prologue is `"use client"`. Returns false for an unreadable or absent path.
|
|
7
|
+
*/
|
|
8
|
+
function isClientComponentFile(file) {
|
|
9
|
+
return isClientFile(file);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Compose an island key: `<sectionKey>:<componentName>` (e.g.
|
|
13
|
+
* `spw-essential/floorplan:UnitFilter`). The key is what a marker in the DOM
|
|
14
|
+
* carries and what the browser loader resolves the client module by, so the
|
|
15
|
+
* emitter and the loader must derive it identically.
|
|
16
|
+
*/
|
|
17
|
+
function islandKey(sectionKey, componentName) {
|
|
18
|
+
return `${sectionKey}:${componentName}`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//#endregion
|
|
22
|
+
export { hasClientDirective, isClientComponentFile, islandKey };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { isClientComponentFile } from "./detect.js";
|
|
2
|
+
import { extname, join } from "node:path";
|
|
3
|
+
import { readdir } from "node:fs/promises";
|
|
4
|
+
|
|
5
|
+
//#region src/islands/discover.ts
|
|
6
|
+
const COMPONENT_EXTS = /* @__PURE__ */ new Set([".tsx", ".jsx"]);
|
|
7
|
+
/** Every `"use client"` component file anywhere under a section directory (recursive). */
|
|
8
|
+
async function findSectionIslands(sectionDir) {
|
|
9
|
+
const out = [];
|
|
10
|
+
for (const entry of await readdir(sectionDir, { withFileTypes: true })) {
|
|
11
|
+
const full = join(sectionDir, entry.name);
|
|
12
|
+
if (entry.isDirectory()) out.push(...await findSectionIslands(full));
|
|
13
|
+
else if (COMPONENT_EXTS.has(extname(entry.name)) && isClientComponentFile(full)) out.push(full);
|
|
14
|
+
}
|
|
15
|
+
return out;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
//#endregion
|
|
19
|
+
export { findSectionIslands };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Plugin } from "esbuild";
|
|
2
|
+
//#region src/islands/esbuild-plugin.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Wrap every `"use client"` `.tsx`/`.jsx` in the build graph so it renders through
|
|
5
|
+
* `IslandMarker`, keyed `islandKey(sectionKey, <file-basename>)`. `sectionKey` is
|
|
6
|
+
* fixed per bundle (one section per renderer build). Non-client modules and other
|
|
7
|
+
* extensions fall through to esbuild untouched.
|
|
8
|
+
*/
|
|
9
|
+
declare function islandTransformEsbuildPlugin(opts: {
|
|
10
|
+
sectionKey: string;
|
|
11
|
+
}): Plugin;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { islandTransformEsbuildPlugin };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { islandKey } from "./detect.js";
|
|
2
|
+
import { wrapClientModuleSource } from "./wrap.js";
|
|
3
|
+
import { basename, extname } from "node:path";
|
|
4
|
+
import { readFile } from "node:fs/promises";
|
|
5
|
+
|
|
6
|
+
//#region src/islands/esbuild-plugin.ts
|
|
7
|
+
const LOADER = {
|
|
8
|
+
".tsx": "tsx",
|
|
9
|
+
".jsx": "jsx"
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Wrap every `"use client"` `.tsx`/`.jsx` in the build graph so it renders through
|
|
13
|
+
* `IslandMarker`, keyed `islandKey(sectionKey, <file-basename>)`. `sectionKey` is
|
|
14
|
+
* fixed per bundle (one section per renderer build). Non-client modules and other
|
|
15
|
+
* extensions fall through to esbuild untouched.
|
|
16
|
+
*/
|
|
17
|
+
function islandTransformEsbuildPlugin(opts) {
|
|
18
|
+
return {
|
|
19
|
+
name: "template-kit:island-transform-esbuild",
|
|
20
|
+
setup(b) {
|
|
21
|
+
b.onLoad({ filter: /\.(tsx|jsx)$/ }, async (args) => {
|
|
22
|
+
const code = await readFile(args.path, "utf8");
|
|
23
|
+
const wrapped = wrapClientModuleSource(code, islandKey(opts.sectionKey, basename(args.path, extname(args.path))));
|
|
24
|
+
const ext = extname(args.path);
|
|
25
|
+
if (wrapped === null) return {
|
|
26
|
+
contents: code,
|
|
27
|
+
loader: LOADER[ext]
|
|
28
|
+
};
|
|
29
|
+
return {
|
|
30
|
+
contents: wrapped,
|
|
31
|
+
loader: LOADER[ext]
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
//#endregion
|
|
39
|
+
export { islandTransformEsbuildPlugin };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/islands/wrap.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Rewrite a client module's source so its default export renders through
|
|
4
|
+
* `IslandMarker` with `islandKey`. Returns null when `code` is not a client
|
|
5
|
+
* component (`hasClientDirective` false) or has no default export — the caller
|
|
6
|
+
* then leaves the module untouched. The rebound original is `__trIslandReal`;
|
|
7
|
+
* it still flows through the consumer's JSX/TS transform unchanged.
|
|
8
|
+
*/
|
|
9
|
+
declare function wrapClientModuleSource(code: string, islandKey: string): string | null;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { wrapClientModuleSource };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { hasClientDirective } from "../eslint/is-client-file.js";
|
|
2
|
+
import MagicString from "../node_modules/magic-string/dist/magic-string.es.js";
|
|
3
|
+
|
|
4
|
+
//#region src/islands/wrap.ts
|
|
5
|
+
const DEFAULT_EXPORT = /export\s+default\s+/;
|
|
6
|
+
/**
|
|
7
|
+
* The codemod as a `MagicString`, so a caller (the Vite plugin) can emit a
|
|
8
|
+
* hi-res sourcemap alongside the rewritten code. Returns null on the same terms
|
|
9
|
+
* as `wrapClientModuleSource` — a non-client module or one with no default
|
|
10
|
+
* export. The rebound original is `__trIslandReal`; it still flows through the
|
|
11
|
+
* consumer's JSX/TS transform unchanged.
|
|
12
|
+
*/
|
|
13
|
+
function wrapClientModuleMagic(code, islandKey) {
|
|
14
|
+
if (!hasClientDirective(code)) return null;
|
|
15
|
+
if (!DEFAULT_EXPORT.test(code)) return null;
|
|
16
|
+
const s = new MagicString(code);
|
|
17
|
+
s.replace(DEFAULT_EXPORT, "const __trIslandReal = ");
|
|
18
|
+
s.append(wrapperSource(islandKey));
|
|
19
|
+
return s;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Rewrite a client module's source so its default export renders through
|
|
23
|
+
* `IslandMarker` with `islandKey`. Returns null when `code` is not a client
|
|
24
|
+
* component (`hasClientDirective` false) or has no default export — the caller
|
|
25
|
+
* then leaves the module untouched. The rebound original is `__trIslandReal`;
|
|
26
|
+
* it still flows through the consumer's JSX/TS transform unchanged.
|
|
27
|
+
*/
|
|
28
|
+
function wrapClientModuleSource(code, islandKey) {
|
|
29
|
+
return wrapClientModuleMagic(code, islandKey)?.toString() ?? null;
|
|
30
|
+
}
|
|
31
|
+
function wrapperSource(islandKey) {
|
|
32
|
+
return `
|
|
33
|
+
;
|
|
34
|
+
import { createElement as __trCreateElement, useId as __trUseId } from "react";
|
|
35
|
+
import { IslandMarker as __TrIslandMarker } from "@homepages/template-kit";
|
|
36
|
+
export default function __trIslandWrapper(__trProps) {
|
|
37
|
+
const __trIslandId = __trUseId();
|
|
38
|
+
return __trCreateElement(
|
|
39
|
+
__TrIslandMarker,
|
|
40
|
+
{ islandKey: ${JSON.stringify(islandKey)}, islandId: __trIslandId, props: __trProps },
|
|
41
|
+
__trCreateElement(__trIslandReal, __trProps),
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
`;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
//#endregion
|
|
48
|
+
export { wrapClientModuleMagic, wrapClientModuleSource };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
//#region node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs
|
|
2
|
+
var comma = ",".charCodeAt(0);
|
|
3
|
+
var semicolon = ";".charCodeAt(0);
|
|
4
|
+
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
5
|
+
var intToChar = /* @__PURE__ */ new Uint8Array(64);
|
|
6
|
+
var charToInt = /* @__PURE__ */ new Uint8Array(128);
|
|
7
|
+
for (let i = 0; i < chars.length; i++) {
|
|
8
|
+
const c = chars.charCodeAt(i);
|
|
9
|
+
intToChar[i] = c;
|
|
10
|
+
charToInt[c] = i;
|
|
11
|
+
}
|
|
12
|
+
function encodeInteger(builder, num, relative) {
|
|
13
|
+
let delta = num - relative;
|
|
14
|
+
delta = delta < 0 ? -delta << 1 | 1 : delta << 1;
|
|
15
|
+
do {
|
|
16
|
+
let clamped = delta & 31;
|
|
17
|
+
delta >>>= 5;
|
|
18
|
+
if (delta > 0) clamped |= 32;
|
|
19
|
+
builder.write(intToChar[clamped]);
|
|
20
|
+
} while (delta > 0);
|
|
21
|
+
return num;
|
|
22
|
+
}
|
|
23
|
+
var bufLength = 1024 * 16;
|
|
24
|
+
var td = typeof TextDecoder !== "undefined" ? /* @__PURE__ */ new TextDecoder() : typeof Buffer !== "undefined" ? { decode(buf) {
|
|
25
|
+
return Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength).toString();
|
|
26
|
+
} } : { decode(buf) {
|
|
27
|
+
let out = "";
|
|
28
|
+
for (let i = 0; i < buf.length; i++) out += String.fromCharCode(buf[i]);
|
|
29
|
+
return out;
|
|
30
|
+
} };
|
|
31
|
+
var StringWriter = class {
|
|
32
|
+
constructor() {
|
|
33
|
+
this.pos = 0;
|
|
34
|
+
this.out = "";
|
|
35
|
+
this.buffer = new Uint8Array(bufLength);
|
|
36
|
+
}
|
|
37
|
+
write(v) {
|
|
38
|
+
const { buffer } = this;
|
|
39
|
+
buffer[this.pos++] = v;
|
|
40
|
+
if (this.pos === bufLength) {
|
|
41
|
+
this.out += td.decode(buffer);
|
|
42
|
+
this.pos = 0;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
flush() {
|
|
46
|
+
const { buffer, out, pos } = this;
|
|
47
|
+
return pos > 0 ? out + td.decode(buffer.subarray(0, pos)) : out;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
function encode(decoded) {
|
|
51
|
+
const writer = new StringWriter();
|
|
52
|
+
let sourcesIndex = 0;
|
|
53
|
+
let sourceLine = 0;
|
|
54
|
+
let sourceColumn = 0;
|
|
55
|
+
let namesIndex = 0;
|
|
56
|
+
for (let i = 0; i < decoded.length; i++) {
|
|
57
|
+
const line = decoded[i];
|
|
58
|
+
if (i > 0) writer.write(semicolon);
|
|
59
|
+
if (line.length === 0) continue;
|
|
60
|
+
let genColumn = 0;
|
|
61
|
+
for (let j = 0; j < line.length; j++) {
|
|
62
|
+
const segment = line[j];
|
|
63
|
+
if (j > 0) writer.write(comma);
|
|
64
|
+
genColumn = encodeInteger(writer, segment[0], genColumn);
|
|
65
|
+
if (segment.length === 1) continue;
|
|
66
|
+
sourcesIndex = encodeInteger(writer, segment[1], sourcesIndex);
|
|
67
|
+
sourceLine = encodeInteger(writer, segment[2], sourceLine);
|
|
68
|
+
sourceColumn = encodeInteger(writer, segment[3], sourceColumn);
|
|
69
|
+
if (segment.length === 4) continue;
|
|
70
|
+
namesIndex = encodeInteger(writer, segment[4], namesIndex);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return writer.flush();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
//#endregion
|
|
77
|
+
export { encode };
|