@evanion/astro-widget 0.1.0 → 0.2.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 +23 -0
- package/dist/index.js +3 -3
- package/dist/types.d.ts +4 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +5 -3
- package/src/astro-modules.d.ts +11 -0
- package/src/components/Widgets.astro +6 -2
- package/src/types.ts +4 -0
- package/src/validate-blocks.ts +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,26 @@
|
|
|
1
|
+
## 0.2.0 (2026-09-10)
|
|
2
|
+
|
|
3
|
+
### 🩹 Fixes
|
|
4
|
+
|
|
5
|
+
- ⚠️ **astro-widget:** report validation problems in english ([e51907c](https://github.com/Evanion/libraries/commit/e51907c))
|
|
6
|
+
- ⚠️ **astro-widget:** keep placement data out of block props ([2378269](https://github.com/Evanion/libraries/commit/2378269))
|
|
7
|
+
|
|
8
|
+
### ⚠️ Breaking Changes
|
|
9
|
+
|
|
10
|
+
- **astro-widget:** report validation problems in english ([e51907c](https://github.com/Evanion/libraries/commit/e51907c))
|
|
11
|
+
BlockProblem.message strings changed. A caller matching on the
|
|
12
|
+
old text must match "unknown block type", "missing field <name>" and "blocks is
|
|
13
|
+
not a list" instead.
|
|
14
|
+
- **astro-widget:** keep placement data out of block props ([2378269](https://github.com/Evanion/libraries/commit/2378269))
|
|
15
|
+
a block that read placement data out of its own props must now
|
|
16
|
+
read it from `meta` on the item chrome instead.
|
|
17
|
+
Part of #71
|
|
18
|
+
|
|
19
|
+
### ❤️ Thank You
|
|
20
|
+
|
|
21
|
+
- Claude Opus 5 (1M context)
|
|
22
|
+
- Mikael Pettersson @Evanion
|
|
23
|
+
|
|
1
24
|
## 0.1.0 (2026-08-30)
|
|
2
25
|
|
|
3
26
|
### 🚀 Features
|
package/dist/index.js
CHANGED
|
@@ -8,7 +8,7 @@ function t(e, n, r = {}) {
|
|
|
8
8
|
if (!Array.isArray(e)) return [{
|
|
9
9
|
index: -1,
|
|
10
10
|
type: "-",
|
|
11
|
-
message: "
|
|
11
|
+
message: "blocks is not a list"
|
|
12
12
|
}];
|
|
13
13
|
let i = [];
|
|
14
14
|
return e.forEach((e, a) => {
|
|
@@ -16,14 +16,14 @@ function t(e, n, r = {}) {
|
|
|
16
16
|
if (!(o in n)) i.push({
|
|
17
17
|
index: a,
|
|
18
18
|
type: o,
|
|
19
|
-
message: "
|
|
19
|
+
message: "unknown block type"
|
|
20
20
|
});
|
|
21
21
|
else for (let t of r[o] ?? []) {
|
|
22
22
|
let n = e[t];
|
|
23
23
|
(n == null || typeof n == "string" && n.trim() === "") && i.push({
|
|
24
24
|
index: a,
|
|
25
25
|
type: o,
|
|
26
|
-
message: `
|
|
26
|
+
message: `missing field ${t}`
|
|
27
27
|
});
|
|
28
28
|
}
|
|
29
29
|
Array.isArray(e?.children) && i.push(...t(e.children, n, r));
|
package/dist/types.d.ts
CHANGED
|
@@ -9,6 +9,10 @@ export interface BlockItem {
|
|
|
9
9
|
<slot />, not through a `children` prop. A block that wants nesting
|
|
10
10
|
renders <Widgets items={children} registry={registry} /> itself. */
|
|
11
11
|
children?: BlockItem[];
|
|
12
|
+
/** Placement and presentation data for `chrome.item`. Handed to the item
|
|
13
|
+
wrapper and never spread into the block's own props, because where a
|
|
14
|
+
block sits is not something the block should know. */
|
|
15
|
+
meta?: Record<string, unknown>;
|
|
12
16
|
/** Everything else is passed to the component as props. */
|
|
13
17
|
[key: string]: unknown;
|
|
14
18
|
}
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,MAAM,WAAW,SAAS;IACxB,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;;2EAGuE;IACvE,QAAQ,CAAC,EAAE,SAAS,EAAE,CAAC;IACvB,2DAA2D;IAC3D,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEpD,2CAA2C;AAC3C,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,MAAM,WAAW,SAAS;IACxB,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;;2EAGuE;IACvE,QAAQ,CAAC,EAAE,SAAS,EAAE,CAAC;IACvB;;6DAEyD;IACzD,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,2DAA2D;IAC3D,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEpD,2CAA2C;AAC3C,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evanion/astro-widget",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Render CMS-driven Astro sections from structured block data. Build-time, zero runtime.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"astro",
|
|
@@ -47,15 +47,17 @@
|
|
|
47
47
|
"!src/**/*.test.*",
|
|
48
48
|
"!src/**/*.spec.*",
|
|
49
49
|
"!src/**/*.test-d.*",
|
|
50
|
+
"!src/**/__fixtures__/**",
|
|
50
51
|
"!src/test-setup.ts",
|
|
51
52
|
"README.md",
|
|
52
53
|
"LICENSE",
|
|
53
54
|
"CHANGELOG.md"
|
|
54
55
|
],
|
|
55
56
|
"publishConfig": {
|
|
56
|
-
"access": "public"
|
|
57
|
+
"access": "public",
|
|
58
|
+
"provenance": true
|
|
57
59
|
},
|
|
58
60
|
"peerDependencies": {
|
|
59
|
-
"astro": "
|
|
61
|
+
"astro": "^7.3.1"
|
|
60
62
|
}
|
|
61
63
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ambient types for `.astro` imports.
|
|
3
|
+
*
|
|
4
|
+
* Apps get these from `astro sync`, which writes `.astro/types.d.ts` into the
|
|
5
|
+
* project. A library has no Astro project to sync, so the one declaration the
|
|
6
|
+
* tests need is written by hand.
|
|
7
|
+
*/
|
|
8
|
+
declare module '*.astro' {
|
|
9
|
+
const Component: import('astro/runtime/server/index.js').AstroComponentFactory;
|
|
10
|
+
export default Component;
|
|
11
|
+
}
|
|
@@ -29,10 +29,14 @@ const Item = chrome?.item as never;
|
|
|
29
29
|
const Component = registry[item?.type] as never;
|
|
30
30
|
if (!Component) return null;
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
// `meta` is placement data for the item chrome -- grid column, span,
|
|
33
|
+
// ordering, CMS edit affordances. It is destructured out here so it never
|
|
34
|
+
// reaches the block: where a block sits is not something the block should
|
|
35
|
+
// know, and spreading it in would collide with the block's own props.
|
|
36
|
+
const { type, id, children, meta, ...props } = item;
|
|
33
37
|
|
|
34
38
|
return Item ? (
|
|
35
|
-
<Item type={type} id={id} {...props}>
|
|
39
|
+
<Item type={type} id={id} meta={meta} {...props}>
|
|
36
40
|
<Component {...props} id={id} ctx={ctx} children={children} />
|
|
37
41
|
</Item>
|
|
38
42
|
) : (
|
package/src/types.ts
CHANGED
|
@@ -9,6 +9,10 @@ export interface BlockItem {
|
|
|
9
9
|
<slot />, not through a `children` prop. A block that wants nesting
|
|
10
10
|
renders <Widgets items={children} registry={registry} /> itself. */
|
|
11
11
|
children?: BlockItem[];
|
|
12
|
+
/** Placement and presentation data for `chrome.item`. Handed to the item
|
|
13
|
+
wrapper and never spread into the block's own props, because where a
|
|
14
|
+
block sits is not something the block should know. */
|
|
15
|
+
meta?: Record<string, unknown>;
|
|
12
16
|
/** Everything else is passed to the component as props. */
|
|
13
17
|
[key: string]: unknown;
|
|
14
18
|
}
|
package/src/validate-blocks.ts
CHANGED
|
@@ -13,7 +13,7 @@ export function validateBlocks(
|
|
|
13
13
|
required: Record<string, string[]> = {}
|
|
14
14
|
): BlockProblem[] {
|
|
15
15
|
if (!Array.isArray(items)) {
|
|
16
|
-
return [{ index: -1, type: '-', message: '
|
|
16
|
+
return [{ index: -1, type: '-', message: 'blocks is not a list' }];
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
const problems: BlockProblem[] = [];
|
|
@@ -22,7 +22,7 @@ export function validateBlocks(
|
|
|
22
22
|
const type = typeof item?.type === 'string' ? item.type : '-';
|
|
23
23
|
|
|
24
24
|
if (!(type in registry)) {
|
|
25
|
-
problems.push({ index, type, message: '
|
|
25
|
+
problems.push({ index, type, message: 'unknown block type' });
|
|
26
26
|
} else {
|
|
27
27
|
for (const field of required[type] ?? []) {
|
|
28
28
|
const value = item[field];
|
|
@@ -31,7 +31,7 @@ export function validateBlocks(
|
|
|
31
31
|
value === null ||
|
|
32
32
|
(typeof value === 'string' && value.trim() === '');
|
|
33
33
|
if (blank) {
|
|
34
|
-
problems.push({ index, type, message: `
|
|
34
|
+
problems.push({ index, type, message: `missing field ${field}` });
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
}
|