@getvitops/emdash 2.0.0-alpha.1 → 2.0.0-alpha.3

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 CHANGED
@@ -1,5 +1,57 @@
1
1
  # @getvitops/emdash
2
2
 
3
+ ## 2.0.0-alpha.3
4
+
5
+ ### Patch Changes
6
+
7
+ - @getvitops/generator@8.3.0-alpha.3
8
+ - @getvitops/utils@8.3.0-alpha.3
9
+
10
+ ## 2.0.0-alpha.2
11
+
12
+ ### Major Changes
13
+
14
+ - 0a47856: **Breaking: every block type is now `vitops_<name>`** (`vitops_cards`, `vitops_hero`, `vitops_actionLink`, …), where the Portable Text blocks were `vitops.<name>` and the section block type was already `vitops_section`. EmDash validates a block type's slug as `[a-z][a-z0-9_]*`, so `vitops.section` was never possible and the toolkit had two styles for one kind of thing. Underscore is the one form valid everywhere, so it is now the only one.
15
+
16
+ Migration: in stored content and in `seed/seed.json`, rename `_type` values from `vitops.<name>` to `vitops_<name>`; in `PortableText` `components`, rename the keys the same way; the `blocks: { include, exclude }` option takes full type names, so rename those too. `vt_*` names in a site are that site's own types and are unaffected. A search-and-replace of `vitops.(actionLink|imageCompare|copyButton|banner|details|carousel|gallery|cards|accordion|hero|marquee|logos|steps|stats|callout|entries|pricing|embed|form|reviews|nav|badges|widgetArea)` with `vitops_$1` covers it. `vitops emdash build` reports any block left on the old name as having no component.
17
+
18
+ ### Minor Changes
19
+
20
+ - 0a47856: Build correctness and gaps from the second upstream round.
21
+
22
+ - **`@getvitops/emdash`: fixes a circular import that emptied the plugin block map in the static build.** `Section.astro` and `WidgetArea.astro` imported `emdash/ui` statically, which imports `virtual:emdash/block-components`, which is `@getvitops/emdash/astro` again. Depending on import order, every `vitops_*` block inside a section body was dropped from prerendered pages with only a `PortableText [components.type] is missing …` warning. Both now import it lazily, and a test fails if any renderer imports `emdash/ui` statically. No code change needed in sites.
23
+ - **`@getvitops/cli`: `vitops emdash build`** runs `astro build` and then `check-prerender`, and fails when the build reports a block type with no component (reported once per type). The template's `build`, `deploy` and `deploy:dev` scripts use it; existing sites replace `astro build && vitops emdash check-prerender` with `vitops emdash build`. `check-prerender` also warns (fails with `--strict`) on a page without exactly one `<h1>`.
24
+ - **`@getvitops/emdash`: `vitops_hero` and `vitops_section` heading level** accepts `h1`–`h6` and `p` (a heading that is styled but not in the outline). The hero defaults to `h1`; set the level to `2` on a page whose layout already renders an `h1` (the template's seed does).
25
+ - **`@getvitops/emdash`: `vitops_logos`** shows an entry's name as text (`.logos__name`) when it has no image. `@getvitops/core` adds the rule (all formats).
26
+ - **`@getvitops/emdash`: an empty content widget** (no text, no blocks) no longer renders its title, and an area whose widgets are all empty renders nothing.
27
+ - **`@getvitops/create`:** the template's `pages` collection gets `urlPattern: "/{slug}"` (the sitemap listed `/pages/<slug>`, which 404s; existing sites change it under Content Types), and `.gitignore` ignores only `src/styles/tailwind.css` and `tokens.json`, so site CSS kept in `src/styles/` is committed.
28
+ - **`@getvitops/emdash`: per-item colour.** The rows of `vitops_cards`, `vitops_stats`, `vitops_steps` and the hero's `cards` take their own `tone` / `color` (blank inherits the block's), so one block can hold a pine item and an amber one. Hero cards also take an `eyebrow` and a button (`ctaLabel` / `ctaHref`; with a button the card is no longer a stretched link).
29
+ - **`@getvitops/generator` / `@getvitops/emdash`: solid fills read.** The generator emits `--color-<hue>-<step>-on` for every step of every hue, the foreground for a fill at that step picked by the same APCA rule as `text-on-<role>` (css and tailwind formats, a plain `:root`, not `@theme`). A block fill chosen by `color` (hue and step) uses it instead of a fixed white..
30
+ - **`@getvitops/core`: `.counter__value.sr-only`** hides itself, so a build that never emitted the `.sr-only` utility no longer shows a counting figure twice (all formats).
31
+ - **`@getvitops/astro` / `@getvitops/core`: `SiteFooter` groups.** A top-level item of the `footer-sitemap` menu with children becomes a column (its label is the heading, its children the links, one level only); childless items stay in the flat list. Each column is a named `<nav>`.
32
+ - **`@getvitops/astro`: planned links and header buttons.** A menu item with `draft` in its CSS classes stays in the menu but is not rendered (at every level, in the header and the footer). `<SiteNav>` has an `actions` slot for header buttons that are not menu items, and an item with `cta` in its CSS classes renders as a button.
33
+ - **`@getvitops/cli`: `check-prerender` warnings** (fail with `--strict`): links to pages the build did not produce, a form with no delivery address (no `site.notifications.email`, location `email` or `site.crm`), and form fields missing from every `site.templates` form entry (the generated privacy policy reads those). It reads `./site.json`, or `--site=<path>`. `vitops setup … --dry-run` is accepted as `--dry`.
34
+ - **`@getvitops/emdash` / `@getvitops/astro`: "tick any number" form field** (`vitops_form` field kind `checkboxes`): a fieldset of checkboxes sharing one name. The conversion route joins repeated values (`IT, Marketing`) instead of keeping the last. The "required" toggle is not applied to the group (HTML cannot require one of several).
35
+ - **`@getvitops/core`: size hooks.** `.steps__title`, `.stats__figure` and `.card__title` read `--steps-title-size` (default one step below `heading`), `--stats-figure-size` and `--card-title-size`, set on the block through its `style` field. They set the `--heading-fs` / `--display-fs` properties the type-role utilities already read, so no extra class or prop is needed (all formats).
36
+ - **`@getvitops/create`:** the template's `site.json` lists its contact form under `site.templates`, so the privacy policy inventory and the new check agree.
37
+ - **`@getvitops/emdash`: `theme` on every block, on widget areas and on your own markup.** A `theme` select (`<role>` tinted, `<role>:solid` filled, populated from the site's roles by a new `themes/list` route) is a common field on every `vitops_*` block, applied to the block's own root with the role's computed readable text. `<VitopsWidgetArea theme="…">` takes the same, and `themeAttrs('surface')` gives `{ class, style }` for a layout `<body>`. `vitops_section`'s existing `theme` now goes through the same path.
38
+ - **`@getvitops/cli` / `@getvitops/emdash`: pages with a dropped block fail the build.** `vitops_section` and widget areas emit an invisible `<template data-vitops-unrendered="…">` for any body block with no renderer, and `check-prerender` fails the page naming the types (nested bodies only; `vitops emdash build` also scans the build log, which covers top-level bodies). A regression test imports the plugin entry first with a mock of the real virtual module, so the old import cycle fails it.
39
+ - **`@getvitops/emdash`: `formTemplateFromBlock(block)`** turns a saved `vitops_form` value into a `site.templates` form entry (names as submitted, a `checkboxes` field as a `checkbox` with options), to paste into `site.json` so the generated privacy policy lists what the form collects. The build cannot read the CMS database, so this is run by hand; `check-prerender` warns when fields are missing.
40
+ - **`@getvitops/utils`: `hasFormDelivery`** (`@getvitops/utils/notify`): the one test for "has this form anywhere to go", used by `check-prerender`.
41
+ - **`@getvitops/emdash`:** a `color` hue tint now flips with the colour scheme (`light-dark()`); hero option cards sit at `h2` under an `h1` hero; menu items also accept `hidden: true` (same as the `draft` class); `vitops docs blocks` documents `theme`, the per-row colours, the `--<role>-fs` type-size hook and the form checks.
42
+ - **`@getvitops/create`:** the template redirects `/home` to `/`, and the guides use `vp exec` instead of `vpx`.
43
+
44
+ ### Patch Changes
45
+
46
+ - 0a47856: New package `@getvitops/skills`: agent skills for sites built with the toolchain (`custom-blocks`, `content-and-deploys`, `contact-form`, `csp`). The emdash template depends on it and runs `skills experimental_sync` on `prepare`, which links them into `.agents/skills/` and `.claude/skills/`, so they update with `vp update` instead of being copied at scaffold time. Existing sites: `vp add @getvitops/skills && vp add -D skills`, set `prepare` to `vp config && skills experimental_sync -y -a claude-code --no-frozen-lockfile`, gitignore the four linked names, and delete the site's own copies of those four skills (the sync never replaces a directory it did not create).
47
+
48
+ The emdash template's `AGENTS.md` is shortened to the always-relevant rules. Deploy and content mechanics (where each kind of data is the truth, prerendering, publish-triggered rebuilds, refreshing dev), the contact form, and the CSP move into those skills. Corrects the nesting guidance: a block type with a `portableText` field (such as `vitops_section`) holds other blocks, while `vitops_*` Portable Text blocks do not. Adds guidance for agents to record reusable toolkit gaps in `UPSTREAM.md`. The generated stylesheet is no longer described as always `tailwind.css`.
49
+
50
+ - Updated dependencies [0a47856]
51
+ - Updated dependencies [0a47856]
52
+ - @getvitops/generator@8.3.0-alpha.2
53
+ - @getvitops/utils@8.3.0-alpha.2
54
+
3
55
  ## 2.0.0-alpha.1
4
56
 
5
57
  ### Minor Changes
package/README.md CHANGED
@@ -129,16 +129,16 @@ export default defineConfig({
129
129
 
130
130
  | Slash-menu entry | `_type` | Renders |
131
131
  | ---------------- | --------------------- | ---------------------------------------------------------- |
132
- | Link or button | `vitops.actionLink` | sprite-icon `<a>`, styled `.link`/`.btn`/`.cta` |
133
- | Image compare | `vitops.imageCompare` | `<wc-image-compare>` before/after slider |
134
- | Copy snippet | `vitops.copyButton` | `<wc-copy>` with code/inline fallback |
135
- | Banner | `vitops.banner` | `<wc-dismissable>` banner with tone colours |
136
- | Disclosure | `vitops.details` | native `<details>`/`<summary>` |
137
- | Accordion | `vitops.accordion` | a group of `<details>`; optionally one-open-at-a-time |
138
- | Carousel | `vitops.carousel` | `@getvitops/astro`'s `<Carousel />` over a Slides repeater |
139
- | Gallery | `vitops.gallery` | `<Gallery />` — thumbnail grid opening a lightbox carousel |
140
- | Cards | `vitops.cards` | `<Cards />` — a grid of `.card`s, whole-card click with JS |
141
- | Marquee | `vitops.marquee` | `<Marquee />` — a continuously scrolling row |
132
+ | Link or button | `vitops_actionLink` | sprite-icon `<a>`, styled `.link`/`.btn`/`.cta` |
133
+ | Image compare | `vitops_imageCompare` | `<wc-image-compare>` before/after slider |
134
+ | Copy snippet | `vitops_copyButton` | `<wc-copy>` with code/inline fallback |
135
+ | Banner | `vitops_banner` | `<wc-dismissable>` banner with tone colours |
136
+ | Disclosure | `vitops_details` | native `<details>`/`<summary>` |
137
+ | Accordion | `vitops_accordion` | a group of `<details>`; optionally one-open-at-a-time |
138
+ | Carousel | `vitops_carousel` | `@getvitops/astro`'s `<Carousel />` over a Slides repeater |
139
+ | Gallery | `vitops_gallery` | `<Gallery />` — thumbnail grid opening a lightbox carousel |
140
+ | Cards | `vitops_cards` | `<Cards />` — a grid of `.card`s, whole-card click with JS |
141
+ | Marquee | `vitops_marquee` | `<Marquee />` — a continuously scrolling row |
142
142
 
143
143
  All blocks render accessible markup that works without JavaScript; the
144
144
  web components progressively enhance it. Each is a thin adapter over the matching
@@ -155,7 +155,7 @@ URLs with any other scheme (`javascript:`, `data:`) are dropped at render time.
155
155
  ```js
156
156
  vitopsEmdash({
157
157
  blocks: {
158
- exclude: ['vitops.marquee'], // or `include: [...]` as an allowlist
158
+ exclude: ['vitops_marquee'], // or `include: [...]` as an allowlist
159
159
  extra: [
160
160
  {
161
161
  type: 'acme.pricing',
@@ -168,12 +168,12 @@ vitopsEmdash({
168
168
  ```
169
169
 
170
170
  `extra` adds **editor** definitions only. This plugin cannot render a block it has never heard of,
171
- so the site maps each of its own types to a component, and can replace a `vitops.*` renderer the same way:
171
+ so the site maps each of its own types to a component, and can replace a `vitops_*` renderer the same way:
172
172
 
173
173
  ```astro
174
174
  <PortableText
175
175
  value={page.data.content}
176
- components={{ type: { 'acme.pricing': PricingTable, 'vitops.cards': MyCards } }}
176
+ components={{ type: { 'acme.pricing': PricingTable, 'vitops_cards': MyCards } }}
177
177
  />
178
178
  ```
179
179
 
@@ -197,15 +197,17 @@ guarded — but wasteful).
197
197
 
198
198
  ## Patterns that contain other blocks
199
199
 
200
- A Portable Text block cannot hold other blocks — a repeater's rows are scalar fields. So a section
201
- with columns, a hero, or a card holding a button is not a `vitops.*` block. Two routes:
200
+ A `vitops_*` Portable Text block holds only scalar fields and repeaters, so it cannot hold other
201
+ blocks. A block _type_ with a `portableText` field can: `vitops_section`'s `body` holds any blocks,
202
+ so a section containing cards or stats is a section whose body holds `vitops_cards` or
203
+ `vitops_stats`. For a hero or a card holding a button, two routes:
202
204
 
203
205
  - A **`blocks` field** (EmDash's typed page-composition field): define block types such as `hero` or
204
206
  `split` in the seed, and map each to an Astro component built from `@getvitops/astro`
205
207
  (`Subgrid`, `Cards`, the `.split` classes) with `defineBlockComponents`.
206
208
  - **Sections** (`/section`): compose the pattern once as reusable content and let editors insert copies.
207
209
 
208
- EmDash's built-in `columns` block renders its children with marks only, so a `vitops.*` block placed
210
+ EmDash's built-in `columns` block renders its children with marks only, so a `vitops_*` block placed
209
211
  inside one does not render. Use a `blocks` field for layout instead.
210
212
 
211
213
  Not yet blocks: tree, entries, reviews (`ReviewCard` reads `.vitops/reviews.json`, which needs a
package/dist/index.d.mts CHANGED
@@ -7,13 +7,12 @@ type BlockKitFieldDef = Extract<NonNullable<PortableTextBlockConfig['fields']>[n
7
7
  type PortableTextBlockDef = Omit<PortableTextBlockConfig, 'fields'> & {
8
8
  fields?: BlockKitFieldDef[];
9
9
  };
10
- /** Every block gets the escape hatches last, so the editor reads content first. */
11
10
  export declare const BLOCKS: PortableTextBlockDef[];
12
11
  /** Which Vitops blocks a site's editor offers, and any it adds of its own. */
13
12
  interface BlockSelection {
14
- /** Offer only these `vitops.*` types. Unknown names throw — a typo must not silently offer nothing. */
13
+ /** Offer only these `vitops_*` types. Unknown names throw — a typo must not silently offer nothing. */
15
14
  include?: string[];
16
- /** Drop these `vitops.*` types. Applied after `include`. */
15
+ /** Drop these `vitops_*` types. Applied after `include`. */
17
16
  exclude?: string[];
18
17
  /**
19
18
  * The site's own blocks. These are EDITOR definitions only: the plugin cannot render a
@@ -48,9 +47,29 @@ interface DesignSystemEditorOptions {
48
47
  * it cannot describe a field the editor doesn't offer.
49
48
  */
50
49
  export declare function renderBlocksDoc(blocks?: readonly PortableTextBlockDef[]): string;
51
- /** Block-type slugs may not contain a dot, so `vitops.section` is stored as `vitops_section`. */
50
+ /** The `fields` row shape of a `site.templates` form entry (`FormFieldSchema`). */
51
+ interface FormTemplateField {
52
+ name: string;
53
+ type: 'text' | 'email' | 'tel' | 'textarea' | 'select' | 'checkbox';
54
+ label: string;
55
+ required?: boolean;
56
+ options?: {
57
+ label: string;
58
+ value: string;
59
+ }[];
60
+ }
61
+ interface FormTemplate {
62
+ type: 'form';
63
+ action: string;
64
+ method: 'post';
65
+ honeypot: true;
66
+ fields: FormTemplateField[];
67
+ }
68
+ /** `block` is a saved `vitops_form` value (the object with `fields`, `action`, …). */
69
+ export declare function formTemplateFromBlock(block: unknown): FormTemplate;
70
+ /** Block-type slugs may not contain a dot, so `vitops_section` is stored as `vitops_section`. */
52
71
  export declare const SECTION_SLUG = "vitops_section";
53
- /** `vitops.section`: kicker, heading, lead-in, tone/backdrop, optional heading-left layout, and a body of blocks. */
72
+ /** `vitops_section`: kicker, heading, lead-in, tone/backdrop, optional heading-left layout, and a body of blocks. */
54
73
  export declare const SECTION_BLOCK_TYPE: ApplySeedBlockTypeInput;
55
74
  /**
56
75
  * Every block type this plugin ships, in the shape `seed.json`'s `blockTypes` takes. Spread
@@ -136,7 +155,7 @@ export interface VitopsEmdashOptions {
136
155
  */
137
156
  designSystemEditor?: DesignSystemEditorOptions | false;
138
157
  /**
139
- * Which blocks the editor offers. All of the `vitops.*` blocks by default. Use `exclude` to
158
+ * Which blocks the editor offers. All of the `vitops_*` blocks by default. Use `exclude` to
140
159
  * drop one a client should not see, `include` for an allowlist, and `extra` to add the
141
160
  * site's own — whose renderers the site supplies, see {@link BlockSelection}.
142
161
  */
@@ -156,5 +175,5 @@ export interface VitopsEmdashOptions {
156
175
  export declare function vitopsEmdash(options?: VitopsEmdashOptions): PluginDescriptor;
157
176
  /** Runtime side — EmDash imports and calls this from the descriptor's entrypoint. */
158
177
  export declare function createPlugin(options?: VitopsEmdashOptions): import("emdash").ResolvedPlugin<import("emdash").PluginStorageConfig>;
159
- export { type BlockKitFieldDef, type BlockSelection, type DesignSystemEditorOptions, type HostingTarget, type PortableTextBlockDef, type VitopsHosting, type VitopsHostingOptions, createPlugin as default };
178
+ export { type BlockKitFieldDef, type BlockSelection, type DesignSystemEditorOptions, type FormTemplate, type FormTemplateField, type HostingTarget, type PortableTextBlockDef, type VitopsHosting, type VitopsHostingOptions, createPlugin as default };
160
179
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/blocks.ts","../src/design-system-route.ts","../src/blocks-doc.ts","../src/block-types.ts","../src/astro/blocks/tone.ts","../src/hosting.ts","../src/index.ts"],"mappings":";;;KAuBY,mBAAmB,QAC7B,YAAY;EAEV;;KAWQ,uBAAuB,KAAK;EACtC,SAAS;;;qBA8/BE,QAAQ;;UAMJ;;EAEf;;EAEA;;;;;;;EAOA,QAAQ;;;;;;;;wBASM,aAAa,YAAW,iBAAsB;UCvgC7C;;;;;;;;EAQf;;EAEA;;;;;;;wBC9Bc,gBAAgB,kBAAiB;;qBCZpC;;qBA+DA,oBAAoB;;;;;;wBAejB,oBAAoB;;wBCnDpB,UAAU;UAcT;;EAEf;;EAEA;;;;;;;;wBASc,YAAY,gBAAgB,kBAAkB;KC7ClD;UAIK;;EAEf,SAAS;EACT;;IAEE;;IAEA;;IAEA;;;;;;;IAOA;;EAEF;;IAEE;;IAEA;;IAEA;;IAEA;;;UAIa;EACf,QAAQ;EACR,SAAS;;EAET;;EAEA;;wBAoBoB,cAAc,UAAS,uBAA4B,QAAQ;iBClBhE;;;;;;;;;;;EAWf;;EAEA;;;;;;;;;EASA,qBAAqB;;;;;;EAMrB,SAAS;;;;;;;EAOT;;;;;;wBAOc,aAAa,UAAS,sBAA2B;;wBAmBjD,aAAa,UAAS,uCAAwB,gCAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/blocks.ts","../src/design-system-route.ts","../src/blocks-doc.ts","../src/form-template.ts","../src/block-types.ts","../src/astro/blocks/tone.ts","../src/hosting.ts","../src/index.ts"],"mappings":";;;KAwBY,mBAAmB,QAC7B,YAAY;EAEV;;KAWQ,uBAAuB,KAAK;EACtC,SAAS;;qBAqlCE,QAAQ;;UAMJ;;EAEf;;EAEA;;;;;;;EAOA,QAAQ;;;;;;;;wBASM,aAAa,YAAW,iBAAsB;UC/lC7C;;;;;;;;EAQf;;EAEA;;;;;;;wBC9Bc,gBAAgB,kBAAiB;;UCjBhC;EACf;EACA;EACA;EACA;EACA;IAAY;IAAe;;;UAGZ;EACf;EACA;EACA;EACA;EACA,QAAQ;;;wBAIM,sBAAsB,iBAAiB;;qBCZ1C;;qBAoEA,oBAAoB;;;;;;wBAejB,oBAAoB;;wBCrDpB,UAAU;UAcT;;EAEf;;EAEA;;;;;;;;wBASc,YAAY,gBAAgB,kBAAkB;KChDlD;UAIK;;EAEf,SAAS;EACT;;IAEE;;IAEA;;IAEA;;;;;;;IAOA;;EAEF;;IAEE;;IAEA;;IAEA;;IAEA;;;UAIa;EACf,QAAQ;EACR,SAAS;;EAET;;EAEA;;wBAoBoB,cAAc,UAAS,uBAA4B,QAAQ;iBCfhE;;;;;;;;;;;EAWf;;EAEA;;;;;;;;;EASA,qBAAqB;;;;;;EAMrB,SAAS;;;;;;;EAOT;;;;;;wBAOc,aAAa,UAAS,sBAA2B;;wBAmBjD,aAAa,UAAS,uCAAwB,gCAAA"}