astroidjs 0.4.1 → 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.
@@ -43,7 +43,7 @@ export declare const SECTION_SETTINGS: Record<string, SectionField>;
43
43
  * array — `"2"` for a top-level section, `"2.blocks.0"` for a block inside it —
44
44
  * and every marker the component stamps is built from it. Passing it down (rather
45
45
  * than having each component work out its own depth) is what lets the exact same
46
- * component render as a section or as a block, and what keeps `data-louise-sfield`
46
+ * component render as a section or as a block, and what keeps `data-louise-node`
47
47
  * paths correct at any nesting depth.
48
48
  */
49
49
  export interface SectionRenderProps {
@@ -194,7 +194,13 @@ export function generateMapEmbedComponent(config) {
194
194
  " for (const entry of entries) {",
195
195
  " if (!entry.isIntersecting) continue;",
196
196
  " obs.unobserve(entry.target);",
197
- " init(entry.target as HTMLElement);",
197
+ " // `init` is async and nothing awaits it, so without this catch a",
198
+ " // failed chunk fetch — a page load racing a deploy is enough — is a",
199
+ " // silent unhandled rejection: the container just stays an empty",
200
+ " // tinted box with nothing in the console to explain it.",
201
+ " init(entry.target as HTMLElement).catch((err) => {",
202
+ ' console.error("[astroid:map] map failed to load", err);',
203
+ " });",
198
204
  " }",
199
205
  " },",
200
206
  ' { rootMargin: "200px" },',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astroidjs",
3
- "version": "0.4.1",
3
+ "version": "0.6.0",
4
4
  "description": "Astroid — an opinionated meta-framework over Louise Toolkit and Astro for building editable, multi-editor sites on Cloudflare Workers.",
5
5
  "keywords": [
6
6
  "astro",
@@ -60,7 +60,7 @@
60
60
  "access": "public"
61
61
  },
62
62
  "dependencies": {
63
- "louise-toolkit": "0.20.0"
63
+ "louise-toolkit": "0.22.0"
64
64
  },
65
65
  "devDependencies": {
66
66
  "@types/node": "^24.13.3",
@@ -12,10 +12,16 @@
12
12
  // `data-louise-field="<collection>:<key>:<field>"` (saved as a
13
13
  // versioned draft when the page is mounted with `versionedPageId`).
14
14
  // • SECTION field — pass `base` (this item's path, e.g. `"2"` or `"2.blocks.0"`)
15
- // plus `field`; emits `data-louise-sfield="<base>.<field>"`
16
- // (+ `data-louise-multiline`) for the on-canvas section editor.
17
- // `sfield` stays as the escape hatch for a path you build
18
- // yourself — an array entry: sfield={`${base}.items.${i}.title`}.
15
+ // plus `field`; emits `data-louise-node="<base>.<field>"` for
16
+ // the on-canvas section editor. `sfield` stays as the escape
17
+ // hatch for a path you build yourself — an array entry:
18
+ // sfield={`${base}.items.${i}.title`}.
19
+ //
20
+ // Since ADR 0010 A2 this is the SAME attribute the section
21
+ // boundary carries, one path deeper. The catalog says whether a
22
+ // field is edited in place and with which editor, so `type` and
23
+ // `multiline` no longer affect a section field's markup — they
24
+ // are accepted for compatibility and ignored.
19
25
  //
20
26
  // The `base` form is what ADR 0005 §2 asks for: "a site author writes `<Editable
21
27
  // field="heading">` and never hand-stamps the deeper path". `<Section>` supplies
@@ -76,20 +82,26 @@ const editing = edit ?? (Astro.locals as { editMode?: boolean }).editMode ?? fal
76
82
  // spreading that into `Record<string, string>` is a type error.
77
83
  const richText: Record<string, string> =
78
84
  type === "richtext" ? { "data-louise-type": "richtext" } : {};
79
- const multilineMarker: Record<string, string> = multiline ? { "data-louise-multiline": "" } : {};
80
85
 
81
86
  let markers: Record<string, string> = {};
82
87
  if (editing) {
83
88
  if (sectionPath) {
84
- markers = {
85
- "data-louise-sfield": sectionPath,
86
- ...richText,
87
- ...multilineMarker,
88
- };
89
+ // ONE marker (ADR 0010 A2). This used to emit `data-louise-sfield` plus
90
+ // `data-louise-type="richtext"` plus `data-louise-multiline` — three
91
+ // attributes describing a field the catalog already fully describes. The
92
+ // editor now reads the field's type to know whether it's rich text and
93
+ // whether it holds more than one line, so `type` and `multiline` are inert
94
+ // here and kept only so an existing call site doesn't fail to compile.
95
+ markers = { "data-louise-node": sectionPath };
89
96
  } else if (collection && key !== undefined && field) {
97
+ // The PAGE-field contract is untouched: a collection row's field is not a
98
+ // node in a sections tree, so it keeps its own marker and its own type hint.
90
99
  markers = { "data-louise-field": `${collection}:${key}:${field}`, ...richText };
91
100
  }
92
101
  }
102
+ // Referenced so the deprecated prop doesn't read as unused while it's still
103
+ // accepted; it no longer affects the markup.
104
+ void multiline;
93
105
  ---
94
106
 
95
107
  <Tag {...rest} {...markers}><slot /></Tag>
@@ -8,12 +8,14 @@
8
8
  // the page's `sections` column, not props a template hand-wrote, so what renders
9
9
  // is exactly what the on-canvas editor edits in place.
10
10
  //
11
- // Two marker responsibilities, split the way ADR 0005 §2 splits them:
12
- // • the BOUNDARY (`data-louise-section` / `data-louise-block`) is stamped here,
11
+ // Two marker responsibilities:
12
+ // • the BOUNDARY (`data-louise-node="<path>"`, ADR 0010) is stamped here,
13
13
  // because only the dispatcher knows an item's position;
14
- // • the FIELDS (`data-louise-sfield`) are stamped by `<Editable base={base}
15
- // field="…">` inside each component, because only the component knows which
16
- // of its text nodes are editable.
14
+ // • the FIELDS are stamped by `<Editable base={base} field="…">` inside each
15
+ // component, because only the component knows which of its text nodes are
16
+ // editable. Since A2 those carry the SAME `data-louise-node` attribute, one
17
+ // path deeper — the catalog says whether a field is edited in place, so the
18
+ // marker no longer has to.
17
19
  //
18
20
  // Blocks recurse through this same component with a deeper `base`. That's the
19
21
  // whole trick: a component never learns its own depth, so a type that renders as
@@ -79,15 +81,16 @@ const type = String(item._type);
79
81
  // (`<i>.blocks.<j>`), which is what the client's depth-agnostic path parser walks.
80
82
  const blocks = Array.isArray(item.blocks) ? item.blocks : [];
81
83
 
82
- // The boundary marker the on-canvas chrome draws its ring on. `class="contents"`
83
- // keeps this wrapper out of layout entirely — the ring is drawn as a box-shadow
84
- // on the element itself (ADR 0005 §3), so an extra block box here would offset
84
+ // The boundary marker the on-canvas chrome draws its ring on. It is the item's
85
+ // path, verbatim — pre-0010 this line string-sniffed `base` for ".blocks." to pick
86
+ // between two attribute names, which was the three-attribute editing model leaking
87
+ // into an otherwise uniform recursive render (ADR 0010, Context). The editor
88
+ // resolves what a path CAN do from the catalog; the render just says where it is.
89
+ //
90
+ // `class="contents"` keeps this wrapper out of layout entirely — the ring is drawn
91
+ // as a box-shadow on the element itself, so an extra block box here would offset
85
92
  // every section's spacing for the sake of an attribute.
86
- const boundary = editing
87
- ? base.includes(".blocks.")
88
- ? { "data-louise-block": base }
89
- : { "data-louise-section": base }
90
- : {};
93
+ const boundary = editing ? { "data-louise-node": base } : {};
91
94
 
92
95
  const shared = { item, base, edit: editing, mediaMeta };
93
96
 
@@ -53,7 +53,7 @@ const mediaMeta =
53
53
 
54
54
  {/*
55
55
  The host element. `mountSections(el, opts)` takes the element to scan for
56
- `[data-louise-sfield]` markers and to hang on-canvas chrome off, so rendering
56
+ `[data-louise-node]` markers and to hang on-canvas chrome off, so rendering
57
57
  it here — rather than asking every page to remember a wrapper — is what makes
58
58
  `<Sections>` self-sufficient: drop it on a page and the editor can find it.
59
59
  A plain block wrapper, not `display: contents`, because the chrome positions
@@ -116,7 +116,7 @@ export const SECTION_SETTINGS: Record<string, SectionField> = {
116
116
  * array — `"2"` for a top-level section, `"2.blocks.0"` for a block inside it —
117
117
  * and every marker the component stamps is built from it. Passing it down (rather
118
118
  * than having each component work out its own depth) is what lets the exact same
119
- * component render as a section or as a block, and what keeps `data-louise-sfield`
119
+ * component render as a section or as a block, and what keeps `data-louise-node`
120
120
  * paths correct at any nesting depth.
121
121
  */
122
122
  export interface SectionRenderProps {