@refrakt-md/runes 0.41.3 → 0.43.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/dist/collection-helpers.d.ts.map +1 -1
- package/dist/collection-helpers.js +2 -1
- package/dist/collection-helpers.js.map +1 -1
- package/dist/collection-resolve.d.ts.map +1 -1
- package/dist/collection-resolve.js +2 -1
- package/dist/collection-resolve.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +27 -1
- package/dist/config.js.map +1 -1
- package/dist/deferred-body.d.ts.map +1 -1
- package/dist/deferred-body.js +2 -1
- package/dist/deferred-body.js.map +1 -1
- package/dist/examples.d.ts.map +1 -1
- package/dist/examples.js +2 -0
- package/dist/examples.js.map +1 -1
- package/dist/expand-pipeline.d.ts.map +1 -1
- package/dist/expand-pipeline.js +2 -1
- package/dist/expand-pipeline.js.map +1 -1
- package/dist/fence-escape.d.ts +1 -1
- package/dist/fence-escape.d.ts.map +1 -1
- package/dist/fence-escape.js +7 -3
- package/dist/fence-escape.js.map +1 -1
- package/dist/format-indent.d.ts +21 -0
- package/dist/format-indent.d.ts.map +1 -0
- package/dist/format-indent.js +169 -0
- package/dist/format-indent.js.map +1 -0
- package/dist/index.d.ts +39 -72
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -8
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +3 -14
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/lib/component.d.ts +5 -1
- package/dist/lib/component.d.ts.map +1 -1
- package/dist/lib/component.js +0 -1
- package/dist/lib/component.js.map +1 -1
- package/dist/lib/composition-errors.d.ts +6 -1
- package/dist/lib/composition-errors.d.ts.map +1 -1
- package/dist/lib/composition-errors.js +6 -1
- package/dist/lib/composition-errors.js.map +1 -1
- package/dist/lib/composition.d.ts +12 -0
- package/dist/lib/composition.d.ts.map +1 -1
- package/dist/lib/composition.js +251 -15
- package/dist/lib/composition.js.map +1 -1
- package/dist/lib/header-roles.d.ts +32 -0
- package/dist/lib/header-roles.d.ts.map +1 -0
- package/dist/lib/header-roles.js +52 -0
- package/dist/lib/header-roles.js.map +1 -0
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +38 -0
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/resolver.d.ts +6 -0
- package/dist/lib/resolver.d.ts.map +1 -1
- package/dist/lib/resolver.js +29 -11
- package/dist/lib/resolver.js.map +1 -1
- package/dist/lib/slots.d.ts +5 -2
- package/dist/lib/slots.d.ts.map +1 -1
- package/dist/lib/slots.js +1 -1
- package/dist/lib/slots.js.map +1 -1
- package/dist/nodes.d.ts +11 -0
- package/dist/nodes.d.ts.map +1 -1
- package/dist/nodes.js +34 -0
- package/dist/nodes.js.map +1 -1
- package/dist/parse.d.ts +4 -0
- package/dist/parse.d.ts.map +1 -0
- package/dist/parse.js +20 -0
- package/dist/parse.js.map +1 -0
- package/dist/reference.d.ts +2 -0
- package/dist/reference.d.ts.map +1 -1
- package/dist/reference.js +10 -1
- package/dist/reference.js.map +1 -1
- package/dist/tags/accordion.d.ts +1 -0
- package/dist/tags/accordion.d.ts.map +1 -1
- package/dist/tags/accordion.js +1 -1
- package/dist/tags/accordion.js.map +1 -1
- package/dist/tags/actions.d.ts +20 -0
- package/dist/tags/actions.d.ts.map +1 -0
- package/dist/tags/actions.js +72 -0
- package/dist/tags/actions.js.map +1 -0
- package/dist/tags/blog.d.ts.map +1 -1
- package/dist/tags/blog.js +0 -1
- package/dist/tags/blog.js.map +1 -1
- package/dist/tags/budget.d.ts.map +1 -1
- package/dist/tags/budget.js +0 -1
- package/dist/tags/budget.js.map +1 -1
- package/dist/tags/card.d.ts +3 -1
- package/dist/tags/card.d.ts.map +1 -1
- package/dist/tags/card.js +7 -4
- package/dist/tags/card.js.map +1 -1
- package/dist/tags/common.d.ts +9 -0
- package/dist/tags/common.d.ts.map +1 -1
- package/dist/tags/common.js +11 -0
- package/dist/tags/common.js.map +1 -1
- package/dist/tags/hint.d.ts.map +1 -1
- package/dist/tags/hint.js +0 -1
- package/dist/tags/hint.js.map +1 -1
- package/dist/tags/reveal.d.ts +1 -0
- package/dist/tags/reveal.d.ts.map +1 -1
- package/dist/tags/reveal.js +1 -1
- package/dist/tags/reveal.js.map +1 -1
- package/dist/tags/section.d.ts +43 -2
- package/dist/tags/section.d.ts.map +1 -1
- package/dist/tags/section.js +168 -10
- package/dist/tags/section.js.map +1 -1
- package/dist/tags/tabs.d.ts +1 -0
- package/dist/tags/tabs.d.ts.map +1 -1
- package/dist/tags/tabs.js +1 -1
- package/dist/tags/tabs.js.map +1 -1
- package/package.json +4 -4
- package/dist/documents/doc.d.ts +0 -4
- package/dist/documents/doc.d.ts.map +0 -1
- package/dist/documents/doc.js +0 -4
- package/dist/documents/doc.js.map +0 -1
- package/dist/documents/page.d.ts +0 -10
- package/dist/documents/page.d.ts.map +0 -1
- package/dist/documents/page.js +0 -30
- package/dist/documents/page.js.map +0 -1
package/dist/interfaces.d.ts
CHANGED
|
@@ -4,21 +4,10 @@ import type { Config, Node, NodeType as MarkdocNodeType, Tag } from '@markdoc/ma
|
|
|
4
4
|
declare const Ast: {
|
|
5
5
|
fromJSON: (text: string) => Node | Node[];
|
|
6
6
|
isAst(value?: any): value is Markdoc.AstType;
|
|
7
|
-
isFunction(value?: any): value is import("@markdoc/markdoc/dist/src/
|
|
8
|
-
isVariable(value?: any): value is import("@markdoc/markdoc/dist/src/
|
|
7
|
+
isFunction(value?: any): value is import("@markdoc/markdoc/dist/src/types.js").Function;
|
|
8
|
+
isVariable(value?: any): value is import("@markdoc/markdoc/dist/src/types.js").Variable;
|
|
9
9
|
getAstValues(value: any): Generator<Markdoc.AstType, void, unknown>;
|
|
10
|
-
resolve(value: any, config?:
|
|
11
|
-
nodes: Partial<Record<import("@markdoc/markdoc/dist/src/types.js").NodeType, import("@markdoc/markdoc/dist/src/types.js").Schema<Readonly<Partial<any>>, string>>>;
|
|
12
|
-
tags: Record<string, import("@markdoc/markdoc/dist/src/types.js").Schema<Readonly<Partial<any>>, string>>;
|
|
13
|
-
variables: Record<string, any>;
|
|
14
|
-
functions: Record<string, import("@markdoc/markdoc/dist/src/types.js").ConfigFunction>;
|
|
15
|
-
partials: Record<string, any>;
|
|
16
|
-
validation?: {
|
|
17
|
-
parents?: Node[] | undefined;
|
|
18
|
-
validateFunctions?: boolean | undefined;
|
|
19
|
-
environment?: string | undefined;
|
|
20
|
-
} | undefined;
|
|
21
|
-
}>>): any;
|
|
10
|
+
resolve(value: any, config?: import("@markdoc/markdoc/dist/src/types.js").Config): any;
|
|
22
11
|
Function: typeof import("@markdoc/markdoc/dist/src/ast/function.js").default;
|
|
23
12
|
Node: typeof Node;
|
|
24
13
|
Variable: typeof import("@markdoc/markdoc/dist/src/ast/variable.js").default;
|
package/dist/interfaces.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,OAAO,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,IAAI,eAAe,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvF,QAAA,MAAQ,GAAG
|
|
1
|
+
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,OAAO,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,IAAI,eAAe,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvF,QAAA,MAAQ,GAAG;;;;;;;;;;CAAY,CAAC;AAExB,MAAM,WAAW,iBAAiB;IACjC,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,OAAO,CAAC;CACf;AAED,MAAM,MAAM,kBAAkB,GAAG,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC;AAEzD,MAAM,MAAM,UAAU,GAAG,eAAe,GAAG,iBAAiB,GAAG,kBAAkB,CAAC;AAElF,qBAAa,SAAS,CAAC,EAAE,SAAS,eAAe,EAAE,GAAG,SAAS,QAAQ,CAAE,SAAQ,GAAG,CAAC,IAAI;gBAC5E,IAAI,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,GAAG,CAAC,EAAE,MAAM;IAIrF,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC;CAGnC;AAED,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,QAAQ,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC"}
|
package/dist/lib/component.d.ts
CHANGED
|
@@ -7,7 +7,11 @@ export interface TransformResult {
|
|
|
7
7
|
tag: NodeType;
|
|
8
8
|
id?: string;
|
|
9
9
|
class?: string;
|
|
10
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* @deprecated Ignored since v0.43.0 and removed in the release after. It
|
|
12
|
+
* stamped `data-field` on the rune root, which nothing read (SPEC-133,
|
|
13
|
+
* WORK-650). Kept so a plugin that still passes it type-checks.
|
|
14
|
+
*/
|
|
11
15
|
property?: string;
|
|
12
16
|
/** A `null` or `undefined` slot value is skipped, so pass optional tags directly. */
|
|
13
17
|
properties?: Record<string, RenderableNodeCursor<Tag> | Tag | Tag[] | null | undefined>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../src/lib/component.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAElD,OAAO,KAAK,EAAE,GAAG,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEvD,OAAO,EAAE,WAAW,EAAE,CAAC;AAEvB,MAAM,WAAW,eAAe;IAC/B,GAAG,EAAE,QAAQ,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf
|
|
1
|
+
{"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../src/lib/component.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAElD,OAAO,KAAK,EAAE,GAAG,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEvD,OAAO,EAAE,WAAW,EAAE,CAAC;AAEvB,MAAM,WAAW,eAAe;IAC/B,GAAG,EAAE,QAAQ,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qFAAqF;IACrF,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,EAAE,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IACxF,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,EAAE,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAClF,QAAQ,EAAE,mBAAmB,CAAC;CAC9B;AAED,0FAA0F;AAC1F,MAAM,WAAW,qBAAsB,SAAQ,eAAe;IAC7D,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,qBAAqB,GAAG,GAAG,CAuE5E;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAc7C"}
|
package/dist/lib/component.js
CHANGED
|
@@ -64,7 +64,6 @@ export function createComponentRenderable(result) {
|
|
|
64
64
|
const childArray = (Array.isArray(result.children) ? result.children : [result.children]).filter((c) => !pureDataMetas.has(c));
|
|
65
65
|
const tag = new Markdoc.Tag(result.tag, {
|
|
66
66
|
id: result.id,
|
|
67
|
-
'data-field': result.property ? toKebabCase(result.property) : result.property,
|
|
68
67
|
'data-rune': runeName,
|
|
69
68
|
class: result.class,
|
|
70
69
|
...(Object.keys(fields).length > 0 ? { 'data-rune-fields': JSON.stringify(fields) } : {}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component.js","sourceRoot":"","sources":["../../src/lib/component.ts"],"names":[],"mappings":"AACA,OAAO,OAAO,MAAM,kBAAkB,CAAC;AAEvC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEvD,OAAO,EAAE,WAAW,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"component.js","sourceRoot":"","sources":["../../src/lib/component.ts"],"names":[],"mappings":"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"}
|
|
@@ -24,8 +24,12 @@ export declare const COMPOSITION_ERRORS: {
|
|
|
24
24
|
readonly 'invalid-value': "A frontmatter value has the wrong shape (`tag`, `aliases`, `schema`, …).";
|
|
25
25
|
readonly 'attribute-invalid': "An `attributes` entry is malformed.";
|
|
26
26
|
readonly 'attribute-reserved': "An enum attribute would render as a `data-*` the engine writes itself.";
|
|
27
|
-
readonly 'content-model-type': "`content.type` is not `sequence` or `
|
|
27
|
+
readonly 'content-model-type': "`content.type` is not `sequence`, `sections` or `delimited`.";
|
|
28
28
|
readonly 'content-model-invalid': "The `content` model, or one of its fields, is malformed.";
|
|
29
|
+
readonly 'delimiter-unsupported': "A delimited model’s `delimiter` is not `hr`.";
|
|
30
|
+
readonly 'dynamic-zones': "A delimited model declares `dynamicZones` (or a `zoneModel`).";
|
|
31
|
+
readonly 'zone-field-twice': "A field name is declared in two zones of a delimited model.";
|
|
32
|
+
readonly 'implicit-section-mismatch': "`implicitSection.attributes` does not give exactly the keys of `emitAttributes`.";
|
|
29
33
|
readonly 'schema-invalid': "The `schema` table is rejected by its own checks.";
|
|
30
34
|
readonly 'registers-invalid': "The `registers` declaration is rejected by its own checks.";
|
|
31
35
|
readonly 'template-parse': "Markdoc cannot parse the template.";
|
|
@@ -39,6 +43,7 @@ export declare const COMPOSITION_ERRORS: {
|
|
|
39
43
|
readonly 'slot-unknown-field': "A slot names no field of the content model.";
|
|
40
44
|
readonly 'slot-placed-twice': "The same slot is placed twice.";
|
|
41
45
|
readonly 'each-on-single-field': "`each` is used on a field that holds one value, not a list.";
|
|
46
|
+
readonly 'each-on-list-ambiguous': "`each` is used on a greedy field that can collect several lists.";
|
|
42
47
|
readonly 'each-item-unplaced': "An `each` slot never places its item with a bare `{% slot /%}`.";
|
|
43
48
|
readonly 'field-unplaced': "A content-model field is placed by no slot.";
|
|
44
49
|
readonly 'metablock-invalid': "A `{% metablock %}` is malformed: no name, content, an extra attribute, or inline.";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"composition-errors.d.ts","sourceRoot":"","sources":["../../src/lib/composition-errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,kBAAkB
|
|
1
|
+
{"version":3,"file":"composition-errors.d.ts","sourceRoot":"","sources":["../../src/lib/composition-errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgErB,CAAC;AAEX,MAAM,MAAM,oBAAoB,GAAG,MAAM,OAAO,kBAAkB,CAAC;AAEnE;;;;;;GAMG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IAC1C,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;wDACoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;gBAEN,IAAI,EAAE,oBAAoB,EAAE,OAAO,EAAE,MAAM;CAKvD"}
|
|
@@ -25,8 +25,12 @@ export const COMPOSITION_ERRORS = {
|
|
|
25
25
|
'invalid-value': 'A frontmatter value has the wrong shape (`tag`, `aliases`, `schema`, …).',
|
|
26
26
|
'attribute-invalid': 'An `attributes` entry is malformed.',
|
|
27
27
|
'attribute-reserved': 'An enum attribute would render as a `data-*` the engine writes itself.',
|
|
28
|
-
'content-model-type': '`content.type` is not `sequence` or `
|
|
28
|
+
'content-model-type': '`content.type` is not `sequence`, `sections` or `delimited`.',
|
|
29
29
|
'content-model-invalid': 'The `content` model, or one of its fields, is malformed.',
|
|
30
|
+
'delimiter-unsupported': 'A delimited model’s `delimiter` is not `hr`.',
|
|
31
|
+
'dynamic-zones': 'A delimited model declares `dynamicZones` (or a `zoneModel`).',
|
|
32
|
+
'zone-field-twice': 'A field name is declared in two zones of a delimited model.',
|
|
33
|
+
'implicit-section-mismatch': '`implicitSection.attributes` does not give exactly the keys of `emitAttributes`.',
|
|
30
34
|
'schema-invalid': 'The `schema` table is rejected by its own checks.',
|
|
31
35
|
'registers-invalid': 'The `registers` declaration is rejected by its own checks.',
|
|
32
36
|
// The template
|
|
@@ -41,6 +45,7 @@ export const COMPOSITION_ERRORS = {
|
|
|
41
45
|
'slot-unknown-field': 'A slot names no field of the content model.',
|
|
42
46
|
'slot-placed-twice': 'The same slot is placed twice.',
|
|
43
47
|
'each-on-single-field': '`each` is used on a field that holds one value, not a list.',
|
|
48
|
+
'each-on-list-ambiguous': '`each` is used on a greedy field that can collect several lists.',
|
|
44
49
|
'each-item-unplaced': 'An `each` slot never places its item with a bare `{% slot /%}`.',
|
|
45
50
|
'field-unplaced': 'A content-model field is placed by no slot.',
|
|
46
51
|
'metablock-invalid': 'A `{% metablock %}` is malformed: no name, content, an extra attribute, or inline.',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"composition-errors.js","sourceRoot":"","sources":["../../src/lib/composition-errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;IACjC,0CAA0C;IAC1C,gBAAgB,EAAE,kDAAkD;IACpE,gBAAgB,EAAE,gDAAgD;IAClE,kBAAkB,EAAE,sDAAsD;IAC1E,eAAe,EAAE,+DAA+D;IAChF,WAAW,EAAE,+DAA+D;IAC5E,kBAAkB,EAAE,4EAA4E;IAChG,YAAY,EAAE,oCAAoC;IAClD,aAAa,EAAE,uDAAuD;IACtE,eAAe,EAAE,0EAA0E;IAC3F,mBAAmB,EAAE,qCAAqC;IAC1D,oBAAoB,EAAE,wEAAwE;IAC9F,oBAAoB,EAAE,
|
|
1
|
+
{"version":3,"file":"composition-errors.js","sourceRoot":"","sources":["../../src/lib/composition-errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;IACjC,0CAA0C;IAC1C,gBAAgB,EAAE,kDAAkD;IACpE,gBAAgB,EAAE,gDAAgD;IAClE,kBAAkB,EAAE,sDAAsD;IAC1E,eAAe,EAAE,+DAA+D;IAChF,WAAW,EAAE,+DAA+D;IAC5E,kBAAkB,EAAE,4EAA4E;IAChG,YAAY,EAAE,oCAAoC;IAClD,aAAa,EAAE,uDAAuD;IACtE,eAAe,EAAE,0EAA0E;IAC3F,mBAAmB,EAAE,qCAAqC;IAC1D,oBAAoB,EAAE,wEAAwE;IAC9F,oBAAoB,EAAE,8DAA8D;IACpF,uBAAuB,EAAE,0DAA0D;IACnF,uBAAuB,EAAE,8CAA8C;IACvE,eAAe,EAAE,+DAA+D;IAChF,kBAAkB,EAAE,6DAA6D;IACjF,2BAA2B,EAC1B,kFAAkF;IACnF,gBAAgB,EAAE,mDAAmD;IACrE,mBAAmB,EAAE,4DAA4D;IAEjF,eAAe;IACf,gBAAgB,EAAE,oCAAoC;IACtD,kBAAkB,EAAE,qEAAqE;IACzF,kBAAkB,EAAE,yCAAyC;IAC7D,mBAAmB,EAAE,yCAAyC;IAC9D,wBAAwB,EAAE,0DAA0D;IACpF,cAAc,EAAE,+EAA+E;IAC/F,qBAAqB,EACpB,4EAA4E;IAC7E,kBAAkB,EAAE,+CAA+C;IACnE,oBAAoB,EAAE,6CAA6C;IACnE,mBAAmB,EAAE,gCAAgC;IACrD,sBAAsB,EAAE,6DAA6D;IACrF,wBAAwB,EAAE,kEAAkE;IAC5F,oBAAoB,EAAE,iEAAiE;IACvF,gBAAgB,EAAE,6CAA6C;IAC/D,mBAAmB,EAClB,oFAAoF;IACrF,uBAAuB,EAAE,sDAAsD;IAC/E,sBAAsB,EAAE,8CAA8C;IACtE,wBAAwB,EAAE,sCAAsC;IAEhE,gDAAgD;IAChD,mBAAmB,EAAE,6DAA6D;IAClF,iBAAiB,EAAE,oEAAoE;IACvF,kBAAkB,EAAE,qEAAqE;IAEzF,oCAAoC;IACpC,mBAAmB,EAAE,4DAA4D;IACjF,iBAAiB,EAAE,iDAAiD;IACpE,kBAAkB,EAAE,wDAAwD;IAC5E,qBAAqB,EAAE,oDAAoD;IAC3E,gBAAgB,EAAE,0DAA0D;IAC5E,sBAAsB,EAAE,mDAAmD;IAC3E,oBAAoB,EAAE,iEAAiE;IACvF,gBAAgB,EAAE,yCAAyC;IAC3D,mBAAmB,EAAE,mDAAmD;IACxE,qBAAqB,EAAE,yEAAyE;IAChG,kBAAkB,EAAE,oDAAoD;IACxE,wBAAwB,EACvB,iHAAiH;CACzG,CAAC;AAIX;;;;;;GAMG;AACH,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAO1C,YAAY,IAA0B,EAAE,OAAe;QACtD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IAClB,CAAC;CACD"}
|
|
@@ -76,10 +76,22 @@ export declare function frontmatterKeyLine(frontmatter: string, path: readonly s
|
|
|
76
76
|
/** Schema types a placed rune may emit under a composed type: a media object
|
|
77
77
|
* that becomes a property of the outer entity, not a peer of it (D9). */
|
|
78
78
|
export declare const SUBORDINATE_SCHEMA_TYPES: ReadonlySet<string>;
|
|
79
|
+
/**
|
|
80
|
+
* `{% slot name="x" each %}` is the spec's spelling, and Markdoc's tag grammar
|
|
81
|
+
* has no bare boolean attribute. Rewrite it to `each=true` inside slot tags
|
|
82
|
+
* only, outside quoted values, before parsing.
|
|
83
|
+
*/
|
|
84
|
+
export declare function normaliseEach(body: string): string;
|
|
79
85
|
export interface CompiledComposition {
|
|
80
86
|
/** The transform `createContentModelSchema` calls where it would call `transform`. */
|
|
81
87
|
transform: (resolved: ResolvedContent, attrs: Record<string, any>, config: Config, node: Node) => RenderableTreeNodes;
|
|
82
88
|
info: CompositionInfo;
|
|
89
|
+
/**
|
|
90
|
+
* The template expanded for one instance: what `transform` hands Markdoc,
|
|
91
|
+
* before it is transformed. Validation reads it to see which slot each
|
|
92
|
+
* placed node came from (ADR-046 decision 3).
|
|
93
|
+
*/
|
|
94
|
+
place: (resolved: ResolvedContent, attrs: Record<string, any>) => Node[];
|
|
83
95
|
}
|
|
84
96
|
export interface CompileCompositionOptions {
|
|
85
97
|
contentModel: ContentModel | ((attrs: Record<string, any>) => ContentModel);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"composition.d.ts","sourceRoot":"","sources":["../../src/lib/composition.ts"],"names":[],"mappings":"AA4DA,OAAO,KAAK,EACX,MAAM,EACN,IAAI,EAEJ,mBAAmB,EACnB,MAAM,EACN,eAAe,EAEf,MAAM,kBAAkB,CAAC;AAI1B,OAAO,KAAK,EAEX,YAAY,
|
|
1
|
+
{"version":3,"file":"composition.d.ts","sourceRoot":"","sources":["../../src/lib/composition.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/composition.js
CHANGED
|
@@ -62,11 +62,12 @@ import yaml from 'yaml';
|
|
|
62
62
|
import { CompositionError } from './composition-errors.js';
|
|
63
63
|
import { METABLOCK_ATTR, METABLOCK_OWNER_ATTR } from '@refrakt-md/transform';
|
|
64
64
|
import { createComponentRenderable } from './component.js';
|
|
65
|
-
import { resolveEmitReference, sectionLookup } from './resolver.js';
|
|
65
|
+
import { IMPLICIT_SECTION_KEY, resolveEmitReference, sectionLookup } from './resolver.js';
|
|
66
66
|
import { OWNER_ATTR, SLOT_ATTR, findAllByName } from './schema-table.js';
|
|
67
67
|
import { SchemaSideTable } from './schema-side-table.js';
|
|
68
68
|
import { declareSlotMarkers, declareSlotMarkersOnNodes } from './slot-markers.js';
|
|
69
69
|
import { registersSources } from './registers.js';
|
|
70
|
+
import { parse } from '../parse.js';
|
|
70
71
|
const { Ast, Tag: MarkdocTag } = Markdoc;
|
|
71
72
|
/** Compositions by schema — the same pattern as `schemaTables`: tooling has only
|
|
72
73
|
* the schema to read from. */
|
|
@@ -142,28 +143,83 @@ export const SUBORDINATE_SCHEMA_TYPES = new Set([
|
|
|
142
143
|
'AudioObject',
|
|
143
144
|
'MediaObject',
|
|
144
145
|
]);
|
|
146
|
+
/** `match` alternatives that are a Markdown list. */
|
|
147
|
+
const LIST_MATCHES = new Set(['list', 'list:ordered', 'list:unordered']);
|
|
148
|
+
/**
|
|
149
|
+
* SPEC-169 D1 — what a composition accepts of a delimited model: `hr` as the
|
|
150
|
+
* delimiter, fixed zones, and each field name in one zone only, because the
|
|
151
|
+
* slots are the union of the zones' fields. Shared by the definition parser
|
|
152
|
+
* (which can locate the key) and the template compiler (which also sees a
|
|
153
|
+
* model handed to it in code).
|
|
154
|
+
*/
|
|
155
|
+
function checkDelimitedModel(m, fail) {
|
|
156
|
+
if (m.dynamicZones) {
|
|
157
|
+
fail('dynamic-zones', 'a delimited model with `dynamicZones` is not supported by a composition: its zones have no fixed names, so a template has nothing to place. Declare fixed `zones` (SPEC-169 D1).', ['dynamicZones']);
|
|
158
|
+
}
|
|
159
|
+
if (m.delimiter !== 'hr') {
|
|
160
|
+
fail('delimiter-unsupported', `a delimited model splits on \`hr\` (\`---\`) only, not \`${String(m.delimiter)}\` (SPEC-169 D1).`, ['delimiter']);
|
|
161
|
+
}
|
|
162
|
+
if (!Array.isArray(m.zones) || m.zones.length === 0) {
|
|
163
|
+
fail('content-model-invalid', 'a delimited model needs a non-empty list of `zones`.', [
|
|
164
|
+
'zones',
|
|
165
|
+
]);
|
|
166
|
+
}
|
|
167
|
+
const owner = new Map();
|
|
168
|
+
for (const zone of m.zones) {
|
|
169
|
+
for (const f of zone.fields ?? []) {
|
|
170
|
+
const first = owner.get(f.name);
|
|
171
|
+
if (first !== undefined) {
|
|
172
|
+
fail('zone-field-twice', `field \`${f.name}\` is declared in zone \`${first}\` and in zone \`${zone.name}\`. A composition's slots are the union of the zones' fields, so a name belongs to one zone (SPEC-169 D1).`, ['zones', f.name]);
|
|
173
|
+
}
|
|
174
|
+
owner.set(f.name, zone.name);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/** SPEC-169 D3 — an implicit section binds `$each` exactly as a real one does. */
|
|
179
|
+
function checkImplicitSection(m, fail) {
|
|
180
|
+
if (!m.implicitSection)
|
|
181
|
+
return;
|
|
182
|
+
const given = Object.keys(m.implicitSection.attributes ?? {}).sort();
|
|
183
|
+
const emitted = Object.keys(m.emitAttributes ?? {}).sort();
|
|
184
|
+
if (given.join('\0') !== emitted.join('\0')) {
|
|
185
|
+
const missing = emitted.filter((k) => !given.includes(k));
|
|
186
|
+
const extra = given.filter((k) => !emitted.includes(k));
|
|
187
|
+
fail('implicit-section-mismatch', `\`implicitSection.attributes\` must give exactly the keys of \`emitAttributes\` (${emitted.join(', ') || 'none'}), so \`$each\` is bound the same way for a real and an implicit section${missing.length ? `; missing ${missing.map((k) => `\`${k}\``).join(', ')}` : ''}${extra.length ? `; not emitted ${extra.map((k) => `\`${k}\``).join(', ')}` : ''} (SPEC-169 D3).`, ['implicitSection']);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
145
190
|
/**
|
|
146
191
|
* Every field the content model resolves, by name. A composition reads
|
|
147
|
-
* `sequence` and `
|
|
148
|
-
* than half-supported.
|
|
192
|
+
* `sequence`, `sections` and fixed-zone `delimited` models; the others are
|
|
193
|
+
* rejected by name rather than half-supported.
|
|
149
194
|
*/
|
|
150
195
|
function slotFields(model, fail) {
|
|
151
196
|
const fields = new Map();
|
|
152
197
|
const m = typeof model === 'function' ? model({}) : model;
|
|
153
198
|
if ('when' in m) {
|
|
154
|
-
fail('content-model-type', 'a conditional (`when`) content model is not supported by a composition — the template, not the model, is where an assembly varies.');
|
|
199
|
+
fail('content-model-type', 'a conditional (`when`) content model is not supported by a composition — the template, not the model, is where an assembly varies. Each case has a declarative form: `implicitSection` on a sections model, `each` over a list field, or a template that places every alternative, with an empty one rendering nothing (SPEC-169 D2).');
|
|
155
200
|
}
|
|
156
201
|
const s = m;
|
|
157
202
|
const addField = (f) => {
|
|
158
203
|
const emitted = f.emitTag !== undefined && f.itemModel !== undefined;
|
|
159
204
|
const refs = emitted ? (f.emitAttributes ?? {}) : {};
|
|
160
|
-
|
|
205
|
+
const alternatives = f.match.split('|');
|
|
206
|
+
const listOnly = alternatives.every((a) => LIST_MATCHES.has(a));
|
|
207
|
+
const listItems = !emitted && !f.greedy && listOnly;
|
|
208
|
+
const ambiguousList = !emitted && !!f.greedy && alternatives.some((a) => LIST_MATCHES.has(a));
|
|
209
|
+
fields.set(f.name, {
|
|
210
|
+
list: !!f.greedy || emitted || listItems,
|
|
211
|
+
each: Object.keys(refs),
|
|
212
|
+
refs,
|
|
213
|
+
...(listItems ? { listItems } : {}),
|
|
214
|
+
...(ambiguousList ? { ambiguousList } : {}),
|
|
215
|
+
});
|
|
161
216
|
};
|
|
162
217
|
if (s.type === 'sequence') {
|
|
163
218
|
for (const f of s.fields ?? [])
|
|
164
219
|
addField(f);
|
|
165
220
|
}
|
|
166
221
|
else if (s.type === 'sections') {
|
|
222
|
+
checkImplicitSection(s, fail);
|
|
167
223
|
for (const f of s.fields ?? [])
|
|
168
224
|
addField(f);
|
|
169
225
|
const refs = s.emitAttributes ?? {};
|
|
@@ -174,11 +230,31 @@ function slotFields(model, fail) {
|
|
|
174
230
|
sections: s.emitTag === undefined,
|
|
175
231
|
});
|
|
176
232
|
}
|
|
233
|
+
else if (s.type === 'delimited') {
|
|
234
|
+
checkDelimitedModel(s, fail);
|
|
235
|
+
for (const zone of s.zones ?? [])
|
|
236
|
+
for (const f of zone.fields ?? [])
|
|
237
|
+
addField(f);
|
|
238
|
+
}
|
|
177
239
|
else {
|
|
178
|
-
fail('content-model-type', `a \`${s.type}\` content model is not supported by a composition. Declare a \`sequence\` or \`
|
|
240
|
+
fail('content-model-type', `a \`${s.type}\` content model is not supported by a composition. Declare a \`sequence\`, \`sections\` or \`delimited\` model, whose fields are the slots.`);
|
|
179
241
|
}
|
|
180
242
|
return fields;
|
|
181
243
|
}
|
|
244
|
+
/**
|
|
245
|
+
* The resolved fields a template's slots read. A delimited model resolves each
|
|
246
|
+
* zone to its own record; its slots are the zones' fields, so the zones are
|
|
247
|
+
* merged — `checkDelimitedModel` has made their names disjoint.
|
|
248
|
+
*/
|
|
249
|
+
function slotValues(model, resolved) {
|
|
250
|
+
if (model.type !== 'delimited')
|
|
251
|
+
return resolved;
|
|
252
|
+
const out = {};
|
|
253
|
+
for (const zone of model.zones ?? []) {
|
|
254
|
+
Object.assign(out, resolved[zone.name] ?? {});
|
|
255
|
+
}
|
|
256
|
+
return out;
|
|
257
|
+
}
|
|
182
258
|
// ---------------------------------------------------------------------------
|
|
183
259
|
// Template parsing and the construction-time checks
|
|
184
260
|
// ---------------------------------------------------------------------------
|
|
@@ -187,7 +263,7 @@ function slotFields(model, fail) {
|
|
|
187
263
|
* has no bare boolean attribute. Rewrite it to `each=true` inside slot tags
|
|
188
264
|
* only, outside quoted values, before parsing.
|
|
189
265
|
*/
|
|
190
|
-
function normaliseEach(body) {
|
|
266
|
+
export function normaliseEach(body) {
|
|
191
267
|
return body.replace(/\{%-?\s*slot\b([^%]*?)(-?%\})/g, (whole, inner, close) => {
|
|
192
268
|
let out = '';
|
|
193
269
|
let quote = null;
|
|
@@ -286,8 +362,9 @@ export function compileComposition(template, options) {
|
|
|
286
362
|
if (typeof tag !== 'string' || !/^[a-z][a-z0-9]*$/.test(tag)) {
|
|
287
363
|
fail('invalid-value', '`tag` must be an element name.');
|
|
288
364
|
}
|
|
289
|
-
const ast =
|
|
365
|
+
const ast = parse(normaliseEach(body));
|
|
290
366
|
const fields = slotFields(options.contentModel, fail);
|
|
367
|
+
const structural = (typeof options.contentModel === 'function' ? options.contentModel({}) : options.contentModel);
|
|
291
368
|
const declared = new Set(options.attributes);
|
|
292
369
|
const selfNames = new Set([rune, ...(template.aliases ?? [])]);
|
|
293
370
|
const placedSlots = new Map();
|
|
@@ -405,6 +482,9 @@ export function compileComposition(template, options) {
|
|
|
405
482
|
placedSlots.set(name, n);
|
|
406
483
|
slotOrder.push(name);
|
|
407
484
|
if (each) {
|
|
485
|
+
if (field.ambiguousList) {
|
|
486
|
+
fail('each-on-list-ambiguous', `slot \`${name}\` iterates with \`each\`, but field \`${name}\` is greedy and can collect several lists, so it is unclear whose items are meant. Make it a non-greedy field matching one list, whose items \`each\` then iterates (SPEC-169 D4).`);
|
|
487
|
+
}
|
|
408
488
|
if (!field.list) {
|
|
409
489
|
fail('each-on-single-field', `slot \`${name}\` iterates with \`each\`, but field \`${name}\` holds a single value, not a list (D26).`);
|
|
410
490
|
}
|
|
@@ -476,11 +556,16 @@ export function compileComposition(template, options) {
|
|
|
476
556
|
...(schemaType ? { schemaType } : {}),
|
|
477
557
|
};
|
|
478
558
|
const attributeNames = [...declared];
|
|
479
|
-
const
|
|
559
|
+
const place = (resolved, attrs) => {
|
|
480
560
|
const bound = {};
|
|
481
561
|
for (const name of attributeNames)
|
|
482
562
|
bound[name] = attrs[name];
|
|
483
|
-
const ctx = {
|
|
563
|
+
const ctx = {
|
|
564
|
+
rune,
|
|
565
|
+
resolved: slotValues(structural, resolved),
|
|
566
|
+
attrs: bound,
|
|
567
|
+
fields,
|
|
568
|
+
};
|
|
484
569
|
const placed = expand(ast.children, ctx);
|
|
485
570
|
// Top-level template nodes are the composed rune's own (D10). A slot
|
|
486
571
|
// placed at the top level already carries both markers.
|
|
@@ -488,6 +573,10 @@ export function compileComposition(template, options) {
|
|
|
488
573
|
if (n.attributes[OWNER_ATTR] === undefined)
|
|
489
574
|
n.attributes[OWNER_ATTR] = rune;
|
|
490
575
|
}
|
|
576
|
+
return placed;
|
|
577
|
+
};
|
|
578
|
+
const transform = (resolved, attrs, config) => {
|
|
579
|
+
const placed = place(resolved, attrs);
|
|
491
580
|
const children = Markdoc.transform(placed, templateConfig(config));
|
|
492
581
|
// The field bag holds every attribute the author set (or that defaulted):
|
|
493
582
|
// it is what `modifiers`, the schema row's attribute sources and
|
|
@@ -508,7 +597,7 @@ export function compileComposition(template, options) {
|
|
|
508
597
|
copyRegisteredNodes(root, nodeSources);
|
|
509
598
|
return root;
|
|
510
599
|
};
|
|
511
|
-
return { transform, info };
|
|
600
|
+
return { transform, info, place };
|
|
512
601
|
}
|
|
513
602
|
function asNodes(value) {
|
|
514
603
|
if (Array.isArray(value))
|
|
@@ -582,6 +671,18 @@ function substituteNode(node, ctx) {
|
|
|
582
671
|
}
|
|
583
672
|
/** The items a list field resolved to, each with its `$each` binding and content. */
|
|
584
673
|
function itemsOf(field, value) {
|
|
674
|
+
if (field.listItems) {
|
|
675
|
+
// SPEC-169 D4 — one Markdown list: each item is placed as it is, with no
|
|
676
|
+
// extraction, so `$each` binds nothing. A tight item's text is an `inline`
|
|
677
|
+
// node; it is given the paragraph a loose item would have had.
|
|
678
|
+
return asNodes(value)
|
|
679
|
+
.flatMap((list) => (list.type === 'list' ? list.children : []))
|
|
680
|
+
.filter((item) => item.type === 'item')
|
|
681
|
+
.map((item) => ({
|
|
682
|
+
each: {},
|
|
683
|
+
content: item.children.map((c) => c.type === 'inline' ? new Ast.Node('paragraph', {}, [c]) : c),
|
|
684
|
+
}));
|
|
685
|
+
}
|
|
585
686
|
return asNodes(value).map((item) => {
|
|
586
687
|
if (field.sections) {
|
|
587
688
|
// A section entry: heading info under `$` keys, then the body's fields.
|
|
@@ -594,9 +695,12 @@ function itemsOf(field, value) {
|
|
|
594
695
|
extracted[k.slice(1)] = v;
|
|
595
696
|
}
|
|
596
697
|
const lookup = sectionLookup(String(entry.$heading ?? ''), extracted);
|
|
698
|
+
// An implicit section (SPEC-169 D3) has no heading to read: its
|
|
699
|
+
// declared attributes are the values, under the same keys.
|
|
700
|
+
const implicit = entry[IMPLICIT_SECTION_KEY];
|
|
597
701
|
const each = {};
|
|
598
702
|
for (const [key, ref] of Object.entries(field.refs)) {
|
|
599
|
-
each[key] = resolveEmitReference(ref, lookup);
|
|
703
|
+
each[key] = implicit ? implicit[key] : resolveEmitReference(ref, lookup);
|
|
600
704
|
}
|
|
601
705
|
const content = Object.entries(entry)
|
|
602
706
|
.filter(([k]) => !k.startsWith('$'))
|
|
@@ -965,9 +1069,69 @@ function parseFields(raw, where, fail) {
|
|
|
965
1069
|
}
|
|
966
1070
|
if (typeof def.match !== 'string')
|
|
967
1071
|
at('content-model-invalid', `\`${where}.${name}\` needs a \`match\`.`);
|
|
1072
|
+
if (def.itemModel !== undefined) {
|
|
1073
|
+
def.itemModel = parseItemModel(def.itemModel, `${where}.${name}.itemModel`, (code, msg) => fail(code, msg, [section, name, 'itemModel']));
|
|
1074
|
+
}
|
|
968
1075
|
return { name, ...def };
|
|
969
1076
|
});
|
|
970
1077
|
}
|
|
1078
|
+
const ITEM_FIELD_KEYS = new Set([
|
|
1079
|
+
'name',
|
|
1080
|
+
'match',
|
|
1081
|
+
'optional',
|
|
1082
|
+
'greedy',
|
|
1083
|
+
'extract',
|
|
1084
|
+
'pattern',
|
|
1085
|
+
'itemModel',
|
|
1086
|
+
]);
|
|
1087
|
+
/**
|
|
1088
|
+
* An `itemModel` as YAML writes it. YAML has no regular expressions, so every
|
|
1089
|
+
* `pattern` other than `remainder` arrives as a string and is compiled here, at
|
|
1090
|
+
* every nesting level — the resolver applies a pattern only when it is a
|
|
1091
|
+
* `RegExp`, so a string one would match nothing, silently (BUG-038).
|
|
1092
|
+
*/
|
|
1093
|
+
function parseItemModel(raw, where, fail) {
|
|
1094
|
+
const fields = raw?.fields;
|
|
1095
|
+
if (!raw || typeof raw !== 'object' || Array.isArray(raw) || !Array.isArray(fields)) {
|
|
1096
|
+
fail('content-model-invalid', `\`${where}\` must be a mapping with a \`fields\` list.`);
|
|
1097
|
+
}
|
|
1098
|
+
return {
|
|
1099
|
+
fields: fields.map((f) => {
|
|
1100
|
+
const entry = f;
|
|
1101
|
+
if (!entry || typeof entry !== 'object' || typeof entry.name !== 'string') {
|
|
1102
|
+
fail('content-model-invalid', `a \`${where}\` field needs a \`name\`.`);
|
|
1103
|
+
}
|
|
1104
|
+
const field = entry;
|
|
1105
|
+
const label = `\`${where}\` field \`${field.name}\``;
|
|
1106
|
+
for (const key of Object.keys(field)) {
|
|
1107
|
+
if (!ITEM_FIELD_KEYS.has(key)) {
|
|
1108
|
+
fail('content-model-invalid', `${label}: unknown key \`${key}\` (expected ${[...ITEM_FIELD_KEYS].join(', ')}).`);
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
if (typeof field.match !== 'string') {
|
|
1112
|
+
fail('content-model-invalid', `${label} needs a \`match\`.`);
|
|
1113
|
+
}
|
|
1114
|
+
const out = { ...field };
|
|
1115
|
+
if (field.pattern !== undefined) {
|
|
1116
|
+
if (typeof field.pattern !== 'string') {
|
|
1117
|
+
fail('content-model-invalid', `${label}: \`pattern\` must be a string.`);
|
|
1118
|
+
}
|
|
1119
|
+
if (field.pattern !== 'remainder') {
|
|
1120
|
+
try {
|
|
1121
|
+
out.pattern = new RegExp(field.pattern);
|
|
1122
|
+
}
|
|
1123
|
+
catch (e) {
|
|
1124
|
+
fail('content-model-invalid', `${label}: \`pattern\` is not a regular expression: ${e.message}`);
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
if (field.itemModel !== undefined) {
|
|
1129
|
+
out.itemModel = parseItemModel(field.itemModel, `${where}.${field.name}.itemModel`, fail);
|
|
1130
|
+
}
|
|
1131
|
+
return out;
|
|
1132
|
+
}),
|
|
1133
|
+
};
|
|
1134
|
+
}
|
|
971
1135
|
function parseHeadingExtract(raw, sectionFail) {
|
|
972
1136
|
const fail = (code, msg) => sectionFail(code, msg, ['headingExtract']);
|
|
973
1137
|
const fields = raw?.fields;
|
|
@@ -1007,16 +1171,27 @@ const SECTIONS_KEYS = new Set([
|
|
|
1007
1171
|
'emitAttributes',
|
|
1008
1172
|
'headingExtract',
|
|
1009
1173
|
'knownSections',
|
|
1174
|
+
'implicitSection',
|
|
1010
1175
|
]);
|
|
1176
|
+
/** `dynamicZones` and `zoneModel` are accepted as keys so that their rejection
|
|
1177
|
+
* can say why, rather than reporting an unknown key. */
|
|
1178
|
+
const DELIMITED_KEYS = new Set(['type', 'delimiter', 'zones', 'dynamicZones', 'zoneModel']);
|
|
1179
|
+
const ZONE_KEYS = new Set(['name', 'primary', 'fields']);
|
|
1011
1180
|
function parseContentModel(raw, fail) {
|
|
1012
1181
|
if (raw === undefined)
|
|
1013
1182
|
return { type: 'sequence', fields: [] };
|
|
1014
1183
|
if (!raw || typeof raw !== 'object' || Array.isArray(raw))
|
|
1015
1184
|
fail('content-model-invalid', '`content` must be a mapping.');
|
|
1016
1185
|
const c = raw;
|
|
1017
|
-
const allowed = c.type === 'sequence'
|
|
1186
|
+
const allowed = c.type === 'sequence'
|
|
1187
|
+
? SEQUENCE_KEYS
|
|
1188
|
+
: c.type === 'sections'
|
|
1189
|
+
? SECTIONS_KEYS
|
|
1190
|
+
: c.type === 'delimited'
|
|
1191
|
+
? DELIMITED_KEYS
|
|
1192
|
+
: null;
|
|
1018
1193
|
if (!allowed) {
|
|
1019
|
-
fail('content-model-type', `\`content.type\` must be \`sequence\` or \`
|
|
1194
|
+
fail('content-model-type', `\`content.type\` must be \`sequence\`, \`sections\` or \`delimited\`${c.type ? `, not \`${String(c.type)}\`` : ''}: a composition's slots are the model's fields.`);
|
|
1020
1195
|
}
|
|
1021
1196
|
for (const key of Object.keys(c)) {
|
|
1022
1197
|
if (!allowed.has(key)) {
|
|
@@ -1029,6 +1204,8 @@ function parseContentModel(raw, fail) {
|
|
|
1029
1204
|
fields: parseFields(c.fields, 'content.fields', fail),
|
|
1030
1205
|
};
|
|
1031
1206
|
}
|
|
1207
|
+
if (c.type === 'delimited')
|
|
1208
|
+
return parseDelimitedModel(c, fail);
|
|
1032
1209
|
if (c.fields !== undefined && c.preamble !== undefined) {
|
|
1033
1210
|
fail('content-model-invalid', '`content` declares both `fields` and `preamble`; they are one thing — use `preamble`.');
|
|
1034
1211
|
}
|
|
@@ -1047,7 +1224,23 @@ function parseContentModel(raw, fail) {
|
|
|
1047
1224
|
fail('content-model-invalid', '`content.emitAttributes` must map names to `$heading`, `$<field>` or a literal.', ['emitAttributes']);
|
|
1048
1225
|
}
|
|
1049
1226
|
}
|
|
1050
|
-
|
|
1227
|
+
let implicit;
|
|
1228
|
+
if (c.implicitSection !== undefined) {
|
|
1229
|
+
const is = c.implicitSection;
|
|
1230
|
+
const attrs = is?.attributes ?? {};
|
|
1231
|
+
if (!is ||
|
|
1232
|
+
typeof is !== 'object' ||
|
|
1233
|
+
Array.isArray(is) ||
|
|
1234
|
+
Object.keys(is).some((k) => k !== 'attributes') ||
|
|
1235
|
+
!attrs ||
|
|
1236
|
+
typeof attrs !== 'object' ||
|
|
1237
|
+
Array.isArray(attrs) ||
|
|
1238
|
+
!Object.values(attrs).every((v) => typeof v === 'string')) {
|
|
1239
|
+
fail('content-model-invalid', '`content.implicitSection` must be `{ attributes: { <name>: <literal>, … } }`.', ['implicitSection']);
|
|
1240
|
+
}
|
|
1241
|
+
implicit = { attributes: attrs };
|
|
1242
|
+
}
|
|
1243
|
+
const model = {
|
|
1051
1244
|
type: 'sections',
|
|
1052
1245
|
sectionHeading: typeof c.sectionHeading === 'string' ? c.sectionHeading : 'heading',
|
|
1053
1246
|
fields: parseFields(c.preamble ?? c.fields, c.preamble ? 'content.preamble' : 'content.fields', fail),
|
|
@@ -1058,7 +1251,50 @@ function parseContentModel(raw, fail) {
|
|
|
1058
1251
|
...(c.knownSections
|
|
1059
1252
|
? { knownSections: c.knownSections }
|
|
1060
1253
|
: {}),
|
|
1254
|
+
...(implicit ? { implicitSection: implicit } : {}),
|
|
1255
|
+
};
|
|
1256
|
+
checkImplicitSection(model, fail);
|
|
1257
|
+
return model;
|
|
1258
|
+
}
|
|
1259
|
+
/** A `delimited` model (SPEC-169 D1): `hr`, fixed zones, one zone per name. */
|
|
1260
|
+
function parseDelimitedModel(c, fail) {
|
|
1261
|
+
if (c.zoneModel !== undefined && !c.dynamicZones) {
|
|
1262
|
+
fail('dynamic-zones', '`content.zoneModel` describes dynamic zones, which a composition does not support: their zones have no fixed names, so a template has nothing to place. Declare fixed `zones` (SPEC-169 D1).', ['zoneModel']);
|
|
1263
|
+
}
|
|
1264
|
+
const delimiter = c.delimiter ?? 'hr';
|
|
1265
|
+
if (!Array.isArray(c.zones) && !c.dynamicZones) {
|
|
1266
|
+
fail('content-model-invalid', '`content.zones` must be a list of zones.', ['zones']);
|
|
1267
|
+
}
|
|
1268
|
+
const zones = (c.zones ?? []).map((z) => {
|
|
1269
|
+
const zone = z;
|
|
1270
|
+
if (!zone || typeof zone !== 'object' || typeof zone.name !== 'string' || zone.name === '') {
|
|
1271
|
+
fail('content-model-invalid', 'each of `content.zones` needs a `name`.', ['zones']);
|
|
1272
|
+
}
|
|
1273
|
+
const name = zone.name;
|
|
1274
|
+
for (const key of Object.keys(zone)) {
|
|
1275
|
+
if (!ZONE_KEYS.has(key)) {
|
|
1276
|
+
fail('content-model-invalid', `zone \`${name}\`: unknown key \`${key}\` (expected ${[...ZONE_KEYS].join(', ')}).`, ['zones', name]);
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
return {
|
|
1280
|
+
name,
|
|
1281
|
+
type: 'sequence',
|
|
1282
|
+
fields: parseFields(zone.fields, `content.zones.${name}.fields`, (code, msg, at) => fail(code, msg, ['zones', name, ...(at ?? [])])),
|
|
1283
|
+
...(zone.primary === true ? { primary: true } : {}),
|
|
1284
|
+
};
|
|
1285
|
+
});
|
|
1286
|
+
const primaries = zones.filter((z) => z.primary);
|
|
1287
|
+
if (primaries.length > 1) {
|
|
1288
|
+
fail('content-model-invalid', `zones ${primaries.map((z) => `\`${z.name}\``).join(', ')} are all \`primary\`; at most one zone receives content written with no \`---\`.`, ['zones']);
|
|
1289
|
+
}
|
|
1290
|
+
const model = {
|
|
1291
|
+
type: 'delimited',
|
|
1292
|
+
delimiter: delimiter,
|
|
1293
|
+
zones,
|
|
1294
|
+
...(c.dynamicZones ? { dynamicZones: true } : {}),
|
|
1061
1295
|
};
|
|
1296
|
+
checkDelimitedModel(model, fail);
|
|
1297
|
+
return model;
|
|
1062
1298
|
}
|
|
1063
1299
|
/**
|
|
1064
1300
|
* The generated, block-less engine config of a composed rune (D2a). Not
|