@homepages/template-kit 0.4.0 → 0.5.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 +96 -0
- package/README.md +38 -27
- package/dist/base.css +6 -4
- package/dist/cli/dev/fill-state.js +5 -3
- package/dist/cli/link/overlay.js +1 -1
- package/dist/cli/new/scaffold/template/sections/hero/fixtures.ts +7 -7
- package/dist/contracts/slot-catalog.d.ts +2 -2
- package/dist/contracts/slot-catalog.js +3 -1
- package/dist/eslint/rules/no-raw-element.js +3 -2
- package/dist/fixtures/helpers.d.ts +23 -0
- package/dist/fixtures/helpers.js +50 -0
- package/dist/fixtures/sample-property.d.ts +7 -17
- package/dist/fixtures/sample-property.js +179 -57
- package/dist/fixtures/scenario.d.ts +20 -0
- package/dist/fixtures/scenarios/for-rent-condo.d.ts +5 -0
- package/dist/fixtures/scenarios/for-rent-condo.js +364 -0
- package/dist/fixtures/scenarios/index.d.ts +8 -0
- package/dist/fixtures/scenarios/index.js +13 -0
- package/dist/fixtures/scenarios/luxury-multi-unit.d.ts +5 -0
- package/dist/fixtures/scenarios/luxury-multi-unit.js +19 -0
- package/dist/fixtures/scenarios/sparse-single-family.d.ts +5 -0
- package/dist/fixtures/scenarios/sparse-single-family.js +233 -0
- package/dist/fixtures.d.ts +8 -2
- package/dist/fixtures.js +7 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +2 -1
- package/dist/island-runtime.js +22 -7
- package/dist/islands/wrap.d.ts +1 -0
- package/dist/islands/wrap.js +1 -1
- package/dist/package.js +1 -1
- package/dist/primitives/Image.d.ts +1 -1
- package/dist/primitives/Video.d.ts +38 -0
- package/dist/primitives/Video.js +63 -0
- package/dist/primitives/index.d.ts +2 -1
- package/dist/rules/registry.js +3 -3
- package/dist/schema/index.d.ts +2 -2
- package/dist/schema/runtime-values.d.ts +20 -1
- package/dist/schema/section-props.d.ts +8 -1
- package/dist/schema/section-schema.d.ts +2 -2
- package/dist/schema/slot-types.d.ts +15 -1
- package/dist/schema/slot-types.js +34 -0
- package/dist/schema/synthesize-nullable.js +1 -0
- package/{docs → guide}/INDEX.md +7 -6
- package/{docs → guide}/check.md +2 -2
- package/{docs → guide}/islands.md +6 -1
- package/{docs → guide}/llms.txt +34 -14
- package/{docs → guide}/overview.md +4 -4
- package/{docs → guide}/pack.md +2 -2
- package/{docs → guide}/primitives.md +59 -11
- package/{docs → guide}/recipes/INDEX.md +1 -0
- package/{docs → guide}/recipes/collection-slot.md +10 -8
- package/guide/recipes/fixture-states.md +109 -0
- package/{docs → guide}/recipes/image-slot-crop.md +5 -3
- package/guide/recipes/pick-a-scenario.md +119 -0
- package/{docs → guide}/rules/INDEX.md +2 -2
- package/{docs → guide}/rules/fixtures-invalid.md +2 -2
- package/{docs → guide}/rules/no-raw-element.md +13 -8
- package/{docs → guide}/rules/render-invariant.md +4 -3
- package/{docs → guide}/schema-system.md +97 -16
- package/{docs → guide}/theme-and-css.md +3 -2
- package/guide/upgrading.md +61 -0
- package/{docs → guide}/vocabulary.md +3 -1
- package/package.json +9 -3
- package/dist/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.js +0 -77
- package/dist/node_modules/magic-string/dist/magic-string.es.js +0 -939
- package/docs/recipes/fixture-states.md +0 -68
- /package/{docs → guide}/assets.md +0 -0
- /package/{docs → guide}/dev.md +0 -0
- /package/{docs → guide}/eslint.md +0 -0
- /package/{docs → guide}/new.md +0 -0
- /package/{docs → guide}/quickstart.md +0 -0
- /package/{docs → guide}/recipes/bind-property-fact.md +0 -0
- /package/{docs → guide}/recipes/fill-spec-decision.md +0 -0
- /package/{docs → guide}/recipes/interactive-island.md +0 -0
- /package/{docs → guide}/recipes/organize-section-folder.md +0 -0
- /package/{docs → guide}/recipes/prepare-submission.md +0 -0
- /package/{docs → guide}/recipes/second-template.md +0 -0
- /package/{docs → guide}/recipes/select-slot.md +0 -0
- /package/{docs → guide}/recipes/static-asset.md +0 -0
- /package/{docs → guide}/recipes/third-party-package.md +0 -0
- /package/{docs → guide}/rules/audit-severity.md +0 -0
- /package/{docs → guide}/rules/bundle-binary-asset.md +0 -0
- /package/{docs → guide}/rules/bundle-incomplete.md +0 -0
- /package/{docs → guide}/rules/css-reason.md +0 -0
- /package/{docs → guide}/rules/determinism-drift.md +0 -0
- /package/{docs → guide}/rules/image-bare-needs-reason.md +0 -0
- /package/{docs → guide}/rules/license-denied.md +0 -0
- /package/{docs → guide}/rules/lockfile-missing.md +0 -0
- /package/{docs → guide}/rules/lockfile-stale.md +0 -0
- /package/{docs → guide}/rules/manifest-invalid.md +0 -0
- /package/{docs → guide}/rules/missing-slot-marker.md +0 -0
- /package/{docs → guide}/rules/no-bare-css-import.md +0 -0
- /package/{docs → guide}/rules/no-client-directive-in-contract.md +0 -0
- /package/{docs → guide}/rules/no-client-runtime-in-server.md +0 -0
- /package/{docs → guide}/rules/no-css-import-from-render-path.md +0 -0
- /package/{docs → guide}/rules/no-hex.md +0 -0
- /package/{docs → guide}/rules/no-inline-style.md +0 -0
- /package/{docs → guide}/rules/no-nondeterminism.md +0 -0
- /package/{docs → guide}/rules/no-templates.md +0 -0
- /package/{docs → guide}/rules/parse-error.md +0 -0
- /package/{docs → guide}/rules/props-from-schema.md +0 -0
- /package/{docs → guide}/rules/schema-invalid.md +0 -0
- /package/{docs → guide}/rules/serializable-island-props.md +0 -0
- /package/{docs → guide}/rules/server-vs-client.md +0 -0
- /package/{docs → guide}/rules/sidebar-order.md +0 -0
- /package/{docs → guide}/rules/single-react.md +0 -0
- /package/{docs → guide}/rules/size-assets.md +0 -0
- /package/{docs → guide}/rules/size-island-bundle.md +0 -0
- /package/{docs → guide}/rules/size-renderer-bundle.md +0 -0
- /package/{docs → guide}/rules/size-section-css.md +0 -0
- /package/{docs → guide}/rules/slot-group-marker.md +0 -0
- /package/{docs → guide}/rules/slot-marker-literal.md +0 -0
- /package/{docs → guide}/rules/typecheck.md +0 -0
- /package/{docs → guide}/rules/unlayered-fence.md +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
purpose: The section authoring contract — schema.ts, fill-spec.ts, fixtures.ts, and the closed source/transform vocabulary.
|
|
3
3
|
status: living
|
|
4
|
-
related: [primitives.md, theme-and-css.md, vocabulary.md]
|
|
4
|
+
related: [primitives.md, theme-and-css.md, vocabulary.md, recipes/pick-a-scenario.md]
|
|
5
5
|
updated: 2026-07-16
|
|
6
6
|
---
|
|
7
7
|
# The schema system
|
|
@@ -12,7 +12,10 @@ Everything here is imported from the package root:
|
|
|
12
12
|
import { direct, type SectionProps, type SectionSchemaShape } from "@homepages/template-kit";
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
One specifier for everything a section renders from, on purpose. The lone exception is
|
|
16
|
+
`@homepages/template-kit/fixtures`, which `fixtures.ts` imports the golden scenarios from
|
|
17
|
+
— dev-only sample data is kept off the root barrel so it can never reach a published
|
|
18
|
+
renderer's import graph.
|
|
16
19
|
|
|
17
20
|
A section is **four files in one folder**. Three of them are declarations the
|
|
18
21
|
platform reads; the fourth is your React.
|
|
@@ -75,6 +78,38 @@ than AI-produced, with `values` declaring the closed set the fact resolves to:
|
|
|
75
78
|
listing_status: { type: "select", required: false, source: direct("listing_intent"), values: ["for_sale", "for_rent"] },
|
|
76
79
|
```
|
|
77
80
|
|
|
81
|
+
### Video slots
|
|
82
|
+
|
|
83
|
+
A `video` slot (or a `video_collection`) declares a hosted video the platform serves —
|
|
84
|
+
not a link to a third-party player. It takes the same `frame` as an image, plus a
|
|
85
|
+
`playback` config, and it takes **no `crop`**: a video is selected, never edited, so
|
|
86
|
+
there is no cropper to steer and no re-edit state on the value.
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
hero_loop: {
|
|
90
|
+
type: "video",
|
|
91
|
+
frame: { breakpoint: 768, desktop: { aspect: 16 / 9 } },
|
|
92
|
+
playback: { autoplay: true, muted: true, loop: true, controls: false, preload: "auto" },
|
|
93
|
+
},
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Playback is **author-declared per slot** because the platform cannot infer it from the
|
|
97
|
+
asset — a silent hero loop and a narrated walkthrough need opposite behavior. The fields
|
|
98
|
+
are `autoplay`, `loop`, `muted`, `controls`, `playsinline`, and `preload`
|
|
99
|
+
(`"none" | "metadata" | "auto"`); `preload: "none"` is the bandwidth lever for a
|
|
100
|
+
below-fold video most visitors never reach. Omit `playback` entirely and
|
|
101
|
+
[`Video`](primitives.md#video--the-hosted-video-primitive) renders a plain controls
|
|
102
|
+
player.
|
|
103
|
+
|
|
104
|
+
**`autoplay` requires `muted`.** Every browser blocks unmuted autoplay, so a slot
|
|
105
|
+
declaring one without the other fails `check` rather than shipping a video that silently
|
|
106
|
+
never plays. The type system cannot express the pair, so the `check` failure is the guard.
|
|
107
|
+
|
|
108
|
+
A `VideoValue` is `{ video_id, url, poster, alt, width?, height? }`. `url` is always a
|
|
109
|
+
single progressive MP4 rendition — there is no `responsive` ladder and no `mobile` variant
|
|
110
|
+
to pass along, unlike an image. Read `url`, `poster`, `alt`, and the intrinsic
|
|
111
|
+
`width`/`height`, and hand them to `Video`.
|
|
112
|
+
|
|
78
113
|
### Grouping slots into one editor card
|
|
79
114
|
|
|
80
115
|
`meta.groups` collapses several slots into a single card in the editor sidebar. Each
|
|
@@ -132,7 +167,7 @@ is no framing for a renderer to apply. A slot's `crop` config steers the editor'
|
|
|
132
167
|
not your markup.
|
|
133
168
|
|
|
134
169
|
The markup a section is *required* to emit — the section root, the editor's slot
|
|
135
|
-
markers, images — comes from the kit's
|
|
170
|
+
markers, images, videos — comes from the kit's six primitives; everything else is your own
|
|
136
171
|
JSX. See [Contract primitives](primitives.md).
|
|
137
172
|
|
|
138
173
|
Renderers must be **pure functions of props** — no fetches, no globals, no
|
|
@@ -167,7 +202,7 @@ export const fillSpec = {
|
|
|
167
202
|
## `fixtures.ts` — content for local preview
|
|
168
203
|
|
|
169
204
|
`base` is one fully-specified baseline: every required slot, with a real value.
|
|
170
|
-
`states` adds named
|
|
205
|
+
`states` adds named states, each overriding part of it — use them for the
|
|
171
206
|
structural cases your section is designed to handle (a missing logo, a long
|
|
172
207
|
headline, an empty list).
|
|
173
208
|
|
|
@@ -191,26 +226,72 @@ const fixtures: FixtureModule = {
|
|
|
191
226
|
export default fixtures;
|
|
192
227
|
```
|
|
193
228
|
|
|
194
|
-
### Build on
|
|
229
|
+
### Build on a scenario, not on lorem ipsum
|
|
195
230
|
|
|
196
|
-
Preview is only as honest as the data behind it, so the kit ships
|
|
197
|
-
build fixtures from
|
|
198
|
-
|
|
231
|
+
Preview is only as honest as the data behind it, so the kit ships three complete,
|
|
232
|
+
property-facts-shaped scenarios to build fixtures from — real addresses, unit counts, and
|
|
233
|
+
contacts, the cases that actually break a layout. Pick the one whose breadth matches the
|
|
234
|
+
state you're exercising:
|
|
199
235
|
|
|
200
236
|
```ts
|
|
201
|
-
import {
|
|
237
|
+
import { scenarios, primaryContact, poisByCategory, propertyMetrics, contactCards, mkResponsive }
|
|
238
|
+
from "@homepages/template-kit/fixtures";
|
|
239
|
+
|
|
240
|
+
const s = scenarios.luxuryMultiUnit; // or sparseSingleFamily / forRentCondo
|
|
202
241
|
```
|
|
203
242
|
|
|
204
|
-
|
|
|
243
|
+
| Scenario | Breadth |
|
|
244
|
+
|---|---|
|
|
245
|
+
| `luxuryMultiUnit` | 12-unit multi-family, for-sale, 3-agent team, 24 POIs, 20 photos, both logos, video + 3D tour — the breadth ceiling every section's `base` fixture builds on |
|
|
246
|
+
| `sparseSingleFamily` | 1-unit single-family, for-sale, 1 contact, 4 POIs, 5 photos, no logos, no video/tour — the sparse floor a `states` entry exercises |
|
|
247
|
+
| `forRentCondo` | 1-unit condo/townhome, for-rent, 2 contacts, 8 POIs, 10 photos, both logos, video only — the mid case |
|
|
248
|
+
|
|
249
|
+
`scenarios` is also a `Record<ScenarioKey, Scenario>` for a picker; import a named
|
|
250
|
+
scenario (`luxuryMultiUnit`, `sparseSingleFamily`, `forRentCondo`) directly when you only
|
|
251
|
+
need one. This is a **separate entry**, deliberately not on the root barrel — dev-only
|
|
252
|
+
sample data must never be reachable from a published renderer bundle's import graph.
|
|
253
|
+
|
|
254
|
+
### Fill every slot from the scenario, by its fill-spec source
|
|
255
|
+
|
|
256
|
+
A fixture's job is to answer, for every slot, "what would this look like on a real
|
|
257
|
+
property?" — never to invent an answer. The scenario already has one; the fill-by-source
|
|
258
|
+
rule says where to find it, keyed to the same `source` / `produced_by` a slot declares in
|
|
259
|
+
`schema.ts`:
|
|
260
|
+
|
|
261
|
+
| Slot's fill-spec source | How the fixture fills it |
|
|
205
262
|
|---|---|
|
|
206
|
-
|
|
|
207
|
-
|
|
|
208
|
-
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
263
|
+
| direct (a fact) | read it off the scenario — `s.facts.address`, `primaryContact(s).fields.phone` |
|
|
264
|
+
| derived | a helper — `propertyMetrics(s)`, `poisByCategory(s)`, `contactCards(s)` |
|
|
265
|
+
| ai | a short sample fill **grounded in the scenario's facts** — a headline about *this* property, never lorem ipsum or invented facts |
|
|
266
|
+
|
|
267
|
+
A fixture that gets this wrong is worse than a missing one: a slot bound
|
|
268
|
+
`direct("beds")` whose fixture value doesn't match `s.facts.units[0].beds` teaches
|
|
269
|
+
nothing about the layout it's supposed to preview.
|
|
270
|
+
|
|
271
|
+
The helper functions project a scenario's raw facts into the shape a fixture usually
|
|
272
|
+
wants, without re-typing the scenario's data:
|
|
273
|
+
|
|
274
|
+
| Helper | Returns |
|
|
275
|
+
|---|---|
|
|
276
|
+
| `primaryContact(s)` | The scenario's primary contact (`ContactFixture`, position 0 by construction) — throws if the scenario has none |
|
|
277
|
+
| `contactCards(s)` | Every attached contact, in order (`ContactFixture[]`) |
|
|
278
|
+
| `poisByCategory(s)` | The scenario's POIs bucketed by category (`Record<PoiFixture["category"], PoiFixture[]>`) |
|
|
279
|
+
| `propertyMetrics(s)` | Beds/baths/sqft/price off the lowest-position unit, `*Min`/`*Max`/`priceStart` across all units, and `addressLine1`/`addressLine2` |
|
|
212
280
|
| `mkResponsive(url, width, height)` | Synthesizes a deterministic `ResponsiveImage` descriptor so `<Image responsive>` can be previewed and snapshotted |
|
|
213
281
|
|
|
282
|
+
`propertyMetrics` returns kit fact vocabulary — `addressLine1`/`addressLine2`, never a
|
|
283
|
+
template's own slot names, so the kit never learns what a section calls its slots. Map it
|
|
284
|
+
to your slots at the call site: `address_street: m.addressLine1`.
|
|
285
|
+
|
|
286
|
+
`s.photos`, `s.pois`, `s.amenities`, `s.contacts`, `s.media`, and `s.facts`
|
|
287
|
+
(the raw `PropertyFacts`) are also readable straight off the scenario for slots that don't
|
|
288
|
+
need a helper's projection — a gallery slot can bind directly to `s.photos`. A contact's
|
|
289
|
+
org name and logos (`logo_light`/`logo_dark`) live on `ContactFixture["fields"]`, not on
|
|
290
|
+
a sibling "brand" object — read them off `primaryContact(s).fields` or `s.contacts`.
|
|
291
|
+
|
|
292
|
+
See [Pick a scenario](recipes/pick-a-scenario.md) for the full picker and helper
|
|
293
|
+
cheat-sheet.
|
|
294
|
+
|
|
214
295
|
## Variants — rendering differently based on the facts
|
|
215
296
|
|
|
216
297
|
A variant axis picks a case from the property's facts, before any content is
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
purpose: The kit's two CSS entries, how a section's own CSS reaches the page, the TokenTheme a template supplies, and the breakpoint ladder.
|
|
3
3
|
status: living
|
|
4
4
|
related: [primitives.md, schema-system.md, eslint.md, rules/INDEX.md, check.md]
|
|
5
|
-
updated: 2026-07-
|
|
5
|
+
updated: 2026-07-16
|
|
6
6
|
---
|
|
7
7
|
# Theme and CSS
|
|
8
8
|
|
|
@@ -224,7 +224,8 @@ not make: `font-smoothing`, `button { cursor: pointer }` (Tailwind v4 leaves but
|
|
|
224
224
|
Ship `base.css` without a Tailwind entry on the page and you get an unreset page.
|
|
225
225
|
|
|
226
226
|
`base.css` references **no design token of yours** — nothing global is opinionated about
|
|
227
|
-
your brand. Its one tintable surface is the `Image`
|
|
227
|
+
your brand. Its one tintable surface is the placeholder fill shared by the `Image` and
|
|
228
|
+
`Video` frames — one class, one `--tr-image-frame-bg`, so you retint both at once; see
|
|
228
229
|
[`Image`](primitives.md#image--the-defensive-image-primitive).
|
|
229
230
|
|
|
230
231
|
## The breakpoint ladder
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
purpose: How to move a workspace to a new template-kit version, and what each kind of release means for you.
|
|
3
|
+
status: living
|
|
4
|
+
related: [check.md, pack.md, overview.md]
|
|
5
|
+
updated: 2026-07-16
|
|
6
|
+
---
|
|
7
|
+
# Upgrading the kit
|
|
8
|
+
|
|
9
|
+
Your workspace declares the kit like this:
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@homepages/template-kit": "^0.4.0"
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The kit is pre-1.0, and at 0.x that caret means **`>=0.4.0 <0.5.0`**. That is
|
|
18
|
+
deliberate: it gives you every safe update automatically and never a breaking one
|
|
19
|
+
without you asking.
|
|
20
|
+
|
|
21
|
+
## Two kinds of release
|
|
22
|
+
|
|
23
|
+
**Patch (0.4.0 → 0.4.1) — features and fixes.** While the kit is pre-1.0, both
|
|
24
|
+
land as patches. Your caret already allows them:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm update @homepages/template-kit
|
|
28
|
+
npm run check
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Minor (0.4.x → 0.5.0) — breaking.** At 0.x the minor is the breaking axis, so a
|
|
32
|
+
minor bump means something you author against changed. `npm update` will **not**
|
|
33
|
+
move you: a 0.x caret never crosses a minor. That is the caret doing its job.
|
|
34
|
+
|
|
35
|
+
To take it, ask for it:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npm install @homepages/template-kit@^0.5.0
|
|
39
|
+
npm run check
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
`check` is your migration list — it reports what the new version rejects. Read the
|
|
43
|
+
CHANGELOG in the package (`node_modules/@homepages/template-kit/CHANGELOG.md`) for
|
|
44
|
+
what changed and why.
|
|
45
|
+
|
|
46
|
+
## How long you have
|
|
47
|
+
|
|
48
|
+
Submissions are accepted against the current kit line **and the one before it**.
|
|
49
|
+
So when 0.5.0 ships, a template packed on 0.4.x still submits fine — you have a
|
|
50
|
+
full release cycle to migrate, and you are never blocked mid-template.
|
|
51
|
+
|
|
52
|
+
Once a third line ships, the oldest drops out: `template-kit pack` still succeeds
|
|
53
|
+
on it, but submitting that pack is refused, with the exact range to set in the
|
|
54
|
+
message.
|
|
55
|
+
|
|
56
|
+
## Checking where you are
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm ls @homepages/template-kit # what you have installed
|
|
60
|
+
npm view @homepages/template-kit version # the current release
|
|
61
|
+
```
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
purpose: The closed authoring vocabulary — slot types, direct() sources, derived() transforms, with selection semantics.
|
|
3
3
|
status: living
|
|
4
4
|
related: [schema-system.md]
|
|
5
|
-
updated: 2026-07-
|
|
5
|
+
updated: 2026-07-16
|
|
6
6
|
---
|
|
7
7
|
# The closed authoring vocabulary
|
|
8
8
|
|
|
@@ -20,6 +20,8 @@ of their field shapes.
|
|
|
20
20
|
| `select` | `string` (`string \| null` if optional) | a closed set of choices the user picks from |
|
|
21
21
|
| `image` | `ImageValue` (`ImageValue \| null` if optional) | one framed photo (add `crop`/`frame`) |
|
|
22
22
|
| `image_collection` | `ImageCollectionValue` | a gallery of framed photos |
|
|
23
|
+
| `video` | `VideoValue` (`VideoValue \| null` if optional) | one hosted video (add `frame`/`playback`) |
|
|
24
|
+
| `video_collection` | `VideoCollectionValue` | several hosted videos |
|
|
23
25
|
| `list` | `string[]` for a `text` element, `unknown[]` otherwise | a flat list of scalar items |
|
|
24
26
|
| `poi_list` | `PoiRow[]` | neighborhood points of interest |
|
|
25
27
|
| `url` | `string` (`string \| null` if optional) | a link the user edits in a URL field |
|
package/package.json
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@homepages/template-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Authoring kit for HomePages marketing-section templates: schema system, contract primitives, theme tokens, and the template-kit CLI.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"engines": {
|
|
8
8
|
"node": ">=20.0.0"
|
|
9
9
|
},
|
|
10
|
+
"workspaces": [
|
|
11
|
+
".",
|
|
12
|
+
"create-homepages-workspace"
|
|
13
|
+
],
|
|
10
14
|
"repository": {
|
|
11
15
|
"type": "git",
|
|
12
16
|
"url": "git+https://github.com/falktravis/template-kit.git"
|
|
@@ -16,7 +20,7 @@
|
|
|
16
20
|
},
|
|
17
21
|
"files": [
|
|
18
22
|
"dist",
|
|
19
|
-
"
|
|
23
|
+
"guide",
|
|
20
24
|
"tsconfig.json",
|
|
21
25
|
"tsconfig.base.json",
|
|
22
26
|
"CHANGELOG.md"
|
|
@@ -67,7 +71,8 @@
|
|
|
67
71
|
"lint:pkg": "publint --strict && attw --pack . --profile esm-only --exclude-entrypoints styles.css base.css",
|
|
68
72
|
"verify:consumer": "node scripts/verify-consumer.mjs",
|
|
69
73
|
"size:islands": "node scripts/check-island-runtime-size.mjs",
|
|
70
|
-
"check": "npm run typecheck && npm run lint && npm run build && npm run size:islands && npm run test && npm run lint:pkg && npm run verify:consumer",
|
|
74
|
+
"check": "npm run typecheck && npm run lint && npm run build && npm run size:islands && npm run test && npm run lint:pkg && npm run verify:consumer && npm run check:scaffolder",
|
|
75
|
+
"check:scaffolder": "npm run typecheck -w create-homepages-workspace && npm run test -w create-homepages-workspace",
|
|
71
76
|
"changeset": "changeset",
|
|
72
77
|
"release": "changeset publish"
|
|
73
78
|
},
|
|
@@ -102,6 +107,7 @@
|
|
|
102
107
|
"vite": "^6.0.5"
|
|
103
108
|
},
|
|
104
109
|
"dependencies": {
|
|
110
|
+
"magic-string": "^0.30.21",
|
|
105
111
|
"zod": "^4.4.3"
|
|
106
112
|
}
|
|
107
113
|
}
|
|
@@ -1,77 +0,0 @@
|
|
|
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 };
|