@reddoorla/maintenance 0.71.0 → 0.74.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/README.md +15 -14
- package/dist/airtable-6L3JD7FY.js +9 -0
- package/dist/{announce-3JE5FKW7.js → announce-V6EYPPUR.js} +6 -6
- package/dist/{blux-FKZYMKLF.js → blux-OL5HKP26.js} +950 -69
- package/dist/blux-OL5HKP26.js.map +1 -0
- package/dist/{bump-deps-K3JMLMBB.js → bump-deps-OQR3IXLN.js} +2 -2
- package/dist/chunk-2OP4JKIQ.js +19 -0
- package/dist/chunk-2OP4JKIQ.js.map +1 -0
- package/dist/{chunk-5QC5KJHR.js → chunk-3PU2QWOJ.js} +2 -2
- package/dist/{chunk-Y7LZHPDF.js → chunk-4BHNP6Y2.js} +2 -2
- package/dist/{chunk-KOAGMTRI.js → chunk-6OYICQSJ.js} +47 -3
- package/dist/chunk-6OYICQSJ.js.map +1 -0
- package/dist/{chunk-WN4NEHE7.js → chunk-D4FVAIEJ.js} +5 -14
- package/dist/chunk-D4FVAIEJ.js.map +1 -0
- package/dist/{chunk-YWRQEDB3.js → chunk-GXVX4HUH.js} +46 -7
- package/dist/chunk-GXVX4HUH.js.map +1 -0
- package/dist/{chunk-J2SHWT2O.js → chunk-GYNRZCM6.js} +7 -2
- package/dist/{chunk-J2SHWT2O.js.map → chunk-GYNRZCM6.js.map} +1 -1
- package/dist/{chunk-VR246V3G.js → chunk-HBFMTM2E.js} +6 -6
- package/dist/chunk-HBFMTM2E.js.map +1 -0
- package/dist/{chunk-PSJQE6T6.js → chunk-I55YWV6T.js} +4 -4
- package/dist/{chunk-52TDNN7K.js → chunk-IDBMYDVH.js} +4 -4
- package/dist/{chunk-AYM2EFSK.js → chunk-JCITWZQR.js} +14 -14
- package/dist/chunk-JCITWZQR.js.map +1 -0
- package/dist/{chunk-CMQMNFFJ.js → chunk-JR67FZVC.js} +7 -3
- package/dist/chunk-JR67FZVC.js.map +1 -0
- package/dist/{chunk-MPRLMGJU.js → chunk-KKL3RYFQ.js} +2 -2
- package/dist/{chunk-2PWQ6MPG.js → chunk-KLVMJYZZ.js} +2 -2
- package/dist/{chunk-LPMQXS2N.js → chunk-LJPCMXR7.js} +1 -2
- package/dist/chunk-LJPCMXR7.js.map +1 -0
- package/dist/{chunk-6J25IIAI.js → chunk-NUIBQPB3.js} +187 -72
- package/dist/chunk-NUIBQPB3.js.map +1 -0
- package/dist/{chunk-M7HOQ4W7.js → chunk-PERP7LSS.js} +277 -21
- package/dist/chunk-PERP7LSS.js.map +1 -0
- package/dist/chunk-RHPDQW6D.js +29 -0
- package/dist/chunk-RHPDQW6D.js.map +1 -0
- package/dist/{chunk-F6OE6MGQ.js → chunk-SK44IFZN.js} +2 -2
- package/dist/cli/bin.js +31 -19
- package/dist/cli/bin.js.map +1 -1
- package/dist/cli/commands/audit.js +8 -8
- package/dist/configs/playwright-a11y.d.ts +1 -1
- package/dist/configs/playwright-a11y.js +1 -3
- package/dist/{convert-to-pnpm-6F4RAFEJ.js → convert-to-pnpm-OVMASATZ.js} +2 -2
- package/dist/{digest-GZCZYJKC.js → digest-LEMZS5ZK.js} +102 -10
- package/dist/digest-LEMZS5ZK.js.map +1 -0
- package/dist/{ensure-site-H5VMBPLF.js → ensure-site-3SOAWTZF.js} +2 -2
- package/dist/forms/index.d.ts +3 -2
- package/dist/forms/index.js +16 -9
- package/dist/forms/index.js.map +1 -1
- package/dist/{github-signals-SQECQNST.js → github-signals-TF3VSNIN.js} +5 -5
- package/dist/{health-endpoint-QXWM6GW2.js → health-endpoint-JZGYCMTV.js} +2 -2
- package/dist/index.d.ts +108 -22
- package/dist/index.js +127 -35
- package/dist/index.js.map +1 -1
- package/dist/{init-KQOIPLVT.js → init-7PTP4O2K.js} +5 -5
- package/dist/{launch-RX4VI7F2.js → launch-W33FWWOZ.js} +9 -9
- package/dist/{lighthouse-airtable-TTXULEGU.js → lighthouse-airtable-ZXNMDEPE.js} +3 -3
- package/dist/{onboard-TFBL62J3.js → onboard-PX36YDZA.js} +2 -2
- package/dist/{orchestrate-DYA4XAQJ.js → orchestrate-NYRYEKQM.js} +5 -5
- package/dist/{preflight-S3GYME3Q.js → preflight-JCQFKB6M.js} +7 -7
- package/dist/{renovate-dispatch-MZPAWVBL.js → renovate-dispatch-6II2JVOX.js} +29 -27
- package/dist/renovate-dispatch-6II2JVOX.js.map +1 -0
- package/dist/{report-BLZ67QAQ.js → report-POHQEV6F.js} +24 -8
- package/dist/report-POHQEV6F.js.map +1 -0
- package/dist/screenouts-7P5GOZMV.js +57 -0
- package/dist/screenouts-7P5GOZMV.js.map +1 -0
- package/dist/{self-updating-GSH427XP.js → self-updating-2YSVNMPP.js} +2 -2
- package/dist/{selftest-KPTL6KC4.js → selftest-OO2WDSDM.js} +12 -9
- package/dist/selftest-OO2WDSDM.js.map +1 -0
- package/dist/{smoke-suite-GP3W57JP.js → smoke-suite-CSP23NZM.js} +2 -2
- package/dist/spam-classifier-VG4ICIWS.js +217 -0
- package/dist/spam-classifier-VG4ICIWS.js.map +1 -0
- package/dist/submissions-BNRGY3JQ.js +122 -0
- package/dist/submissions-BNRGY3JQ.js.map +1 -0
- package/dist/submissions-MDKWJYMM.js +281 -0
- package/dist/submissions-MDKWJYMM.js.map +1 -0
- package/dist/{svelte-codemods-GYZZX742.js → svelte-codemods-V54KOBWU.js} +2 -2
- package/dist/{sync-configs-CQNOTJ2B.js → sync-configs-UBCJRASZ.js} +2 -2
- package/dist/{upgrade-RTAJZD56.js → upgrade-WR6ICPAG.js} +2 -2
- package/dist/{websites-SVI4KYSH.js → websites-U6642XSE.js} +10 -2
- package/dist/{write-audits-to-airtable-3XFNWMUE.js → write-audits-to-airtable-22T6D733.js} +4 -4
- package/package.json +1 -1
- package/dist/airtable-2PJ4NSAV.js +0 -9
- package/dist/blux-FKZYMKLF.js.map +0 -1
- package/dist/chunk-6J25IIAI.js.map +0 -1
- package/dist/chunk-AYM2EFSK.js.map +0 -1
- package/dist/chunk-CMQMNFFJ.js.map +0 -1
- package/dist/chunk-KOAGMTRI.js.map +0 -1
- package/dist/chunk-LPMQXS2N.js.map +0 -1
- package/dist/chunk-M7HOQ4W7.js.map +0 -1
- package/dist/chunk-QTHKOIFJ.js +0 -13
- package/dist/chunk-QTHKOIFJ.js.map +0 -1
- package/dist/chunk-VR246V3G.js.map +0 -1
- package/dist/chunk-WN4NEHE7.js.map +0 -1
- package/dist/chunk-YWRQEDB3.js.map +0 -1
- package/dist/digest-GZCZYJKC.js.map +0 -1
- package/dist/renovate-dispatch-MZPAWVBL.js.map +0 -1
- package/dist/report-BLZ67QAQ.js.map +0 -1
- package/dist/selftest-KPTL6KC4.js.map +0 -1
- /package/dist/{airtable-2PJ4NSAV.js.map → airtable-6L3JD7FY.js.map} +0 -0
- /package/dist/{announce-3JE5FKW7.js.map → announce-V6EYPPUR.js.map} +0 -0
- /package/dist/{bump-deps-K3JMLMBB.js.map → bump-deps-OQR3IXLN.js.map} +0 -0
- /package/dist/{chunk-5QC5KJHR.js.map → chunk-3PU2QWOJ.js.map} +0 -0
- /package/dist/{chunk-Y7LZHPDF.js.map → chunk-4BHNP6Y2.js.map} +0 -0
- /package/dist/{chunk-PSJQE6T6.js.map → chunk-I55YWV6T.js.map} +0 -0
- /package/dist/{chunk-52TDNN7K.js.map → chunk-IDBMYDVH.js.map} +0 -0
- /package/dist/{chunk-MPRLMGJU.js.map → chunk-KKL3RYFQ.js.map} +0 -0
- /package/dist/{chunk-2PWQ6MPG.js.map → chunk-KLVMJYZZ.js.map} +0 -0
- /package/dist/{chunk-F6OE6MGQ.js.map → chunk-SK44IFZN.js.map} +0 -0
- /package/dist/{convert-to-pnpm-6F4RAFEJ.js.map → convert-to-pnpm-OVMASATZ.js.map} +0 -0
- /package/dist/{ensure-site-H5VMBPLF.js.map → ensure-site-3SOAWTZF.js.map} +0 -0
- /package/dist/{github-signals-SQECQNST.js.map → github-signals-TF3VSNIN.js.map} +0 -0
- /package/dist/{health-endpoint-QXWM6GW2.js.map → health-endpoint-JZGYCMTV.js.map} +0 -0
- /package/dist/{init-KQOIPLVT.js.map → init-7PTP4O2K.js.map} +0 -0
- /package/dist/{launch-RX4VI7F2.js.map → launch-W33FWWOZ.js.map} +0 -0
- /package/dist/{lighthouse-airtable-TTXULEGU.js.map → lighthouse-airtable-ZXNMDEPE.js.map} +0 -0
- /package/dist/{onboard-TFBL62J3.js.map → onboard-PX36YDZA.js.map} +0 -0
- /package/dist/{orchestrate-DYA4XAQJ.js.map → orchestrate-NYRYEKQM.js.map} +0 -0
- /package/dist/{preflight-S3GYME3Q.js.map → preflight-JCQFKB6M.js.map} +0 -0
- /package/dist/{self-updating-GSH427XP.js.map → self-updating-2YSVNMPP.js.map} +0 -0
- /package/dist/{smoke-suite-GP3W57JP.js.map → smoke-suite-CSP23NZM.js.map} +0 -0
- /package/dist/{svelte-codemods-GYZZX742.js.map → svelte-codemods-V54KOBWU.js.map} +0 -0
- /package/dist/{sync-configs-CQNOTJ2B.js.map → sync-configs-UBCJRASZ.js.map} +0 -0
- /package/dist/{upgrade-RTAJZD56.js.map → upgrade-WR6ICPAG.js.map} +0 -0
- /package/dist/{websites-SVI4KYSH.js.map → websites-U6642XSE.js.map} +0 -0
- /package/dist/{write-audits-to-airtable-3XFNWMUE.js.map → write-audits-to-airtable-22T6D733.js.map} +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
CDN_HOSTS,
|
|
2
3
|
collectAssetUrls
|
|
3
4
|
} from "./chunk-SL24DCGC.js";
|
|
4
5
|
|
|
@@ -188,12 +189,26 @@ function slugify(s) {
|
|
|
188
189
|
}
|
|
189
190
|
function normalizePages(raw) {
|
|
190
191
|
const diagnostics = [];
|
|
191
|
-
const
|
|
192
|
-
|
|
192
|
+
const seen = /* @__PURE__ */ new Set();
|
|
193
|
+
const pages = raw.pages.map((p, i) => {
|
|
194
|
+
const urlSlug = String(p.url ?? "").trim();
|
|
195
|
+
const path = i === 0 ? "" : urlSlug ? slugify(urlSlug) : slugify(String(p.title ?? ""));
|
|
196
|
+
let uid = i === 0 ? "home" : path;
|
|
197
|
+
if (seen.has(uid)) {
|
|
198
|
+
const base2 = uid;
|
|
199
|
+
for (let n = 2; seen.has(uid); n++) uid = `${base2}-${n}`;
|
|
200
|
+
diagnostics.push({
|
|
201
|
+
kind: "duplicate-page-uid",
|
|
202
|
+
where: base2,
|
|
203
|
+
message: `page ${i} ("${String(p.title ?? "")}") slugs to "${base2}" already used \u2014 renamed to "${uid}"`
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
seen.add(uid);
|
|
193
207
|
return {
|
|
194
208
|
uid,
|
|
195
209
|
title: String(p.title ?? ""),
|
|
196
210
|
description: String(p.description ?? ""),
|
|
211
|
+
path,
|
|
197
212
|
sections: (p.items ?? []).map((b) => sectionFromBlock(b, uid, diagnostics))
|
|
198
213
|
};
|
|
199
214
|
});
|
|
@@ -212,6 +227,7 @@ function normalizeTheme(raw) {
|
|
|
212
227
|
const m = entry[innerKey] ?? {};
|
|
213
228
|
const transform = cleanCssValue(m["text-transform"]);
|
|
214
229
|
const tracking = cleanCssValue(m["letter-spacing"]);
|
|
230
|
+
const margin = cleanCssValue(m["margin"]);
|
|
215
231
|
const mobileSize = cleanCssValue(m["__media_mobile_font-size"]);
|
|
216
232
|
const mobileLineHeight = cleanCssValue(m["__media_mobile_line-height"]);
|
|
217
233
|
textStyles.push({
|
|
@@ -224,10 +240,38 @@ function normalizeTheme(raw) {
|
|
|
224
240
|
lineHeight: cleanCssValue(m["line-height"]) || "1.5",
|
|
225
241
|
...transform && transform !== "none" ? { transform } : {},
|
|
226
242
|
...tracking ? { letterSpacing: tracking } : {},
|
|
243
|
+
...margin && margin !== "0" ? { margin } : {},
|
|
227
244
|
...mobileSize ? { mobileSize } : {},
|
|
228
245
|
...mobileLineHeight ? { mobileLineHeight } : {}
|
|
229
246
|
});
|
|
230
247
|
}
|
|
248
|
+
const cleanCssMap = (v) => {
|
|
249
|
+
const out = {};
|
|
250
|
+
for (const [k, val] of Object.entries(v ?? {})) {
|
|
251
|
+
if (k === "font-ident") continue;
|
|
252
|
+
const s = cleanCssValue(typeof val === "number" ? String(val) : val);
|
|
253
|
+
if (s) out[k] = s;
|
|
254
|
+
}
|
|
255
|
+
return out;
|
|
256
|
+
};
|
|
257
|
+
const buttonStyles = [];
|
|
258
|
+
for (const v of Object.values(raw.styles.buttons ?? {})) {
|
|
259
|
+
const entry = v ?? {};
|
|
260
|
+
const innerKey = Object.keys(entry).find((k) => /^\.buttons\d+$/.test(k));
|
|
261
|
+
if (!innerKey) continue;
|
|
262
|
+
const css = cleanCssMap(entry[innerKey]);
|
|
263
|
+
if (Object.keys(css).length === 0) continue;
|
|
264
|
+
const hover = cleanCssMap(entry[`${innerKey}:hover`]);
|
|
265
|
+
const active = cleanCssMap(entry[`${innerKey}:active`]);
|
|
266
|
+
buttonStyles.push({
|
|
267
|
+
role: innerKey.slice(1),
|
|
268
|
+
// ".buttons2" -> "buttons2"
|
|
269
|
+
label: str(entry._label),
|
|
270
|
+
css,
|
|
271
|
+
...Object.keys(hover).length ? { hover } : {},
|
|
272
|
+
...Object.keys(active).length ? { active } : {}
|
|
273
|
+
});
|
|
274
|
+
}
|
|
231
275
|
const fonts = raw.settings.fonts ?? {};
|
|
232
276
|
const roleFont = (r) => textStyles.find((t) => t.role === r)?.fontFamily ?? "";
|
|
233
277
|
return {
|
|
@@ -240,7 +284,8 @@ function normalizeTheme(raw) {
|
|
|
240
284
|
parseGoogleFonts(str(fonts.google)),
|
|
241
285
|
typekitFontLoads(str(fonts.string))
|
|
242
286
|
),
|
|
243
|
-
textStyles
|
|
287
|
+
textStyles,
|
|
288
|
+
buttonStyles
|
|
244
289
|
};
|
|
245
290
|
}
|
|
246
291
|
|
|
@@ -330,8 +375,17 @@ function assembleIR(input) {
|
|
|
330
375
|
alt: String(m.name ?? "")
|
|
331
376
|
};
|
|
332
377
|
});
|
|
378
|
+
const faviconId = raw.settings.favicon?.media;
|
|
379
|
+
const favicon = faviconId ? { assetId: faviconId, sourceUrl: urlMap.get(faviconId) ?? null } : void 0;
|
|
380
|
+
if (favicon && !favicon.sourceUrl) {
|
|
381
|
+
diagnostics.push({
|
|
382
|
+
kind: "unresolved-asset",
|
|
383
|
+
where: favicon.assetId,
|
|
384
|
+
message: `no CDN url for favicon ${favicon.assetId}`
|
|
385
|
+
});
|
|
386
|
+
}
|
|
333
387
|
return {
|
|
334
|
-
meta: raw.meta,
|
|
388
|
+
meta: { ...raw.meta, ...favicon ? { favicon } : {} },
|
|
335
389
|
theme,
|
|
336
390
|
pages,
|
|
337
391
|
collections,
|
|
@@ -644,6 +698,7 @@ function emitThemeCss(theme) {
|
|
|
644
698
|
if (t.fontFamily) lines.push(` --text-${t.role}--font-family: ${t.fontFamily};`);
|
|
645
699
|
if (t.transform) lines.push(` --text-${t.role}--text-transform: ${t.transform};`);
|
|
646
700
|
if (t.letterSpacing) lines.push(` --text-${t.role}--letter-spacing: ${t.letterSpacing};`);
|
|
701
|
+
if (t.margin) lines.push(` --text-${t.role}--margin: ${t.margin};`);
|
|
647
702
|
if (t.mobileSize) lines.push(` --text-${t.role}--mobile-font-size: ${t.mobileSize};`);
|
|
648
703
|
if (t.mobileLineHeight)
|
|
649
704
|
lines.push(` --text-${t.role}--mobile-line-height: ${t.mobileLineHeight};`);
|
|
@@ -667,12 +722,40 @@ function emitRolesCss(theme) {
|
|
|
667
722
|
` line-height: var(--text-${r}--line-height);`,
|
|
668
723
|
` letter-spacing: var(--text-${r}--letter-spacing, normal);`,
|
|
669
724
|
` text-transform: var(--text-${r}--text-transform, none);`,
|
|
670
|
-
` margin: 0;`,
|
|
725
|
+
` margin: var(--text-${r}--margin, 0);`,
|
|
671
726
|
`}`
|
|
672
727
|
);
|
|
673
728
|
}
|
|
674
729
|
return lines.join("\n") + "\n";
|
|
675
730
|
}
|
|
731
|
+
function emitButtonsCss(theme) {
|
|
732
|
+
if (!theme.buttonStyles.length) return "";
|
|
733
|
+
const lines = [
|
|
734
|
+
"/* Button skins \u2014 one .buttonsN per Blux button style; raw anchors carry",
|
|
735
|
+
" `ib middle buttonsN` verbatim. Generated by blux emit. */",
|
|
736
|
+
".ib {",
|
|
737
|
+
" display: inline-block;",
|
|
738
|
+
"}",
|
|
739
|
+
"/* Text links (`ib middle links`) are underlined by the Blux platform CSS;",
|
|
740
|
+
" an inline-block box does not inherit an ancestor's text-decoration, so",
|
|
741
|
+
" the affordance must be declared on the anchor itself. */",
|
|
742
|
+
".links {",
|
|
743
|
+
" text-decoration: underline;",
|
|
744
|
+
"}"
|
|
745
|
+
];
|
|
746
|
+
const rule = (selector, css) => {
|
|
747
|
+
lines.push(`${selector} {`);
|
|
748
|
+
for (const [k, v] of Object.entries(css)) lines.push(` ${k}: ${v};`);
|
|
749
|
+
lines.push("}");
|
|
750
|
+
};
|
|
751
|
+
for (const b of theme.buttonStyles) {
|
|
752
|
+
if (b.label) lines.push(`/* ${b.role} \u2014 ${b.label} */`);
|
|
753
|
+
rule(`.${b.role}`, b.css);
|
|
754
|
+
if (b.hover) rule(`.${b.role}:hover`, b.hover);
|
|
755
|
+
if (b.active) rule(`.${b.role}:active`, b.active);
|
|
756
|
+
}
|
|
757
|
+
return lines.join("\n") + "\n";
|
|
758
|
+
}
|
|
676
759
|
|
|
677
760
|
// src/blux/emit/review.ts
|
|
678
761
|
function buildReviewManifest(ir, opts) {
|
|
@@ -769,6 +852,28 @@ function cssProp(style, prop) {
|
|
|
769
852
|
const m = new RegExp(`(?:^|;|\\s)${prop}\\s*:\\s*([^;]+)`, "i").exec(style);
|
|
770
853
|
return m?.[1]?.trim();
|
|
771
854
|
}
|
|
855
|
+
var MARGIN_UTIL_RE = /\bmargin-(\d+)(r|l|t|b)\b/g;
|
|
856
|
+
var MARGIN_SIDES = { r: "right", l: "left", t: "top", b: "bottom" };
|
|
857
|
+
function utilityStylesFromClass(className) {
|
|
858
|
+
const out = {};
|
|
859
|
+
for (const m of className.matchAll(MARGIN_UTIL_RE)) {
|
|
860
|
+
const [, n, side] = m;
|
|
861
|
+
if (n && side) out[`margin-${MARGIN_SIDES[side]}`] = `${n}%`;
|
|
862
|
+
}
|
|
863
|
+
return out;
|
|
864
|
+
}
|
|
865
|
+
function textLeafStyle(el) {
|
|
866
|
+
const out = utilityStylesFromClass(el.classNames ?? "");
|
|
867
|
+
for (const decl of (el.getAttribute("style") ?? "").split(";")) {
|
|
868
|
+
const colon = decl.indexOf(":");
|
|
869
|
+
if (colon < 0) continue;
|
|
870
|
+
const prop = decl.slice(0, colon).trim().toLowerCase();
|
|
871
|
+
const value = decl.slice(colon + 1).trim();
|
|
872
|
+
if (!value) continue;
|
|
873
|
+
if (prop === "color" || prop === "padding" || prop.startsWith("margin")) out[prop] = value;
|
|
874
|
+
}
|
|
875
|
+
return Object.keys(out).length ? out : null;
|
|
876
|
+
}
|
|
772
877
|
var CENTERED = /* @__PURE__ */ new Set(["center", "center center", "50% 50%", "50%"]);
|
|
773
878
|
function readBgSizing(el) {
|
|
774
879
|
const style = el.getAttribute("style") ?? "";
|
|
@@ -860,17 +965,93 @@ function mediaFromElement(el) {
|
|
|
860
965
|
var DEFAULT_TOKEN = { cols: 1, raw: "grid-1" };
|
|
861
966
|
var isElement = (n) => n.tagName !== void 0 && n.tagName !== null;
|
|
862
967
|
var hasClass = (el, c) => el.classNames.split(/\s+/).includes(c);
|
|
968
|
+
var isFeedTemplate = (el) => {
|
|
969
|
+
const id = el.getAttribute("id") ?? "";
|
|
970
|
+
const style = el.getAttribute("style") ?? "";
|
|
971
|
+
const hidden = /display\s*:\s*none/i.test(style);
|
|
972
|
+
return hidden && (/-template$/.test(id) || /\{\{[a-z_]+\}\}/i.test(el.innerHTML));
|
|
973
|
+
};
|
|
863
974
|
var isMediaHolder = (el) => hasClass(el, "block-media-holder") || hasClass(el, "camediaload") && !!el.getAttribute("data-media") || el.tagName === "VIDEO";
|
|
864
975
|
var isLeafElement = (el) => hasClass(el, "block-title") || hasClass(el, "block-body") || hasClass(el, "block-subtitle") || isMediaHolder(el);
|
|
865
976
|
var isLeafAnchor = (el) => el.tagName === "A" && collectStructuralChildren(el).length === 0;
|
|
866
977
|
var isStructural = (el) => isLeafElement(el) || el.hasAttribute("data-exec") || // Blux custom-code embed (e.g. map mount)
|
|
867
978
|
hasClass(el, "cagrid") || isLeafAnchor(el) || parseGridToken(el.classNames) !== null;
|
|
868
|
-
|
|
979
|
+
var isCellBoundary = (el) => hasClass(el, "block-grid-container") || hasClass(el, "block-subcontent");
|
|
980
|
+
function inlineBg(el) {
|
|
981
|
+
const c = cssProp(el.getAttribute("style") ?? "", "background-color")?.trim();
|
|
982
|
+
if (!c) return void 0;
|
|
983
|
+
const low = c.toLowerCase().replace(/\s+/g, "");
|
|
984
|
+
if (low === "transparent" || low === "rgba(0,0,0,0)") return void 0;
|
|
985
|
+
return c;
|
|
986
|
+
}
|
|
987
|
+
function inlinePadding(el) {
|
|
988
|
+
const c = cssProp(el.getAttribute("style") ?? "", "padding")?.trim();
|
|
989
|
+
if (!c) return void 0;
|
|
990
|
+
if (/^(0(px|%|em|rem)?\s*)+$/i.test(c)) return void 0;
|
|
991
|
+
return c;
|
|
992
|
+
}
|
|
993
|
+
function inlineMinHeight(el) {
|
|
994
|
+
const c = cssProp(el.getAttribute("style") ?? "", "min-height")?.trim();
|
|
995
|
+
if (!c) return void 0;
|
|
996
|
+
if (/^(0(px|%|em|rem|vh|vw)?|auto)$/i.test(c)) return void 0;
|
|
997
|
+
return c;
|
|
998
|
+
}
|
|
999
|
+
function layerBackground(el) {
|
|
1000
|
+
for (const child of el.childNodes) {
|
|
1001
|
+
if (!isElement(child) || !hasClass(child, "block-background-layer")) continue;
|
|
1002
|
+
const s = child.getAttribute("style") ?? "";
|
|
1003
|
+
const bg = (cssProp(s, "background") ?? cssProp(s, "background-color"))?.trim();
|
|
1004
|
+
if (bg && !/^(none|transparent)$/i.test(bg)) return bg;
|
|
1005
|
+
}
|
|
1006
|
+
return void 0;
|
|
1007
|
+
}
|
|
1008
|
+
function collectStructuralChildren(el, inherited = {}) {
|
|
869
1009
|
const out = [];
|
|
1010
|
+
const layerBg = inherited.nested === true ? layerBackground(el) : void 0;
|
|
1011
|
+
const base2 = layerBg !== void 0 ? { ...inherited, layerBackground: layerBg } : inherited;
|
|
870
1012
|
for (const child of el.childNodes) {
|
|
871
1013
|
if (!isElement(child)) continue;
|
|
872
|
-
if (
|
|
873
|
-
|
|
1014
|
+
if (hasClass(child, "block-background-layer")) continue;
|
|
1015
|
+
if (isFeedTemplate(child)) continue;
|
|
1016
|
+
const nested = base2.nested === true || isCellBoundary(child);
|
|
1017
|
+
const background = inlineBg(child) ?? base2.background;
|
|
1018
|
+
const padding = (nested ? inlinePadding(child) : void 0) ?? base2.padding;
|
|
1019
|
+
const minHeight = (nested ? inlineMinHeight(child) : void 0) ?? base2.minHeight;
|
|
1020
|
+
const valign = nested && hasClass(child, "valignmiddle") || base2.valign === true;
|
|
1021
|
+
const card = {
|
|
1022
|
+
...background !== void 0 ? { background } : {},
|
|
1023
|
+
...padding !== void 0 ? { padding } : {},
|
|
1024
|
+
...minHeight !== void 0 ? { minHeight } : {},
|
|
1025
|
+
...base2.layerBackground !== void 0 ? { layerBackground: base2.layerBackground } : {},
|
|
1026
|
+
...valign ? { valign } : {},
|
|
1027
|
+
...base2.fill === true ? { fill: true } : {},
|
|
1028
|
+
...nested ? { nested } : {}
|
|
1029
|
+
};
|
|
1030
|
+
const group = !isStructural(child) && (hasClass(child, "block-subcontent") && parseGridToken(child.classNames) === null || nested && (inlinePadding(child) !== void 0 || inlineMinHeight(child) !== void 0 || layerBackground(child) !== void 0)) && collectStructuralChildren(child).length >= 2;
|
|
1031
|
+
if (isStructural(child)) {
|
|
1032
|
+
const inheritedCard = {
|
|
1033
|
+
...base2.background !== void 0 ? { background: base2.background } : {},
|
|
1034
|
+
...base2.padding !== void 0 ? { padding: base2.padding } : {},
|
|
1035
|
+
...base2.minHeight !== void 0 ? { minHeight: base2.minHeight } : {},
|
|
1036
|
+
...base2.layerBackground !== void 0 ? { layerBackground: base2.layerBackground } : {},
|
|
1037
|
+
...base2.valign === true ? { valign: true } : {},
|
|
1038
|
+
...base2.fill === true ? { fill: true } : {},
|
|
1039
|
+
...nested ? { nested } : {}
|
|
1040
|
+
};
|
|
1041
|
+
out.push({
|
|
1042
|
+
el: child,
|
|
1043
|
+
...Object.keys(inheritedCard).length > 0 ? { card: inheritedCard } : {}
|
|
1044
|
+
});
|
|
1045
|
+
} else if (group) {
|
|
1046
|
+
const ownLayer = !isCellBoundary(child) ? layerBackground(child) : void 0;
|
|
1047
|
+
const groupCard = ownLayer !== void 0 ? { ...card, layerBackground: ownLayer } : card;
|
|
1048
|
+
out.push({
|
|
1049
|
+
el: child,
|
|
1050
|
+
...Object.keys(groupCard).length > 0 ? { card: groupCard } : {}
|
|
1051
|
+
});
|
|
1052
|
+
} else {
|
|
1053
|
+
out.push(...collectStructuralChildren(child, card));
|
|
1054
|
+
}
|
|
874
1055
|
}
|
|
875
1056
|
return out;
|
|
876
1057
|
}
|
|
@@ -888,23 +1069,37 @@ function isDisabledWithin(caption, holder) {
|
|
|
888
1069
|
}
|
|
889
1070
|
return false;
|
|
890
1071
|
}
|
|
891
|
-
function parseNode(el) {
|
|
1072
|
+
function parseNode(el, nested = false) {
|
|
892
1073
|
if (hasClass(el, "block-title") && /^H[1-6]$/.test(el.tagName ?? "")) {
|
|
893
1074
|
const role = textRoleFromClass(el.classNames);
|
|
1075
|
+
const style = textLeafStyle(el);
|
|
894
1076
|
return {
|
|
895
1077
|
kind: "heading",
|
|
896
1078
|
...role ? { role } : {},
|
|
1079
|
+
...style ? { style } : {},
|
|
897
1080
|
level: headingLevel(el),
|
|
898
1081
|
html: el.innerHTML
|
|
899
1082
|
};
|
|
900
1083
|
}
|
|
901
1084
|
if (hasClass(el, "block-body")) {
|
|
902
1085
|
const role = textRoleFromClass(el.classNames);
|
|
903
|
-
|
|
1086
|
+
const style = textLeafStyle(el);
|
|
1087
|
+
return {
|
|
1088
|
+
kind: "body",
|
|
1089
|
+
...role ? { role } : {},
|
|
1090
|
+
...style ? { style } : {},
|
|
1091
|
+
html: el.innerHTML
|
|
1092
|
+
};
|
|
904
1093
|
}
|
|
905
1094
|
if (hasClass(el, "block-subtitle")) {
|
|
906
1095
|
const role = textRoleFromClass(el.classNames);
|
|
907
|
-
|
|
1096
|
+
const style = textLeafStyle(el);
|
|
1097
|
+
return {
|
|
1098
|
+
kind: "subtitle",
|
|
1099
|
+
...role ? { role } : {},
|
|
1100
|
+
...style ? { style } : {},
|
|
1101
|
+
text: blockPlainText(el.innerHTML)
|
|
1102
|
+
};
|
|
908
1103
|
}
|
|
909
1104
|
if (isMediaHolder(el)) {
|
|
910
1105
|
const media = mediaFromElement(el);
|
|
@@ -922,14 +1117,52 @@ function parseNode(el) {
|
|
|
922
1117
|
if (el.tagName === "A") {
|
|
923
1118
|
return { kind: "raw", html: el.outerHTML };
|
|
924
1119
|
}
|
|
925
|
-
return parseContainer(el);
|
|
926
|
-
}
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
1120
|
+
return parseContainer(el, nested);
|
|
1121
|
+
}
|
|
1122
|
+
var nodePainted = (style) => "background" in style || "background-color" in style || "min-height" in style;
|
|
1123
|
+
function withCardStyle(node, card) {
|
|
1124
|
+
if (!card || card.background === void 0 && card.padding === void 0 && card.minHeight === void 0 && card.layerBackground === void 0 && !card.valign && !card.fill)
|
|
1125
|
+
return node;
|
|
1126
|
+
if (node.kind === "row" || node.kind === "stack") {
|
|
1127
|
+
const style2 = { ...node.style ?? {} };
|
|
1128
|
+
if (card.background !== void 0) style2["background-color"] = card.background;
|
|
1129
|
+
if (card.layerBackground !== void 0) style2["background"] = card.layerBackground;
|
|
1130
|
+
if (card.padding !== void 0) style2.padding = card.padding;
|
|
1131
|
+
if (card.minHeight !== void 0) style2["min-height"] = card.minHeight;
|
|
1132
|
+
if (card.valign) style2["_valign"] = "middle";
|
|
1133
|
+
if (card.fill && nodePainted(style2)) style2["_fill"] = "column";
|
|
1134
|
+
if (Object.keys(style2).length === 0) return node;
|
|
1135
|
+
return { ...node, style: style2 };
|
|
1136
|
+
}
|
|
1137
|
+
if (node.kind === "media" && card.padding === void 0 && !card.valign) {
|
|
1138
|
+
if (card.minHeight !== void 0 && node.media.minHeight === void 0)
|
|
1139
|
+
return { ...node, media: { ...node.media, minHeight: card.minHeight } };
|
|
1140
|
+
return node;
|
|
1141
|
+
}
|
|
1142
|
+
if (card.padding === void 0 && card.minHeight === void 0 && card.layerBackground === void 0 && !card.valign)
|
|
1143
|
+
return node;
|
|
1144
|
+
const style = {};
|
|
1145
|
+
if (card.padding !== void 0) style.padding = card.padding;
|
|
1146
|
+
if (card.background !== void 0) style["background-color"] = card.background;
|
|
1147
|
+
if (card.layerBackground !== void 0) style["background"] = card.layerBackground;
|
|
1148
|
+
if (card.minHeight !== void 0) style["min-height"] = card.minHeight;
|
|
1149
|
+
if (card.valign) style["_valign"] = "middle";
|
|
1150
|
+
if (card.fill && nodePainted(style)) style["_fill"] = "column";
|
|
1151
|
+
return { kind: "stack", children: [node], style };
|
|
1152
|
+
}
|
|
1153
|
+
function parseContainer(el, nested = false) {
|
|
1154
|
+
const kids = collectStructuralChildren(
|
|
1155
|
+
el,
|
|
1156
|
+
isCellBoundary(el) || hasClass(el, "cagrid") ? { nested: true, ...hasClass(el, "cagridFlexHeight") ? { fill: true } : {} } : nested ? { nested: true } : {}
|
|
1157
|
+
);
|
|
1158
|
+
const parsed = kids.map((k) => ({
|
|
1159
|
+
token: parseGridToken(k.el.classNames),
|
|
1160
|
+
node: withCardStyle(parseNode(k.el, k.card?.nested === true), k.card)
|
|
1161
|
+
})).filter((p) => !(p.node.kind === "raw" && p.node.html.trim() === ""));
|
|
930
1162
|
const isGrid = hasClass(el, "cagrid");
|
|
931
1163
|
const tokenCount = parsed.filter((p) => p.token).length;
|
|
932
|
-
|
|
1164
|
+
const hasWidthToken = parsed.some((p) => p.token && p.token.cols !== 1 && p.token.cols !== "any");
|
|
1165
|
+
if ((isGrid || tokenCount >= 2 || hasWidthToken) && parsed.length > 0) {
|
|
933
1166
|
const cells = parsed.map((p) => ({ token: p.token ?? DEFAULT_TOKEN, node: p.node }));
|
|
934
1167
|
if (hasClass(el, "caslider")) {
|
|
935
1168
|
const cols = Number(el.getAttribute("data-columns"));
|
|
@@ -940,10 +1173,15 @@ function parseContainer(el) {
|
|
|
940
1173
|
}
|
|
941
1174
|
const [only] = parsed;
|
|
942
1175
|
if (parsed.length === 1 && only) return only.node;
|
|
943
|
-
if (parsed.length === 0) return { kind: "raw", html: el
|
|
1176
|
+
if (parsed.length === 0) return { kind: "raw", html: rawInnerHtml(el) };
|
|
944
1177
|
return { kind: "stack", children: parsed.map((p) => p.node) };
|
|
945
1178
|
}
|
|
1179
|
+
function rawInnerHtml(el) {
|
|
1180
|
+
const html = el.innerHTML;
|
|
1181
|
+
return /\{\{[a-z_]+\}\}/i.test(html) ? "" : html;
|
|
1182
|
+
}
|
|
946
1183
|
var BAND_ID_RE = /^page-block-(\d+)$/;
|
|
1184
|
+
var BLOCK_CLASS_RE = /\bblocks\d+\b/;
|
|
947
1185
|
function bandBackground(el) {
|
|
948
1186
|
if (!hasClass(el, "camediaload")) return void 0;
|
|
949
1187
|
const rawId = el.getAttribute("data-media");
|
|
@@ -972,8 +1210,10 @@ function parseGridBands(html) {
|
|
|
972
1210
|
const idStr = m[1];
|
|
973
1211
|
if (idStr === void 0) continue;
|
|
974
1212
|
const background = bandBackground(child);
|
|
1213
|
+
const blockClass = BLOCK_CLASS_RE.exec(child.classNames)?.[0];
|
|
975
1214
|
bands.push({
|
|
976
1215
|
index: Number(idStr),
|
|
1216
|
+
...blockClass ? { blockClass } : {},
|
|
977
1217
|
...background ? { background } : {},
|
|
978
1218
|
root: parseContainer(child)
|
|
979
1219
|
});
|
|
@@ -1060,7 +1300,11 @@ function isEmptyRaw(node) {
|
|
|
1060
1300
|
return text.length === 0;
|
|
1061
1301
|
}
|
|
1062
1302
|
function base(band) {
|
|
1063
|
-
return {
|
|
1303
|
+
return {
|
|
1304
|
+
index: band.index,
|
|
1305
|
+
...band.blockClass ? { blockClass: band.blockClass } : {},
|
|
1306
|
+
...band.background ? { background: band.background } : {}
|
|
1307
|
+
};
|
|
1064
1308
|
}
|
|
1065
1309
|
function nodeText(node) {
|
|
1066
1310
|
switch (node.kind) {
|
|
@@ -1077,8 +1321,18 @@ function nodeText(node) {
|
|
|
1077
1321
|
return "";
|
|
1078
1322
|
}
|
|
1079
1323
|
}
|
|
1324
|
+
function unboxed(node) {
|
|
1325
|
+
let n = node;
|
|
1326
|
+
while (n.kind === "stack" && n.children.length === 1) {
|
|
1327
|
+
const only = n.children[0];
|
|
1328
|
+
if (!only) break;
|
|
1329
|
+
n = only;
|
|
1330
|
+
}
|
|
1331
|
+
return n;
|
|
1332
|
+
}
|
|
1080
1333
|
function pureCellMedia(cell) {
|
|
1081
|
-
|
|
1334
|
+
const n = unboxed(cell.node);
|
|
1335
|
+
return n.kind === "media" ? n.media : null;
|
|
1082
1336
|
}
|
|
1083
1337
|
function textRoleMeta(heading, subtitle) {
|
|
1084
1338
|
return {
|
|
@@ -1093,6 +1347,12 @@ function cellRatio(cell) {
|
|
|
1093
1347
|
if (t.cols === "any") return 50;
|
|
1094
1348
|
return Math.round(100 / t.cols);
|
|
1095
1349
|
}
|
|
1350
|
+
var isTextNode = (n) => n.kind === "heading" || n.kind === "body" || n.kind === "subtitle";
|
|
1351
|
+
var isBlankText = (n) => {
|
|
1352
|
+
if (n.kind === "heading" || n.kind === "body") return blockPlainText(n.html) === "";
|
|
1353
|
+
if (n.kind === "subtitle") return n.text.trim() === "";
|
|
1354
|
+
return false;
|
|
1355
|
+
};
|
|
1096
1356
|
function carouselSlides(cells) {
|
|
1097
1357
|
const out = [];
|
|
1098
1358
|
for (const c of cells) {
|
|
@@ -1101,12 +1361,18 @@ function carouselSlides(cells) {
|
|
|
1101
1361
|
out.push({ media: n.media });
|
|
1102
1362
|
continue;
|
|
1103
1363
|
}
|
|
1104
|
-
if (n.kind === "stack" && n.children.length
|
|
1105
|
-
const [m,
|
|
1106
|
-
|
|
1364
|
+
if (n.kind === "stack" && n.children.length >= 2) {
|
|
1365
|
+
const [m, ...rest] = n.children;
|
|
1366
|
+
const h = rest.find((r) => r.kind === "heading");
|
|
1367
|
+
if (m?.kind === "media" && h?.kind === "heading" && rest.every(isTextNode)) {
|
|
1368
|
+
const sub = rest.find(
|
|
1369
|
+
(r) => r !== h && (r.kind === "body" || r.kind === "subtitle") && !isBlankText(r)
|
|
1370
|
+
);
|
|
1371
|
+
const subcaption = sub?.kind === "body" ? { html: sub.html, ...sub.role ? { role: sub.role } : {} } : sub?.kind === "subtitle" ? { html: sub.text, ...sub.role ? { role: sub.role } : {} } : void 0;
|
|
1107
1372
|
out.push({
|
|
1108
1373
|
media: m.media,
|
|
1109
|
-
caption: { html: h.html, level: h.level, ...h.role ? { role: h.role } : {} }
|
|
1374
|
+
caption: { html: h.html, level: h.level, ...h.role ? { role: h.role } : {} },
|
|
1375
|
+
...subcaption ? { subcaption } : {}
|
|
1110
1376
|
});
|
|
1111
1377
|
continue;
|
|
1112
1378
|
}
|
|
@@ -1134,12 +1400,18 @@ function rewriteMapMounts(node, isMapMount) {
|
|
|
1134
1400
|
token: c.token,
|
|
1135
1401
|
node: rewriteMapMounts(c.node, isMapMount)
|
|
1136
1402
|
})),
|
|
1137
|
-
//
|
|
1138
|
-
// Carousel to Grid
|
|
1139
|
-
|
|
1403
|
+
// Preserve the row's own markers when rebuilding: dropping the slider
|
|
1404
|
+
// would silently demote a Carousel to Grid, and dropping the style would
|
|
1405
|
+
// lose a card background — for every band whenever a map config exists.
|
|
1406
|
+
...node.slider ? { slider: node.slider } : {},
|
|
1407
|
+
...node.style ? { style: node.style } : {}
|
|
1140
1408
|
};
|
|
1141
1409
|
case "stack":
|
|
1142
|
-
return {
|
|
1410
|
+
return {
|
|
1411
|
+
kind: "stack",
|
|
1412
|
+
children: node.children.map((n) => rewriteMapMounts(n, isMapMount)),
|
|
1413
|
+
...node.style ? { style: node.style } : {}
|
|
1414
|
+
};
|
|
1143
1415
|
case "heading":
|
|
1144
1416
|
case "body":
|
|
1145
1417
|
case "subtitle":
|
|
@@ -1375,10 +1647,192 @@ function extractToggles(html) {
|
|
|
1375
1647
|
return groups.length === labels.length && groups.every((g) => g !== void 0) ? groups : [];
|
|
1376
1648
|
}
|
|
1377
1649
|
|
|
1650
|
+
// src/blux/grid/feed-grid.ts
|
|
1651
|
+
var termMatchesTag = (term, tag) => term === tag || term.endsWith("s") && term.slice(0, -1) === tag || tag.endsWith("s") && tag.slice(0, -1) === term;
|
|
1652
|
+
function tagFilter(expr) {
|
|
1653
|
+
const groups = (expr ?? "").split("||").map(
|
|
1654
|
+
(g) => g.split("&&").map((t) => t.trim().toLowerCase()).filter(Boolean)
|
|
1655
|
+
).filter((g) => g.length > 0);
|
|
1656
|
+
if (!groups.length) return () => true;
|
|
1657
|
+
return (tags) => {
|
|
1658
|
+
const set = tags.map((t) => t.toLowerCase());
|
|
1659
|
+
return groups.some((g) => g.every((term) => set.some((tag) => termMatchesTag(term, tag))));
|
|
1660
|
+
};
|
|
1661
|
+
}
|
|
1662
|
+
function sortRecords(records, sort) {
|
|
1663
|
+
if (sort === "title") {
|
|
1664
|
+
return [...records].sort(
|
|
1665
|
+
(a, b) => String(a["title"] ?? "").localeCompare(String(b["title"] ?? ""))
|
|
1666
|
+
);
|
|
1667
|
+
}
|
|
1668
|
+
if (sort === "fdate" || sort === "date") {
|
|
1669
|
+
return [...records].sort(
|
|
1670
|
+
(a, b) => String(b["date"] ?? "").localeCompare(String(a["date"] ?? ""))
|
|
1671
|
+
);
|
|
1672
|
+
}
|
|
1673
|
+
return records;
|
|
1674
|
+
}
|
|
1675
|
+
function cropRatioOf(v) {
|
|
1676
|
+
if (typeof v !== "string") return void 0;
|
|
1677
|
+
const m = /^\s*(\d+(?:\.\d+)?)\s*:\s*(\d+(?:\.\d+)?)\s*$/.exec(v);
|
|
1678
|
+
if (!m) return void 0;
|
|
1679
|
+
const w = Number(m[1]);
|
|
1680
|
+
const h = Number(m[2]);
|
|
1681
|
+
return w > 0 && h > 0 ? `${w}:${h}` : void 0;
|
|
1682
|
+
}
|
|
1683
|
+
var isDisabled = (r) => r["disabled"] === true || r["disable"] === true;
|
|
1684
|
+
var styleDisabled = (cfg) => !!cfg && typeof cfg === "object" && cfg["class"] === "disable";
|
|
1685
|
+
function resolveFeedTiles(bandDef, resolvers) {
|
|
1686
|
+
const sources = Array.isArray(bandDef.sources) ? bandDef.sources.map(String) : [];
|
|
1687
|
+
const source = sources[0];
|
|
1688
|
+
if (!source) return null;
|
|
1689
|
+
const cfg = bandDef.sourceConfig ?? {};
|
|
1690
|
+
const filterExpr = cfg["filters"]?.tag;
|
|
1691
|
+
const match = tagFilter(filterExpr);
|
|
1692
|
+
const sort = cfg["sort"];
|
|
1693
|
+
const bodyOff = styleDisabled(cfg["_body"]);
|
|
1694
|
+
const titleOff = styleDisabled(cfg["_title"]);
|
|
1695
|
+
const ratio = cropRatioOf(cfg["mediaRatio"] ?? cfg["ratio"]);
|
|
1696
|
+
const framed = (m) => m && ratio ? { ...m, cropRatio: ratio, fit: "cover" } : m;
|
|
1697
|
+
if (source === "__media") {
|
|
1698
|
+
const matched = [];
|
|
1699
|
+
for (const [uuid, entry] of resolvers.media) {
|
|
1700
|
+
const type = String(entry["type"] ?? "");
|
|
1701
|
+
if (!type.startsWith("image/")) continue;
|
|
1702
|
+
if (!match(entry["tags"] ?? [])) continue;
|
|
1703
|
+
matched.push({ ...entry, __uuid: uuid });
|
|
1704
|
+
}
|
|
1705
|
+
const tiles2 = sortRecords(matched, sort).map((entry) => {
|
|
1706
|
+
const media = framed(
|
|
1707
|
+
resolvers.mediaFor(
|
|
1708
|
+
String(entry["__uuid"]),
|
|
1709
|
+
entry["type"],
|
|
1710
|
+
entry["name"]
|
|
1711
|
+
)
|
|
1712
|
+
);
|
|
1713
|
+
const tile = {};
|
|
1714
|
+
if (media) tile.media = media;
|
|
1715
|
+
if (!titleOff && entry["name"]) tile.title = escapeHtml(String(entry["name"]));
|
|
1716
|
+
if (!bodyOff && entry["description"]) tile.body = plainToHtml(String(entry["description"]));
|
|
1717
|
+
return tile;
|
|
1718
|
+
}).filter((t) => t.media || t.title || t.body);
|
|
1719
|
+
return tiles2.length ? tiles2 : null;
|
|
1720
|
+
}
|
|
1721
|
+
const records = resolvers.feeds.get(source);
|
|
1722
|
+
if (!records) return null;
|
|
1723
|
+
const enabled = records.filter((r) => !isDisabled(r));
|
|
1724
|
+
const filtered = filterExpr ? enabled.filter((r) => match(r["tags"] ?? [])) : enabled;
|
|
1725
|
+
const ordered = sortRecords(filtered, sort);
|
|
1726
|
+
const tiles = ordered.map((r) => {
|
|
1727
|
+
const tile = {};
|
|
1728
|
+
const m = r["media"];
|
|
1729
|
+
if (m?.media) {
|
|
1730
|
+
const media = framed(resolvers.mediaFor(m.media, m.type));
|
|
1731
|
+
if (media) tile.media = media;
|
|
1732
|
+
}
|
|
1733
|
+
if (!titleOff && r["title"]) tile.title = String(r["title"]);
|
|
1734
|
+
if (!bodyOff && r["body"]) tile.body = String(r["body"]);
|
|
1735
|
+
return tile;
|
|
1736
|
+
});
|
|
1737
|
+
return tiles.length ? tiles : null;
|
|
1738
|
+
}
|
|
1739
|
+
function materializeFeedGrid(opts) {
|
|
1740
|
+
const { heading, tiles, columns, spacing, overlay } = opts;
|
|
1741
|
+
const headingNode = heading ? {
|
|
1742
|
+
kind: "heading",
|
|
1743
|
+
level: heading.level,
|
|
1744
|
+
html: heading.html,
|
|
1745
|
+
...heading.role ? { role: heading.role } : {}
|
|
1746
|
+
} : null;
|
|
1747
|
+
if (!tiles || !tiles.length) return headingNode;
|
|
1748
|
+
const cols = Math.max(1, Math.round(columns));
|
|
1749
|
+
const cells = tiles.map((t) => {
|
|
1750
|
+
const parts = [];
|
|
1751
|
+
if (t.media) parts.push({ kind: "media", media: t.media });
|
|
1752
|
+
if (t.title) parts.push({ kind: "heading", level: 6, html: t.title, role: "text6" });
|
|
1753
|
+
if (t.body) parts.push({ kind: "body", html: t.body });
|
|
1754
|
+
let node;
|
|
1755
|
+
if (overlay && t.media) {
|
|
1756
|
+
node = {
|
|
1757
|
+
kind: "stack",
|
|
1758
|
+
children: parts,
|
|
1759
|
+
style: {
|
|
1760
|
+
_overlay: overlay.ratio,
|
|
1761
|
+
...overlay.color ? { _overlayColor: overlay.color } : {},
|
|
1762
|
+
...overlay.valign ? { _overlayValign: overlay.valign } : {}
|
|
1763
|
+
}
|
|
1764
|
+
};
|
|
1765
|
+
} else {
|
|
1766
|
+
node = parts.length === 1 ? parts[0] : { kind: "stack", children: parts };
|
|
1767
|
+
}
|
|
1768
|
+
return {
|
|
1769
|
+
token: {
|
|
1770
|
+
cols,
|
|
1771
|
+
raw: `grid-${cols}${spacing ? `-s${spacing}` : ""}`,
|
|
1772
|
+
...spacing ? { spacing } : {}
|
|
1773
|
+
},
|
|
1774
|
+
node
|
|
1775
|
+
};
|
|
1776
|
+
});
|
|
1777
|
+
const row = { kind: "row", cells };
|
|
1778
|
+
return headingNode ? { kind: "stack", children: [headingNode, row] } : row;
|
|
1779
|
+
}
|
|
1780
|
+
function escapeHtml(s) {
|
|
1781
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
1782
|
+
}
|
|
1783
|
+
function plainToHtml(s) {
|
|
1784
|
+
const inner = escapeHtml(s.trim()).replace(/\r?\n/g, "<br>");
|
|
1785
|
+
return `<p>${inner}</p>`;
|
|
1786
|
+
}
|
|
1787
|
+
function extFor(mime, name) {
|
|
1788
|
+
const byMime = {
|
|
1789
|
+
"image/jpeg": "jpg",
|
|
1790
|
+
"image/jpg": "jpg",
|
|
1791
|
+
"image/png": "png",
|
|
1792
|
+
"image/svg+xml": "svg",
|
|
1793
|
+
"image/gif": "gif",
|
|
1794
|
+
"image/webp": "webp",
|
|
1795
|
+
"image/avif": "avif",
|
|
1796
|
+
"image/bmp": "bmp",
|
|
1797
|
+
"image/tiff": "tiff"
|
|
1798
|
+
};
|
|
1799
|
+
if (mime && byMime[mime]) return byMime[mime];
|
|
1800
|
+
const m = /\.([a-z0-9]{2,5})$/i.exec(name ?? "");
|
|
1801
|
+
const ext = m?.[1]?.toLowerCase();
|
|
1802
|
+
const IMG = /* @__PURE__ */ new Set(["jpg", "jpeg", "png", "svg", "gif", "webp", "avif", "bmp", "tif", "tiff"]);
|
|
1803
|
+
return ext && IMG.has(ext) ? ext === "jpeg" ? "jpg" : ext : null;
|
|
1804
|
+
}
|
|
1805
|
+
function isFeedBand(item) {
|
|
1806
|
+
return !!item && typeof item === "object" && Array.isArray(item.sources) && item.sources.length > 0;
|
|
1807
|
+
}
|
|
1808
|
+
function feedAssetBase(htmls, siteId) {
|
|
1809
|
+
for (const html of htmls) {
|
|
1810
|
+
const m = /data-base="(https?:\/\/[^"]+?\/)"/i.exec(html);
|
|
1811
|
+
if (m?.[1]) return m[1].replace(/^http:/, "https:");
|
|
1812
|
+
}
|
|
1813
|
+
return `https://${CDN_HOSTS[0]}/${siteId}/`;
|
|
1814
|
+
}
|
|
1815
|
+
function buildFeedResolvers(feeds, mediaLibrary, base2) {
|
|
1816
|
+
const feedMap = /* @__PURE__ */ new Map();
|
|
1817
|
+
for (const [id, f] of Object.entries(feeds)) {
|
|
1818
|
+
if (Array.isArray(f?.items)) feedMap.set(id, f.items);
|
|
1819
|
+
}
|
|
1820
|
+
const mediaMap = new Map(Object.entries(mediaLibrary));
|
|
1821
|
+
return {
|
|
1822
|
+
feeds: feedMap,
|
|
1823
|
+
media: mediaMap,
|
|
1824
|
+
mediaFor: (uuid, type, name) => {
|
|
1825
|
+
const ext = extFor(type, name);
|
|
1826
|
+
if (!ext) return null;
|
|
1827
|
+
return { kind: "image", assetId: uuid, base: base2, ext };
|
|
1828
|
+
}
|
|
1829
|
+
};
|
|
1830
|
+
}
|
|
1831
|
+
|
|
1378
1832
|
// src/blux/emit/block-styles.ts
|
|
1379
|
-
function blockStylesByIndex(siteJson) {
|
|
1833
|
+
function blockStylesByIndex(siteJson, pageIndex = 0) {
|
|
1380
1834
|
const out = /* @__PURE__ */ new Map();
|
|
1381
|
-
const blocks = siteJson?.content?.pages?.[
|
|
1835
|
+
const blocks = siteJson?.content?.pages?.[pageIndex]?.items;
|
|
1382
1836
|
if (!Array.isArray(blocks)) return out;
|
|
1383
1837
|
blocks.forEach((b, i) => {
|
|
1384
1838
|
const styles = b?.styles ?? {};
|
|
@@ -1391,6 +1845,30 @@ function blockStylesByIndex(siteJson) {
|
|
|
1391
1845
|
});
|
|
1392
1846
|
return out;
|
|
1393
1847
|
}
|
|
1848
|
+
var CONTAINER_RE = /^\.(blocks\d+)container$/;
|
|
1849
|
+
function blockClassDefaults(siteJson) {
|
|
1850
|
+
const out = /* @__PURE__ */ new Map();
|
|
1851
|
+
const blocks = siteJson?.styles?.blocks;
|
|
1852
|
+
if (!Array.isArray(blocks)) return out;
|
|
1853
|
+
for (const slot of blocks) {
|
|
1854
|
+
if (slot === null || typeof slot !== "object") continue;
|
|
1855
|
+
for (const [selector, css] of Object.entries(slot)) {
|
|
1856
|
+
const blockClass = CONTAINER_RE.exec(selector)?.[1];
|
|
1857
|
+
if (!blockClass || css === null || typeof css !== "object") continue;
|
|
1858
|
+
const rec = css;
|
|
1859
|
+
const padding = cleanCssValue(rec["padding"]);
|
|
1860
|
+
const mobilePadding = cleanCssValue(rec["__media_mobile_padding"]);
|
|
1861
|
+
const maxWidth = cleanCssValue(rec["max-width"]);
|
|
1862
|
+
const defaults = {
|
|
1863
|
+
...padding ? { padding } : {},
|
|
1864
|
+
...mobilePadding ? { mobilePadding } : {},
|
|
1865
|
+
...maxWidth ? { maxWidth } : {}
|
|
1866
|
+
};
|
|
1867
|
+
if (Object.keys(defaults).length) out.set(blockClass, defaults);
|
|
1868
|
+
}
|
|
1869
|
+
}
|
|
1870
|
+
return out;
|
|
1871
|
+
}
|
|
1394
1872
|
|
|
1395
1873
|
// src/blux/emit/grid-slice.ts
|
|
1396
1874
|
function stripTags(html) {
|
|
@@ -1446,9 +1924,10 @@ function sliceSpecToPlanSlice(spec) {
|
|
|
1446
1924
|
return {
|
|
1447
1925
|
slice_type: "carousel",
|
|
1448
1926
|
variation: "default",
|
|
1449
|
-
items: spec.slides.map(
|
|
1450
|
-
|
|
1451
|
-
|
|
1927
|
+
items: spec.slides.map((s) => ({
|
|
1928
|
+
...s.caption ? { caption: blockPlainText(s.caption.html) } : {},
|
|
1929
|
+
...s.subcaption ? { subcaption: blockPlainText(s.subcaption.html) } : {}
|
|
1930
|
+
})),
|
|
1452
1931
|
primary: { band: spec.index }
|
|
1453
1932
|
};
|
|
1454
1933
|
case "MediaFull":
|
|
@@ -1526,13 +2005,17 @@ function collectPlanAssets(specs, resolve, diagnostics) {
|
|
|
1526
2005
|
}
|
|
1527
2006
|
function buildGridPlan(specs, ir) {
|
|
1528
2007
|
const page = ir.pages[0];
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
2008
|
+
return buildGridSitePlan(
|
|
2009
|
+
[{ uid: page?.uid ?? "home", title: page?.title ?? page?.uid ?? "home", specs }],
|
|
2010
|
+
ir
|
|
2011
|
+
);
|
|
2012
|
+
}
|
|
2013
|
+
function buildGridSitePlan(pages, ir) {
|
|
2014
|
+
const documents = pages.map((p) => ({
|
|
1532
2015
|
type: "page",
|
|
1533
|
-
uid,
|
|
1534
|
-
data: { title: richText(`<h1>${title}</h1>`), slices: specs.map(sliceSpecToPlanSlice) }
|
|
1535
|
-
};
|
|
2016
|
+
uid: p.uid,
|
|
2017
|
+
data: { title: richText(`<h1>${p.title}</h1>`), slices: p.specs.map(sliceSpecToPlanSlice) }
|
|
2018
|
+
}));
|
|
1536
2019
|
const assetById = new Map(ir.assets.map((a) => [a.id, a]));
|
|
1537
2020
|
const sourceUrlById = new Map(ir.assets.map((a) => [a.id, a.sourceUrl]));
|
|
1538
2021
|
const resolve = (m) => {
|
|
@@ -1541,9 +2024,13 @@ function buildGridPlan(specs, ir) {
|
|
|
1541
2024
|
return url ? { id: m.assetId, url, alt: asset?.alt ?? "" } : null;
|
|
1542
2025
|
};
|
|
1543
2026
|
const diagnostics = [...ir.diagnostics ?? []];
|
|
1544
|
-
const assets = collectPlanAssets(
|
|
2027
|
+
const assets = collectPlanAssets(
|
|
2028
|
+
pages.flatMap((p) => p.specs),
|
|
2029
|
+
resolve,
|
|
2030
|
+
diagnostics
|
|
2031
|
+
);
|
|
1545
2032
|
const customTypes = ir.collections.map(buildCustomType);
|
|
1546
|
-
return { customTypes, documents
|
|
2033
|
+
return { customTypes, documents, assets, stylesManifest: [], diagnostics };
|
|
1547
2034
|
}
|
|
1548
2035
|
|
|
1549
2036
|
// src/blux/emit/presentation.ts
|
|
@@ -1562,7 +2049,7 @@ function renderNode(node, resolve) {
|
|
|
1562
2049
|
const rn = renderNode(c.node, resolve);
|
|
1563
2050
|
if (rn) cells.push({ token: renderToken(c.token), node: rn });
|
|
1564
2051
|
}
|
|
1565
|
-
return { kind: "row", cells };
|
|
2052
|
+
return { kind: "row", cells, ...node.style ? { style: node.style } : {} };
|
|
1566
2053
|
}
|
|
1567
2054
|
case "stack": {
|
|
1568
2055
|
const children = [];
|
|
@@ -1570,19 +2057,30 @@ function renderNode(node, resolve) {
|
|
|
1570
2057
|
const rn = renderNode(c, resolve);
|
|
1571
2058
|
if (rn) children.push(rn);
|
|
1572
2059
|
}
|
|
1573
|
-
return { kind: "stack", children };
|
|
2060
|
+
return { kind: "stack", children, ...node.style ? { style: node.style } : {} };
|
|
1574
2061
|
}
|
|
1575
2062
|
case "heading":
|
|
1576
2063
|
return {
|
|
1577
2064
|
kind: "heading",
|
|
1578
2065
|
level: node.level,
|
|
1579
2066
|
html: node.html,
|
|
1580
|
-
...node.role ? { role: node.role } : {}
|
|
2067
|
+
...node.role ? { role: node.role } : {},
|
|
2068
|
+
...node.style ? { style: node.style } : {}
|
|
1581
2069
|
};
|
|
1582
2070
|
case "body":
|
|
1583
|
-
return {
|
|
2071
|
+
return {
|
|
2072
|
+
kind: "body",
|
|
2073
|
+
html: node.html,
|
|
2074
|
+
...node.role ? { role: node.role } : {},
|
|
2075
|
+
...node.style ? { style: node.style } : {}
|
|
2076
|
+
};
|
|
1584
2077
|
case "subtitle":
|
|
1585
|
-
return {
|
|
2078
|
+
return {
|
|
2079
|
+
kind: "subtitle",
|
|
2080
|
+
text: node.text,
|
|
2081
|
+
...node.role ? { role: node.role } : {},
|
|
2082
|
+
...node.style ? { style: node.style } : {}
|
|
2083
|
+
};
|
|
1586
2084
|
case "media": {
|
|
1587
2085
|
const m = resolve(node.media);
|
|
1588
2086
|
return m ? { kind: "media", media: m } : null;
|
|
@@ -1599,12 +2097,45 @@ function hasMapWidget(node) {
|
|
|
1599
2097
|
if (node.kind === "stack") return node.children.some(hasMapWidget);
|
|
1600
2098
|
return false;
|
|
1601
2099
|
}
|
|
2100
|
+
function markPanelRows(node, toggleCount) {
|
|
2101
|
+
if (node.kind === "row") {
|
|
2102
|
+
return {
|
|
2103
|
+
...node,
|
|
2104
|
+
cells: node.cells.map((c) => ({ ...c, node: markPanelRows(c.node, toggleCount) }))
|
|
2105
|
+
};
|
|
2106
|
+
}
|
|
2107
|
+
if (node.kind === "stack") {
|
|
2108
|
+
const children = node.children.map((c) => markPanelRows(c, toggleCount));
|
|
2109
|
+
for (let i = 0; i + 1 < children.length; i++) {
|
|
2110
|
+
const cur = children[i];
|
|
2111
|
+
const next = children[i + 1];
|
|
2112
|
+
if (cur?.kind === "widget" && cur.widget.type === "map" && next?.kind === "row" && next.cells.length === toggleCount) {
|
|
2113
|
+
children[i + 1] = { ...next, panels: true };
|
|
2114
|
+
}
|
|
2115
|
+
}
|
|
2116
|
+
return { ...node, children };
|
|
2117
|
+
}
|
|
2118
|
+
return node;
|
|
2119
|
+
}
|
|
1602
2120
|
function buildPresentation(specs, deps) {
|
|
1603
2121
|
const bands = {};
|
|
1604
2122
|
for (const spec of specs) {
|
|
1605
2123
|
const bp = {};
|
|
1606
2124
|
const style = deps.styleFor(spec.index);
|
|
1607
2125
|
if (style) bp.style = style;
|
|
2126
|
+
const defaults = spec.blockClass ? deps.defaultsFor(spec.blockClass) : void 0;
|
|
2127
|
+
if (defaults) {
|
|
2128
|
+
const own = bp.style ?? {};
|
|
2129
|
+
const fill = {};
|
|
2130
|
+
if (own["_contentPadding"] === void 0 && defaults.padding) {
|
|
2131
|
+
fill["_contentPadding"] = defaults.padding;
|
|
2132
|
+
if (defaults.mobilePadding) fill["_contentPaddingMobile"] = defaults.mobilePadding;
|
|
2133
|
+
}
|
|
2134
|
+
if (own["_max-content-width"] === void 0 && defaults.maxWidth) {
|
|
2135
|
+
fill["_max-content-width"] = defaults.maxWidth;
|
|
2136
|
+
}
|
|
2137
|
+
if (Object.keys(fill).length) bp.style = { ...own, ...fill };
|
|
2138
|
+
}
|
|
1608
2139
|
if (spec.background) {
|
|
1609
2140
|
const bg = deps.resolveMedia(spec.background);
|
|
1610
2141
|
if (bg) bp.background = bg;
|
|
@@ -1633,14 +2164,15 @@ function buildPresentation(specs, deps) {
|
|
|
1633
2164
|
for (const s of spec.slides) {
|
|
1634
2165
|
const media = deps.resolveMedia(s.media);
|
|
1635
2166
|
if (!media) break;
|
|
1636
|
-
const slide = {
|
|
1637
|
-
media
|
|
1638
|
-
};
|
|
2167
|
+
const slide = { media };
|
|
1639
2168
|
if (s.caption) {
|
|
1640
2169
|
const caption = { level: s.caption.level };
|
|
1641
2170
|
if (s.caption.role !== void 0) caption.role = s.caption.role;
|
|
1642
2171
|
slide.caption = caption;
|
|
1643
2172
|
}
|
|
2173
|
+
if (s.subcaption) {
|
|
2174
|
+
slide.subcaption = s.subcaption.role !== void 0 ? { role: s.subcaption.role } : {};
|
|
2175
|
+
}
|
|
1644
2176
|
slides.push(slide);
|
|
1645
2177
|
}
|
|
1646
2178
|
if (slides.length > 0) {
|
|
@@ -1665,8 +2197,9 @@ function buildPresentation(specs, deps) {
|
|
|
1665
2197
|
break;
|
|
1666
2198
|
case "Grid": {
|
|
1667
2199
|
const tree = renderNode(spec.root, deps.resolveMedia);
|
|
1668
|
-
|
|
1669
|
-
if (
|
|
2200
|
+
const co = deps.map && hasMapWidget(spec.root) ? deps.map : null;
|
|
2201
|
+
if (co) bp.map = co;
|
|
2202
|
+
if (tree) bp.tree = co ? markPanelRows(tree, co.toggles.length) : tree;
|
|
1670
2203
|
break;
|
|
1671
2204
|
}
|
|
1672
2205
|
}
|
|
@@ -1699,6 +2232,7 @@ function convertExport({
|
|
|
1699
2232
|
const assetsById = new Map(ir.assets.map((a) => [a.id, a]));
|
|
1700
2233
|
const sourceUrlById = new Map(ir.assets.map((a) => [a.id, a.sourceUrl]));
|
|
1701
2234
|
const styles = blockStylesByIndex(siteJson);
|
|
2235
|
+
const defaults = blockClassDefaults(siteJson);
|
|
1702
2236
|
const deps = {
|
|
1703
2237
|
resolveMedia: (m) => {
|
|
1704
2238
|
const url = mediaUrl(m, sourceUrlById);
|
|
@@ -1713,17 +2247,284 @@ function convertExport({
|
|
|
1713
2247
|
...m.fit ? { fit: m.fit } : {},
|
|
1714
2248
|
...m.position ? { position: m.position } : {},
|
|
1715
2249
|
...m.minHeight ? { minHeight: m.minHeight } : {},
|
|
2250
|
+
...m.cropRatio ? { cropRatio: m.cropRatio } : {},
|
|
1716
2251
|
...m.playback ? { playback: m.playback } : {}
|
|
1717
2252
|
};
|
|
1718
2253
|
return rm;
|
|
1719
2254
|
},
|
|
1720
2255
|
styleFor: (i) => styles.get(i),
|
|
2256
|
+
defaultsFor: (blockClass) => defaults.get(blockClass),
|
|
1721
2257
|
map: mapConfig ? mapRenderFromConfig(mapConfig) : null
|
|
1722
2258
|
};
|
|
1723
2259
|
const plan = buildGridPlan(specs, ir);
|
|
1724
2260
|
const presentation = buildPresentation(specs, deps);
|
|
1725
2261
|
return { bands, specs, ir, mapConfig, plan, presentation };
|
|
1726
2262
|
}
|
|
2263
|
+
function leadingHeadings(root) {
|
|
2264
|
+
if (root.kind === "heading" || root.kind === "subtitle") return [root];
|
|
2265
|
+
if (root.kind === "stack") {
|
|
2266
|
+
const out = [];
|
|
2267
|
+
for (const c of root.children) {
|
|
2268
|
+
if (c.kind === "heading" || c.kind === "subtitle") out.push(c);
|
|
2269
|
+
else break;
|
|
2270
|
+
}
|
|
2271
|
+
return out;
|
|
2272
|
+
}
|
|
2273
|
+
return [];
|
|
2274
|
+
}
|
|
2275
|
+
function feedColumns(item) {
|
|
2276
|
+
const n = Number(item.columns);
|
|
2277
|
+
return Number.isFinite(n) && n > 0 ? n : 3;
|
|
2278
|
+
}
|
|
2279
|
+
function tileOverlay(item) {
|
|
2280
|
+
const cfg = item?.sourceConfig;
|
|
2281
|
+
if (!cfg || cfg["overlay"] !== true) return null;
|
|
2282
|
+
const ratio = cropRatioOf(cfg["mediaRatio"] ?? cfg["ratio"]);
|
|
2283
|
+
if (!ratio) return null;
|
|
2284
|
+
const color = typeof cfg["overlayColor"] === "string" ? cfg["overlayColor"] : void 0;
|
|
2285
|
+
const valign = typeof cfg["contentvalign"] === "string" ? cfg["contentvalign"] : void 0;
|
|
2286
|
+
return { ratio, ...color ? { color } : {}, ...valign ? { valign } : {} };
|
|
2287
|
+
}
|
|
2288
|
+
function isEmptyish(root) {
|
|
2289
|
+
switch (root.kind) {
|
|
2290
|
+
case "heading":
|
|
2291
|
+
case "subtitle":
|
|
2292
|
+
return true;
|
|
2293
|
+
case "raw":
|
|
2294
|
+
return root.html.trim() === "";
|
|
2295
|
+
case "media":
|
|
2296
|
+
case "widget":
|
|
2297
|
+
return false;
|
|
2298
|
+
case "row":
|
|
2299
|
+
return root.cells.length === 0;
|
|
2300
|
+
case "stack":
|
|
2301
|
+
return root.children.every(isEmptyish);
|
|
2302
|
+
default:
|
|
2303
|
+
return false;
|
|
2304
|
+
}
|
|
2305
|
+
}
|
|
2306
|
+
function materializeFeedBands(bands, pageItems, resolvers, diagnostics) {
|
|
2307
|
+
if (!Array.isArray(pageItems)) return;
|
|
2308
|
+
for (const band of bands) {
|
|
2309
|
+
const item = pageItems[band.index];
|
|
2310
|
+
if (!isFeedBand(item)) continue;
|
|
2311
|
+
if (!isEmptyish(band.root)) {
|
|
2312
|
+
diagnostics.push({
|
|
2313
|
+
kind: "empty-feed-grid",
|
|
2314
|
+
where: String(band.index),
|
|
2315
|
+
message: `band ${band.index} has parsed content but site.json item is a feed source \u2014 positional join misaligned, left as parsed`
|
|
2316
|
+
});
|
|
2317
|
+
continue;
|
|
2318
|
+
}
|
|
2319
|
+
const tiles = resolveFeedTiles(item, resolvers);
|
|
2320
|
+
if (!tiles) {
|
|
2321
|
+
diagnostics.push({
|
|
2322
|
+
kind: "empty-feed-grid",
|
|
2323
|
+
where: String(band.index),
|
|
2324
|
+
message: `feed band ${band.index} (source ${String(item.sources[0])}) resolved to no tiles`
|
|
2325
|
+
});
|
|
2326
|
+
continue;
|
|
2327
|
+
}
|
|
2328
|
+
const spacing = parseInt(String(item.spacing ?? ""), 10);
|
|
2329
|
+
const row = materializeFeedGrid({
|
|
2330
|
+
tiles,
|
|
2331
|
+
columns: feedColumns(item),
|
|
2332
|
+
...Number.isFinite(spacing) && spacing > 0 ? { spacing } : {},
|
|
2333
|
+
...tileOverlay(item) ? { overlay: tileOverlay(item) } : {}
|
|
2334
|
+
});
|
|
2335
|
+
if (!row) continue;
|
|
2336
|
+
const headings = leadingHeadings(band.root);
|
|
2337
|
+
band.root = headings.length ? { kind: "stack", children: [...headings, row] } : row;
|
|
2338
|
+
}
|
|
2339
|
+
}
|
|
2340
|
+
function sitePages(siteJson) {
|
|
2341
|
+
const { pages } = normalizePages(parseBluxSite(siteJson));
|
|
2342
|
+
return pages.map((p) => ({ uid: p.uid, path: p.path, title: p.title }));
|
|
2343
|
+
}
|
|
2344
|
+
function convertSite({
|
|
2345
|
+
siteJson,
|
|
2346
|
+
htmlByUid
|
|
2347
|
+
}) {
|
|
2348
|
+
const ir = assembleIR({ siteJson, htmls: [...htmlByUid.values()] });
|
|
2349
|
+
const assetsById = new Map(ir.assets.map((a) => [a.id, a]));
|
|
2350
|
+
const sourceUrlById = new Map(ir.assets.map((a) => [a.id, a.sourceUrl]));
|
|
2351
|
+
const defaults = blockClassDefaults(siteJson);
|
|
2352
|
+
const raw = parseBluxSite(siteJson);
|
|
2353
|
+
const assetBase = feedAssetBase([...htmlByUid.values()], ir.meta.bluxSiteId);
|
|
2354
|
+
const feedResolvers = buildFeedResolvers(raw.feeds, raw.media, assetBase);
|
|
2355
|
+
const pageItemsByIndex = siteJson?.content?.pages;
|
|
2356
|
+
const pages = [];
|
|
2357
|
+
const presentation = { pages: {} };
|
|
2358
|
+
ir.pages.forEach((page, pageIndex) => {
|
|
2359
|
+
const html = htmlByUid.get(page.uid);
|
|
2360
|
+
if (html === void 0) {
|
|
2361
|
+
ir.diagnostics.push({
|
|
2362
|
+
kind: "missing-page-html",
|
|
2363
|
+
where: page.uid,
|
|
2364
|
+
message: `no rendered html for page "${page.uid}" (${page.path || "/"}) \u2014 page skipped`
|
|
2365
|
+
});
|
|
2366
|
+
return;
|
|
2367
|
+
}
|
|
2368
|
+
const bands = parseGridBands(html);
|
|
2369
|
+
materializeFeedBands(
|
|
2370
|
+
bands,
|
|
2371
|
+
pageItemsByIndex?.[pageIndex]?.items,
|
|
2372
|
+
feedResolvers,
|
|
2373
|
+
ir.diagnostics
|
|
2374
|
+
);
|
|
2375
|
+
const mapConfig = extractMapConfig(html);
|
|
2376
|
+
const specs = classifyBands(bands, mapConfig ? { isMapMount: makeIsMapMount(mapConfig) } : {});
|
|
2377
|
+
const styles = blockStylesByIndex(siteJson, pageIndex);
|
|
2378
|
+
const deps = {
|
|
2379
|
+
resolveMedia: (m) => {
|
|
2380
|
+
const url = mediaUrl(m, sourceUrlById);
|
|
2381
|
+
if (!url) return null;
|
|
2382
|
+
const alt = assetsById.get(m.assetId)?.alt;
|
|
2383
|
+
const rm = {
|
|
2384
|
+
kind: m.kind,
|
|
2385
|
+
url,
|
|
2386
|
+
...alt ? { alt } : {},
|
|
2387
|
+
...m.width !== void 0 ? { width: m.width } : {},
|
|
2388
|
+
...m.aspect !== void 0 ? { aspect: m.aspect } : {},
|
|
2389
|
+
...m.fit ? { fit: m.fit } : {},
|
|
2390
|
+
...m.position ? { position: m.position } : {},
|
|
2391
|
+
...m.minHeight ? { minHeight: m.minHeight } : {},
|
|
2392
|
+
...m.cropRatio ? { cropRatio: m.cropRatio } : {},
|
|
2393
|
+
...m.playback ? { playback: m.playback } : {}
|
|
2394
|
+
};
|
|
2395
|
+
return rm;
|
|
2396
|
+
},
|
|
2397
|
+
styleFor: (i) => styles.get(i),
|
|
2398
|
+
defaultsFor: (blockClass) => defaults.get(blockClass),
|
|
2399
|
+
map: mapConfig ? mapRenderFromConfig(mapConfig) : null
|
|
2400
|
+
};
|
|
2401
|
+
presentation.pages[page.uid] = buildPresentation(specs, deps);
|
|
2402
|
+
pages.push({ uid: page.uid, title: page.title, path: page.path, bands, specs, mapConfig });
|
|
2403
|
+
});
|
|
2404
|
+
const plan = buildGridSitePlan(
|
|
2405
|
+
pages.map((p) => ({ uid: p.uid, title: p.title, specs: p.specs })),
|
|
2406
|
+
ir
|
|
2407
|
+
);
|
|
2408
|
+
return { pages, ir, plan, presentation };
|
|
2409
|
+
}
|
|
2410
|
+
|
|
2411
|
+
// src/blux/emit/site-config.ts
|
|
2412
|
+
function parseNavItems(items) {
|
|
2413
|
+
if (!Array.isArray(items)) return [];
|
|
2414
|
+
const out = [];
|
|
2415
|
+
for (const raw of items) {
|
|
2416
|
+
const label = typeof raw?.title === "string" ? raw.title.trim() : "";
|
|
2417
|
+
if (!label) continue;
|
|
2418
|
+
const href = typeof raw?.link === "string" ? raw.link : "";
|
|
2419
|
+
const children = parseNavItems(raw?.items);
|
|
2420
|
+
out.push({ label, href, ...children.length ? { children } : {} });
|
|
2421
|
+
}
|
|
2422
|
+
return out;
|
|
2423
|
+
}
|
|
2424
|
+
var SOCIAL_DOMAINS = {
|
|
2425
|
+
facebook: ["facebook.com", "fb.com"],
|
|
2426
|
+
twitter: ["twitter.com", "x.com"],
|
|
2427
|
+
instagram: ["instagram.com"],
|
|
2428
|
+
pinterest: ["pinterest.com"],
|
|
2429
|
+
linkedin: ["linkedin.com"],
|
|
2430
|
+
"linkedin-company": ["linkedin.com"],
|
|
2431
|
+
youtube: ["youtube.com", "youtu.be"],
|
|
2432
|
+
reddit: ["reddit.com"]
|
|
2433
|
+
};
|
|
2434
|
+
function hostMatches(host, domain) {
|
|
2435
|
+
return host === domain || host.endsWith("." + domain);
|
|
2436
|
+
}
|
|
2437
|
+
function hostOf(url) {
|
|
2438
|
+
try {
|
|
2439
|
+
return new URL(url).hostname.toLowerCase();
|
|
2440
|
+
} catch {
|
|
2441
|
+
return "";
|
|
2442
|
+
}
|
|
2443
|
+
}
|
|
2444
|
+
function footerRegion(html) {
|
|
2445
|
+
const lower = html.toLowerCase();
|
|
2446
|
+
const start = lower.lastIndexOf("<footer");
|
|
2447
|
+
if (start === -1) return html;
|
|
2448
|
+
const end = lower.indexOf("</footer>", start);
|
|
2449
|
+
return end === -1 ? html.slice(start) : html.slice(start, end + "</footer>".length);
|
|
2450
|
+
}
|
|
2451
|
+
function socialHrefResolverFromHtml(htmls) {
|
|
2452
|
+
const hrefs = [];
|
|
2453
|
+
const re = /href\s*=\s*["']([^"']+)["']/gi;
|
|
2454
|
+
for (const html of htmls) {
|
|
2455
|
+
if (typeof html !== "string") continue;
|
|
2456
|
+
const region = footerRegion(html);
|
|
2457
|
+
let m;
|
|
2458
|
+
while (m = re.exec(region)) {
|
|
2459
|
+
const url = m[1];
|
|
2460
|
+
if (url && /^https?:\/\//i.test(url)) hrefs.push(url);
|
|
2461
|
+
}
|
|
2462
|
+
}
|
|
2463
|
+
return (network) => {
|
|
2464
|
+
const domains = SOCIAL_DOMAINS[network];
|
|
2465
|
+
if (!domains) return void 0;
|
|
2466
|
+
return hrefs.find((u) => {
|
|
2467
|
+
const host = hostOf(u);
|
|
2468
|
+
return host && domains.some((d) => hostMatches(host, d));
|
|
2469
|
+
});
|
|
2470
|
+
};
|
|
2471
|
+
}
|
|
2472
|
+
function parseSocials(raw, resolveSocialHref) {
|
|
2473
|
+
const out = [];
|
|
2474
|
+
const items = Array.isArray(raw) ? raw : [];
|
|
2475
|
+
for (const it of items) {
|
|
2476
|
+
const media = it?.media;
|
|
2477
|
+
if (!media || media.type !== "social") continue;
|
|
2478
|
+
const networks = media.networks;
|
|
2479
|
+
if (!networks || typeof networks !== "object") continue;
|
|
2480
|
+
const urls = media.urls ?? {};
|
|
2481
|
+
for (const [network, on] of Object.entries(networks)) {
|
|
2482
|
+
if (on !== true) continue;
|
|
2483
|
+
const fromExport = typeof urls[network] === "string" ? urls[network] : void 0;
|
|
2484
|
+
const url = fromExport ?? resolveSocialHref?.(network);
|
|
2485
|
+
out.push({ network, ...url ? { href: url } : {} });
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2488
|
+
return out;
|
|
2489
|
+
}
|
|
2490
|
+
function collectTitles(node, acc) {
|
|
2491
|
+
if (Array.isArray(node)) {
|
|
2492
|
+
for (const n of node) collectTitles(n, acc);
|
|
2493
|
+
return acc;
|
|
2494
|
+
}
|
|
2495
|
+
if (node && typeof node === "object") {
|
|
2496
|
+
const rec = node;
|
|
2497
|
+
if (typeof rec.title === "string" && rec.title.trim()) acc.push(rec.title.trim());
|
|
2498
|
+
for (const k of Object.keys(rec)) if (k !== "title") collectTitles(rec[k], acc);
|
|
2499
|
+
}
|
|
2500
|
+
return acc;
|
|
2501
|
+
}
|
|
2502
|
+
var COPYRIGHT_RE = /©|\(c\)|\bcopyright\b|rights reserved/i;
|
|
2503
|
+
function parseFooterText(raw) {
|
|
2504
|
+
return collectTitles(raw, []).find((t) => COPYRIGHT_RE.test(t));
|
|
2505
|
+
}
|
|
2506
|
+
function buildSiteConfig(siteJson, resolveLogo, resolveSocialHref) {
|
|
2507
|
+
const j = siteJson;
|
|
2508
|
+
const navRoot = Array.isArray(j.navigation) ? j.navigation[0] : j.navigation;
|
|
2509
|
+
const footRoot = Array.isArray(j.footer) ? j.footer[0] : j.footer;
|
|
2510
|
+
const items = parseNavItems(navRoot?.items);
|
|
2511
|
+
const logoMedia = navRoot?.logo?.media;
|
|
2512
|
+
const logoUuid = typeof logoMedia?.media === "string" ? logoMedia.media : void 0;
|
|
2513
|
+
const logoUrl = logoUuid ? resolveLogo(logoUuid) : null;
|
|
2514
|
+
const maxWidth = typeof logoMedia?.["max-width"] === "string" ? logoMedia["max-width"] : void 0;
|
|
2515
|
+
const socials = parseSocials(footRoot?.items, resolveSocialHref);
|
|
2516
|
+
const text = parseFooterText(footRoot?.items);
|
|
2517
|
+
return {
|
|
2518
|
+
nav: {
|
|
2519
|
+
...logoUrl ? { logo: { url: logoUrl, ...maxWidth ? { maxWidth } : {} } } : {},
|
|
2520
|
+
items
|
|
2521
|
+
},
|
|
2522
|
+
footer: {
|
|
2523
|
+
socials,
|
|
2524
|
+
...text ? { text } : {}
|
|
2525
|
+
}
|
|
2526
|
+
};
|
|
2527
|
+
}
|
|
1727
2528
|
|
|
1728
2529
|
// src/blux/emit/validate-layout.ts
|
|
1729
2530
|
function tokKey(t) {
|
|
@@ -1963,11 +2764,19 @@ function walkBand(bp, map) {
|
|
|
1963
2764
|
};
|
|
1964
2765
|
return out;
|
|
1965
2766
|
}
|
|
1966
|
-
function
|
|
2767
|
+
function rewritePage(p, map) {
|
|
1967
2768
|
const bands = {};
|
|
1968
|
-
for (const [k, bp] of Object.entries(
|
|
2769
|
+
for (const [k, bp] of Object.entries(p.bands)) bands[k] = walkBand(bp, map);
|
|
1969
2770
|
return { bands };
|
|
1970
2771
|
}
|
|
2772
|
+
function rewriteManifestUrls(manifest, urlMap) {
|
|
2773
|
+
if ("pages" in manifest && manifest.pages) {
|
|
2774
|
+
const pages = {};
|
|
2775
|
+
for (const [uid, p] of Object.entries(manifest.pages)) pages[uid] = rewritePage(p, urlMap);
|
|
2776
|
+
return { pages };
|
|
2777
|
+
}
|
|
2778
|
+
return rewritePage(manifest, urlMap);
|
|
2779
|
+
}
|
|
1971
2780
|
|
|
1972
2781
|
// src/cli/commands/blux.ts
|
|
1973
2782
|
async function runBluxCommand(action, dir, opts) {
|
|
@@ -2021,9 +2830,10 @@ async function runBluxCommand(action, dir, opts) {
|
|
|
2021
2830
|
await writeFile(join(out, "ir.json"), JSON.stringify(ir, null, 2));
|
|
2022
2831
|
await writeFile(join(out, "migration-plan.json"), JSON.stringify(plan, null, 2));
|
|
2023
2832
|
const rolesCss = emitRolesCss(ir.theme);
|
|
2833
|
+
const buttonsCss = emitButtonsCss(ir.theme);
|
|
2024
2834
|
await writeFile(
|
|
2025
2835
|
join(out, "theme.css"),
|
|
2026
|
-
emitThemeCss(ir.theme) + (rolesCss ? "\n" + rolesCss : "")
|
|
2836
|
+
emitThemeCss(ir.theme) + (rolesCss ? "\n" + rolesCss : "") + (buttonsCss ? "\n" + buttonsCss : "")
|
|
2027
2837
|
);
|
|
2028
2838
|
await writeFile(join(out, "review-manifest.json"), JSON.stringify(manifest, null, 2));
|
|
2029
2839
|
await writeFile(
|
|
@@ -2068,12 +2878,16 @@ async function runBluxCommand(action, dir, opts) {
|
|
|
2068
2878
|
WARNING missing assets: ${r.missingAssets.join(", ")}` : "";
|
|
2069
2879
|
let manifestNote = "";
|
|
2070
2880
|
const manifestPath = join(dirname(planPath), "blux-presentation.json");
|
|
2881
|
+
let manifestRaw = null;
|
|
2071
2882
|
try {
|
|
2072
|
-
|
|
2883
|
+
manifestRaw = await readFile(manifestPath, "utf-8");
|
|
2884
|
+
} catch {
|
|
2885
|
+
}
|
|
2886
|
+
if (manifestRaw !== null) {
|
|
2887
|
+
const manifest = JSON.parse(manifestRaw);
|
|
2073
2888
|
const rewritten = rewriteManifestUrls(manifest, r.assetUrlByCdn);
|
|
2074
2889
|
await writeFile(manifestPath, JSON.stringify(rewritten, null, 2) + "\n");
|
|
2075
2890
|
manifestNote = "\nmanifest media rewritten to Prismic urls";
|
|
2076
|
-
} catch {
|
|
2077
2891
|
}
|
|
2078
2892
|
return {
|
|
2079
2893
|
output: `custom types pushed: ${pushed.join(", ") || "none"}
|
|
@@ -2163,15 +2977,24 @@ assets: ${r.assetsUploaded} uploaded, ${r.assetsReused} reused | documents: ${r.
|
|
|
2163
2977
|
}
|
|
2164
2978
|
if (action === "convert") {
|
|
2165
2979
|
if (!dir) return { output: "blux convert needs a Blux export directory.", code: 1 };
|
|
2166
|
-
let html;
|
|
2167
2980
|
let siteJson;
|
|
2168
2981
|
try {
|
|
2169
|
-
html = await readFile(join(dir, "index.html"), "utf-8");
|
|
2170
2982
|
siteJson = JSON.parse(await readFile(join(dir, "site.json"), "utf-8"));
|
|
2171
2983
|
} catch (err) {
|
|
2172
2984
|
return { output: `could not read export in ${dir}: ${err.message}`, code: 1 };
|
|
2173
2985
|
}
|
|
2174
|
-
const
|
|
2986
|
+
const htmlByUid = /* @__PURE__ */ new Map();
|
|
2987
|
+
for (const p of sitePages(siteJson)) {
|
|
2988
|
+
const file = p.path ? join(dir, p.path, "index.html") : join(dir, "index.html");
|
|
2989
|
+
try {
|
|
2990
|
+
htmlByUid.set(p.uid, await readFile(file, "utf-8"));
|
|
2991
|
+
} catch {
|
|
2992
|
+
}
|
|
2993
|
+
}
|
|
2994
|
+
if (!htmlByUid.size) {
|
|
2995
|
+
return { output: `could not read any page html in ${dir}`, code: 1 };
|
|
2996
|
+
}
|
|
2997
|
+
const { pages, ir, plan, presentation } = convertSite({ siteJson, htmlByUid });
|
|
2175
2998
|
const outDir = opts.out ?? join(dir, "blux-out");
|
|
2176
2999
|
await mkdir(outDir, { recursive: true });
|
|
2177
3000
|
await writeFile(join(outDir, "migration-plan.json"), JSON.stringify(plan, null, 2));
|
|
@@ -2179,18 +3002,76 @@ assets: ${r.assetsUploaded} uploaded, ${r.assetsReused} reused | documents: ${r.
|
|
|
2179
3002
|
join(outDir, "blux-presentation.json"),
|
|
2180
3003
|
JSON.stringify(presentation, null, 2) + "\n"
|
|
2181
3004
|
);
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
3005
|
+
{
|
|
3006
|
+
const buttonsCss = emitButtonsCss(ir.theme);
|
|
3007
|
+
await writeFile(
|
|
3008
|
+
join(outDir, "theme.css"),
|
|
3009
|
+
emitThemeCss(ir.theme) + "\n" + emitRolesCss(ir.theme) + (buttonsCss ? "\n" + buttonsCss : "")
|
|
3010
|
+
);
|
|
3011
|
+
}
|
|
3012
|
+
const mapConfigs = Object.fromEntries(
|
|
3013
|
+
pages.filter((p) => p.mapConfig).map((p) => [p.uid, p.mapConfig])
|
|
2185
3014
|
);
|
|
2186
|
-
if (
|
|
2187
|
-
await writeFile(join(outDir, "map-config.json"), JSON.stringify(
|
|
3015
|
+
if (Object.keys(mapConfigs).length) {
|
|
3016
|
+
await writeFile(join(outDir, "map-config.json"), JSON.stringify(mapConfigs, null, 2) + "\n");
|
|
2188
3017
|
}
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
3018
|
+
{
|
|
3019
|
+
const sourceUrlById = new Map(ir.assets.map((a) => [a.id, a.sourceUrl]));
|
|
3020
|
+
const base2 = feedAssetBase([...htmlByUid.values()], ir.meta.bluxSiteId);
|
|
3021
|
+
const mediaDict = siteJson.media ?? {};
|
|
3022
|
+
const extByMime = {
|
|
3023
|
+
"image/png": "png",
|
|
3024
|
+
"image/jpeg": "jpg",
|
|
3025
|
+
"image/svg+xml": "svg",
|
|
3026
|
+
"image/gif": "gif",
|
|
3027
|
+
"image/webp": "webp"
|
|
3028
|
+
};
|
|
3029
|
+
const resolveLogo = (uuid) => {
|
|
3030
|
+
const scraped = sourceUrlById.get(uuid);
|
|
3031
|
+
if (scraped) return scraped;
|
|
3032
|
+
const ext = extByMime[String(mediaDict[uuid]?.type ?? "")];
|
|
3033
|
+
return ext ? `${base2}${uuid}.${ext}` : null;
|
|
3034
|
+
};
|
|
3035
|
+
const resolveSocialHref = socialHrefResolverFromHtml([...htmlByUid.values()]);
|
|
3036
|
+
const siteConfig = buildSiteConfig(siteJson, resolveLogo, resolveSocialHref);
|
|
3037
|
+
await writeFile(join(outDir, "site-config.json"), JSON.stringify(siteConfig, null, 2) + "\n");
|
|
3038
|
+
}
|
|
3039
|
+
let faviconLine = "";
|
|
3040
|
+
if (ir.meta.favicon?.sourceUrl) {
|
|
3041
|
+
const { assetId, sourceUrl } = ir.meta.favicon;
|
|
3042
|
+
try {
|
|
3043
|
+
const res = await (opts.fetchImpl ?? fetch)(sourceUrl);
|
|
3044
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
3045
|
+
await writeFile(join(outDir, "favicon.png"), new Uint8Array(await res.arrayBuffer()));
|
|
3046
|
+
faviconLine = `
|
|
3047
|
+
favicon \u2192 ${join(outDir, "favicon.png")}`;
|
|
3048
|
+
} catch (err) {
|
|
3049
|
+
await writeFile(
|
|
3050
|
+
join(outDir, "favicon.json"),
|
|
3051
|
+
JSON.stringify({ assetId, url: sourceUrl }, null, 2) + "\n"
|
|
3052
|
+
);
|
|
3053
|
+
faviconLine = `
|
|
3054
|
+
favicon fetch failed (${err.message}) \u2014 url preserved in ${join(outDir, "favicon.json")}`;
|
|
3055
|
+
}
|
|
3056
|
+
}
|
|
3057
|
+
const layoutByUid = {};
|
|
3058
|
+
const reportLines = [];
|
|
3059
|
+
for (const p of pages) {
|
|
3060
|
+
const pagePresentation = presentation.pages[p.uid];
|
|
3061
|
+
if (!pagePresentation) continue;
|
|
3062
|
+
const layout = validateLayout(p.specs, pagePresentation);
|
|
3063
|
+
layoutByUid[p.uid] = layout;
|
|
3064
|
+
reportLines.push(`[${p.uid}] ${formatLayoutReport(layout)}`);
|
|
3065
|
+
}
|
|
3066
|
+
await writeFile(
|
|
3067
|
+
join(outDir, "layout-report.json"),
|
|
3068
|
+
JSON.stringify({ pages: layoutByUid }, null, 2) + "\n"
|
|
3069
|
+
);
|
|
3070
|
+
const totalBands = pages.reduce((n, p) => n + p.bands.length, 0);
|
|
3071
|
+
const missing = ir.diagnostics.filter((d) => d.kind === "missing-page-html");
|
|
2192
3072
|
return {
|
|
2193
|
-
output: `Converted ${
|
|
3073
|
+
output: `Converted ${pages.length} pages / ${totalBands} bands \u2192 ${outDir} (${plan.documents.length} page documents` + (Object.keys(mapConfigs).length ? `, map config on ${Object.keys(mapConfigs).join(", ")}` : "") + ")" + (missing.length ? `
|
|
3074
|
+
skipped (no html): ${missing.map((d) => d.where).join(", ")}` : "") + faviconLine + "\n" + reportLines.join("\n"),
|
|
2194
3075
|
code: 0
|
|
2195
3076
|
};
|
|
2196
3077
|
}
|
|
@@ -2202,4 +3083,4 @@ assets: ${r.assetsUploaded} uploaded, ${r.assetsReused} reused | documents: ${r.
|
|
|
2202
3083
|
export {
|
|
2203
3084
|
runBluxCommand
|
|
2204
3085
|
};
|
|
2205
|
-
//# sourceMappingURL=blux-
|
|
3086
|
+
//# sourceMappingURL=blux-OL5HKP26.js.map
|