@elastic/isomer-sdk 0.1.0 → 0.3.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/NOTICE.txt +0 -286
- package/README.md +13 -2
- package/THIRD_PARTY_LICENSES.md +1 -885
- package/dist/author/authored_fields.d.ts +93 -18
- package/dist/author/authored_fields.d.ts.map +1 -1
- package/dist/author/authored_fields.js +63 -43
- package/dist/author/authored_fields.js.map +1 -1
- package/dist/author/authoring_input.d.ts +7 -0
- package/dist/author/authoring_input.d.ts.map +1 -0
- package/dist/author/authoring_input.js +66 -0
- package/dist/author/authoring_input.js.map +1 -0
- package/dist/author/authoring_model.d.ts +33 -0
- package/dist/author/authoring_model.d.ts.map +1 -0
- package/dist/author/authoring_model.js +142 -0
- package/dist/author/authoring_model.js.map +1 -0
- package/dist/author/declarations.d.ts +13 -0
- package/dist/author/declarations.d.ts.map +1 -0
- package/dist/author/declarations.js +288 -0
- package/dist/author/declarations.js.map +1 -0
- package/dist/author/index.d.ts +4 -1
- package/dist/author/index.d.ts.map +1 -1
- package/dist/author/index.js +4 -1
- package/dist/author/index.js.map +1 -1
- package/dist/author/jsx_shim.d.ts +50 -30
- package/dist/author/jsx_shim.d.ts.map +1 -1
- package/dist/author/jsx_shim.js +146 -138
- package/dist/author/jsx_shim.js.map +1 -1
- package/dist/author/print_jsx.d.ts +19 -0
- package/dist/author/print_jsx.d.ts.map +1 -0
- package/dist/author/print_jsx.js +372 -0
- package/dist/author/print_jsx.js.map +1 -0
- package/dist/author/prompt.d.ts +2 -2
- package/dist/author/prompt.d.ts.map +1 -1
- package/dist/author/prompt.js +7 -2
- package/dist/author/prompt.js.map +1 -1
- package/dist/author/schema_to_typescript.d.ts +37 -0
- package/dist/author/schema_to_typescript.d.ts.map +1 -0
- package/dist/author/schema_to_typescript.js +289 -0
- package/dist/author/schema_to_typescript.js.map +1 -0
- package/dist/cjs/author/authored_fields.js +68 -47
- package/dist/cjs/author/authored_fields.js.map +1 -1
- package/dist/cjs/author/authoring_input.js +70 -0
- package/dist/cjs/author/authoring_input.js.map +1 -0
- package/dist/cjs/author/authoring_model.js +149 -0
- package/dist/cjs/author/authoring_model.js.map +1 -0
- package/dist/cjs/author/declarations.js +292 -0
- package/dist/cjs/author/declarations.js.map +1 -0
- package/dist/cjs/author/index.js +10 -1
- package/dist/cjs/author/index.js.map +1 -1
- package/dist/cjs/author/jsx_shim.js +148 -140
- package/dist/cjs/author/jsx_shim.js.map +1 -1
- package/dist/cjs/author/print_jsx.js +378 -0
- package/dist/cjs/author/print_jsx.js.map +1 -0
- package/dist/cjs/author/prompt.js +7 -2
- package/dist/cjs/author/prompt.js.map +1 -1
- package/dist/cjs/author/schema_to_typescript.js +298 -0
- package/dist/cjs/author/schema_to_typescript.js.map +1 -0
- package/dist/cjs/composition/body_node_base.js +11 -4
- package/dist/cjs/composition/body_node_base.js.map +1 -1
- package/dist/cjs/composition/error.js +2 -0
- package/dist/cjs/composition/error.js.map +1 -1
- package/dist/cjs/composition/index.js +2 -1
- package/dist/cjs/composition/index.js.map +1 -1
- package/dist/cjs/composition/structured_value.js.map +1 -1
- package/dist/cjs/define/frame.js +2 -3
- package/dist/cjs/define/frame.js.map +1 -1
- package/dist/cjs/define/index.js +7 -1
- package/dist/cjs/define/index.js.map +1 -1
- package/dist/cjs/define/primitive_example.js +26 -0
- package/dist/cjs/define/primitive_example.js.map +1 -0
- package/dist/cjs/define/primitive_icon.js +17 -0
- package/dist/cjs/define/primitive_icon.js.map +1 -0
- package/dist/cjs/define/primitive_module.js +24 -7
- package/dist/cjs/define/primitive_module.js.map +1 -1
- package/dist/cjs/define/slack_assets.js.map +1 -1
- package/dist/cjs/entries/index.js +8 -2
- package/dist/cjs/entries/index.js.map +1 -1
- package/dist/cjs/entries/markdown.js +2 -1
- package/dist/cjs/entries/markdown.js.map +1 -1
- package/dist/cjs/entries/slack.js +1 -2
- package/dist/cjs/entries/slack.js.map +1 -1
- package/dist/cjs/pack/capabilities.js +17 -11
- package/dist/cjs/pack/capabilities.js.map +1 -1
- package/dist/cjs/pack/compose.js +4 -1
- package/dist/cjs/pack/compose.js.map +1 -1
- package/dist/cjs/pack/index.js +2 -1
- package/dist/cjs/pack/index.js.map +1 -1
- package/dist/cjs/pack/primitive_pack.js +27 -5
- package/dist/cjs/pack/primitive_pack.js.map +1 -1
- package/dist/cjs/render/anchors.js +1 -1
- package/dist/cjs/render/anchors.js.map +1 -1
- package/dist/cjs/render/format_number.js +2 -1
- package/dist/cjs/render/format_number.js.map +1 -1
- package/dist/cjs/render/html/envelope.js +12 -6
- package/dist/cjs/render/html/envelope.js.map +1 -1
- package/dist/cjs/render/layout_check.js.map +1 -1
- package/dist/cjs/render/markdown/builder.js +18 -8
- package/dist/cjs/render/markdown/builder.js.map +1 -1
- package/dist/cjs/render/markdown/format.js +70 -30
- package/dist/cjs/render/markdown/format.js.map +1 -1
- package/dist/cjs/render/markdown/host_tags.js +67 -0
- package/dist/cjs/render/markdown/host_tags.js.map +1 -0
- package/dist/cjs/render/markdown/index.js +3 -1
- package/dist/cjs/render/markdown/index.js.map +1 -1
- package/dist/cjs/render/markdown/split.js +325 -0
- package/dist/cjs/render/markdown/split.js.map +1 -0
- package/dist/cjs/render/primitive_dispatch.js +11 -25
- package/dist/cjs/render/primitive_dispatch.js.map +1 -1
- package/dist/cjs/render/react/content.js +3 -1
- package/dist/cjs/render/react/content.js.map +1 -1
- package/dist/cjs/render/slack/format.js +1 -601
- package/dist/cjs/render/slack/format.js.map +1 -1
- package/dist/cjs/render/slack/index.js +1 -2
- package/dist/cjs/render/slack/index.js.map +1 -1
- package/dist/cjs/render/slack/markdown_content.js +172 -115
- package/dist/cjs/render/slack/markdown_content.js.map +1 -1
- package/dist/cjs/testing/conformance.js +40 -24
- package/dist/cjs/testing/conformance.js.map +1 -1
- package/dist/cjs/testing/icon.js +248 -0
- package/dist/cjs/testing/icon.js.map +1 -0
- package/dist/cjs/testing/index.js +3 -1
- package/dist/cjs/testing/index.js.map +1 -1
- package/dist/cjs/testing/registration.js +5 -3
- package/dist/cjs/testing/registration.js.map +1 -1
- package/dist/cjs/validate/authoring_schema.js +17 -1
- package/dist/cjs/validate/authoring_schema.js.map +1 -1
- package/dist/cjs/validate/index.js +2 -1
- package/dist/cjs/validate/index.js.map +1 -1
- package/dist/cjs/validate/json_schema.js +10 -3
- package/dist/cjs/validate/json_schema.js.map +1 -1
- package/dist/cjs/validate/url.js +2 -1
- package/dist/cjs/validate/url.js.map +1 -1
- package/dist/cjs/validate/validation.js +2 -45
- package/dist/cjs/validate/validation.js.map +1 -1
- package/dist/composition/body_node_base.d.ts +7 -6
- package/dist/composition/body_node_base.d.ts.map +1 -1
- package/dist/composition/body_node_base.js +10 -3
- package/dist/composition/body_node_base.js.map +1 -1
- package/dist/composition/error.d.ts +2 -0
- package/dist/composition/error.d.ts.map +1 -1
- package/dist/composition/error.js +2 -0
- package/dist/composition/error.js.map +1 -1
- package/dist/composition/index.d.ts +1 -1
- package/dist/composition/index.d.ts.map +1 -1
- package/dist/composition/index.js +1 -1
- package/dist/composition/index.js.map +1 -1
- package/dist/composition/structured_value.d.ts +3 -3
- package/dist/composition/structured_value.d.ts.map +1 -1
- package/dist/composition/structured_value.js.map +1 -1
- package/dist/define/frame.d.ts +9 -20
- package/dist/define/frame.d.ts.map +1 -1
- package/dist/define/frame.js +2 -3
- package/dist/define/frame.js.map +1 -1
- package/dist/define/index.d.ts +3 -1
- package/dist/define/index.d.ts.map +1 -1
- package/dist/define/index.js +3 -1
- package/dist/define/index.js.map +1 -1
- package/dist/define/primitive_example.d.ts +30 -0
- package/dist/define/primitive_example.d.ts.map +1 -0
- package/dist/define/primitive_example.js +21 -0
- package/dist/define/primitive_example.js.map +1 -0
- package/dist/define/primitive_icon.d.ts +11 -0
- package/dist/define/primitive_icon.d.ts.map +1 -0
- package/dist/define/primitive_icon.js +14 -0
- package/dist/define/primitive_icon.js.map +1 -0
- package/dist/define/primitive_module.d.ts +45 -24
- package/dist/define/primitive_module.d.ts.map +1 -1
- package/dist/define/primitive_module.js +24 -7
- package/dist/define/primitive_module.js.map +1 -1
- package/dist/define/slack_assets.d.ts +1 -1
- package/dist/define/slack_assets.d.ts.map +1 -1
- package/dist/define/slack_assets.js.map +1 -1
- package/dist/entries/index.d.ts +3 -3
- package/dist/entries/index.d.ts.map +1 -1
- package/dist/entries/index.js +3 -3
- package/dist/entries/index.js.map +1 -1
- package/dist/entries/markdown.d.ts +1 -1
- package/dist/entries/markdown.d.ts.map +1 -1
- package/dist/entries/markdown.js +1 -1
- package/dist/entries/markdown.js.map +1 -1
- package/dist/entries/slack.d.ts +1 -1
- package/dist/entries/slack.d.ts.map +1 -1
- package/dist/entries/slack.js +1 -1
- package/dist/entries/slack.js.map +1 -1
- package/dist/pack/capabilities.d.ts +24 -10
- package/dist/pack/capabilities.d.ts.map +1 -1
- package/dist/pack/capabilities.js +17 -11
- package/dist/pack/capabilities.js.map +1 -1
- package/dist/pack/compose.d.ts +4 -1
- package/dist/pack/compose.d.ts.map +1 -1
- package/dist/pack/compose.js +4 -1
- package/dist/pack/compose.js.map +1 -1
- package/dist/pack/index.d.ts +2 -2
- package/dist/pack/index.d.ts.map +1 -1
- package/dist/pack/index.js +2 -2
- package/dist/pack/index.js.map +1 -1
- package/dist/pack/primitive_pack.d.ts +14 -3
- package/dist/pack/primitive_pack.d.ts.map +1 -1
- package/dist/pack/primitive_pack.js +25 -4
- package/dist/pack/primitive_pack.js.map +1 -1
- package/dist/render/anchors.d.ts +2 -2
- package/dist/render/anchors.d.ts.map +1 -1
- package/dist/render/anchors.js +1 -1
- package/dist/render/anchors.js.map +1 -1
- package/dist/render/format_number.d.ts.map +1 -1
- package/dist/render/format_number.js +2 -1
- package/dist/render/format_number.js.map +1 -1
- package/dist/render/html/envelope.d.ts +3 -3
- package/dist/render/html/envelope.js +12 -6
- package/dist/render/html/envelope.js.map +1 -1
- package/dist/render/layout_check.d.ts +1 -1
- package/dist/render/layout_check.d.ts.map +1 -1
- package/dist/render/layout_check.js.map +1 -1
- package/dist/render/markdown/builder.d.ts +5 -4
- package/dist/render/markdown/builder.d.ts.map +1 -1
- package/dist/render/markdown/builder.js +16 -7
- package/dist/render/markdown/builder.js.map +1 -1
- package/dist/render/markdown/format.d.ts +9 -0
- package/dist/render/markdown/format.d.ts.map +1 -1
- package/dist/render/markdown/format.js +67 -31
- package/dist/render/markdown/format.js.map +1 -1
- package/dist/render/markdown/host_tags.d.ts +14 -0
- package/dist/render/markdown/host_tags.d.ts.map +1 -0
- package/dist/render/markdown/host_tags.js +63 -0
- package/dist/render/markdown/host_tags.js.map +1 -0
- package/dist/render/markdown/index.d.ts +1 -0
- package/dist/render/markdown/index.d.ts.map +1 -1
- package/dist/render/markdown/index.js +1 -0
- package/dist/render/markdown/index.js.map +1 -1
- package/dist/render/markdown/split.d.ts +32 -0
- package/dist/render/markdown/split.d.ts.map +1 -0
- package/dist/render/markdown/split.js +321 -0
- package/dist/render/markdown/split.js.map +1 -0
- package/dist/render/primitive_dispatch.d.ts +6 -6
- package/dist/render/primitive_dispatch.d.ts.map +1 -1
- package/dist/render/primitive_dispatch.js +12 -26
- package/dist/render/primitive_dispatch.js.map +1 -1
- package/dist/render/react/content.d.ts +1 -1
- package/dist/render/react/content.d.ts.map +1 -1
- package/dist/render/react/content.js +3 -1
- package/dist/render/react/content.js.map +1 -1
- package/dist/render/slack/format.d.ts +0 -25
- package/dist/render/slack/format.d.ts.map +1 -1
- package/dist/render/slack/format.js +1 -599
- package/dist/render/slack/format.js.map +1 -1
- package/dist/render/slack/index.d.ts +1 -1
- package/dist/render/slack/index.d.ts.map +1 -1
- package/dist/render/slack/index.js +1 -1
- package/dist/render/slack/index.js.map +1 -1
- package/dist/render/slack/markdown_content.d.ts +10 -4
- package/dist/render/slack/markdown_content.d.ts.map +1 -1
- package/dist/render/slack/markdown_content.js +169 -113
- package/dist/render/slack/markdown_content.js.map +1 -1
- package/dist/testing/conformance.d.ts +19 -14
- package/dist/testing/conformance.d.ts.map +1 -1
- package/dist/testing/conformance.js +40 -24
- package/dist/testing/conformance.js.map +1 -1
- package/dist/testing/icon.d.ts +11 -0
- package/dist/testing/icon.d.ts.map +1 -0
- package/dist/testing/icon.js +244 -0
- package/dist/testing/icon.js.map +1 -0
- package/dist/testing/index.d.ts +2 -1
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +1 -0
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/registration.d.ts +1 -1
- package/dist/testing/registration.d.ts.map +1 -1
- package/dist/testing/registration.js +6 -4
- package/dist/testing/registration.js.map +1 -1
- package/dist/validate/authoring_schema.d.ts +6 -0
- package/dist/validate/authoring_schema.d.ts.map +1 -1
- package/dist/validate/authoring_schema.js +15 -0
- package/dist/validate/authoring_schema.js.map +1 -1
- package/dist/validate/index.d.ts +1 -1
- package/dist/validate/index.d.ts.map +1 -1
- package/dist/validate/index.js +1 -1
- package/dist/validate/index.js.map +1 -1
- package/dist/validate/json_schema.d.ts.map +1 -1
- package/dist/validate/json_schema.js +10 -3
- package/dist/validate/json_schema.js.map +1 -1
- package/dist/validate/url.d.ts.map +1 -1
- package/dist/validate/url.js +2 -1
- package/dist/validate/url.js.map +1 -1
- package/dist/validate/validation.d.ts +1 -11
- package/dist/validate/validation.d.ts.map +1 -1
- package/dist/validate/validation.js +3 -46
- package/dist/validate/validation.js.map +1 -1
- package/package.json +3 -2
|
@@ -2,7 +2,7 @@ import { type ReactElement, type ReactNode } from 'react';
|
|
|
2
2
|
import type { z, ZodObject } from 'zod';
|
|
3
3
|
import type { Composition } from '../composition/composition.js';
|
|
4
4
|
import type { PrimitiveNode } from '../define/primitive_module.js';
|
|
5
|
-
import { type AuthoredChildBrand, type AuthoredTextBrand } from './authored_fields.js';
|
|
5
|
+
import { type AuthoredChildBrand, type AuthoredNodesBrand, type AuthoredTextBrand, type AuthoredToItemBrand, type ItemSchema } from './authored_fields.js';
|
|
6
6
|
import { type AuthorComponent } from './jsx.js';
|
|
7
7
|
/** A {@link Composition} whose `body` is the pack's own authoring node type. */
|
|
8
8
|
export type AuthorComposition<TNode extends PrimitiveNode = PrimitiveNode> = Omit<Composition<TNode>, 'body'> & {
|
|
@@ -31,7 +31,7 @@ type SchemaOf<P> = P extends {
|
|
|
31
31
|
} ? S extends ZodObject ? S : never : never;
|
|
32
32
|
/** A bare `ZodObject` has a string index; a real shape does not. */
|
|
33
33
|
type LooseSchema<TSchema> = string extends keyof ShapeOf<TSchema> ? true : false;
|
|
34
|
-
type Branded<F> = F extends AuthoredChildBrand<string, unknown> | AuthoredTextBrand ? F : F extends {
|
|
34
|
+
type Branded<F> = F extends AuthoredChildBrand<string, unknown> | AuthoredTextBrand | AuthoredNodesBrand ? F : F extends {
|
|
35
35
|
_zod: {
|
|
36
36
|
def: {
|
|
37
37
|
type: 'optional' | 'nullable' | 'default' | 'readonly';
|
|
@@ -40,47 +40,61 @@ type Branded<F> = F extends AuthoredChildBrand<string, unknown> | AuthoredTextBr
|
|
|
40
40
|
};
|
|
41
41
|
} ? Branded<Inner> : F;
|
|
42
42
|
type AuthoredNames<TSchema> = {
|
|
43
|
-
[K in keyof ShapeOf<TSchema>]: Branded<ShapeOf<TSchema>[K]> extends AuthoredChildBrand<string, unknown> | AuthoredTextBrand ? K : never;
|
|
43
|
+
[K in keyof ShapeOf<TSchema>]: Branded<ShapeOf<TSchema>[K]> extends AuthoredChildBrand<string, unknown> | AuthoredTextBrand | AuthoredNodesBrand ? K : never;
|
|
44
44
|
}[keyof ShapeOf<TSchema>];
|
|
45
|
-
type
|
|
45
|
+
type SlotValue<V> = NonNullable<V> extends readonly (infer Item)[] ? Item : NonNullable<V>;
|
|
46
|
+
/**
|
|
47
|
+
* A field holding body nodes, or an array of them: its `type` is wide or one of
|
|
48
|
+
* the pack's `TTypes`, so a discriminated config object does not count.
|
|
49
|
+
*/
|
|
50
|
+
type NodeSlotKey<T, TTypes extends string> = {
|
|
51
|
+
[K in keyof T]-?: K extends 'type' ? never : SlotValue<T[K]> extends {
|
|
52
|
+
type: infer Type extends string;
|
|
53
|
+
} ? string extends Type ? K : [Type] extends [TTypes] ? K : never : never;
|
|
54
|
+
}[keyof T];
|
|
55
|
+
type IsUnion<T, U = T> = [T] extends [never] ? false : T extends unknown ? [U] extends [T] ? false : true : false;
|
|
56
|
+
/** `T` when it is exactly one key. */
|
|
57
|
+
type Only<T> = [T] extends [never] ? never : IsUnion<T> extends true ? never : T;
|
|
58
|
+
/**
|
|
59
|
+
* The one unbranded node field JSX children fill. With several, each stays a
|
|
60
|
+
* prop, as at runtime.
|
|
61
|
+
*/
|
|
62
|
+
type PassthroughSlot<TSchema extends ZodObject, TTypes extends string> = Only<Exclude<NodeSlotKey<z.infer<TSchema>, TTypes>, AuthoredNames<TSchema>>>;
|
|
63
|
+
type FilledNames<TSchema extends ZodObject, TTypes extends string> = AuthoredNames<TSchema> | PassthroughSlot<TSchema, TTypes>;
|
|
64
|
+
type AuthorPropsForSchema<TSchema extends ZodObject, TTypes extends string> = LooseSchema<TSchema> extends true ? Record<string, unknown> & {
|
|
46
65
|
children?: ReactNode;
|
|
47
|
-
} : Omit<z.infer<TSchema>, 'type' |
|
|
66
|
+
} : Omit<z.infer<TSchema>, 'type' | FilledNames<TSchema, TTypes>> & Partial<Pick<z.infer<TSchema>, Extract<FilledNames<TSchema, TTypes>, keyof z.infer<TSchema>>>> & {
|
|
48
67
|
children?: ReactNode;
|
|
49
68
|
};
|
|
50
|
-
type AuthorPropsFor<P> = [SchemaOf<P>] extends [never] ? Record<string, unknown> & {
|
|
69
|
+
type AuthorPropsFor<P, TTypes extends string> = [SchemaOf<P>] extends [never] ? Record<string, unknown> & {
|
|
51
70
|
children?: ReactNode;
|
|
52
|
-
} : AuthorPropsForSchema<SchemaOf<P
|
|
53
|
-
type ChildEntry<F> = 0 extends 1 & F ? NoKeys : F extends AuthoredChildBrand<infer Name, infer Props> ? [Name] extends [string] ? {
|
|
71
|
+
} : AuthorPropsForSchema<SchemaOf<P>, TTypes>;
|
|
72
|
+
type ChildEntry<F, TOwner extends string, TDepth extends unknown[]> = 0 extends 1 & F ? NoKeys : F extends AuthoredChildBrand<infer Name, infer Props> ? [Name] extends [string] ? {
|
|
54
73
|
[K in Capitalize<Name>]: AuthorComponent<Props & {
|
|
55
74
|
children?: ReactNode;
|
|
56
|
-
},
|
|
57
|
-
} : NoKeys : NoKeys;
|
|
75
|
+
}, `${TOwner}.${K}`>;
|
|
76
|
+
} & (F extends AuthoredToItemBrand ? NoKeys : ChildComponentsOf<ItemSchema<F>, TOwner, [...TDepth, unknown]>) : NoKeys : NoKeys;
|
|
58
77
|
type UnionToIntersection<T> = (T extends unknown ? (value: T) => void : never) extends (value: infer R) => void ? R : never;
|
|
59
|
-
|
|
60
|
-
|
|
78
|
+
/** Child components branded on `TSchema`, then on each child's item schema, five levels deep. */
|
|
79
|
+
type ChildComponentsOf<TSchema, TOwner extends string, TDepth extends unknown[] = []> = TDepth['length'] extends 5 ? NoKeys : LooseSchema<TSchema> extends true ? NoKeys : UnionToIntersection<{
|
|
80
|
+
[K in keyof ShapeOf<TSchema>]: ChildEntry<Branded<ShapeOf<TSchema>[K]>, TOwner, TDepth>;
|
|
61
81
|
}[keyof ShapeOf<TSchema>]>;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
...infer Tail
|
|
65
|
-
] ? ChildComponentsOf<SchemaOf<Head>> & ChildMapOfTuple<Tail extends readonly {
|
|
66
|
-
type: string;
|
|
67
|
-
}[] ? Tail : []> : NoKeys;
|
|
68
|
-
type ChildComponentMap<TPrimitives extends readonly {
|
|
69
|
-
type: string;
|
|
70
|
-
}[]> = ChildMapOfTuple<TPrimitives>;
|
|
82
|
+
/** A primitive's child components, as members of its own component. */
|
|
83
|
+
type MembersOf<P, TType extends string> = [SchemaOf<P>] extends [never] ? NoKeys : ChildComponentsOf<SchemaOf<P>, TType>;
|
|
71
84
|
/**
|
|
72
85
|
* PascalCase authoring components keyed from a pack's primitive `type` list.
|
|
73
|
-
* `slideFrame` becomes `SlideFrame`. Props come from the primitive's schema
|
|
86
|
+
* `slideFrame` becomes `SlideFrame`. Props come from the primitive's schema,
|
|
87
|
+
* and each branded child is a member: `SlideFrame.Footer`.
|
|
74
88
|
*/
|
|
75
89
|
export type PrimitiveComponentMap<TPrimitives extends readonly {
|
|
76
90
|
type: string;
|
|
77
91
|
}[]> = {
|
|
78
|
-
[P in TPrimitives[number] as Capitalize<LiteralType<P['type'] & string>>]: AuthorComponent<AuthorPropsFor<P
|
|
92
|
+
[P in TPrimitives[number] as Capitalize<LiteralType<P['type'] & string>>]: AuthorComponent<AuthorPropsFor<P, LiteralType<TPrimitives[number]['type'] & string>>, P['type'] & string> & MembersOf<P, P['type'] & string>;
|
|
79
93
|
};
|
|
80
94
|
/**
|
|
81
95
|
* A pack's JSX authoring front: the root `Composition` element, one
|
|
82
|
-
* PascalCase component per primitive
|
|
83
|
-
* back to plain data.
|
|
96
|
+
* PascalCase component per primitive with its branded children as members,
|
|
97
|
+
* and the conversion back to plain data.
|
|
84
98
|
*/
|
|
85
99
|
export type JsxShim<TNode extends PrimitiveNode = PrimitiveNode, TPrimitives extends readonly {
|
|
86
100
|
type: string;
|
|
@@ -90,14 +104,19 @@ export type JsxShim<TNode extends PrimitiveNode = PrimitiveNode, TPrimitives ext
|
|
|
90
104
|
Composition: AuthorComponent<CompositionAuthorProps<TNode>, 'view'>;
|
|
91
105
|
/** Throws when the root is not the `Composition` element, or when a child is not a registered primitive. */
|
|
92
106
|
toComposition: (element: ReactElement<CompositionAuthorProps<TNode>>) => AuthorComposition<TNode>;
|
|
93
|
-
} & PrimitiveComponentMap<TPrimitives
|
|
107
|
+
} & PrimitiveComponentMap<TPrimitives>;
|
|
94
108
|
/**
|
|
95
109
|
* Builds a pack's {@link JsxShim} from its primitive list.
|
|
96
110
|
*
|
|
97
111
|
* Branded schema fields ({@link fromChildren}, {@link fromTextChildren}) fill
|
|
98
|
-
* from JSX children, and each child
|
|
99
|
-
*
|
|
100
|
-
*
|
|
112
|
+
* from JSX children, and each child becomes a member of its primitive's
|
|
113
|
+
* component. Several branded fields share one children list, and each takes
|
|
114
|
+
* the elements of its member.
|
|
115
|
+
* Elements of a registered primitive that match none of them fill the one
|
|
116
|
+
* unbranded child slot from {@link PrimitiveDefinition.children}, or the one
|
|
117
|
+
* {@link fromNodeChildren} field. A primitive with no brand still fills that slot, array or
|
|
118
|
+
* single node, from its children. That field is optional on the component's
|
|
119
|
+
* props.
|
|
101
120
|
*/
|
|
102
121
|
export declare const buildJsxShim: <const TPrimitives extends readonly {
|
|
103
122
|
type: string;
|
|
@@ -107,10 +126,11 @@ export declare const buildJsxShim: <const TPrimitives extends readonly {
|
|
|
107
126
|
/** React children as a flat array, with fragments inlined. */
|
|
108
127
|
export declare const flattenChildren: (children: ReactNode) => ReactNode[];
|
|
109
128
|
/**
|
|
110
|
-
* Children joined into one string. Throws on an element child, so a prop typed as text stays text. Collapses whitespace unless `{ collapseWhitespace: false }`.
|
|
129
|
+
* Children joined into one string. Throws on an element child, so a prop typed as text stays text. Collapses whitespace unless `{ collapseWhitespace: false }`; `{ dedent: true }` reads it as source, lines joined by `\n`.
|
|
111
130
|
*/
|
|
112
131
|
export declare const textFromChildren: (children: ReactNode, options?: {
|
|
113
132
|
collapseWhitespace?: boolean;
|
|
133
|
+
dedent?: boolean;
|
|
114
134
|
}) => string;
|
|
115
135
|
export {};
|
|
116
136
|
//# sourceMappingURL=jsx_shim.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jsx_shim.d.ts","sourceRoot":"","sources":["../../src/author/jsx_shim.ts"],"names":[],"mappings":"AAOA,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,CAAC,EAAE,SAAS,EAAW,MAAM,KAAK,CAAC;AAEjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAE9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEhE,OAAO,EACL,KAAK,kBAAkB,
|
|
1
|
+
{"version":3,"file":"jsx_shim.d.ts","sourceRoot":"","sources":["../../src/author/jsx_shim.ts"],"names":[],"mappings":"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"}
|
package/dist/author/jsx_shim.js
CHANGED
|
@@ -7,26 +7,24 @@
|
|
|
7
7
|
import { Children, Fragment, isValidElement, } from 'react';
|
|
8
8
|
import { IsomerError } from '../composition/error.js';
|
|
9
9
|
import { readAuthoredSpec, } from './authored_fields.js';
|
|
10
|
+
import { capitalize, createAuthoringModel, memberType, } from './authoring_model.js';
|
|
10
11
|
import { authorType, defineAuthorComponent } from './jsx.js';
|
|
11
12
|
/**
|
|
12
13
|
* Builds a pack's {@link JsxShim} from its primitive list.
|
|
13
14
|
*
|
|
14
15
|
* Branded schema fields ({@link fromChildren}, {@link fromTextChildren}) fill
|
|
15
|
-
* from JSX children, and each child
|
|
16
|
-
*
|
|
17
|
-
*
|
|
16
|
+
* from JSX children, and each child becomes a member of its primitive's
|
|
17
|
+
* component. Several branded fields share one children list, and each takes
|
|
18
|
+
* the elements of its member.
|
|
19
|
+
* Elements of a registered primitive that match none of them fill the one
|
|
20
|
+
* unbranded child slot from {@link PrimitiveDefinition.children}, or the one
|
|
21
|
+
* {@link fromNodeChildren} field. A primitive with no brand still fills that slot, array or
|
|
22
|
+
* single node, from its children. That field is optional on the component's
|
|
23
|
+
* props.
|
|
18
24
|
*/
|
|
19
25
|
export const buildJsxShim = (primitives = []) => {
|
|
20
26
|
const primitiveTypes = new Set(primitives.map((primitive) => primitive.type));
|
|
21
|
-
const childSlotsByType =
|
|
22
|
-
primitive.type,
|
|
23
|
-
inferChildSlots('children' in primitive ? primitive.children : undefined),
|
|
24
|
-
]));
|
|
25
|
-
const { authoredByType, childComponents } = collectAuthored(primitives);
|
|
26
|
-
assertUniqueComponentNames([
|
|
27
|
-
...primitives.map(({ type }) => type),
|
|
28
|
-
...childComponents.keys(),
|
|
29
|
-
]);
|
|
27
|
+
const { authoredByType, membersByType, childSlotsByType } = createAuthoringModel(primitives);
|
|
30
28
|
const view = defineAuthorComponent('view');
|
|
31
29
|
const env = {
|
|
32
30
|
authoredByType,
|
|
@@ -36,56 +34,15 @@ export const buildJsxShim = (primitives = []) => {
|
|
|
36
34
|
return {
|
|
37
35
|
Composition: view,
|
|
38
36
|
toComposition: (element) => toAuthorComposition(element, env),
|
|
39
|
-
...Object.fromEntries(primitives.map((
|
|
40
|
-
capitalize(primitive.type),
|
|
41
|
-
defineAuthorComponent(primitive.type),
|
|
42
|
-
])),
|
|
43
|
-
...Object.fromEntries([...childComponents].map(([type, component]) => [
|
|
37
|
+
...Object.fromEntries(primitives.map(({ type }) => [
|
|
44
38
|
capitalize(type),
|
|
45
|
-
|
|
39
|
+
Object.assign(defineAuthorComponent(type), Object.fromEntries((membersByType.get(type) ?? []).map(({ member, authorType }) => [
|
|
40
|
+
member,
|
|
41
|
+
defineAuthorComponent(authorType),
|
|
42
|
+
]))),
|
|
46
43
|
])),
|
|
47
44
|
};
|
|
48
45
|
};
|
|
49
|
-
const collectAuthored = (primitives) => {
|
|
50
|
-
const authoredByType = new Map();
|
|
51
|
-
const signatures = new Map();
|
|
52
|
-
const childComponents = new Map();
|
|
53
|
-
for (const primitive of primitives) {
|
|
54
|
-
const schema = primitive.schema;
|
|
55
|
-
if (!isZodType(schema)) {
|
|
56
|
-
continue;
|
|
57
|
-
}
|
|
58
|
-
const spec = readAuthoredSpec(schema);
|
|
59
|
-
if (spec.children.length === 0 && spec.text.length === 0) {
|
|
60
|
-
continue;
|
|
61
|
-
}
|
|
62
|
-
authoredByType.set(primitive.type, spec);
|
|
63
|
-
for (const field of spec.children) {
|
|
64
|
-
const prior = signatures.get(field.childType);
|
|
65
|
-
if (prior !== undefined && prior !== field.signature) {
|
|
66
|
-
throw new IsomerError('DUPLICATE_AUTHORED_CHILD', `Child type "${field.childType}" is branded with two different item shapes.`);
|
|
67
|
-
}
|
|
68
|
-
signatures.set(field.childType, field.signature);
|
|
69
|
-
if (!childComponents.has(field.childType)) {
|
|
70
|
-
childComponents.set(field.childType, defineAuthorComponent(field.childType));
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
return { authoredByType, childComponents };
|
|
75
|
-
};
|
|
76
|
-
/** Throws when two types, or a type and the root `Composition`, capitalize to one component name. */
|
|
77
|
-
const assertUniqueComponentNames = (types) => {
|
|
78
|
-
const typeByName = new Map([['Composition', 'view']]);
|
|
79
|
-
for (const type of types) {
|
|
80
|
-
const name = capitalize(type);
|
|
81
|
-
const earlier = typeByName.get(name);
|
|
82
|
-
if (earlier !== undefined && earlier !== type) {
|
|
83
|
-
throw new IsomerError('DUPLICATE_PRIMITIVE_TYPE', `buildJsxShim: "${earlier}" and "${type}" both become the component ${name}`);
|
|
84
|
-
}
|
|
85
|
-
typeByName.set(name, type);
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
const isZodType = (schema) => typeof schema === 'object' && schema !== null && '_zod' in schema;
|
|
89
46
|
const toAuthorComposition = (element, env) => {
|
|
90
47
|
requireAuthorElement(element, 'view');
|
|
91
48
|
const props = element.props;
|
|
@@ -125,12 +82,12 @@ const bodyNodeFromElement = (node, env) => {
|
|
|
125
82
|
for (const [key, value] of Object.entries(withoutChildren(element))) {
|
|
126
83
|
const childField = authored?.children.find((field) => field.field === key);
|
|
127
84
|
converted[key] = childField
|
|
128
|
-
? valueFromChildField(value, childField, env)
|
|
85
|
+
? valueFromChildField(value, childField, env, type)
|
|
129
86
|
: convertPropValue(value, key, slots, parseChild);
|
|
130
87
|
}
|
|
131
88
|
const rawChildren = element.props.children;
|
|
132
89
|
if (authored && (authored.children.length > 0 || authored.text.length > 0)) {
|
|
133
|
-
fillAuthoredFields(converted, authored, rawChildren, env);
|
|
90
|
+
fillAuthoredFields(converted, authored, rawChildren, env, slots, parseChild, type);
|
|
134
91
|
}
|
|
135
92
|
else {
|
|
136
93
|
const unique = slots.length === 1 ? slots[0] : undefined;
|
|
@@ -138,7 +95,7 @@ const bodyNodeFromElement = (node, env) => {
|
|
|
138
95
|
converted[unique.field] === undefined &&
|
|
139
96
|
rawChildren !== undefined) {
|
|
140
97
|
const nested = flattenChildren(rawChildren).map(parseChild);
|
|
141
|
-
converted[unique.field] =
|
|
98
|
+
converted[unique.field] = slotValue(nested, unique);
|
|
142
99
|
}
|
|
143
100
|
else if (slots.length === 0 && flattenChildren(rawChildren).length > 0) {
|
|
144
101
|
throw new IsomerError('UNEXPECTED_CHILDREN', `<${capitalize(type)}> takes no JSX children; set its fields through props.`);
|
|
@@ -146,31 +103,79 @@ const bodyNodeFromElement = (node, env) => {
|
|
|
146
103
|
}
|
|
147
104
|
return omitUndefined({ ...converted, type });
|
|
148
105
|
};
|
|
149
|
-
const fillAuthoredFields = (converted, authored, rawChildren, env) => {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
106
|
+
const fillAuthoredFields = (converted, authored, rawChildren, env, slots, parseChild, parentType) => {
|
|
107
|
+
const unsetChildren = authored.children.filter((field) => converted[field.field] === undefined);
|
|
108
|
+
const unsetText = authored.text.filter((field) => converted[field.field] === undefined);
|
|
109
|
+
const brandedFields = new Set(authored.children.map((field) => field.field));
|
|
110
|
+
const unbranded = slots.filter(({ field }) => !brandedFields.has(field));
|
|
111
|
+
const slot = unbranded.length === 1 ? unbranded[0] : undefined;
|
|
112
|
+
const slotOpen = slot !== undefined && converted[slot.field] === undefined;
|
|
113
|
+
if (rawChildren === undefined ||
|
|
114
|
+
(unsetChildren.length === 0 && unsetText.length === 0 && !slotOpen)) {
|
|
115
|
+
for (const field of unsetText) {
|
|
116
|
+
if (!field.optional) {
|
|
117
|
+
throw new IsomerError('MISSING_AUTHORED_TEXT', `Expected text children for "${field.field}".`);
|
|
118
|
+
}
|
|
153
119
|
}
|
|
154
|
-
|
|
120
|
+
return;
|
|
155
121
|
}
|
|
156
|
-
|
|
157
|
-
|
|
122
|
+
const flat = flattenChildren(rawChildren);
|
|
123
|
+
const elements = flat.filter(isAuthorElement);
|
|
124
|
+
const textNodes = flat.filter((child) => !isAuthorElement(child));
|
|
125
|
+
const claimed = new Set();
|
|
126
|
+
for (const field of unsetChildren) {
|
|
127
|
+
const matching = elements.filter((child) => getAuthorType(child) === memberType(parentType, field));
|
|
128
|
+
if (matching.length === 0) {
|
|
129
|
+
if (flat.length === 0 && field.array && !field.optional) {
|
|
130
|
+
converted[field.field] = [];
|
|
131
|
+
}
|
|
158
132
|
continue;
|
|
159
133
|
}
|
|
160
|
-
|
|
134
|
+
for (const child of matching) {
|
|
135
|
+
claimed.add(child);
|
|
136
|
+
}
|
|
137
|
+
converted[field.field] = valueFromBrand(matching, field, env, parentType);
|
|
138
|
+
}
|
|
139
|
+
const brandedTypes = new Set(authored.children.map((field) => memberType(parentType, field)));
|
|
140
|
+
const stray = elements.filter((child) => brandedTypes.has(getAuthorType(child)) && !claimed.has(child));
|
|
141
|
+
if (stray.length > 0) {
|
|
142
|
+
const childType = getAuthorType(stray[0]);
|
|
143
|
+
throw new IsomerError('UNEXPECTED_CHILDREN', `<${capitalize(parentType)}> already has its <${capitalize(childType)}>.`);
|
|
144
|
+
}
|
|
145
|
+
const leftover = elements.filter((child) => !claimed.has(child));
|
|
146
|
+
if (slotOpen && slot && leftover.length > 0) {
|
|
147
|
+
const nested = leftover.map(parseChild);
|
|
148
|
+
converted[slot.field] = slotValue(nested, slot);
|
|
149
|
+
}
|
|
150
|
+
else if (leftover.length > 0) {
|
|
151
|
+
const childType = getAuthorType(leftover[0]);
|
|
152
|
+
const [empty, ...moreEmpty] = unsetChildren.filter(({ field }) => converted[field] === undefined);
|
|
153
|
+
if (empty && moreEmpty.length === 0 && !slotOpen) {
|
|
154
|
+
throw new IsomerError('AUTHOR_TYPE_MISMATCH', `Expected <${capitalize(memberType(parentType, empty))}> but received <${capitalize(childType)}>.`);
|
|
155
|
+
}
|
|
156
|
+
throw new IsomerError('UNEXPECTED_CHILDREN', `<${capitalize(childType)}> is not a child of <${capitalize(parentType)}>.`);
|
|
157
|
+
}
|
|
158
|
+
if (textNodes.length === 0) {
|
|
159
|
+
for (const field of unsetText) {
|
|
161
160
|
if (!field.optional) {
|
|
162
161
|
throw new IsomerError('MISSING_AUTHORED_TEXT', `Expected text children for "${field.field}".`);
|
|
163
162
|
}
|
|
164
|
-
continue;
|
|
165
163
|
}
|
|
166
|
-
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
if (unsetText.length === 0) {
|
|
167
|
+
throw new IsomerError('EXPECTED_JSX_ELEMENT', 'Expected an Isomer JSX element.');
|
|
168
|
+
}
|
|
169
|
+
for (const field of unsetText) {
|
|
170
|
+
converted[field.field] = textFromChildren(textNodes, {
|
|
167
171
|
collapseWhitespace: field.collapseWhitespace,
|
|
172
|
+
...(field.dedent ? { dedent: true } : {}),
|
|
168
173
|
});
|
|
169
174
|
}
|
|
170
175
|
};
|
|
171
|
-
const valueFromChildField = (value, field, env) => {
|
|
176
|
+
const valueFromChildField = (value, field, env, owner) => {
|
|
172
177
|
if (isJsxNodes(value)) {
|
|
173
|
-
return
|
|
178
|
+
return valueFromBrand(flattenChildren(value), field, env, owner);
|
|
174
179
|
}
|
|
175
180
|
return value;
|
|
176
181
|
};
|
|
@@ -184,47 +189,76 @@ const isJsxNodes = (value) => {
|
|
|
184
189
|
return (Array.isArray(value) &&
|
|
185
190
|
value.some((item) => isAuthorElement(item) || isValidElement(item)));
|
|
186
191
|
};
|
|
187
|
-
|
|
188
|
-
const
|
|
189
|
-
const
|
|
192
|
+
/** The field's array of items, or its one item; throws on a second element for a single-item field. */
|
|
193
|
+
const valueFromBrand = (elements, field, env, owner) => {
|
|
194
|
+
const items = elements.map((child) => itemFromElement(child, field, env, owner));
|
|
195
|
+
if (field.array) {
|
|
196
|
+
return items;
|
|
197
|
+
}
|
|
198
|
+
if (items.length > 1) {
|
|
199
|
+
throw new IsomerError('UNEXPECTED_CHILDREN', `"${field.field}" takes one <${capitalize(memberType(owner, field))}>, not ${items.length}.`);
|
|
200
|
+
}
|
|
201
|
+
return items[0];
|
|
202
|
+
};
|
|
203
|
+
const itemFromElement = (child, field, env, owner) => {
|
|
204
|
+
const element = requireAuthorElement(child, memberType(owner, field));
|
|
190
205
|
if (field.toItem) {
|
|
191
206
|
return field.toItem(element.props, {
|
|
192
207
|
parseChildren: (nested) => flattenChildren(nested).map((node) => bodyNodeFromElement(node, env)),
|
|
193
208
|
});
|
|
194
209
|
}
|
|
195
210
|
const props = withoutChildren(element);
|
|
196
|
-
const
|
|
211
|
+
const nested = flattenChildren(element.props.children);
|
|
212
|
+
const elements = nested.filter(isAuthorElement);
|
|
213
|
+
const text = nested.filter((child) => !isAuthorElement(child));
|
|
197
214
|
if (field.textField !== undefined &&
|
|
198
215
|
props[field.textField] === undefined &&
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
props[field.textField] = textFromChildren(nestedChildren);
|
|
216
|
+
text.length > 0) {
|
|
217
|
+
props[field.textField] = textFromChildren(text);
|
|
202
218
|
}
|
|
203
|
-
fillNestedBrands(field.itemSchema, props,
|
|
219
|
+
fillNestedBrands(field.itemSchema, props, elements, env, owner, capitalize(memberType(owner, field)));
|
|
204
220
|
return props;
|
|
205
221
|
};
|
|
206
|
-
const fillNestedBrands = (itemSchema, props,
|
|
207
|
-
if (
|
|
222
|
+
const fillNestedBrands = (itemSchema, props, elements, env, owner, parent) => {
|
|
223
|
+
if (elements.length === 0) {
|
|
208
224
|
return;
|
|
209
225
|
}
|
|
210
|
-
const
|
|
211
|
-
|
|
226
|
+
const fields = readAuthoredSpec(itemSchema).children;
|
|
227
|
+
const claimed = new Set();
|
|
228
|
+
for (const field of fields) {
|
|
212
229
|
if (props[field.field] !== undefined) {
|
|
213
230
|
continue;
|
|
214
231
|
}
|
|
215
|
-
const matching =
|
|
216
|
-
if (matching.length
|
|
217
|
-
|
|
232
|
+
const matching = elements.filter((child) => getAuthorType(child) === memberType(owner, field));
|
|
233
|
+
if (matching.length > 0) {
|
|
234
|
+
matching.forEach((child) => claimed.add(child));
|
|
235
|
+
props[field.field] = valueFromBrand(matching, field, env, owner);
|
|
218
236
|
}
|
|
219
|
-
props[field.field] = matching.map((child) => itemFromElement(child, field, env));
|
|
220
237
|
}
|
|
238
|
+
const [stray] = elements.filter((child) => !claimed.has(child));
|
|
239
|
+
if (stray) {
|
|
240
|
+
const strayType = getAuthorType(stray);
|
|
241
|
+
const held = fields.some((field) => memberType(owner, field) === strayType);
|
|
242
|
+
throw new IsomerError('UNEXPECTED_CHILDREN', held
|
|
243
|
+
? `<${parent}> already has its <${capitalize(strayType)}>.`
|
|
244
|
+
: `<${capitalize(strayType)}> is not a child of <${parent}>.`);
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
/** The slot's nodes, or its one node; throws on a second node for a single-node slot. */
|
|
248
|
+
const slotValue = (nodes, { array, field }) => {
|
|
249
|
+
if (array) {
|
|
250
|
+
return nodes;
|
|
251
|
+
}
|
|
252
|
+
if (nodes.length > 1) {
|
|
253
|
+
throw new IsomerError('UNEXPECTED_CHILDREN', `"${field}" takes one node, not ${nodes.length}.`);
|
|
254
|
+
}
|
|
255
|
+
return nodes[0];
|
|
221
256
|
};
|
|
222
|
-
const hasAuthorElement = (children) => flattenChildren(children).some((child) => isAuthorElement(child));
|
|
223
257
|
const convertPropValue = (value, field, slots, parseChild) => {
|
|
224
|
-
const
|
|
258
|
+
const array = slots.some((slot) => slot.field === field && slot.array);
|
|
225
259
|
const fromJsx = nodesFromJsx(value, parseChild);
|
|
226
260
|
if (fromJsx) {
|
|
227
|
-
return
|
|
261
|
+
return slotValue(fromJsx, { array, field });
|
|
228
262
|
}
|
|
229
263
|
if (Array.isArray(value)) {
|
|
230
264
|
return value.flatMap((item) => {
|
|
@@ -250,51 +284,6 @@ const isAuthorElement = (value) => {
|
|
|
250
284
|
const component = value.type;
|
|
251
285
|
return typeof component[authorType] === 'string';
|
|
252
286
|
};
|
|
253
|
-
/**
|
|
254
|
-
* Reads {@link PrimitiveDefinition.children} against a probe node so JSX can
|
|
255
|
-
* fill the same fields a tree walk would visit. Paths like `body[0]` are array
|
|
256
|
-
* slots; a bare `header` is a single nested node.
|
|
257
|
-
*/
|
|
258
|
-
const inferChildSlots = (children) => {
|
|
259
|
-
if (typeof children !== 'function') {
|
|
260
|
-
return [];
|
|
261
|
-
}
|
|
262
|
-
const probeNode = { type: '__probe__' };
|
|
263
|
-
const node = new Proxy({}, {
|
|
264
|
-
get(_target, prop) {
|
|
265
|
-
if (prop === 'type') {
|
|
266
|
-
return probeNode.type;
|
|
267
|
-
}
|
|
268
|
-
return [probeNode];
|
|
269
|
-
},
|
|
270
|
-
});
|
|
271
|
-
try {
|
|
272
|
-
const refs = children(node);
|
|
273
|
-
if (!Array.isArray(refs)) {
|
|
274
|
-
return [];
|
|
275
|
-
}
|
|
276
|
-
const byField = new Map();
|
|
277
|
-
for (const ref of refs) {
|
|
278
|
-
if (!isChildRef(ref)) {
|
|
279
|
-
continue;
|
|
280
|
-
}
|
|
281
|
-
const field = /^[A-Za-z_]\w*/.exec(ref.path)?.[0];
|
|
282
|
-
if (!field) {
|
|
283
|
-
continue;
|
|
284
|
-
}
|
|
285
|
-
byField.set(field, byField.get(field) === true || /\[\d+\]/.test(ref.path));
|
|
286
|
-
}
|
|
287
|
-
return [...byField.entries()].map(([field, array]) => ({ array, field }));
|
|
288
|
-
}
|
|
289
|
-
catch {
|
|
290
|
-
return [];
|
|
291
|
-
}
|
|
292
|
-
};
|
|
293
|
-
const isChildRef = (value) => typeof value === 'object' &&
|
|
294
|
-
value !== null &&
|
|
295
|
-
'path' in value &&
|
|
296
|
-
typeof value.path === 'string';
|
|
297
|
-
const capitalize = (value) => `${value.slice(0, 1).toUpperCase()}${value.slice(1)}`;
|
|
298
287
|
/** React children as a flat array, with fragments inlined. */
|
|
299
288
|
export const flattenChildren = (children) => Children.toArray(children).flatMap((child) => {
|
|
300
289
|
if (isValidElement(child) && child.type === Fragment) {
|
|
@@ -303,8 +292,24 @@ export const flattenChildren = (children) => Children.toArray(children).flatMap(
|
|
|
303
292
|
}
|
|
304
293
|
return child;
|
|
305
294
|
});
|
|
295
|
+
const lineBreak = /\r\n|[\n\r\u2028\u2029]/;
|
|
296
|
+
// A template literal's source: the break after the opening backtick, the
|
|
297
|
+
// indentation before the closing one, and the indentation every line shares go.
|
|
298
|
+
const dedentSource = (text) => {
|
|
299
|
+
const all = text.split(lineBreak);
|
|
300
|
+
const start = all.length > 1 && all[0] === '' ? 1 : 0;
|
|
301
|
+
const end = all.length - start > 1 && /^ *$/.test(all[all.length - 1])
|
|
302
|
+
? all.length - 1
|
|
303
|
+
: all.length;
|
|
304
|
+
const lines = all.slice(start, end);
|
|
305
|
+
const indents = lines
|
|
306
|
+
.filter((line) => line.trim() !== '')
|
|
307
|
+
.map((line) => line.length - line.trimStart().length);
|
|
308
|
+
const shared = indents.length > 0 ? Math.min(...indents) : 0;
|
|
309
|
+
return lines.map((line) => line.slice(shared)).join('\n');
|
|
310
|
+
};
|
|
306
311
|
/**
|
|
307
|
-
* Children joined into one string. Throws on an element child, so a prop typed as text stays text. Collapses whitespace unless `{ collapseWhitespace: false }`.
|
|
312
|
+
* Children joined into one string. Throws on an element child, so a prop typed as text stays text. Collapses whitespace unless `{ collapseWhitespace: false }`; `{ dedent: true }` reads it as source, lines joined by `\n`.
|
|
308
313
|
*/
|
|
309
314
|
export const textFromChildren = (children, options) => {
|
|
310
315
|
const text = flattenChildren(children)
|
|
@@ -315,6 +320,9 @@ export const textFromChildren = (children, options) => {
|
|
|
315
320
|
throw new IsomerError('EXPECTED_TEXT_CHILDREN', 'Expected text children.');
|
|
316
321
|
})
|
|
317
322
|
.join('');
|
|
323
|
+
if (options?.dedent) {
|
|
324
|
+
return dedentSource(text);
|
|
325
|
+
}
|
|
318
326
|
if (options?.collapseWhitespace === false) {
|
|
319
327
|
return text.trim();
|
|
320
328
|
}
|