@bettercms-ai/types 1.41.0 → 1.42.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/index.d.ts +566 -22
- package/dist/index.js +1040 -10
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -70,6 +70,91 @@ function getBlockType(value) {
|
|
|
70
70
|
return null;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
// src/number-format.ts
|
|
74
|
+
var GROUPS = [",", ".", " ", "\xA0", "\u202F", "'", "\u2019"];
|
|
75
|
+
var COMMA_DECIMAL = /^(de|es|it|nl|pt|id|tr|da|fr|sv|nb|no|fi|pl|cs|ru|uk|el|ro|hu|sk|sl|hr|bg)\b/i;
|
|
76
|
+
var SPACE_GROUP = /^(fr|sv|nb|no|fi|pl|cs|ru|uk|sk|hu|bg)\b/i;
|
|
77
|
+
var UNIT = "(?:[kKmMbBxsdgh]|bn|hr|hrs|min|ms|kg|mg|lb|lbs|oz|km|cm|mm|mi|ft|[kKMGT]B|px|pt|\xB0[CF]?)";
|
|
78
|
+
var SUFFIX = new RegExp(`^(?:\\s?(?:\\p{Sc}|[%\u2030\xD7]|${UNIT}))?\\+?(?:\\s?/\\s?\\p{L}{1,10}){0,2}[)\\]*\u2020]?$`, "u");
|
|
79
|
+
var PREFIX = /^(?:[^\p{L}\p{N}\s.,'\u2019#№\-−–—]{1,3}\s?)?$/u;
|
|
80
|
+
var fractionDigits = (value) => {
|
|
81
|
+
const text = value.toFixed(6).replace(/0+$/, "");
|
|
82
|
+
return text.length - text.indexOf(".") - 1;
|
|
83
|
+
};
|
|
84
|
+
function readNumberFormat(raw) {
|
|
85
|
+
const o = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
86
|
+
const text = (v, max) => typeof v === "string" && v.length <= max && !new RegExp("\\p{Nd}", "u").test(v) ? v : void 0;
|
|
87
|
+
const prefix = text(o.prefix, 8);
|
|
88
|
+
const suffix = text(o.suffix, 24);
|
|
89
|
+
const group = typeof o.group === "string" && GROUPS.includes(o.group) ? o.group : void 0;
|
|
90
|
+
const decimal = o.decimal === "," ? "," : void 0;
|
|
91
|
+
const decimals = typeof o.decimals === "number" && Number.isInteger(o.decimals) && o.decimals > 0 && o.decimals <= 6 ? o.decimals : void 0;
|
|
92
|
+
return {
|
|
93
|
+
...prefix ? { prefix } : {},
|
|
94
|
+
...suffix ? { suffix } : {},
|
|
95
|
+
// A group mark that is also the decimal mark would print a number nobody can read back.
|
|
96
|
+
...group && group !== (decimal ?? ".") ? { group } : {},
|
|
97
|
+
...decimal ? { decimal } : {},
|
|
98
|
+
...decimals ? { decimals } : {}
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function formatNumber(value, format = {}) {
|
|
102
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return "";
|
|
103
|
+
const places = Math.max(format.decimals ?? 0, Math.min(6, fractionDigits(value)));
|
|
104
|
+
const [int, frac] = Math.abs(value).toFixed(places).split(".");
|
|
105
|
+
const grouped = format.group ? int.replace(/\B(?=(\d{3})+(?!\d))/g, format.group) : int;
|
|
106
|
+
return `${value < 0 ? "-" : ""}${format.prefix ?? ""}${grouped}${frac ? `${format.decimal ?? "."}${frac}` : ""}${format.suffix ?? ""}`;
|
|
107
|
+
}
|
|
108
|
+
function parseNumberText(text, opts = {}) {
|
|
109
|
+
if (typeof text !== "string" || text.length === 0 || text.length > 40) return null;
|
|
110
|
+
const digits = /\d/.exec(text);
|
|
111
|
+
if (!digits) return null;
|
|
112
|
+
const start = digits.index;
|
|
113
|
+
const body = /^\d[\d.,'\u2019 \u00a0\u202f]*\d|^\d/.exec(text.slice(start))[0];
|
|
114
|
+
const prefix = text.slice(0, start);
|
|
115
|
+
const suffix = text.slice(start + body.length);
|
|
116
|
+
if (/\d/.test(suffix) || !PREFIX.test(prefix) || !SUFFIX.test(suffix)) return null;
|
|
117
|
+
if (opts.machine && (prefix || suffix || !/^\d+(\.\d+)?$/.test(body))) return null;
|
|
118
|
+
if (/[)\]]$/.test(suffix) !== /^[([]/.test(prefix)) return null;
|
|
119
|
+
const commaLang = COMMA_DECIMAL.test(opts.lang ?? "");
|
|
120
|
+
const marks = [...body].filter((c) => !/\d/.test(c));
|
|
121
|
+
const kinds = [...new Set(marks)];
|
|
122
|
+
let group;
|
|
123
|
+
let decimal;
|
|
124
|
+
if (kinds.length > 2) return null;
|
|
125
|
+
if (kinds.length === 2) {
|
|
126
|
+
const last = marks[marks.length - 1];
|
|
127
|
+
if (last !== "." && last !== "," || marks.filter((m) => m === last).length !== 1) return null;
|
|
128
|
+
decimal = last;
|
|
129
|
+
group = kinds.find((k) => k !== last);
|
|
130
|
+
} else if (kinds.length === 1) {
|
|
131
|
+
const mark = kinds[0];
|
|
132
|
+
const tail = body.slice(body.lastIndexOf(mark) + 1);
|
|
133
|
+
const lone = marks.length === 1 && (mark === "." || mark === ",");
|
|
134
|
+
const asDecimal = lone && (tail.length !== 3 || body.indexOf(mark) > 3 || /^0/.test(body) || (mark === "." ? !commaLang : commaLang));
|
|
135
|
+
if (asDecimal) decimal = mark;
|
|
136
|
+
else group = mark;
|
|
137
|
+
}
|
|
138
|
+
if (group !== void 0 && group === decimal || group && !GROUPS.includes(group)) return null;
|
|
139
|
+
const [intPart, frac = ""] = decimal ? body.split(decimal) : [body];
|
|
140
|
+
const whole = group ? intPart.split(group) : [intPart];
|
|
141
|
+
if (group && (whole.length < 2 || !/^[1-9]\d{0,2}$/.test(whole[0]) || whole.slice(1).some((g) => !/^\d{3}$/.test(g)))) return null;
|
|
142
|
+
const int = whole.join("");
|
|
143
|
+
if (!/^\d+$/.test(int) || int.length > 1 && int.startsWith("0") || int.length + frac.length > 15 || decimal && !/^\d+$/.test(frac)) return null;
|
|
144
|
+
const value = Number(frac ? `${int}.${frac}` : int);
|
|
145
|
+
if (!group && !opts.machine && int.length < 4) group = SPACE_GROUP.test(opts.lang ?? "") ? "\xA0" : commaLang ? "." : ",";
|
|
146
|
+
if (!decimal && (group === "." || commaLang && !opts.machine)) decimal = ",";
|
|
147
|
+
if (group === (decimal ?? ".")) group = void 0;
|
|
148
|
+
const format = {
|
|
149
|
+
...prefix ? { prefix } : {},
|
|
150
|
+
...suffix ? { suffix } : {},
|
|
151
|
+
...group ? { group } : {},
|
|
152
|
+
...decimal === "," ? { decimal } : {},
|
|
153
|
+
...frac ? { decimals: frac.length } : {}
|
|
154
|
+
};
|
|
155
|
+
return Number.isFinite(value) && frac.length <= 6 && formatNumber(value, format) === text ? { value, format } : null;
|
|
156
|
+
}
|
|
157
|
+
|
|
73
158
|
// src/block-bindings.ts
|
|
74
159
|
var BLOCK_BINDINGS = {
|
|
75
160
|
heading: [{ path: "text", kind: "text" }],
|
|
@@ -406,7 +491,7 @@ function fieldStyleCssText(style) {
|
|
|
406
491
|
}
|
|
407
492
|
|
|
408
493
|
// src/component.ts
|
|
409
|
-
var SECTION_DOCTRINE = "STRUCTURE (separate from schema): a page is composed of SECTIONS. NEVER build a page out of loose top-level heading/text/image/button/spacer blocks \u2014 they cannot be moved, duplicated or swapped as a unit, the visual editor cannot outline or name them, and every one of them becomes its own section in the editor. A hero of a headline, a lede and two CTAs is ONE section, not four. TWO SHAPES, and the choice is about REUSE. (1) A band that appears on more than one page, or that needs layout variants, is a COMPONENT with a `sectionType` \u2014 see create_component. Components sharing a `sectionType` are that section's VARIANTS (one Hero: 'Centered' for the home page and 'Two-column' for about, same prop keys so a swap keeps the content). This is also the only shape the editor's 'Add a section' picker can insert, and the only one that gets a family name and a variant switcher. (2) A genuinely one-off band on a single page is a `section` BLOCK whose `props.children` hold its blocks. THE TRADEOFF, stated in the present tense because it is real today: inside a component, ONLY the leaves a declared prop TARGETS are click-to-edit on the canvas \u2014 each declared prop's `target` is re-keyed to that PLACEMENT's own override address, so editing it changes this page and not the shared definition. A prop with no `target` still SHOWS as a dock control, but its override reaches no rendered slot, so editing it changes nothing on the page. Copy that no prop points at is worse still: no binding and no control, unreachable from click-to-edit AND from the dock, changeable only by editing the component definition, which rewrites every page that places it. A `section` block's children stay click-to-edit unconditionally. So when you choose a component, DECLARE A PROP \u2014 WITH A `target` \u2014 for every string, link and image a marketer will ever touch; a component with un-propped editable copy is the defect, not the component. In the dock an unset prop shows EMPTY and inherits the definition's default, so set props explicitly when you want the current copy visible there. An IMPORTED site's components are its own (read the repo); its nav, footer and modals are the Layout. On a blank site, do not hand-write a band's JSON: start from a built-in section blueprint (list_components returns locked `builtin:*` blueprints with no projectId \u2014 hero-centered, hero-split, feature-grid-three, cta-banner and
|
|
494
|
+
var SECTION_DOCTRINE = "STRUCTURE (separate from schema): a page is composed of SECTIONS. NEVER build a page out of loose top-level heading/text/image/button/spacer blocks \u2014 they cannot be moved, duplicated or swapped as a unit, the visual editor cannot outline or name them, and every one of them becomes its own section in the editor. A hero of a headline, a lede and two CTAs is ONE section, not four. TWO SHAPES, and the choice is about REUSE. (1) A band that appears on more than one page, or that needs layout variants, is a COMPONENT with a `sectionType` \u2014 see create_component. Components sharing a `sectionType` are that section's VARIANTS (one Hero: 'Centered' for the home page and 'Two-column' for about, same prop keys so a swap keeps the content). This is also the only shape the editor's 'Add a section' picker can insert, and the only one that gets a family name and a variant switcher. (2) A genuinely one-off band on a single page is a `section` BLOCK whose `props.children` hold its blocks. THE TRADEOFF, stated in the present tense because it is real today: inside a component, ONLY the leaves a declared prop TARGETS are click-to-edit on the canvas \u2014 each declared prop's `target` is re-keyed to that PLACEMENT's own override address, so editing it changes this page and not the shared definition. A prop with no `target` still SHOWS as a dock control, but its override reaches no rendered slot, so editing it changes nothing on the page. Copy that no prop points at is worse still: no binding and no control, unreachable from click-to-edit AND from the dock, changeable only by editing the component definition, which rewrites every page that places it. A `section` block's children stay click-to-edit unconditionally. So when you choose a component, DECLARE A PROP \u2014 WITH A `target` \u2014 for every string, link and image a marketer will ever touch; a component with un-propped editable copy is the defect, not the component. In the dock an unset prop shows EMPTY and inherits the definition's default, so set props explicitly when you want the current copy visible there. An IMPORTED site's components are its own (read the repo); its nav, footer and modals are the Layout. On a blank site, do not hand-write a band's JSON: start from a built-in section blueprint (list_components returns locked `builtin:*` blueprints with no projectId \u2014 hero-centered, hero-split, feature-grid-three, cta-banner and more), each already rooted in a `section` block with its editable leaves declared as props. INLINE its blockJson as a `section` block for a one-off band; for a recurring band, materialize it with create_component `from` so it becomes project-scoped before implementation validation, Output or publication. Direct `builtin:*` component references exist only for legacy delivery compatibility. Two consecutive call-to-action buttons are two sibling `button` blocks inside the same section \u2014 never a `columns` block, which is a `repeat(N,1fr)` grid and would stretch each CTA to half the container. Buttons are inline-level and flow side by side on their own.";
|
|
410
495
|
var COMPONENT_PROP_TYPES = [
|
|
411
496
|
"text",
|
|
412
497
|
"richtext",
|
|
@@ -447,16 +532,75 @@ var COMPONENT_PROP_TYPES = [
|
|
|
447
532
|
// CMS items, as the same-named content-model FIELDS store them: an entry id (or a polymorphic
|
|
448
533
|
// `{ entryId, modelSlug }`), and a list of them. Delivery hydrates them like an entry's.
|
|
449
534
|
"reference",
|
|
450
|
-
"multi-reference"
|
|
535
|
+
"multi-reference",
|
|
536
|
+
// V2 chrome types, each storing what the same-named content-model FIELD stores: a video value,
|
|
537
|
+
// a primitive list (`config.itemType`), and multi-line text (the field lane's V2 `text`).
|
|
538
|
+
"video",
|
|
539
|
+
"array",
|
|
540
|
+
"longtext"
|
|
451
541
|
];
|
|
452
542
|
var SLOT_MAX_ITEMS = 12;
|
|
453
543
|
var SLOT_ITEMS_CAP = 50;
|
|
454
544
|
function slotItems(value) {
|
|
455
545
|
const list = Array.isArray(value) ? value : [value];
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
546
|
+
const out = [];
|
|
547
|
+
for (const item of list) {
|
|
548
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) continue;
|
|
549
|
+
const o = item;
|
|
550
|
+
if (typeof o.componentId === "string" && o.componentId !== "") out.push(item);
|
|
551
|
+
else if (typeof o.componentId !== "string" && typeof o._type === "string" && o._type !== "") out.push({ componentId: o._type, overrides: o });
|
|
552
|
+
}
|
|
553
|
+
return out;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// src/slot-child.ts
|
|
557
|
+
var SLOT_CHILD_KEYS = ["_key", "_type", "_variant", "_settings"];
|
|
558
|
+
var RESERVED = new Set(SLOT_CHILD_KEYS);
|
|
559
|
+
var isRecord2 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
560
|
+
var isSlotChild = (v) => isRecord2(v) && typeof v._type === "string" && v._type !== "";
|
|
561
|
+
function slotChildValues(child) {
|
|
562
|
+
const out = {};
|
|
563
|
+
for (const [k, v] of Object.entries(child)) if (!RESERVED.has(k)) out[k] = v;
|
|
564
|
+
return out;
|
|
565
|
+
}
|
|
566
|
+
function slotShapeProblems(value, opts = {}) {
|
|
567
|
+
const label = opts.label ?? "slot";
|
|
568
|
+
const noun = opts.typeNoun ?? "a block type";
|
|
569
|
+
if (!Array.isArray(value)) return [{ path: [], code: "slot_value_invalid", message: `slot_value_invalid: ${label} must be a list of blocks ({ _key, _type, ...values })` }];
|
|
570
|
+
const out = [];
|
|
571
|
+
if (opts.max !== void 0 && value.length > opts.max) out.push({ path: [], code: "slot_too_many", message: `slot_too_many: ${label} holds at most ${opts.max} blocks, got ${value.length}` });
|
|
572
|
+
if (opts.min !== void 0 && value.length < opts.min) out.push({ path: [], code: "slot_too_few", message: `slot_too_few: ${label} needs at least ${opts.min} blocks, got ${value.length}` });
|
|
573
|
+
const keys = /* @__PURE__ */ new Set();
|
|
574
|
+
value.forEach((child, i) => {
|
|
575
|
+
if (!isRecord2(child)) {
|
|
576
|
+
out.push({ path: [i], code: "slot_value_invalid", message: `slot_value_invalid: ${label}: block ${i + 1} must be an object { _key, _type, ...values }` });
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
if (typeof child._key !== "string" || child._key.trim() === "") {
|
|
580
|
+
out.push({ path: [i, "_key"], code: "slot_child_key_required", message: `slot_child_key_required: ${label}: block ${i + 1} needs a _key (a non-empty string)` });
|
|
581
|
+
} else if (keys.has(child._key)) {
|
|
582
|
+
out.push({ path: [i, "_key"], code: "slot_child_key_duplicate", message: `slot_child_key_duplicate: ${label}: _key '${child._key}' is used by two blocks` });
|
|
583
|
+
} else keys.add(child._key);
|
|
584
|
+
if (typeof child._type !== "string" || child._type.trim() === "") {
|
|
585
|
+
out.push({ path: [i, "_type"], code: "slot_child_type_required", message: `slot_child_type_required: ${label}: block ${i + 1} needs a _type (${noun})` });
|
|
586
|
+
}
|
|
587
|
+
if (child._variant !== void 0) {
|
|
588
|
+
if (!opts.variants) out.push({ path: [i, "_variant"], code: "slot_variant_unsupported", message: `slot_variant_unsupported: ${label}: a component variant is its own component; name it in _type` });
|
|
589
|
+
else if (typeof child._variant !== "string" || child._variant === "") out.push({ path: [i, "_variant"], code: "slot_value_invalid", message: `slot_value_invalid: ${label}: _variant must be a variant name` });
|
|
590
|
+
}
|
|
591
|
+
if (child._settings !== void 0) {
|
|
592
|
+
if (!opts.settings) out.push({ path: [i, "_settings"], code: "slot_settings_undeclared", message: `slot_settings_undeclared: ${label} declares no slotSettings, so a block holds no _settings` });
|
|
593
|
+
else if (!isRecord2(child._settings)) out.push({ path: [i, "_settings"], code: "slot_value_invalid", message: `slot_value_invalid: ${label}: _settings must be an object keyed by the slot's slotSettings` });
|
|
594
|
+
}
|
|
595
|
+
for (const k of Object.keys(child)) {
|
|
596
|
+
if (k.startsWith("_") && !RESERVED.has(k)) {
|
|
597
|
+
out.push({ path: [i, k], code: "slot_child_key_unknown", message: `slot_child_key_unknown: ${label}: '${k}' is not a slot key (${SLOT_CHILD_KEYS.join(", ")}); a block's values have no leading underscore` });
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
});
|
|
601
|
+
return out;
|
|
459
602
|
}
|
|
603
|
+
var slotPathString = (path) => path.map((s, i) => typeof s === "number" ? `[${s}]` : i === 0 ? s : `.${s}`).join("");
|
|
460
604
|
|
|
461
605
|
// src/layout-lucide-icons.ts
|
|
462
606
|
var LAYOUT_SECTION_ICONS = Object.freeze([
|
|
@@ -2457,6 +2601,7 @@ function visibleDeliveredLayout(layout2, now) {
|
|
|
2457
2601
|
|
|
2458
2602
|
// src/dock-icon-names.ts
|
|
2459
2603
|
var DOCK_ICON_NAMES = [
|
|
2604
|
+
"abc",
|
|
2460
2605
|
"access-denied",
|
|
2461
2606
|
"activity",
|
|
2462
2607
|
"add",
|
|
@@ -2464,14 +2609,40 @@ var DOCK_ICON_NAMES = [
|
|
|
2464
2609
|
"add-comment",
|
|
2465
2610
|
"add-document",
|
|
2466
2611
|
"add-user",
|
|
2612
|
+
"address-book",
|
|
2613
|
+
"adjustments",
|
|
2614
|
+
"adjustments-horizontal",
|
|
2615
|
+
"alarm",
|
|
2616
|
+
"alert-triangle",
|
|
2617
|
+
"align-left",
|
|
2467
2618
|
"api",
|
|
2619
|
+
"app-window",
|
|
2620
|
+
"apple",
|
|
2621
|
+
"apps",
|
|
2468
2622
|
"archive",
|
|
2623
|
+
"arrow-back-up",
|
|
2469
2624
|
"arrow-down",
|
|
2625
|
+
"arrow-guide",
|
|
2470
2626
|
"arrow-left",
|
|
2471
2627
|
"arrow-right",
|
|
2472
2628
|
"arrow-top-right",
|
|
2473
2629
|
"arrow-up",
|
|
2630
|
+
"arrows-diagonal",
|
|
2631
|
+
"arrows-down",
|
|
2632
|
+
"arrows-exchange",
|
|
2633
|
+
"arrows-horizontal",
|
|
2634
|
+
"arrows-left-right",
|
|
2635
|
+
"arrows-shuffle",
|
|
2636
|
+
"arrows-sort",
|
|
2637
|
+
"article",
|
|
2638
|
+
"aspect-ratio",
|
|
2474
2639
|
"asterisk",
|
|
2640
|
+
"award",
|
|
2641
|
+
"axis-x",
|
|
2642
|
+
"backpack",
|
|
2643
|
+
"badge",
|
|
2644
|
+
"badge-cc",
|
|
2645
|
+
"badges",
|
|
2475
2646
|
"bar-chart",
|
|
2476
2647
|
"basket",
|
|
2477
2648
|
"bell",
|
|
@@ -2483,25 +2654,76 @@ var DOCK_ICON_NAMES = [
|
|
|
2483
2654
|
"bold",
|
|
2484
2655
|
"bolt",
|
|
2485
2656
|
"book",
|
|
2657
|
+
"book-2",
|
|
2486
2658
|
"bookmark",
|
|
2487
2659
|
"bookmark-filled",
|
|
2660
|
+
"books",
|
|
2488
2661
|
"bottle",
|
|
2662
|
+
"box",
|
|
2663
|
+
"brand-dribbble",
|
|
2664
|
+
"brand-facebook",
|
|
2665
|
+
"brand-instagram",
|
|
2666
|
+
"brand-linkedin",
|
|
2667
|
+
"brand-pinterest",
|
|
2668
|
+
"brand-tiktok",
|
|
2669
|
+
"brand-x",
|
|
2670
|
+
"brand-youtube",
|
|
2671
|
+
"briefcase",
|
|
2672
|
+
"broadcast",
|
|
2673
|
+
"browser",
|
|
2489
2674
|
"bug",
|
|
2675
|
+
"building",
|
|
2676
|
+
"building-skyscraper",
|
|
2677
|
+
"building-store",
|
|
2490
2678
|
"bulb-filled",
|
|
2491
2679
|
"bulb-outline",
|
|
2680
|
+
"calculator",
|
|
2492
2681
|
"calendar",
|
|
2682
|
+
"calendar-dollar",
|
|
2683
|
+
"calendar-event",
|
|
2684
|
+
"calendar-exclamation",
|
|
2685
|
+
"calendar-off",
|
|
2686
|
+
"calendar-plus",
|
|
2687
|
+
"calendar-star",
|
|
2688
|
+
"calendar-time",
|
|
2689
|
+
"camera",
|
|
2690
|
+
"campfire",
|
|
2691
|
+
"carousel-horizontal",
|
|
2493
2692
|
"case",
|
|
2693
|
+
"cash",
|
|
2694
|
+
"category",
|
|
2695
|
+
"category-2",
|
|
2696
|
+
"chart-area",
|
|
2697
|
+
"chart-arrows",
|
|
2698
|
+
"chart-bar",
|
|
2699
|
+
"chart-bar-popular",
|
|
2700
|
+
"chart-donut",
|
|
2701
|
+
"chart-dots",
|
|
2702
|
+
"chart-line",
|
|
2494
2703
|
"chart-upward",
|
|
2704
|
+
"check",
|
|
2705
|
+
"checkbox",
|
|
2706
|
+
"checklist",
|
|
2495
2707
|
"checkmark",
|
|
2496
2708
|
"checkmark-circle",
|
|
2709
|
+
"chef-hat",
|
|
2497
2710
|
"chevron-down",
|
|
2498
2711
|
"chevron-left",
|
|
2499
2712
|
"chevron-right",
|
|
2500
2713
|
"chevron-up",
|
|
2714
|
+
"chevrons-right",
|
|
2501
2715
|
"circle",
|
|
2716
|
+
"circle-check",
|
|
2717
|
+
"circle-dot",
|
|
2718
|
+
"circle-number-1",
|
|
2719
|
+
"circle-plus",
|
|
2720
|
+
"click",
|
|
2502
2721
|
"clipboard",
|
|
2503
2722
|
"clipboard-image",
|
|
2723
|
+
"clipboard-text",
|
|
2504
2724
|
"clock",
|
|
2725
|
+
"clock-check",
|
|
2726
|
+
"clock-hour-4",
|
|
2505
2727
|
"close",
|
|
2506
2728
|
"close-circle",
|
|
2507
2729
|
"code",
|
|
@@ -2509,20 +2731,31 @@ var DOCK_ICON_NAMES = [
|
|
|
2509
2731
|
"cog",
|
|
2510
2732
|
"collapse",
|
|
2511
2733
|
"color-wheel",
|
|
2734
|
+
"columns",
|
|
2735
|
+
"columns-2",
|
|
2736
|
+
"columns-3",
|
|
2512
2737
|
"comment",
|
|
2513
2738
|
"component",
|
|
2514
2739
|
"compose",
|
|
2515
2740
|
"compose-sparkles",
|
|
2516
2741
|
"confetti",
|
|
2517
2742
|
"controls",
|
|
2743
|
+
"cookie",
|
|
2518
2744
|
"copy",
|
|
2519
2745
|
"credit-card",
|
|
2520
2746
|
"crop",
|
|
2521
2747
|
"cube",
|
|
2748
|
+
"currency-dollar",
|
|
2522
2749
|
"dashboard",
|
|
2523
2750
|
"database",
|
|
2751
|
+
"database-search",
|
|
2524
2752
|
"desktop",
|
|
2753
|
+
"device-desktop",
|
|
2754
|
+
"device-mobile",
|
|
2755
|
+
"device-tablet",
|
|
2756
|
+
"devices",
|
|
2525
2757
|
"diamond",
|
|
2758
|
+
"discount",
|
|
2526
2759
|
"document",
|
|
2527
2760
|
"document-pdf",
|
|
2528
2761
|
"document-remove",
|
|
@@ -2532,6 +2765,7 @@ var DOCK_ICON_NAMES = [
|
|
|
2532
2765
|
"document-word",
|
|
2533
2766
|
"document-zip",
|
|
2534
2767
|
"documents",
|
|
2768
|
+
"door-exit",
|
|
2535
2769
|
"dot",
|
|
2536
2770
|
"double-chevron-down",
|
|
2537
2771
|
"double-chevron-left",
|
|
@@ -2541,9 +2775,12 @@ var DOCK_ICON_NAMES = [
|
|
|
2541
2775
|
"download",
|
|
2542
2776
|
"drag-handle",
|
|
2543
2777
|
"drop",
|
|
2778
|
+
"droplet",
|
|
2779
|
+
"droplet-half",
|
|
2544
2780
|
"earth-americas",
|
|
2545
2781
|
"earth-globe",
|
|
2546
2782
|
"edit",
|
|
2783
|
+
"egg",
|
|
2547
2784
|
"ellipsis-horizontal",
|
|
2548
2785
|
"ellipsis-vertical",
|
|
2549
2786
|
"empty",
|
|
@@ -2556,77 +2793,169 @@ var DOCK_ICON_NAMES = [
|
|
|
2556
2793
|
"error-screen",
|
|
2557
2794
|
"expand",
|
|
2558
2795
|
"eye-closed",
|
|
2796
|
+
"eye-off",
|
|
2559
2797
|
"eye-open",
|
|
2560
2798
|
"face-happy",
|
|
2561
2799
|
"face-indifferent",
|
|
2562
2800
|
"face-sad",
|
|
2801
|
+
"feather",
|
|
2563
2802
|
"feedback",
|
|
2803
|
+
"file",
|
|
2804
|
+
"file-certificate",
|
|
2805
|
+
"file-code",
|
|
2806
|
+
"file-download",
|
|
2807
|
+
"file-text",
|
|
2564
2808
|
"filter",
|
|
2809
|
+
"flag",
|
|
2810
|
+
"flame",
|
|
2811
|
+
"flask",
|
|
2812
|
+
"focus-2",
|
|
2565
2813
|
"folder",
|
|
2814
|
+
"folders",
|
|
2815
|
+
"forms",
|
|
2816
|
+
"frame",
|
|
2566
2817
|
"generate",
|
|
2818
|
+
"gift",
|
|
2819
|
+
"git-branch",
|
|
2567
2820
|
"github",
|
|
2821
|
+
"grid-dots",
|
|
2568
2822
|
"groq",
|
|
2823
|
+
"hammer",
|
|
2824
|
+
"hand-finger",
|
|
2825
|
+
"hanger",
|
|
2569
2826
|
"hash",
|
|
2827
|
+
"headphones",
|
|
2828
|
+
"headset",
|
|
2570
2829
|
"heart",
|
|
2571
2830
|
"heart-filled",
|
|
2831
|
+
"heart-handshake",
|
|
2572
2832
|
"help-circle",
|
|
2573
2833
|
"highlight",
|
|
2834
|
+
"history",
|
|
2574
2835
|
"home",
|
|
2836
|
+
"hourglass",
|
|
2575
2837
|
"ice-cream",
|
|
2838
|
+
"id-badge",
|
|
2839
|
+
"id-badge-2",
|
|
2576
2840
|
"image",
|
|
2577
2841
|
"image-remove",
|
|
2578
2842
|
"images",
|
|
2579
2843
|
"inbox",
|
|
2844
|
+
"infinity",
|
|
2845
|
+
"info-circle",
|
|
2580
2846
|
"info-filled",
|
|
2581
2847
|
"info-outline",
|
|
2848
|
+
"info-square-rounded",
|
|
2582
2849
|
"inline",
|
|
2583
2850
|
"inline-element",
|
|
2851
|
+
"input-search",
|
|
2584
2852
|
"insert-above",
|
|
2585
2853
|
"insert-below",
|
|
2586
2854
|
"italic",
|
|
2587
2855
|
"joystick",
|
|
2588
2856
|
"json",
|
|
2857
|
+
"language",
|
|
2589
2858
|
"launch",
|
|
2859
|
+
"layout",
|
|
2860
|
+
"layout-align-center",
|
|
2861
|
+
"layout-board",
|
|
2862
|
+
"layout-board-split",
|
|
2863
|
+
"layout-bottombar",
|
|
2864
|
+
"layout-bottombar-expand",
|
|
2865
|
+
"layout-cards",
|
|
2866
|
+
"layout-columns",
|
|
2867
|
+
"layout-dashboard",
|
|
2868
|
+
"layout-grid",
|
|
2869
|
+
"layout-list",
|
|
2870
|
+
"layout-navbar",
|
|
2871
|
+
"layout-rows",
|
|
2872
|
+
"layout-sidebar",
|
|
2873
|
+
"layout-sidebar-right",
|
|
2874
|
+
"leaf",
|
|
2590
2875
|
"leave",
|
|
2591
2876
|
"lemon",
|
|
2877
|
+
"library-photo",
|
|
2878
|
+
"lifebuoy",
|
|
2592
2879
|
"link",
|
|
2593
2880
|
"link-removed",
|
|
2594
2881
|
"linkedin",
|
|
2595
2882
|
"list",
|
|
2883
|
+
"list-check",
|
|
2884
|
+
"list-details",
|
|
2885
|
+
"list-numbers",
|
|
2886
|
+
"list-tree",
|
|
2596
2887
|
"lock",
|
|
2597
2888
|
"logo-js",
|
|
2598
2889
|
"logo-ts",
|
|
2890
|
+
"mail",
|
|
2891
|
+
"map-2",
|
|
2892
|
+
"map-pin",
|
|
2893
|
+
"map-pins",
|
|
2599
2894
|
"marker",
|
|
2600
2895
|
"marker-removed",
|
|
2601
2896
|
"master-detail",
|
|
2897
|
+
"math-function",
|
|
2898
|
+
"meat",
|
|
2602
2899
|
"menu",
|
|
2900
|
+
"message",
|
|
2901
|
+
"message-2",
|
|
2902
|
+
"message-check",
|
|
2903
|
+
"message-circle",
|
|
2904
|
+
"message-circle-2",
|
|
2905
|
+
"message-plus",
|
|
2906
|
+
"message-star",
|
|
2603
2907
|
"microphone",
|
|
2604
2908
|
"microphone-slash",
|
|
2605
2909
|
"mobile-device",
|
|
2910
|
+
"mood-empty",
|
|
2606
2911
|
"moon",
|
|
2912
|
+
"movie",
|
|
2913
|
+
"news",
|
|
2914
|
+
"notes",
|
|
2607
2915
|
"number",
|
|
2608
2916
|
"ok-hand",
|
|
2609
2917
|
"olist",
|
|
2610
2918
|
"overage",
|
|
2611
2919
|
"package",
|
|
2920
|
+
"packages",
|
|
2921
|
+
"palette",
|
|
2612
2922
|
"panel-left",
|
|
2613
2923
|
"panel-right",
|
|
2924
|
+
"paperclip",
|
|
2614
2925
|
"pause",
|
|
2926
|
+
"pencil",
|
|
2927
|
+
"phone",
|
|
2928
|
+
"photo",
|
|
2929
|
+
"photo-scan",
|
|
2930
|
+
"photo-search",
|
|
2931
|
+
"pig-money",
|
|
2615
2932
|
"pin",
|
|
2616
2933
|
"pin-filled",
|
|
2617
2934
|
"pin-removed",
|
|
2618
2935
|
"play",
|
|
2936
|
+
"player-play",
|
|
2937
|
+
"player-track-next",
|
|
2938
|
+
"playlist-add",
|
|
2619
2939
|
"plug",
|
|
2940
|
+
"plug-connected",
|
|
2941
|
+
"plus-minus",
|
|
2942
|
+
"point",
|
|
2620
2943
|
"presentation",
|
|
2944
|
+
"printer",
|
|
2621
2945
|
"progress-50",
|
|
2622
2946
|
"progress-75",
|
|
2623
2947
|
"projects",
|
|
2624
2948
|
"publish",
|
|
2949
|
+
"qrcode",
|
|
2950
|
+
"quote",
|
|
2625
2951
|
"read-only",
|
|
2952
|
+
"receipt",
|
|
2953
|
+
"recycle",
|
|
2626
2954
|
"redo",
|
|
2627
2955
|
"refresh",
|
|
2628
2956
|
"remove",
|
|
2629
2957
|
"remove-circle",
|
|
2958
|
+
"repeat",
|
|
2630
2959
|
"reset",
|
|
2631
2960
|
"restore",
|
|
2632
2961
|
"retrieve",
|
|
@@ -2634,49 +2963,90 @@ var DOCK_ICON_NAMES = [
|
|
|
2634
2963
|
"revert",
|
|
2635
2964
|
"robot",
|
|
2636
2965
|
"rocket",
|
|
2966
|
+
"rosette",
|
|
2967
|
+
"route",
|
|
2968
|
+
"ruler",
|
|
2969
|
+
"ruler-measure",
|
|
2970
|
+
"salad",
|
|
2971
|
+
"scale",
|
|
2637
2972
|
"schema",
|
|
2973
|
+
"school",
|
|
2638
2974
|
"search",
|
|
2975
|
+
"section",
|
|
2639
2976
|
"select",
|
|
2977
|
+
"send",
|
|
2978
|
+
"server",
|
|
2979
|
+
"settings",
|
|
2640
2980
|
"share",
|
|
2981
|
+
"shield-check",
|
|
2982
|
+
"shield-lock",
|
|
2983
|
+
"shopping-bag",
|
|
2984
|
+
"shopping-cart",
|
|
2985
|
+
"shopping-cart-plus",
|
|
2986
|
+
"signature",
|
|
2987
|
+
"sitemap",
|
|
2988
|
+
"slideshow",
|
|
2641
2989
|
"sort",
|
|
2990
|
+
"sort-descending",
|
|
2991
|
+
"spacing-vertical",
|
|
2642
2992
|
"sparkle",
|
|
2643
2993
|
"sparkles",
|
|
2994
|
+
"speakerphone",
|
|
2644
2995
|
"spinner",
|
|
2645
2996
|
"split-horizontal",
|
|
2646
2997
|
"split-vertical",
|
|
2647
2998
|
"square",
|
|
2648
2999
|
"stack",
|
|
3000
|
+
"stack-2",
|
|
2649
3001
|
"stack-compact",
|
|
3002
|
+
"stairs",
|
|
3003
|
+
"stairs-up",
|
|
2650
3004
|
"star",
|
|
2651
3005
|
"star-filled",
|
|
3006
|
+
"stars",
|
|
2652
3007
|
"stop",
|
|
2653
3008
|
"strikethrough",
|
|
2654
3009
|
"string",
|
|
3010
|
+
"subtask",
|
|
2655
3011
|
"sun",
|
|
3012
|
+
"superscript",
|
|
2656
3013
|
"sync",
|
|
3014
|
+
"table",
|
|
3015
|
+
"table-options",
|
|
2657
3016
|
"tablet-device",
|
|
2658
3017
|
"tag",
|
|
2659
3018
|
"tags",
|
|
2660
3019
|
"target",
|
|
2661
3020
|
"task",
|
|
3021
|
+
"template",
|
|
3022
|
+
"tent",
|
|
2662
3023
|
"terminal",
|
|
3024
|
+
"terminal-2",
|
|
2663
3025
|
"text",
|
|
2664
3026
|
"th-large",
|
|
2665
3027
|
"th-list",
|
|
3028
|
+
"thumb-up",
|
|
2666
3029
|
"thumbs-down",
|
|
2667
3030
|
"thumbs-up",
|
|
3031
|
+
"ticket",
|
|
2668
3032
|
"tiers",
|
|
2669
3033
|
"timeline",
|
|
2670
3034
|
"toggle-arrow-right",
|
|
3035
|
+
"toggle-right",
|
|
2671
3036
|
"token",
|
|
3037
|
+
"tool",
|
|
3038
|
+
"tools-kitchen-2",
|
|
2672
3039
|
"transfer",
|
|
2673
3040
|
"translate",
|
|
2674
3041
|
"trash",
|
|
2675
3042
|
"trend-upward",
|
|
2676
3043
|
"triangle-outline",
|
|
2677
3044
|
"trolley",
|
|
3045
|
+
"truck",
|
|
3046
|
+
"truck-delivery",
|
|
2678
3047
|
"truncate",
|
|
2679
3048
|
"twitter",
|
|
3049
|
+
"typography",
|
|
2680
3050
|
"ulist",
|
|
2681
3051
|
"unarchive",
|
|
2682
3052
|
"underline",
|
|
@@ -2687,12 +3057,22 @@ var DOCK_ICON_NAMES = [
|
|
|
2687
3057
|
"unpublish",
|
|
2688
3058
|
"upload",
|
|
2689
3059
|
"user",
|
|
3060
|
+
"user-circle",
|
|
3061
|
+
"user-plus",
|
|
3062
|
+
"user-search",
|
|
3063
|
+
"user-star",
|
|
2690
3064
|
"users",
|
|
3065
|
+
"users-group",
|
|
2691
3066
|
"versions",
|
|
2692
3067
|
"video",
|
|
3068
|
+
"vocabulary",
|
|
3069
|
+
"vs",
|
|
2693
3070
|
"warning-filled",
|
|
2694
3071
|
"warning-outline",
|
|
2695
|
-
"
|
|
3072
|
+
"weight",
|
|
3073
|
+
"world",
|
|
3074
|
+
"wrench",
|
|
3075
|
+
"zoom-question"
|
|
2696
3076
|
];
|
|
2697
3077
|
var DOCK_ICON_NAME_SET = new Set(DOCK_ICON_NAMES);
|
|
2698
3078
|
|
|
@@ -2703,7 +3083,7 @@ function listItems(f) {
|
|
|
2703
3083
|
if (f.type === "repeater") return f.fields ?? [];
|
|
2704
3084
|
if (f.type === "table") return c.fields ?? f.fields ?? [];
|
|
2705
3085
|
if (f.type === "array" && c.zones?.repeatable) return c.zones.repeatable.fields ?? [];
|
|
2706
|
-
if (f.type === "modular") return null;
|
|
3086
|
+
if (f.type === "modular" || f.type === "slot") return null;
|
|
2707
3087
|
return void 0;
|
|
2708
3088
|
}
|
|
2709
3089
|
function zoneFields(f) {
|
|
@@ -2719,7 +3099,7 @@ function layout(fields, fieldsets, root) {
|
|
|
2719
3099
|
const nonEmpty = new Set(
|
|
2720
3100
|
fields.map((f) => tabOf(byId.get(f.fieldsetId ?? ""))).filter((t) => t && tabIds.includes(t))
|
|
2721
3101
|
);
|
|
2722
|
-
const
|
|
3102
|
+
const strip2 = nonEmpty.size >= 2;
|
|
2723
3103
|
const branches = /* @__PURE__ */ new Map();
|
|
2724
3104
|
const nodeFor = (f, path) => {
|
|
2725
3105
|
const key = `${path}${f.key}`;
|
|
@@ -2740,12 +3120,12 @@ function layout(fields, fieldsets, root) {
|
|
|
2740
3120
|
return { kind: "leaf", key };
|
|
2741
3121
|
};
|
|
2742
3122
|
const pinned = [];
|
|
2743
|
-
const panels = new Map(
|
|
3123
|
+
const panels = new Map(strip2 ? tabIds.filter((t) => nonEmpty.has(t)).map((t) => [t, []]) : []);
|
|
2744
3124
|
const containers = /* @__PURE__ */ new Map();
|
|
2745
3125
|
for (const f of fields) {
|
|
2746
3126
|
const node = nodeFor(f, "");
|
|
2747
3127
|
const set = byId.get(f.fieldsetId ?? "");
|
|
2748
|
-
const target =
|
|
3128
|
+
const target = strip2 && panels.get(tabOf(set) ?? "") || pinned;
|
|
2749
3129
|
if (set?.kind !== "group" && set?.kind !== "row") {
|
|
2750
3130
|
target.push(node);
|
|
2751
3131
|
continue;
|
|
@@ -3155,6 +3535,534 @@ function buttonValueOfInstance(def, overrides) {
|
|
|
3155
3535
|
return readButtonValue({ ...props, label: props.text });
|
|
3156
3536
|
}
|
|
3157
3537
|
|
|
3538
|
+
// src/video-value.ts
|
|
3539
|
+
var VIDEO_VALUE_KEYS = ["url", "poster", "autoplay", "loop", "transcript"];
|
|
3540
|
+
var VIDEO_TRANSCRIPT_MAX = 1e5;
|
|
3541
|
+
var isPlainObject2 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
3542
|
+
var isVideoUrl = (s) => s === "" || /^https?:\/\/[^\s]+$/i.test(s.trim()) || /^\/(?!\/)\S*$/.test(s.trim());
|
|
3543
|
+
function videoUrlOf(value) {
|
|
3544
|
+
const url = typeof value === "string" ? value : isPlainObject2(value) ? value.url : void 0;
|
|
3545
|
+
return typeof url === "string" && url.trim() !== "" ? url.trim() : null;
|
|
3546
|
+
}
|
|
3547
|
+
function videoValueProblem(value) {
|
|
3548
|
+
if (typeof value === "string") return isVideoUrl(value) ? null : "video_value_invalid: url must be an http(s) URL or a site path";
|
|
3549
|
+
if (!isPlainObject2(value)) return "video_value_invalid: must be a URL string or { url, poster?, autoplay?, loop?, transcript? }";
|
|
3550
|
+
const unknown = Object.keys(value).find((k) => !VIDEO_VALUE_KEYS.includes(k));
|
|
3551
|
+
if (unknown !== void 0) return `video_value_invalid: unknown key "${unknown}" (${VIDEO_VALUE_KEYS.join(", ")})`;
|
|
3552
|
+
if (typeof value.url !== "string") return "video_value_invalid: needs a url string";
|
|
3553
|
+
if (!isVideoUrl(value.url)) return "video_value_invalid: url must be an http(s) URL or a site path";
|
|
3554
|
+
if (value.poster !== void 0 && (typeof value.poster !== "string" || !isVideoUrl(value.poster))) {
|
|
3555
|
+
return "video_value_invalid: poster must be an http(s) URL or a site path";
|
|
3556
|
+
}
|
|
3557
|
+
for (const key of ["autoplay", "loop"]) {
|
|
3558
|
+
if (value[key] !== void 0 && typeof value[key] !== "boolean") return `video_value_invalid: ${key} must be true or false`;
|
|
3559
|
+
}
|
|
3560
|
+
if (value.transcript !== void 0 && (typeof value.transcript !== "string" || value.transcript.length > VIDEO_TRANSCRIPT_MAX)) {
|
|
3561
|
+
return `video_value_invalid: transcript must be a string of ${VIDEO_TRANSCRIPT_MAX} characters or fewer`;
|
|
3562
|
+
}
|
|
3563
|
+
return null;
|
|
3564
|
+
}
|
|
3565
|
+
|
|
3566
|
+
// src/table-value.ts
|
|
3567
|
+
var TABLE_COLUMN_TYPES = ["text", "number", "money", "boolean", "rating", "link", "richtext-inline", "reference"];
|
|
3568
|
+
var TABLE_RESPONSIVE = ["scroll", "stack", "cards"];
|
|
3569
|
+
var TABLE_JSONLD_TYPES = ["none", "ItemList", "Dataset", "Offers"];
|
|
3570
|
+
var TABLE_LIMITS = { columns: 50, rows: 1e3, cellChars: 5e3, captionChars: 300, notesChars: 2e3, keyChars: 64, labelChars: 300 };
|
|
3571
|
+
var isObj = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
3572
|
+
var isTableValue = (v) => isObj(v) && Array.isArray(v.columns) && Array.isArray(v.rows);
|
|
3573
|
+
var isTableCellObject = (c) => isObj(c) && "value" in c;
|
|
3574
|
+
var isTableRef = (v) => isObj(v) && "ref" in v;
|
|
3575
|
+
var isTableLink = (v) => isObj(v) && !("ref" in v) && "href" in v;
|
|
3576
|
+
var tableCellValue = (c) => c === void 0 ? null : isTableCellObject(c) ? c.value : c;
|
|
3577
|
+
var tableCellType = (col, row, c) => isTableCellObject(c) && c.type || row?.type || col.type;
|
|
3578
|
+
var TOP_KEYS = /* @__PURE__ */ new Set(["id", "caption", "notes", "headerRow", "headerColumn", "columns", "columnGroups", "rowGroups", "rows", "footnotes", "filterable", "design", "jsonLd"]);
|
|
3579
|
+
var COLUMN_KEYS = /* @__PURE__ */ new Set(["_key", "label", "type", "description", "unit", "currency", "decimals", "align", "sortable", "group", "trueLabel", "falseLabel", "max", "refTo", "highlight"]);
|
|
3580
|
+
var ROW_KEYS = /* @__PURE__ */ new Set(["_key", "cells", "group", "footer", "type", "highlight"]);
|
|
3581
|
+
var GROUP_KEYS = /* @__PURE__ */ new Set(["_key", "label"]);
|
|
3582
|
+
var FOOTNOTE_KEYS = /* @__PURE__ */ new Set(["_key", "text"]);
|
|
3583
|
+
var DESIGN_KEYS = /* @__PURE__ */ new Set(["responsive", "sticky", "striped", "density", "hideCaption"]);
|
|
3584
|
+
var CELL_KEYS = /* @__PURE__ */ new Set(["value", "type", "note"]);
|
|
3585
|
+
var LINK_KEYS = /* @__PURE__ */ new Set(["label", "href", "newTab", "rel"]);
|
|
3586
|
+
var REF_KEYS = /* @__PURE__ */ new Set(["ref", "label", "href", "resolved"]);
|
|
3587
|
+
var TABLE_LINK_RELS = ["follow", ...LINK_RELS];
|
|
3588
|
+
function tableValueProblems(value, opts = {}) {
|
|
3589
|
+
const out = [];
|
|
3590
|
+
const bad = (path, message, code = "table_value_invalid") => out.push({ path, code, message: `${code}: ${message}` });
|
|
3591
|
+
if (!isTableValue(value)) {
|
|
3592
|
+
bad([], "a table is { caption, headerRow, headerColumn, columns: [{ _key, label, type }], rows: [{ _key, cells }] }");
|
|
3593
|
+
return out;
|
|
3594
|
+
}
|
|
3595
|
+
const t = value;
|
|
3596
|
+
const unknownKeys = (o, allowed, at) => {
|
|
3597
|
+
for (const k of Object.keys(o)) if (!allowed.has(k)) bad([...at, k], `unknown key "${k}" (${[...allowed].join(", ")})`);
|
|
3598
|
+
};
|
|
3599
|
+
const str = (v, at, what, max, required = false) => {
|
|
3600
|
+
if (v === void 0 && !required) return;
|
|
3601
|
+
if (typeof v !== "string") bad(at, `${what} must be a string`);
|
|
3602
|
+
else if (v.length > max) bad(at, `${what} is ${v.length} characters; at most ${max}`, "table_limit_exceeded");
|
|
3603
|
+
};
|
|
3604
|
+
const bool = (v, at, what) => {
|
|
3605
|
+
if (v !== void 0 && typeof v !== "boolean") bad(at, `${what} must be true or false`);
|
|
3606
|
+
};
|
|
3607
|
+
const oneOf = (v, at, what, allowed) => {
|
|
3608
|
+
if (v !== void 0 && !allowed.includes(v)) bad(at, `${what} must be one of ${allowed.join(", ")}`);
|
|
3609
|
+
};
|
|
3610
|
+
unknownKeys(t, TOP_KEYS, []);
|
|
3611
|
+
str(t.id, ["id"], "id", TABLE_LIMITS.keyChars);
|
|
3612
|
+
str(t.caption, ["caption"], "caption", TABLE_LIMITS.captionChars, true);
|
|
3613
|
+
if (typeof t.caption === "string" && t.caption.trim() === "" && opts.requireCaption !== false) {
|
|
3614
|
+
bad(["caption"], "give the table a caption that says what it compares (it names the table for screen readers and search)", "table_caption_required");
|
|
3615
|
+
}
|
|
3616
|
+
str(t.notes, ["notes"], "notes", TABLE_LIMITS.notesChars);
|
|
3617
|
+
if (t.notes !== void 0 && opts.allowNote === false && typeof t.notes === "string" && t.notes.trim() !== "") bad(["notes"], "this table takes no note (config.allowNote is false)");
|
|
3618
|
+
bool(t.headerRow, ["headerRow"], "headerRow");
|
|
3619
|
+
bool(t.headerColumn, ["headerColumn"], "headerColumn");
|
|
3620
|
+
bool(t.filterable, ["filterable"], "filterable");
|
|
3621
|
+
if (t.design !== void 0) {
|
|
3622
|
+
if (!isObj(t.design)) bad(["design"], "design must be an object");
|
|
3623
|
+
else {
|
|
3624
|
+
const d = t.design;
|
|
3625
|
+
unknownKeys(d, DESIGN_KEYS, ["design"]);
|
|
3626
|
+
oneOf(d.responsive, ["design", "responsive"], "design.responsive", TABLE_RESPONSIVE);
|
|
3627
|
+
oneOf(d.density, ["design", "density"], "design.density", ["compact", "comfortable"]);
|
|
3628
|
+
for (const k of ["sticky", "striped", "hideCaption"]) bool(d[k], ["design", k], `design.${k}`);
|
|
3629
|
+
}
|
|
3630
|
+
}
|
|
3631
|
+
const keyed = (list, at, keys, textKey, allowed) => {
|
|
3632
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3633
|
+
if (list === void 0) return seen;
|
|
3634
|
+
if (!Array.isArray(list)) {
|
|
3635
|
+
bad([at], `${at} must be an array`);
|
|
3636
|
+
return seen;
|
|
3637
|
+
}
|
|
3638
|
+
if (!allowed && list.length > 0) bad([at], `this table takes no ${at === "footnotes" ? "footnotes (config.allowFootnotes is false)" : "row groups (config.allowGroups is false)"}`);
|
|
3639
|
+
list.forEach((g, i) => {
|
|
3640
|
+
if (!isObj(g)) return bad([at, i], `${at}[${i}] must be an object`);
|
|
3641
|
+
unknownKeys(g, keys, [at, i]);
|
|
3642
|
+
if (typeof g._key !== "string" || g._key === "" || g._key.length > TABLE_LIMITS.keyChars) bad([at, i, "_key"], `needs a _key string of 1 to ${TABLE_LIMITS.keyChars} characters`);
|
|
3643
|
+
else if (seen.has(g._key)) bad([at, i, "_key"], `_key "${g._key}" is used twice`);
|
|
3644
|
+
else seen.add(g._key);
|
|
3645
|
+
str(g[textKey], [at, i, textKey], textKey, textKey === "text" ? TABLE_LIMITS.notesChars : TABLE_LIMITS.labelChars, true);
|
|
3646
|
+
});
|
|
3647
|
+
return seen;
|
|
3648
|
+
};
|
|
3649
|
+
const colGroups = keyed(t.columnGroups, "columnGroups", GROUP_KEYS, "label", true);
|
|
3650
|
+
const rowGroups = keyed(t.rowGroups, "rowGroups", GROUP_KEYS, "label", opts.allowGroups !== false);
|
|
3651
|
+
const notes = keyed(t.footnotes, "footnotes", FOOTNOTE_KEYS, "text", opts.allowFootnotes !== false);
|
|
3652
|
+
const columns = t.columns;
|
|
3653
|
+
const maxColumns = Math.min(opts.maxColumns ?? TABLE_LIMITS.columns, TABLE_LIMITS.columns);
|
|
3654
|
+
if (columns.length > maxColumns) bad(["columns"], `${columns.length} columns; at most ${maxColumns}`, "table_limit_exceeded");
|
|
3655
|
+
const cols = /* @__PURE__ */ new Map();
|
|
3656
|
+
columns.forEach((c, i) => {
|
|
3657
|
+
const at = ["columns", i];
|
|
3658
|
+
if (!isObj(c)) return bad(at, `columns[${i}] must be an object`);
|
|
3659
|
+
unknownKeys(c, COLUMN_KEYS, at);
|
|
3660
|
+
if (typeof c._key !== "string" || c._key === "" || c._key.length > TABLE_LIMITS.keyChars) bad([...at, "_key"], `needs a _key string of 1 to ${TABLE_LIMITS.keyChars} characters`);
|
|
3661
|
+
else if (cols.has(c._key)) bad([...at, "_key"], `_key "${c._key}" is used twice`);
|
|
3662
|
+
str(c.label, [...at, "label"], "label", TABLE_LIMITS.labelChars, true);
|
|
3663
|
+
if (!TABLE_COLUMN_TYPES.includes(c.type)) bad([...at, "type"], `type must be one of ${TABLE_COLUMN_TYPES.join(", ")}`);
|
|
3664
|
+
else if (opts.columnTypes && !opts.columnTypes.includes(c.type)) {
|
|
3665
|
+
bad([...at, "type"], `a ${String(c.type)} column is not offered here (config.columnTypes: ${opts.columnTypes.join(", ")})`, "table_column_type_not_allowed");
|
|
3666
|
+
}
|
|
3667
|
+
str(c.description, [...at, "description"], "description", TABLE_LIMITS.notesChars);
|
|
3668
|
+
str(c.unit, [...at, "unit"], "unit", 16);
|
|
3669
|
+
if (c.currency !== void 0 && (typeof c.currency !== "string" || !/^[A-Z]{3}$/.test(c.currency))) bad([...at, "currency"], "currency must be an ISO 4217 code such as USD");
|
|
3670
|
+
if (c.decimals !== void 0 && (!Number.isInteger(c.decimals) || c.decimals < 0 || c.decimals > 10)) bad([...at, "decimals"], "decimals must be a whole number from 0 to 10");
|
|
3671
|
+
if (c.max !== void 0 && (!Number.isInteger(c.max) || c.max < 1 || c.max > 10)) bad([...at, "max"], "max must be a whole number from 1 to 10");
|
|
3672
|
+
oneOf(c.align, [...at, "align"], "align", ["start", "center", "end"]);
|
|
3673
|
+
for (const k of ["sortable", "highlight"]) bool(c[k], [...at, k], k);
|
|
3674
|
+
str(c.trueLabel, [...at, "trueLabel"], "trueLabel", TABLE_LIMITS.labelChars);
|
|
3675
|
+
str(c.falseLabel, [...at, "falseLabel"], "falseLabel", TABLE_LIMITS.labelChars);
|
|
3676
|
+
if (c.group !== void 0 && (typeof c.group !== "string" || !colGroups.has(c.group))) bad([...at, "group"], `group "${String(c.group)}" is not a key of columnGroups`);
|
|
3677
|
+
if (c.refTo !== void 0 && (!Array.isArray(c.refTo) || c.refTo.some((r) => typeof r !== "string" || r === ""))) bad([...at, "refTo"], 'refTo must be a list of collection ids or "page"');
|
|
3678
|
+
if (typeof c._key === "string" && c._key !== "" && !cols.has(c._key)) cols.set(c._key, c);
|
|
3679
|
+
});
|
|
3680
|
+
if (opts.lockColumns && opts.lockedColumns) {
|
|
3681
|
+
const want = opts.lockedColumns.map((c) => `${c._key}:${c.type}`).join(",");
|
|
3682
|
+
const got = columns.map((c) => isObj(c) ? `${String(c._key)}:${String(c.type)}` : "?").join(",");
|
|
3683
|
+
if (want !== got) bad(["columns"], `this table's columns are set by its developer (config.lockColumns): keep ${opts.lockedColumns.map((c) => c._key).join(", ")}, in that order, with their types`, "table_columns_locked");
|
|
3684
|
+
}
|
|
3685
|
+
const rows = t.rows;
|
|
3686
|
+
const maxRows = Math.min(opts.maxRows ?? TABLE_LIMITS.rows, TABLE_LIMITS.rows);
|
|
3687
|
+
const body = rows.filter((r) => !(isObj(r) && r.footer === true)).length;
|
|
3688
|
+
if (rows.length > TABLE_LIMITS.rows || body > maxRows) bad(["rows"], `${body} rows; at most ${maxRows}`, "table_limit_exceeded");
|
|
3689
|
+
if (opts.minRows !== void 0 && body < opts.minRows) bad(["rows"], `${body} rows; at least ${opts.minRows}`, "table_rows_min");
|
|
3690
|
+
const rowKeys = /* @__PURE__ */ new Set();
|
|
3691
|
+
rows.forEach((r, i) => {
|
|
3692
|
+
const at = ["rows", i];
|
|
3693
|
+
if (!isObj(r)) return bad(at, `rows[${i}] must be an object`);
|
|
3694
|
+
unknownKeys(r, ROW_KEYS, at);
|
|
3695
|
+
if (typeof r._key !== "string" || r._key === "" || r._key.length > TABLE_LIMITS.keyChars) bad([...at, "_key"], `needs a _key string of 1 to ${TABLE_LIMITS.keyChars} characters`);
|
|
3696
|
+
else if (rowKeys.has(r._key)) bad([...at, "_key"], `_key "${r._key}" is used twice`);
|
|
3697
|
+
else rowKeys.add(r._key);
|
|
3698
|
+
if (r.group !== void 0 && (typeof r.group !== "string" || !rowGroups.has(r.group))) bad([...at, "group"], `group "${String(r.group)}" is not a key of rowGroups`);
|
|
3699
|
+
bool(r.footer, [...at, "footer"], "footer");
|
|
3700
|
+
bool(r.highlight, [...at, "highlight"], "highlight");
|
|
3701
|
+
oneOf(r.type, [...at, "type"], "type", TABLE_COLUMN_TYPES);
|
|
3702
|
+
if (!isObj(r.cells)) return bad([...at, "cells"], "cells must be an object keyed by column _key");
|
|
3703
|
+
for (const [k, cell] of Object.entries(r.cells)) {
|
|
3704
|
+
const cAt = [...at, "cells", k];
|
|
3705
|
+
const col = cols.get(k);
|
|
3706
|
+
if (!col) {
|
|
3707
|
+
bad(cAt, `no column has _key "${k}"`);
|
|
3708
|
+
continue;
|
|
3709
|
+
}
|
|
3710
|
+
cellProblems(cell, col, r, cAt, notes, opts, bad);
|
|
3711
|
+
}
|
|
3712
|
+
});
|
|
3713
|
+
return out;
|
|
3714
|
+
}
|
|
3715
|
+
function cellProblems(cell, col, row, at, notes, opts, bad) {
|
|
3716
|
+
if (cell === void 0 || cell === null) return;
|
|
3717
|
+
let v = cell;
|
|
3718
|
+
let vAt = at;
|
|
3719
|
+
if (isTableCellObject(cell)) {
|
|
3720
|
+
for (const k of Object.keys(cell)) if (!CELL_KEYS.has(k)) bad([...at, k], `unknown key "${k}" (value, type, note)`);
|
|
3721
|
+
if (cell.type !== void 0 && !TABLE_COLUMN_TYPES.includes(cell.type)) bad([...at, "type"], `type must be one of ${TABLE_COLUMN_TYPES.join(", ")}`);
|
|
3722
|
+
if (cell.note !== void 0 && (typeof cell.note !== "string" || !notes.has(cell.note))) bad([...at, "note"], `note "${String(cell.note)}" is not a key of footnotes`);
|
|
3723
|
+
v = cell.value;
|
|
3724
|
+
vAt = [...at, "value"];
|
|
3725
|
+
if (v === null) return;
|
|
3726
|
+
}
|
|
3727
|
+
const type = tableCellType(col, row, cell);
|
|
3728
|
+
if (typeof v === "string") {
|
|
3729
|
+
if (v.length > TABLE_LIMITS.cellChars) bad(vAt, `a cell holds at most ${TABLE_LIMITS.cellChars} characters`, "table_limit_exceeded");
|
|
3730
|
+
return;
|
|
3731
|
+
}
|
|
3732
|
+
if (typeof v === "number") {
|
|
3733
|
+
if (!Number.isFinite(v)) bad(vAt, "a number cell must be finite");
|
|
3734
|
+
return;
|
|
3735
|
+
}
|
|
3736
|
+
if (typeof v === "boolean") return;
|
|
3737
|
+
if (!isObj(v)) return bad(vAt, "a cell holds text, a number, true / false, a link { label, href } or a reference { ref }");
|
|
3738
|
+
if ("ref" in v) {
|
|
3739
|
+
if (type !== "reference") return bad(vAt, `a reference { ref } belongs in a reference cell; this cell is ${type}`);
|
|
3740
|
+
for (const k of Object.keys(v)) if (!REF_KEYS.has(k)) bad([...vAt, k], `unknown key "${k}" (ref, label, href)`);
|
|
3741
|
+
if (typeof v.ref !== "string" || v.ref === "") bad([...vAt, "ref"], "ref must be the id of a page or an entry");
|
|
3742
|
+
if (v.label !== void 0 && typeof v.label !== "string") bad([...vAt, "label"], "label must be a string");
|
|
3743
|
+
if (v.href !== void 0 && (typeof v.href !== "string" || isScriptHref(v.href))) bad([...vAt, "href"], "href must be a link the site can hold (no script links)", "link_value_invalid");
|
|
3744
|
+
return;
|
|
3745
|
+
}
|
|
3746
|
+
if (type !== "link") return bad(vAt, `a link { label, href } belongs in a link cell; this cell is ${type}`);
|
|
3747
|
+
for (const k of Object.keys(v)) if (!LINK_KEYS.has(k)) bad([...vAt, k], `unknown key "${k}" (label, href, newTab, rel)`);
|
|
3748
|
+
if (typeof v.label !== "string" && v.label !== void 0) bad([...vAt, "label"], "label must be a string");
|
|
3749
|
+
if (typeof v.href !== "string") return bad([...vAt, "href"], "needs an href string", "link_value_invalid");
|
|
3750
|
+
if (isScriptHref(v.href)) return bad([...vAt, "href"], "script links (javascript:, data:, vbscript:) aren't allowed", "link_value_invalid");
|
|
3751
|
+
const grammar = v.href !== "" ? opts.hrefProblem?.(v.href) : null;
|
|
3752
|
+
if (grammar) bad([...vAt, "href"], grammar, "link_value_invalid");
|
|
3753
|
+
if (v.newTab !== void 0 && typeof v.newTab !== "boolean") bad([...vAt, "newTab"], "newTab must be true or false", "link_value_invalid");
|
|
3754
|
+
if (v.rel !== void 0 && !TABLE_LINK_RELS.includes(v.rel)) bad([...vAt, "rel"], `rel must be one of ${TABLE_LINK_RELS.join(", ")}`, "link_value_invalid");
|
|
3755
|
+
}
|
|
3756
|
+
function tablePathString(path) {
|
|
3757
|
+
return path.map((s, i) => typeof s === "number" ? `[${s}]` : i === 0 ? s : `.${s}`).join("");
|
|
3758
|
+
}
|
|
3759
|
+
function normalizeTableValue(value) {
|
|
3760
|
+
if (!isTableValue(value)) return value;
|
|
3761
|
+
const t = structuredClone(value);
|
|
3762
|
+
t.headerRow = t.headerRow !== false;
|
|
3763
|
+
t.headerColumn = t.headerColumn === true;
|
|
3764
|
+
for (const r of t.rows) {
|
|
3765
|
+
if (!isObj(r) || !isObj(r.cells)) continue;
|
|
3766
|
+
for (const c of Object.values(r.cells)) {
|
|
3767
|
+
const v = isTableCellObject(c) ? c.value : c;
|
|
3768
|
+
if (isTableRef(v)) delete v.resolved;
|
|
3769
|
+
}
|
|
3770
|
+
}
|
|
3771
|
+
return t;
|
|
3772
|
+
}
|
|
3773
|
+
var readTable = (v) => ({ ...v, headerRow: v.headerRow !== false, headerColumn: v.headerColumn === true });
|
|
3774
|
+
function tableRefCells(value) {
|
|
3775
|
+
if (!isTableValue(value)) return [];
|
|
3776
|
+
const cols = new Map(value.columns.filter(isObj).map((c) => [c._key, c]));
|
|
3777
|
+
const out = [];
|
|
3778
|
+
value.rows.forEach((r, i) => {
|
|
3779
|
+
if (!isObj(r) || !isObj(r.cells)) return;
|
|
3780
|
+
for (const [k, c] of Object.entries(r.cells)) {
|
|
3781
|
+
const col = cols.get(k);
|
|
3782
|
+
if (!col) continue;
|
|
3783
|
+
const v = isTableCellObject(c) ? c.value : c;
|
|
3784
|
+
if (!isTableRef(v) || typeof v.ref !== "string" || v.ref === "" || tableCellType(col, r, c) !== "reference") continue;
|
|
3785
|
+
out.push({ cell: v, id: v.ref, path: ["rows", i, "cells", k, ...isTableCellObject(c) ? ["value"] : []], refTo: Array.isArray(col.refTo) && col.refTo.length ? col.refTo : null });
|
|
3786
|
+
}
|
|
3787
|
+
});
|
|
3788
|
+
return out;
|
|
3789
|
+
}
|
|
3790
|
+
var strip = (s) => s.replace(/<[^>]*>/g, "").replace(/ /g, " ").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
|
|
3791
|
+
var TRUE_WORDS = /* @__PURE__ */ new Set(["\u2713", "\u2714", "\u2714\uFE0F", "\u2611", "\u2705", "yes", "y", "true", "included", "available", "supported", "check", "\u25CF"]);
|
|
3792
|
+
var FALSE_WORDS = /* @__PURE__ */ new Set(["\u2717", "\u2715", "\u2716", "\u274C", "\xD7", "x", "no", "n", "false", "not included", "unavailable", "not available", "unsupported", "\u2014", "\u2013", "-", "\u25CB"]);
|
|
3793
|
+
function toBool(v) {
|
|
3794
|
+
if (typeof v === "boolean") return v;
|
|
3795
|
+
if (typeof v !== "string") return null;
|
|
3796
|
+
const s = strip(v).trim().toLowerCase();
|
|
3797
|
+
return TRUE_WORDS.has(s) ? true : FALSE_WORDS.has(s) ? false : null;
|
|
3798
|
+
}
|
|
3799
|
+
function toNumber(v) {
|
|
3800
|
+
if (typeof v === "number") return Number.isFinite(v) ? v : null;
|
|
3801
|
+
if (typeof v !== "string") return null;
|
|
3802
|
+
const s = v.replace(/[,\s]/g, "").replace(/[^\d.+-]/g, "");
|
|
3803
|
+
return s && /^[+-]?\d*\.?\d+$/.test(s) ? Number(s) : null;
|
|
3804
|
+
}
|
|
3805
|
+
var formatNumber2 = (n, decimals) => new Intl.NumberFormat("en-US", decimals != null ? { minimumFractionDigits: decimals, maximumFractionDigits: decimals } : { maximumFractionDigits: 6 }).format(n);
|
|
3806
|
+
function formatMoney(n, currency = "USD", decimals) {
|
|
3807
|
+
try {
|
|
3808
|
+
const whole = Number.isInteger(n) && decimals == null;
|
|
3809
|
+
return new Intl.NumberFormat("en-US", { style: "currency", currency, minimumFractionDigits: whole ? 0 : decimals ?? 2, maximumFractionDigits: whole ? 0 : decimals ?? 2 }).format(n);
|
|
3810
|
+
} catch {
|
|
3811
|
+
return `${formatNumber2(n, decimals)} ${currency}`;
|
|
3812
|
+
}
|
|
3813
|
+
}
|
|
3814
|
+
var isEmptyCell = (v) => v == null || v === "" || isObj(v) && !(isTableRef(v) ? v.ref : v.label || v.href);
|
|
3815
|
+
var refLabel = (r) => r.resolved?.title || r.label || r.ref;
|
|
3816
|
+
var refHref = (r) => r.resolved?.url ?? r.href;
|
|
3817
|
+
function tableCellText(col, row, c) {
|
|
3818
|
+
const v = tableCellValue(c);
|
|
3819
|
+
if (isEmptyCell(v)) return "";
|
|
3820
|
+
switch (tableCellType(col, row, c)) {
|
|
3821
|
+
case "boolean": {
|
|
3822
|
+
const b = toBool(v);
|
|
3823
|
+
return b == null ? strip(String(v)) : b ? col.trueLabel || "Included" : col.falseLabel || "Not included";
|
|
3824
|
+
}
|
|
3825
|
+
case "number": {
|
|
3826
|
+
const n = toNumber(v);
|
|
3827
|
+
return n == null ? strip(String(v)) : `${formatNumber2(n, col.decimals)}${col.unit ? /^[%°]/.test(col.unit) ? col.unit : ` ${col.unit}` : ""}`;
|
|
3828
|
+
}
|
|
3829
|
+
case "money": {
|
|
3830
|
+
const n = toNumber(v);
|
|
3831
|
+
return n == null ? strip(String(v)) : formatMoney(n, col.currency || "USD", col.decimals);
|
|
3832
|
+
}
|
|
3833
|
+
case "rating": {
|
|
3834
|
+
const n = toNumber(v);
|
|
3835
|
+
return n == null ? strip(String(v)) : `${formatNumber2(n, 1).replace(/\.0$/, "")} out of ${col.max ?? 5}`;
|
|
3836
|
+
}
|
|
3837
|
+
case "link":
|
|
3838
|
+
return isObj(v) ? String(v.label || v.href || "") : strip(String(v));
|
|
3839
|
+
case "reference":
|
|
3840
|
+
return isTableRef(v) ? refLabel(v) : strip(String(v));
|
|
3841
|
+
default:
|
|
3842
|
+
return isObj(v) ? String(v.label ?? "") : strip(String(v)).replace(/\s+/g, " ").trim();
|
|
3843
|
+
}
|
|
3844
|
+
}
|
|
3845
|
+
var esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
3846
|
+
var escAttr = (s) => esc(s).replace(/"/g, """);
|
|
3847
|
+
var safeHref = (h) => isScriptHref(h) ? "#" : h;
|
|
3848
|
+
var INLINE_TAGS = /* @__PURE__ */ new Set(["strong", "b", "em", "i", "u", "s", "del", "code", "a", "br", "sup", "sub", "mark", "small", "abbr"]);
|
|
3849
|
+
function sanitizeInline(html) {
|
|
3850
|
+
return html.replace(/<(script|style|iframe|object|embed|template)\b[\s\S]*?<\/\1>/gi, "").replace(/<\/?([a-z][a-z0-9]*)\b([^>]*)>/gi, (m, tag, attrs) => {
|
|
3851
|
+
const t = tag.toLowerCase();
|
|
3852
|
+
if (!INLINE_TAGS.has(t)) return "";
|
|
3853
|
+
const name = t === "b" ? "strong" : t === "i" ? "em" : t;
|
|
3854
|
+
if (m.startsWith("</")) return `</${name}>`;
|
|
3855
|
+
if (t === "a") {
|
|
3856
|
+
const href = attrs.match(/href\s*=\s*("([^"]*)"|'([^']*)')/i);
|
|
3857
|
+
return `<a href="${escAttr(safeHref(href ? href[2] ?? href[3] ?? "" : ""))}">`;
|
|
3858
|
+
}
|
|
3859
|
+
if (t === "abbr") {
|
|
3860
|
+
const title = attrs.match(/title\s*=\s*"([^"]*)"/i);
|
|
3861
|
+
return title ? `<abbr title="${escAttr(title[1])}">` : "<abbr>";
|
|
3862
|
+
}
|
|
3863
|
+
return `<${name}>`;
|
|
3864
|
+
});
|
|
3865
|
+
}
|
|
3866
|
+
var alignOf = (col, t) => col.align ?? (t === "number" || t === "money" || t === "rating" ? "end" : "start");
|
|
3867
|
+
function orderedRows(t) {
|
|
3868
|
+
const groups = (t.rowGroups ?? []).filter(isObj);
|
|
3869
|
+
const known = new Set(groups.map((g) => g._key));
|
|
3870
|
+
const body = t.rows.filter((r) => isObj(r) && !r.footer);
|
|
3871
|
+
const loose = body.filter((r) => !r.group || !known.has(r.group));
|
|
3872
|
+
const bodies = [];
|
|
3873
|
+
if (loose.length || !groups.length) bodies.push({ rows: loose });
|
|
3874
|
+
for (const g of groups) {
|
|
3875
|
+
const rows = body.filter((r) => r.group === g._key);
|
|
3876
|
+
if (rows.length) bodies.push({ group: g, rows });
|
|
3877
|
+
}
|
|
3878
|
+
return { bodies, foot: t.rows.filter((r) => isObj(r) && r.footer) };
|
|
3879
|
+
}
|
|
3880
|
+
function cellHtml(t, col, row, c, fn, asHeader) {
|
|
3881
|
+
const v = tableCellValue(c);
|
|
3882
|
+
const type = tableCellType(col, row, c);
|
|
3883
|
+
const note = isTableCellObject(c) ? c.note : void 0;
|
|
3884
|
+
const n = note ? fn.get(note) : void 0;
|
|
3885
|
+
const sup = n ? `<sup><a href="#${escAttr(t.id ?? "tbl")}-fn-${n}" aria-label="Note ${n}">${n}</a></sup>` : "";
|
|
3886
|
+
let inner;
|
|
3887
|
+
if (isEmptyCell(v)) inner = asHeader ? "" : `<span aria-hidden="true" class="bt-dash">\u2014</span><span class="bt-sr">No value</span>`;
|
|
3888
|
+
else
|
|
3889
|
+
switch (type) {
|
|
3890
|
+
case "boolean": {
|
|
3891
|
+
const b = toBool(v);
|
|
3892
|
+
inner = b == null ? esc(strip(String(v))) : `<span aria-hidden="true" class="bt-bool" data-bool="${b}">${b ? "\u2713" : "\u2013"}</span><span class="bt-sr">${esc(b ? col.trueLabel || "Included" : col.falseLabel || "Not included")}</span>`;
|
|
3893
|
+
break;
|
|
3894
|
+
}
|
|
3895
|
+
case "rating": {
|
|
3896
|
+
const num = toNumber(v);
|
|
3897
|
+
inner = num == null ? esc(strip(String(v))) : `<span aria-hidden="true" class="bt-star">\u2605</span> ${esc(formatNumber2(num, 1).replace(/\.0$/, ""))}<span class="bt-dim"> / ${col.max ?? 5}</span>`;
|
|
3898
|
+
break;
|
|
3899
|
+
}
|
|
3900
|
+
case "link": {
|
|
3901
|
+
const l = isObj(v) ? v : { label: String(v), href: "" };
|
|
3902
|
+
const rel = [l.newTab ? "noopener noreferrer" : "", l.rel && l.rel !== "follow" ? l.rel : ""].filter(Boolean).join(" ");
|
|
3903
|
+
inner = l.href ? `<a href="${escAttr(safeHref(l.href))}"${l.newTab ? ' target="_blank"' : ""}${rel ? ` rel="${rel}"` : ""}>${esc(l.label || l.href)}</a>` : esc(l.label ?? "");
|
|
3904
|
+
break;
|
|
3905
|
+
}
|
|
3906
|
+
case "reference": {
|
|
3907
|
+
if (!isTableRef(v)) {
|
|
3908
|
+
inner = esc(strip(String(v)));
|
|
3909
|
+
break;
|
|
3910
|
+
}
|
|
3911
|
+
const href = refHref(v);
|
|
3912
|
+
inner = href ? `<a href="${escAttr(safeHref(href))}">${esc(refLabel(v))}</a>` : esc(refLabel(v));
|
|
3913
|
+
break;
|
|
3914
|
+
}
|
|
3915
|
+
case "richtext-inline":
|
|
3916
|
+
inner = sanitizeInline(String(isObj(v) ? v.label ?? "" : v));
|
|
3917
|
+
break;
|
|
3918
|
+
default:
|
|
3919
|
+
inner = esc(type === "number" || type === "money" ? tableCellText(col, row, c) : isObj(v) ? String(v.label ?? "") : strip(String(v)));
|
|
3920
|
+
}
|
|
3921
|
+
return { inner: inner + sup, align: alignOf(col, type) };
|
|
3922
|
+
}
|
|
3923
|
+
var TABLE_CSS = '.bt-table .bt-sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.bt-table .bt-scroll{overflow-x:auto}.bt-table table{border-collapse:collapse;width:100%}.bt-table th,.bt-table td{padding:8px 12px;border-bottom:1px solid #e5e5e5;text-align:start;vertical-align:top}.bt-table [data-align="end"]{text-align:end}.bt-table [data-align="center"]{text-align:center}.bt-table caption{text-align:start;font-weight:600;padding-bottom:8px}.bt-table .bt-notes{font-size:.9em;margin-top:8px}';
|
|
3924
|
+
function renderTableHtml(input) {
|
|
3925
|
+
const t = readTable(input);
|
|
3926
|
+
const id = (t.id ?? "tbl").replace(/[^\w-]/g, "") || "tbl";
|
|
3927
|
+
const cols = t.columns.filter(isObj);
|
|
3928
|
+
const n = cols.length;
|
|
3929
|
+
if (!n) return "";
|
|
3930
|
+
const fn = new Map((t.footnotes ?? []).filter(isObj).map((f, i) => [f._key, i + 1]));
|
|
3931
|
+
const groups = (t.columnGroups ?? []).filter((g) => isObj(g) && cols.some((c) => c.group === g._key));
|
|
3932
|
+
const hasNotes = !!t.notes || fn.size > 0;
|
|
3933
|
+
const responsive = t.design?.responsive ?? "scroll";
|
|
3934
|
+
const fig = [];
|
|
3935
|
+
const attrs = [
|
|
3936
|
+
`class="bt-table"`,
|
|
3937
|
+
`data-responsive="${escAttr(responsive)}"`,
|
|
3938
|
+
t.design?.sticky ? `data-sticky="true"` : "",
|
|
3939
|
+
t.design?.striped ? `data-striped="true"` : "",
|
|
3940
|
+
t.design?.density === "compact" ? `data-density="compact"` : ""
|
|
3941
|
+
].filter(Boolean);
|
|
3942
|
+
fig.push(`<figure ${attrs.join(" ")}><style>${TABLE_CSS}</style>`);
|
|
3943
|
+
fig.push(`<div class="bt-scroll" role="region" tabindex="0" aria-labelledby="${id}-caption">`);
|
|
3944
|
+
fig.push(`<table${hasNotes ? ` aria-describedby="${id}-notes"` : ""}>`);
|
|
3945
|
+
fig.push(`<caption id="${id}-caption"${t.design?.hideCaption ? ` class="bt-sr"` : ""}>${esc(t.caption || "Table")}</caption>`);
|
|
3946
|
+
if (t.headerRow) {
|
|
3947
|
+
fig.push("<thead>");
|
|
3948
|
+
if (groups.length) {
|
|
3949
|
+
const cells = [];
|
|
3950
|
+
for (let i = 0; i < n; ) {
|
|
3951
|
+
const g = cols[i].group ? groups.find((x) => x._key === cols[i].group) : void 0;
|
|
3952
|
+
if (!g) {
|
|
3953
|
+
cells.push("<td></td>");
|
|
3954
|
+
i++;
|
|
3955
|
+
continue;
|
|
3956
|
+
}
|
|
3957
|
+
let span = 1;
|
|
3958
|
+
while (i + span < n && cols[i + span].group === g._key) span++;
|
|
3959
|
+
cells.push(`<th scope="colgroup"${span > 1 ? ` colspan="${span}"` : ""}>${esc(g.label)}</th>`);
|
|
3960
|
+
i += span;
|
|
3961
|
+
}
|
|
3962
|
+
fig.push(`<tr>${cells.join("")}</tr>`);
|
|
3963
|
+
}
|
|
3964
|
+
fig.push(
|
|
3965
|
+
`<tr>${cols.map((c, i) => {
|
|
3966
|
+
if (i === 0 && t.headerColumn && !String(c.label ?? "").trim()) return "<td></td>";
|
|
3967
|
+
const align = alignOf(c, c.type);
|
|
3968
|
+
return `<th scope="col"${align !== "start" ? ` data-align="${align}"` : ""}${c.highlight ? ` data-highlight="true"` : ""}${c.description ? ` title="${escAttr(c.description)}"` : ""}>${esc(c.label || `Column ${i + 1}`)}</th>`;
|
|
3969
|
+
}).join("")}</tr>`
|
|
3970
|
+
);
|
|
3971
|
+
fig.push("</thead>");
|
|
3972
|
+
}
|
|
3973
|
+
const rowHtml = (r) => {
|
|
3974
|
+
const cells = cols.map((c, i) => {
|
|
3975
|
+
const asTh = t.headerColumn && i === 0;
|
|
3976
|
+
const { inner, align } = cellHtml(t, c, r, isObj(r.cells) ? r.cells[c._key] : void 0, fn, asTh);
|
|
3977
|
+
const a = `${align !== "start" ? ` data-align="${align}"` : ""}${c.highlight ? ` data-highlight="true"` : ""}`;
|
|
3978
|
+
return asTh ? `<th scope="row"${a}>${inner}</th>` : `<td data-label="${escAttr(c.label || `Column ${i + 1}`)}"${a}>${inner}</td>`;
|
|
3979
|
+
});
|
|
3980
|
+
return `<tr${r.highlight ? ` data-highlight="true"` : ""}>${cells.join("")}</tr>`;
|
|
3981
|
+
};
|
|
3982
|
+
const { bodies, foot } = orderedRows(t);
|
|
3983
|
+
for (const b of bodies) {
|
|
3984
|
+
fig.push("<tbody>");
|
|
3985
|
+
if (b.group) fig.push(`<tr class="bt-group"><th scope="rowgroup" colspan="${n}">${esc(b.group.label)}</th></tr>`);
|
|
3986
|
+
fig.push(b.rows.map(rowHtml).join(""));
|
|
3987
|
+
fig.push("</tbody>");
|
|
3988
|
+
}
|
|
3989
|
+
if (foot.length) fig.push(`<tfoot>${foot.map(rowHtml).join("")}</tfoot>`);
|
|
3990
|
+
fig.push("</table></div>");
|
|
3991
|
+
if (hasNotes) {
|
|
3992
|
+
fig.push(`<div class="bt-notes" id="${id}-notes">`);
|
|
3993
|
+
if (t.notes) fig.push(`<p>${esc(t.notes)}</p>`);
|
|
3994
|
+
if (fn.size) fig.push(`<ol>${(t.footnotes ?? []).filter(isObj).map((f, i) => `<li id="${id}-fn-${i + 1}">${esc(f.text)}</li>`).join("")}</ol>`);
|
|
3995
|
+
fig.push("</div>");
|
|
3996
|
+
}
|
|
3997
|
+
fig.push("</figure>");
|
|
3998
|
+
const html = fig.join("");
|
|
3999
|
+
return responsive === "stack" || responsive === "cards" ? html.replace(/<table(?=[\s>])/, '<table role="table"').replace(/<(thead|tbody|tfoot)(?=[\s>])/g, '<$1 role="rowgroup"').replace(/<tr(?=[\s>])/g, '<tr role="row"').replace(/<th scope="(col|colgroup)"/g, '<th role="columnheader" scope="$1"').replace(/<th scope="(row|rowgroup)"/g, '<th role="rowheader" scope="$1"').replace(/<td(?=[\s>])/g, '<td role="cell"') : html;
|
|
4000
|
+
}
|
|
4001
|
+
var mdSafe = (s) => s.replace(/(\]\([^)]*\))|[<>]/g, (m, link) => link ?? (m === "<" ? "<" : ">"));
|
|
4002
|
+
var mdCell = (s) => mdSafe(s).replace(/\\/g, "\\\\").replace(/\|/g, "\\|").replace(/\s*\n\s*/g, " ").trim();
|
|
4003
|
+
var inlineMd = (html) => strip(
|
|
4004
|
+
sanitizeInline(html).replace(/<(strong)>([\s\S]*?)<\/\1>/g, "**$2**").replace(/<(em)>([\s\S]*?)<\/\1>/g, "_$2_").replace(/<code>([\s\S]*?)<\/code>/g, "`$1`").replace(/<a href="([^"]*)">([\s\S]*?)<\/a>/g, (_m, h, l) => `[${l}](${h.replace(/&/g, "&")})`).replace(/<br>/g, " ")
|
|
4005
|
+
);
|
|
4006
|
+
function tableToMarkdown(input) {
|
|
4007
|
+
const t = readTable(input);
|
|
4008
|
+
const cols = t.columns.filter(isObj);
|
|
4009
|
+
if (!cols.length) return "";
|
|
4010
|
+
const groups = new Map((t.columnGroups ?? []).filter(isObj).map((g) => [g._key, g.label]));
|
|
4011
|
+
const fn = new Map((t.footnotes ?? []).filter(isObj).map((f, i) => [f._key, i + 1]));
|
|
4012
|
+
const pfx = (t.id ?? "t").replace(/[^\w-]/g, "") || "t";
|
|
4013
|
+
const line = (cells) => `| ${cells.join(" | ")} |`;
|
|
4014
|
+
const head = cols.map((c, i) => mdCell([c.group && groups.get(c.group), c.label || (i === 0 && t.headerColumn ? "" : `Column ${i + 1}`)].filter(Boolean).join(" \xB7 ")) || " ");
|
|
4015
|
+
const sep = cols.map((c) => alignOf(c, c.type) === "end" ? "---:" : alignOf(c, c.type) === "center" ? ":---:" : "---");
|
|
4016
|
+
const row = (r) => line(
|
|
4017
|
+
cols.map((c, i) => {
|
|
4018
|
+
const cell = isObj(r.cells) ? r.cells[c._key] : void 0;
|
|
4019
|
+
const v = tableCellValue(cell);
|
|
4020
|
+
const ty = tableCellType(c, r, cell);
|
|
4021
|
+
let s = ty === "richtext-inline" && typeof v === "string" ? inlineMd(v) : tableCellText(c, r, cell);
|
|
4022
|
+
if (ty === "link" && isTableLink(v) && v.href && !isScriptHref(v.href)) s = `[${s}](${v.href})`;
|
|
4023
|
+
if (ty === "reference" && isTableRef(v)) {
|
|
4024
|
+
const href = refHref(v);
|
|
4025
|
+
if (href && !isScriptHref(href)) s = `[${s}](${href})`;
|
|
4026
|
+
}
|
|
4027
|
+
if (!s && !(t.headerColumn && i === 0)) s = "\u2014";
|
|
4028
|
+
if (t.headerColumn && i === 0 && s) s = `**${s}**`;
|
|
4029
|
+
const note = isTableCellObject(cell) ? cell.note : void 0;
|
|
4030
|
+
if (note && fn.get(note)) s += `[^${pfx}-${fn.get(note)}]`;
|
|
4031
|
+
return mdCell(s) || " ";
|
|
4032
|
+
})
|
|
4033
|
+
);
|
|
4034
|
+
const out = [`**${mdCell(t.caption || "Table")}**`, "", line(head), line(sep)];
|
|
4035
|
+
const { bodies, foot } = orderedRows(t);
|
|
4036
|
+
for (const b of bodies) {
|
|
4037
|
+
if (b.group) out.push(line([`**${mdCell(b.group.label)}**`, ...cols.slice(1).map(() => " ")]));
|
|
4038
|
+
b.rows.forEach((r) => out.push(row(r)));
|
|
4039
|
+
}
|
|
4040
|
+
foot.forEach((r) => out.push(row(r)));
|
|
4041
|
+
const after = [];
|
|
4042
|
+
if (t.notes) after.push(mdSafe(t.notes));
|
|
4043
|
+
const described = cols.filter((c) => c.description);
|
|
4044
|
+
if (described.length) after.push(mdSafe(described.map((c) => `${c.label}: ${c.description}`).join(". ") + "."));
|
|
4045
|
+
if (fn.size) after.push((t.footnotes ?? []).filter(isObj).map((f, i) => `[^${pfx}-${i + 1}]: ${mdSafe(f.text)}`).join("\n"));
|
|
4046
|
+
return [out.join("\n"), ...after].join("\n\n");
|
|
4047
|
+
}
|
|
4048
|
+
function tableSearchText(input) {
|
|
4049
|
+
if (!isTableValue(input)) return "";
|
|
4050
|
+
const t = input;
|
|
4051
|
+
const cols = t.columns.filter(isObj);
|
|
4052
|
+
const parts = [t.caption, t.notes ?? ""];
|
|
4053
|
+
for (const c of cols) parts.push(c.label, c.description ?? "");
|
|
4054
|
+
for (const g of [...t.columnGroups ?? [], ...t.rowGroups ?? []]) if (isObj(g)) parts.push(g.label);
|
|
4055
|
+
for (const r of t.rows) {
|
|
4056
|
+
if (!isObj(r) || !isObj(r.cells)) continue;
|
|
4057
|
+
for (const c of cols) {
|
|
4058
|
+
const cell = r.cells[c._key];
|
|
4059
|
+
parts.push(tableCellType(c, r, cell) === "richtext-inline" ? strip(String(tableCellValue(cell) ?? "")) : tableCellText(c, r, cell));
|
|
4060
|
+
}
|
|
4061
|
+
}
|
|
4062
|
+
for (const f of t.footnotes ?? []) if (isObj(f)) parts.push(f.text);
|
|
4063
|
+
return parts.filter((p) => typeof p === "string" && p.trim() !== "").map((p) => p.trim()).join(" ");
|
|
4064
|
+
}
|
|
4065
|
+
|
|
3158
4066
|
// src/content-model.ts
|
|
3159
4067
|
var OPTION_DESCRIPTION_MAX = 140;
|
|
3160
4068
|
|
|
@@ -3218,6 +4126,96 @@ function regionOf(regions, el) {
|
|
|
3218
4126
|
for (const r of regions) if (r.el.contains(el)) slot = r.slot;
|
|
3219
4127
|
return slot;
|
|
3220
4128
|
}
|
|
4129
|
+
|
|
4130
|
+
// src/sections.ts
|
|
4131
|
+
var TAG_HEADS = /* @__PURE__ */ new Set([
|
|
4132
|
+
"h1",
|
|
4133
|
+
"h2",
|
|
4134
|
+
"h3",
|
|
4135
|
+
"h4",
|
|
4136
|
+
"h5",
|
|
4137
|
+
"h6",
|
|
4138
|
+
"p",
|
|
4139
|
+
"a",
|
|
4140
|
+
"img",
|
|
4141
|
+
"li",
|
|
4142
|
+
"list",
|
|
4143
|
+
"blockquote",
|
|
4144
|
+
"figcaption",
|
|
4145
|
+
"button",
|
|
4146
|
+
"summary",
|
|
4147
|
+
"dt",
|
|
4148
|
+
"dd",
|
|
4149
|
+
"th",
|
|
4150
|
+
"td",
|
|
4151
|
+
"pre",
|
|
4152
|
+
"label",
|
|
4153
|
+
"span",
|
|
4154
|
+
"div",
|
|
4155
|
+
"time",
|
|
4156
|
+
"strong",
|
|
4157
|
+
"em",
|
|
4158
|
+
"small",
|
|
4159
|
+
"b",
|
|
4160
|
+
"i",
|
|
4161
|
+
"code",
|
|
4162
|
+
"icon",
|
|
4163
|
+
"bg"
|
|
4164
|
+
]);
|
|
4165
|
+
var topFieldKeyOf = (path) => path.split(/[.[]/, 1)[0] ?? path;
|
|
4166
|
+
function fieldGroupOf(topKey, flat = false) {
|
|
4167
|
+
if (topKey.startsWith("group-")) return { groupKey: topKey, rooted: true };
|
|
4168
|
+
const camel = flat ? /^([a-z][a-z0-9]*)[A-Z]/.exec(topKey)?.[1] : void 0;
|
|
4169
|
+
if (camel) return TAG_HEADS.has(camel) ? { groupKey: topKey, rooted: false } : { groupKey: camel, rooted: true };
|
|
4170
|
+
const head = topKey.split(/[-_]/, 1)[0] || topKey;
|
|
4171
|
+
if (TAG_HEADS.has(head)) return { groupKey: topKey, rooted: false };
|
|
4172
|
+
return { groupKey: head, rooted: true };
|
|
4173
|
+
}
|
|
4174
|
+
function placementBindOf(block) {
|
|
4175
|
+
if (!block || typeof block !== "object" || block.type !== "component") return null;
|
|
4176
|
+
const props = block.props;
|
|
4177
|
+
const bind = props?.bind;
|
|
4178
|
+
if (typeof bind === "string" && bind) return bind;
|
|
4179
|
+
const source = props?.source;
|
|
4180
|
+
if (!source || typeof source !== "object") return null;
|
|
4181
|
+
const groups = Object.values(source).filter((path) => typeof path === "string" && path.length > 0).map((path) => ({ top: topFieldKeyOf(path), group: fieldGroupOf(topFieldKeyOf(path), path === topFieldKeyOf(path)).groupKey }));
|
|
4182
|
+
return (groups.find((g) => g.group !== g.top) ?? groups[0])?.group ?? null;
|
|
4183
|
+
}
|
|
4184
|
+
var CODE_SLOT_PREFIX = "code:";
|
|
4185
|
+
var slotBindOf = (slot) => slot.startsWith(CODE_SLOT_PREFIX) ? slot.slice(CODE_SLOT_PREFIX.length) : slot;
|
|
4186
|
+
function planSections(slots, blocks) {
|
|
4187
|
+
if (!Array.isArray(blocks)) return slots.map((slot) => ({ slot, block: null }));
|
|
4188
|
+
const byBind = /* @__PURE__ */ new Map();
|
|
4189
|
+
for (const slot of slots) if (!byBind.has(slotBindOf(slot))) byBind.set(slotBindOf(slot), slot);
|
|
4190
|
+
const out = [];
|
|
4191
|
+
const named = /* @__PURE__ */ new Set();
|
|
4192
|
+
for (const block of blocks) {
|
|
4193
|
+
const bind = placementBindOf(block);
|
|
4194
|
+
if (bind === null) {
|
|
4195
|
+
out.push({ slot: null, block });
|
|
4196
|
+
continue;
|
|
4197
|
+
}
|
|
4198
|
+
const slot = byBind.get(bind);
|
|
4199
|
+
if (slot === void 0 || named.has(slot)) continue;
|
|
4200
|
+
named.add(slot);
|
|
4201
|
+
out.push({ slot, block });
|
|
4202
|
+
}
|
|
4203
|
+
const held = named.size > 0;
|
|
4204
|
+
slots.forEach((slot, n) => {
|
|
4205
|
+
if (named.has(slot) || out.some((item) => item.slot === slot)) return;
|
|
4206
|
+
if (held && !slot.startsWith(CODE_SLOT_PREFIX)) return;
|
|
4207
|
+
let at = 0;
|
|
4208
|
+
for (let before = n - 1; before >= 0; before--) {
|
|
4209
|
+
const found = out.findIndex((item) => item.slot === slots[before]);
|
|
4210
|
+
if (found >= 0) {
|
|
4211
|
+
at = found + 1;
|
|
4212
|
+
break;
|
|
4213
|
+
}
|
|
4214
|
+
}
|
|
4215
|
+
out.splice(at, 0, { slot, block: null });
|
|
4216
|
+
});
|
|
4217
|
+
return out;
|
|
4218
|
+
}
|
|
3221
4219
|
export {
|
|
3222
4220
|
BLOCK_BINDINGS,
|
|
3223
4221
|
BREAKPOINTS,
|
|
@@ -3227,6 +4225,7 @@ export {
|
|
|
3227
4225
|
BUTTON_PLACEMENT_KEYS,
|
|
3228
4226
|
BUTTON_SIZES,
|
|
3229
4227
|
BUTTON_VARIANTS,
|
|
4228
|
+
CODE_SLOT_PREFIX,
|
|
3230
4229
|
COMPONENT_PROP_TYPES,
|
|
3231
4230
|
DIALOG_SELECTOR,
|
|
3232
4231
|
DOCK_BUDGET,
|
|
@@ -3247,10 +4246,18 @@ export {
|
|
|
3247
4246
|
RESPONSIVE_CSS,
|
|
3248
4247
|
SECTION_DOCTRINE,
|
|
3249
4248
|
SECTION_SPACE_TOKENS,
|
|
4249
|
+
SLOT_CHILD_KEYS,
|
|
3250
4250
|
SLOT_ITEMS_CAP,
|
|
3251
4251
|
SLOT_MAX_ITEMS,
|
|
3252
4252
|
SPACE_BOTTOM_TOKENS,
|
|
3253
4253
|
SPACE_STEP_TOKENS,
|
|
4254
|
+
TABLE_COLUMN_TYPES,
|
|
4255
|
+
TABLE_JSONLD_TYPES,
|
|
4256
|
+
TABLE_LIMITS,
|
|
4257
|
+
TABLE_RESPONSIVE,
|
|
4258
|
+
TAG_HEADS,
|
|
4259
|
+
VIDEO_TRANSCRIPT_MAX,
|
|
4260
|
+
VIDEO_VALUE_KEYS,
|
|
3254
4261
|
anchorTargetRel,
|
|
3255
4262
|
blockStyleToColumnCss,
|
|
3256
4263
|
blockStyleToCss,
|
|
@@ -3271,8 +4278,10 @@ export {
|
|
|
3271
4278
|
dockBudget,
|
|
3272
4279
|
dockScreens,
|
|
3273
4280
|
expandBlockBindings,
|
|
4281
|
+
fieldGroupOf,
|
|
3274
4282
|
fieldStyleCssText,
|
|
3275
4283
|
fieldStyleToCss,
|
|
4284
|
+
formatNumber,
|
|
3276
4285
|
formatPropsAttribute,
|
|
3277
4286
|
getBlockType,
|
|
3278
4287
|
headingPaintCss,
|
|
@@ -3283,6 +4292,8 @@ export {
|
|
|
3283
4292
|
isChromeLandmark,
|
|
3284
4293
|
isLinkObject,
|
|
3285
4294
|
isScriptHref,
|
|
4295
|
+
isSlotChild,
|
|
4296
|
+
isTableValue,
|
|
3286
4297
|
keyWords,
|
|
3287
4298
|
landmarkRegions,
|
|
3288
4299
|
linkAnchorOf,
|
|
@@ -3291,17 +4302,36 @@ export {
|
|
|
3291
4302
|
linkValueProblem,
|
|
3292
4303
|
locatorFor,
|
|
3293
4304
|
normalizeLinkValue,
|
|
4305
|
+
normalizeTableValue,
|
|
3294
4306
|
normalizeWindow,
|
|
4307
|
+
parseNumberText,
|
|
3295
4308
|
parsePropsAttribute,
|
|
3296
4309
|
pickFieldStyle,
|
|
4310
|
+
placementBindOf,
|
|
4311
|
+
planSections,
|
|
3297
4312
|
readButtonValue,
|
|
4313
|
+
readNumberFormat,
|
|
3298
4314
|
readPath,
|
|
3299
4315
|
regionOf,
|
|
4316
|
+
renderTableHtml,
|
|
3300
4317
|
safeCssUrl,
|
|
4318
|
+
slotBindOf,
|
|
4319
|
+
slotChildValues,
|
|
3301
4320
|
slotItems,
|
|
4321
|
+
slotPathString,
|
|
4322
|
+
slotShapeProblems,
|
|
3302
4323
|
spaceTokenCss,
|
|
3303
4324
|
splitButtonStyle,
|
|
4325
|
+
tableCellText,
|
|
4326
|
+
tablePathString,
|
|
4327
|
+
tableRefCells,
|
|
4328
|
+
tableSearchText,
|
|
4329
|
+
tableToMarkdown,
|
|
4330
|
+
tableValueProblems,
|
|
4331
|
+
topFieldKeyOf,
|
|
3304
4332
|
usesHideOn,
|
|
4333
|
+
videoUrlOf,
|
|
4334
|
+
videoValueProblem,
|
|
3305
4335
|
visibleBlocks,
|
|
3306
4336
|
visibleDeliveredLayout,
|
|
3307
4337
|
visibleLayoutStructure,
|