@zeropress/build-pages 0.5.6 → 0.6.1
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 +65 -11
- package/dist/action.js +1561 -299
- package/dist/prebuild.js +135 -23
- package/package.json +2 -2
- package/schemas/zeropress-build-pages.config.v0.1.schema.json +26 -12
- package/src/action.js +1 -1
- package/src/prebuild.js +149 -22
- package/themes/docs/layout.html +1 -1
- package/themes/docs/theme.json +4 -4
package/dist/action.js
CHANGED
|
@@ -52242,7 +52242,7 @@ function invalidSlugValidationResult(value, code2) {
|
|
|
52242
52242
|
}
|
|
52243
52243
|
|
|
52244
52244
|
// node_modules/@zeropress/preview-data-validator/src/index.js
|
|
52245
|
-
var PREVIEW_DATA_VERSION = "0.
|
|
52245
|
+
var PREVIEW_DATA_VERSION = "0.6";
|
|
52246
52246
|
var PREVIEW_DOCUMENT_TYPES = ["plaintext", "markdown", "html"];
|
|
52247
52247
|
var PREVIEW_MENU_ITEM_TYPES = ["custom", "page", "post", "category"];
|
|
52248
52248
|
var PREVIEW_MENU_TARGETS = ["_self", "_blank"];
|
|
@@ -52251,9 +52251,16 @@ var PREVIEW_WIDGET_AREA_ID_PATTERN = /^[a-z][a-z0-9_-]{0,63}$/;
|
|
|
52251
52251
|
var PREVIEW_COLLECTION_ID_PATTERN = /^[a-z][a-z0-9_-]{0,63}$/;
|
|
52252
52252
|
var PREVIEW_COLLECTION_ITEM_TYPES = ["post", "page"];
|
|
52253
52253
|
var PREVIEW_MEDIA_DELIVERY_MODES = ["none", "media_domain"];
|
|
52254
|
+
var PREVIEW_DATETIME_DISPLAY_MODES = ["static", "client"];
|
|
52255
|
+
var PREVIEW_DATETIME_STYLES = ["none", "short", "medium", "long", "full"];
|
|
52256
|
+
var PREVIEW_DISCOVERABILITY_VALUES = ["default", "noindex", "delist"];
|
|
52254
52257
|
var PREVIEW_PERMALINK_OUTPUT_STYLES = ["directory", "html-extension"];
|
|
52255
52258
|
var PREVIEW_PERMALINK_FIELDS = ["posts", "pages", "categories", "tags"];
|
|
52256
52259
|
var PREVIEW_FRONT_PAGE_TYPES = ["theme_index", "page", "standalone_html"];
|
|
52260
|
+
var PREVIEW_DATA_KEY_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*(?:-[a-zA-Z0-9_]+)*$/;
|
|
52261
|
+
var PREVIEW_DATA_MAX_DEPTH = 4;
|
|
52262
|
+
var PREVIEW_DATA_MAX_KEYS = 64;
|
|
52263
|
+
var PREVIEW_DATA_MAX_ARRAY_LENGTH = 256;
|
|
52257
52264
|
var PREVIEW_PERMALINK_TOKENS = Object.freeze({
|
|
52258
52265
|
posts: /* @__PURE__ */ new Set(["slug", "public_id", "year", "month", "day"]),
|
|
52259
52266
|
pages: /* @__PURE__ */ new Set(["slug"]),
|
|
@@ -52307,15 +52314,17 @@ function validateSite(site, path4, errors) {
|
|
|
52307
52314
|
"title",
|
|
52308
52315
|
"description",
|
|
52309
52316
|
"url",
|
|
52310
|
-
"
|
|
52311
|
-
"
|
|
52317
|
+
"media_base_url",
|
|
52318
|
+
"media_delivery_mode",
|
|
52312
52319
|
"favicon",
|
|
52320
|
+
"expose_generator",
|
|
52313
52321
|
"locale",
|
|
52314
|
-
"
|
|
52315
|
-
"
|
|
52316
|
-
"
|
|
52322
|
+
"posts_per_page",
|
|
52323
|
+
"datetime_display",
|
|
52324
|
+
"date_style",
|
|
52325
|
+
"time_style",
|
|
52317
52326
|
"timezone",
|
|
52318
|
-
"
|
|
52327
|
+
"disallow_comments",
|
|
52319
52328
|
"indexing",
|
|
52320
52329
|
"permalinks",
|
|
52321
52330
|
"front_page",
|
|
@@ -52329,19 +52338,23 @@ function validateSite(site, path4, errors) {
|
|
|
52329
52338
|
validateNonEmptyString(site.title, `${path4}.title`, "INVALID_SITE_TITLE", errors);
|
|
52330
52339
|
validateString(site.description, `${path4}.description`, "INVALID_SITE_DESCRIPTION", errors);
|
|
52331
52340
|
validateSiteUri(site.url, `${path4}.url`, "INVALID_SITE_URL", errors);
|
|
52332
|
-
validateSiteUri(site.
|
|
52333
|
-
if (site.
|
|
52334
|
-
validateEnum(site.
|
|
52341
|
+
validateSiteUri(site.media_base_url, `${path4}.media_base_url`, "INVALID_SITE_MEDIA_BASE_URL", errors);
|
|
52342
|
+
if (site.media_delivery_mode !== void 0) {
|
|
52343
|
+
validateEnum(site.media_delivery_mode, `${path4}.media_delivery_mode`, "INVALID_SITE_MEDIA_DELIVERY_MODE", errors, PREVIEW_MEDIA_DELIVERY_MODES);
|
|
52335
52344
|
}
|
|
52336
52345
|
if (site.favicon !== void 0) {
|
|
52337
52346
|
validateSiteFavicon(site.favicon, `${path4}.favicon`, errors);
|
|
52338
52347
|
}
|
|
52348
|
+
if (site.expose_generator !== void 0) {
|
|
52349
|
+
validateBoolean(site.expose_generator, `${path4}.expose_generator`, "INVALID_SITE_EXPOSE_GENERATOR", errors);
|
|
52350
|
+
}
|
|
52339
52351
|
validateNonEmptyString(site.locale, `${path4}.locale`, "INVALID_SITE_LOCALE", errors);
|
|
52340
|
-
validateInteger(site.
|
|
52341
|
-
|
|
52342
|
-
|
|
52352
|
+
validateInteger(site.posts_per_page, `${path4}.posts_per_page`, "INVALID_SITE_POSTS_PER_PAGE", errors, { minimum: 1 });
|
|
52353
|
+
validateEnum(site.datetime_display, `${path4}.datetime_display`, "INVALID_SITE_DATETIME_DISPLAY", errors, PREVIEW_DATETIME_DISPLAY_MODES);
|
|
52354
|
+
validateEnum(site.date_style, `${path4}.date_style`, "INVALID_SITE_DATE_STYLE", errors, PREVIEW_DATETIME_STYLES);
|
|
52355
|
+
validateEnum(site.time_style, `${path4}.time_style`, "INVALID_SITE_TIME_STYLE", errors, PREVIEW_DATETIME_STYLES);
|
|
52343
52356
|
validateNonEmptyString(site.timezone, `${path4}.timezone`, "INVALID_SITE_TIMEZONE", errors);
|
|
52344
|
-
validateBoolean(site.
|
|
52357
|
+
validateBoolean(site.disallow_comments, `${path4}.disallow_comments`, "INVALID_SITE_DISALLOW_COMMENTS", errors);
|
|
52345
52358
|
if (site.indexing !== void 0) {
|
|
52346
52359
|
validateBoolean(site.indexing, `${path4}.indexing`, "INVALID_SITE_INDEXING", errors);
|
|
52347
52360
|
}
|
|
@@ -52357,7 +52370,6 @@ function validateSite(site, path4, errors) {
|
|
|
52357
52370
|
"site_description",
|
|
52358
52371
|
"site_url",
|
|
52359
52372
|
"metadata",
|
|
52360
|
-
"media_delivery_mode",
|
|
52361
52373
|
"media_delivery_base_url",
|
|
52362
52374
|
"language",
|
|
52363
52375
|
"siteLocale",
|
|
@@ -52395,10 +52407,7 @@ function validateSiteFooter(footer, path4, errors) {
|
|
|
52395
52407
|
validateNonEmptyString(footer.copyright_text, `${path4}.copyright_text`, "INVALID_SITE_FOOTER_COPYRIGHT_TEXT", errors);
|
|
52396
52408
|
}
|
|
52397
52409
|
if (footer.attribution !== void 0) {
|
|
52398
|
-
|
|
52399
|
-
if (isObject(footer.attribution) && footer.attribution.enabled !== void 0) {
|
|
52400
|
-
validateBoolean(footer.attribution.enabled, `${path4}.attribution.enabled`, "INVALID_SITE_FOOTER_ATTRIBUTION_ENABLED", errors);
|
|
52401
|
-
}
|
|
52410
|
+
validateBoolean(footer.attribution, `${path4}.attribution`, "INVALID_SITE_FOOTER_ATTRIBUTION", errors);
|
|
52402
52411
|
}
|
|
52403
52412
|
}
|
|
52404
52413
|
function validateMenus(menus, path4, errors) {
|
|
@@ -52424,7 +52433,7 @@ function validatePreviewMenu(menu, path4, errors) {
|
|
|
52424
52433
|
});
|
|
52425
52434
|
}
|
|
52426
52435
|
function validatePreviewMenuItem(item, path4, errors) {
|
|
52427
|
-
validateClosedObject(item, path4, errors, ["title", "url", "type", "target", "children"]);
|
|
52436
|
+
validateClosedObject(item, path4, errors, ["title", "url", "type", "target", "meta", "children"]);
|
|
52428
52437
|
if (!isObject(item)) {
|
|
52429
52438
|
return;
|
|
52430
52439
|
}
|
|
@@ -52432,6 +52441,7 @@ function validatePreviewMenuItem(item, path4, errors) {
|
|
|
52432
52441
|
validateUrlLike(item.url, `${path4}.url`, "INVALID_MENU_ITEM_URL", errors);
|
|
52433
52442
|
validateEnum(item.type, `${path4}.type`, "INVALID_MENU_ITEM_TYPE", errors, PREVIEW_MENU_ITEM_TYPES);
|
|
52434
52443
|
validateEnum(item.target, `${path4}.target`, "INVALID_MENU_ITEM_TARGET", errors, PREVIEW_MENU_TARGETS);
|
|
52444
|
+
validatePreviewMeta(item.meta, `${path4}.meta`, errors);
|
|
52435
52445
|
validateArray(item.children, `${path4}.children`, "INVALID_MENU_ITEM_CHILDREN", errors, (entry, index) => {
|
|
52436
52446
|
validatePreviewMenuItem(entry, `${path4}.children[${index}]`, errors);
|
|
52437
52447
|
});
|
|
@@ -52637,7 +52647,9 @@ function validatePreviewPost(post, path4, errors, authorIds) {
|
|
|
52637
52647
|
"author_id",
|
|
52638
52648
|
"featured_image",
|
|
52639
52649
|
"meta",
|
|
52650
|
+
"data",
|
|
52640
52651
|
"status",
|
|
52652
|
+
"discoverability",
|
|
52641
52653
|
"allow_comments",
|
|
52642
52654
|
"category_slugs",
|
|
52643
52655
|
"tag_slugs"
|
|
@@ -52655,6 +52667,9 @@ function validatePreviewPost(post, path4, errors, authorIds) {
|
|
|
52655
52667
|
validateDateTimeString(post.updated_at_iso, `${path4}.updated_at_iso`, "INVALID_POST_UPDATED_AT_ISO", errors);
|
|
52656
52668
|
validateNonEmptyString(post.author_id, `${path4}.author_id`, "INVALID_POST_AUTHOR_ID", errors);
|
|
52657
52669
|
validateEnum(post.status, `${path4}.status`, "INVALID_POST_STATUS", errors, ["published", "draft"]);
|
|
52670
|
+
if (post.discoverability !== void 0) {
|
|
52671
|
+
validateEnum(post.discoverability, `${path4}.discoverability`, "INVALID_POST_DISCOVERABILITY", errors, PREVIEW_DISCOVERABILITY_VALUES);
|
|
52672
|
+
}
|
|
52658
52673
|
validateBoolean(post.allow_comments, `${path4}.allow_comments`, "INVALID_POST_ALLOW_COMMENTS", errors);
|
|
52659
52674
|
validateSlugArray(post.category_slugs, `${path4}.category_slugs`, "INVALID_POST_CATEGORY_SLUGS", errors);
|
|
52660
52675
|
validateSlugArray(post.tag_slugs, `${path4}.tag_slugs`, "INVALID_POST_TAG_SLUGS", errors);
|
|
@@ -52662,12 +52677,13 @@ function validatePreviewPost(post, path4, errors, authorIds) {
|
|
|
52662
52677
|
validateUrlLike(post.featured_image, `${path4}.featured_image`, "INVALID_POST_FEATURED_IMAGE", errors);
|
|
52663
52678
|
}
|
|
52664
52679
|
validatePreviewMeta(post.meta, `${path4}.meta`, errors);
|
|
52680
|
+
validatePreviewStructuredData(post.data, `${path4}.data`, errors);
|
|
52665
52681
|
if (typeof post.author_id === "string" && post.author_id.trim() !== "" && !authorIds.has(post.author_id)) {
|
|
52666
52682
|
errors.push(issue("INVALID_POST_AUTHOR_REFERENCE", `${path4}.author_id`, "Referenced author_id does not exist"));
|
|
52667
52683
|
}
|
|
52668
52684
|
}
|
|
52669
52685
|
function validatePreviewPage(page, path4, errors) {
|
|
52670
|
-
validateClosedObject(page, path4, errors, ["title", "slug", "path", "content", "document_type", "excerpt", "featured_image", "meta", "status"]);
|
|
52686
|
+
validateClosedObject(page, path4, errors, ["title", "slug", "path", "content", "document_type", "excerpt", "featured_image", "meta", "data", "status", "discoverability"]);
|
|
52671
52687
|
if (!isObject(page)) {
|
|
52672
52688
|
return;
|
|
52673
52689
|
}
|
|
@@ -52683,7 +52699,11 @@ function validatePreviewPage(page, path4, errors) {
|
|
|
52683
52699
|
validateUrlLike(page.featured_image, `${path4}.featured_image`, "INVALID_PAGE_FEATURED_IMAGE", errors);
|
|
52684
52700
|
}
|
|
52685
52701
|
validatePreviewMeta(page.meta, `${path4}.meta`, errors);
|
|
52702
|
+
validatePreviewStructuredData(page.data, `${path4}.data`, errors);
|
|
52686
52703
|
validateEnum(page.status, `${path4}.status`, "INVALID_PAGE_STATUS", errors, ["published", "draft"]);
|
|
52704
|
+
if (page.discoverability !== void 0) {
|
|
52705
|
+
validateEnum(page.discoverability, `${path4}.discoverability`, "INVALID_PAGE_DISCOVERABILITY", errors, PREVIEW_DISCOVERABILITY_VALUES);
|
|
52706
|
+
}
|
|
52687
52707
|
}
|
|
52688
52708
|
function validatePreviewMeta(meta, path4, errors) {
|
|
52689
52709
|
if (meta === void 0) {
|
|
@@ -52700,6 +52720,66 @@ function validatePreviewMeta(meta, path4, errors) {
|
|
|
52700
52720
|
errors.push(issue("INVALID_META_VALUE", `${path4}.${key}`, "meta values must be strings, numbers, booleans, or null"));
|
|
52701
52721
|
}
|
|
52702
52722
|
}
|
|
52723
|
+
function validatePreviewStructuredData(data, path4, errors) {
|
|
52724
|
+
if (data === void 0) {
|
|
52725
|
+
return;
|
|
52726
|
+
}
|
|
52727
|
+
if (!isObject(data)) {
|
|
52728
|
+
errors.push(issue("INVALID_DATA", path4, "data must be an object"));
|
|
52729
|
+
return;
|
|
52730
|
+
}
|
|
52731
|
+
validatePreviewDataObject(data, path4, errors, 0);
|
|
52732
|
+
}
|
|
52733
|
+
function validatePreviewDataValue(value, path4, errors, depth) {
|
|
52734
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") {
|
|
52735
|
+
return;
|
|
52736
|
+
}
|
|
52737
|
+
if (typeof value === "number") {
|
|
52738
|
+
if (!Number.isFinite(value)) {
|
|
52739
|
+
errors.push(issue("INVALID_DATA_VALUE", path4, "data numbers must be finite"));
|
|
52740
|
+
}
|
|
52741
|
+
return;
|
|
52742
|
+
}
|
|
52743
|
+
if (Array.isArray(value)) {
|
|
52744
|
+
validatePreviewDataArray(value, path4, errors, depth);
|
|
52745
|
+
return;
|
|
52746
|
+
}
|
|
52747
|
+
if (isObject(value)) {
|
|
52748
|
+
validatePreviewDataObject(value, path4, errors, depth);
|
|
52749
|
+
return;
|
|
52750
|
+
}
|
|
52751
|
+
errors.push(issue("INVALID_DATA_VALUE", path4, "data values must be JSON-safe strings, numbers, booleans, null, arrays, or objects"));
|
|
52752
|
+
}
|
|
52753
|
+
function validatePreviewDataObject(object, path4, errors, depth) {
|
|
52754
|
+
if (depth > PREVIEW_DATA_MAX_DEPTH) {
|
|
52755
|
+
errors.push(issue("INVALID_DATA_DEPTH", path4, `data nesting must not exceed ${PREVIEW_DATA_MAX_DEPTH} container levels`));
|
|
52756
|
+
return;
|
|
52757
|
+
}
|
|
52758
|
+
const entries = Object.entries(object);
|
|
52759
|
+
if (entries.length > PREVIEW_DATA_MAX_KEYS) {
|
|
52760
|
+
errors.push(issue("INVALID_DATA_OBJECT_SIZE", path4, `data objects must not contain more than ${PREVIEW_DATA_MAX_KEYS} keys`));
|
|
52761
|
+
}
|
|
52762
|
+
for (const [key, value] of entries) {
|
|
52763
|
+
const childPath = `${path4}.${key}`;
|
|
52764
|
+
if (!PREVIEW_DATA_KEY_PATTERN.test(key)) {
|
|
52765
|
+
errors.push(issue("INVALID_DATA_KEY", childPath, "data keys must be valid template path segments"));
|
|
52766
|
+
continue;
|
|
52767
|
+
}
|
|
52768
|
+
validatePreviewDataValue(value, childPath, errors, depth + 1);
|
|
52769
|
+
}
|
|
52770
|
+
}
|
|
52771
|
+
function validatePreviewDataArray(array, path4, errors, depth) {
|
|
52772
|
+
if (depth > PREVIEW_DATA_MAX_DEPTH) {
|
|
52773
|
+
errors.push(issue("INVALID_DATA_DEPTH", path4, `data nesting must not exceed ${PREVIEW_DATA_MAX_DEPTH} container levels`));
|
|
52774
|
+
return;
|
|
52775
|
+
}
|
|
52776
|
+
if (array.length > PREVIEW_DATA_MAX_ARRAY_LENGTH) {
|
|
52777
|
+
errors.push(issue("INVALID_DATA_ARRAY_SIZE", path4, `data arrays must not contain more than ${PREVIEW_DATA_MAX_ARRAY_LENGTH} items`));
|
|
52778
|
+
}
|
|
52779
|
+
array.forEach((value, index) => {
|
|
52780
|
+
validatePreviewDataValue(value, `${path4}[${index}]`, errors, depth + 1);
|
|
52781
|
+
});
|
|
52782
|
+
}
|
|
52703
52783
|
function validatePermalinks(permalinks, path4, errors) {
|
|
52704
52784
|
if (permalinks === void 0) {
|
|
52705
52785
|
return;
|
|
@@ -52930,7 +53010,7 @@ function isOptionalKey(path4, key) {
|
|
|
52930
53010
|
return key === "head_end" || key === "body_end";
|
|
52931
53011
|
}
|
|
52932
53012
|
if (path4 === "site") {
|
|
52933
|
-
return key === "
|
|
53013
|
+
return key === "media_delivery_mode" || key === "favicon" || key === "expose_generator" || key === "indexing" || key === "permalinks" || key === "front_page" || key === "post_index" || key === "footer" || key === "meta";
|
|
52934
53014
|
}
|
|
52935
53015
|
if (path4 === "site.favicon") {
|
|
52936
53016
|
return key === "icon" || key === "svg" || key === "png" || key === "apple_touch_icon";
|
|
@@ -52938,9 +53018,6 @@ function isOptionalKey(path4, key) {
|
|
|
52938
53018
|
if (path4 === "site.footer") {
|
|
52939
53019
|
return key === "copyright_text" || key === "attribution";
|
|
52940
53020
|
}
|
|
52941
|
-
if (path4 === "site.footer.attribution") {
|
|
52942
|
-
return key === "enabled";
|
|
52943
|
-
}
|
|
52944
53021
|
if (path4 === "site.front_page") {
|
|
52945
53022
|
return key === "page_slug" || key === "html";
|
|
52946
53023
|
}
|
|
@@ -52959,6 +53036,9 @@ function isOptionalKey(path4, key) {
|
|
|
52959
53036
|
if (path4.startsWith("content.media[")) {
|
|
52960
53037
|
return key === "alt";
|
|
52961
53038
|
}
|
|
53039
|
+
if (path4.startsWith("menus.") && (path4.includes(".items[") || path4.includes(".children["))) {
|
|
53040
|
+
return key === "meta";
|
|
53041
|
+
}
|
|
52962
53042
|
if (path4.startsWith("widgets.") && path4.includes(".items[")) {
|
|
52963
53043
|
return key === "settings";
|
|
52964
53044
|
}
|
|
@@ -52966,10 +53046,10 @@ function isOptionalKey(path4, key) {
|
|
|
52966
53046
|
return key === "title" || key === "description";
|
|
52967
53047
|
}
|
|
52968
53048
|
if (path4.startsWith("content.posts[")) {
|
|
52969
|
-
return key === "id" || key === "featured_image" || key === "meta";
|
|
53049
|
+
return key === "id" || key === "featured_image" || key === "meta" || key === "data" || key === "discoverability";
|
|
52970
53050
|
}
|
|
52971
53051
|
if (path4.startsWith("content.pages[")) {
|
|
52972
|
-
return key === "path" || key === "excerpt" || key === "featured_image" || key === "meta";
|
|
53052
|
+
return key === "path" || key === "excerpt" || key === "featured_image" || key === "meta" || key === "data" || key === "discoverability";
|
|
52973
53053
|
}
|
|
52974
53054
|
if (path4.startsWith("content.categories[") || path4.startsWith("content.tags[")) {
|
|
52975
53055
|
return key === "description";
|
|
@@ -53014,7 +53094,7 @@ function mapSlugValidationMessage(issueCode) {
|
|
|
53014
53094
|
function rejectLegacyKeys(value, path4, errors, keys, code2) {
|
|
53015
53095
|
for (const key of keys) {
|
|
53016
53096
|
if (key in value) {
|
|
53017
|
-
errors.push(issue(code2, `${path4}.${key}`, "Legacy field is not allowed in preview-data v0.
|
|
53097
|
+
errors.push(issue(code2, `${path4}.${key}`, "Legacy field is not allowed in preview-data v0.6"));
|
|
53018
53098
|
}
|
|
53019
53099
|
}
|
|
53020
53100
|
}
|
|
@@ -53124,9 +53204,46 @@ var PARTIAL_TAG_REGEX = /\{\{(partial:[^}]+)\}\}/g;
|
|
|
53124
53204
|
var TEMPLATE_PATH_SEGMENT_SOURCE = "[a-zA-Z_][a-zA-Z0-9_]*(?:-[a-zA-Z0-9_]+)*";
|
|
53125
53205
|
var TEMPLATE_PATH_REGEX = new RegExp(`^${TEMPLATE_PATH_SEGMENT_SOURCE}(?:\\.${TEMPLATE_PATH_SEGMENT_SOURCE})*$`);
|
|
53126
53206
|
var FOR_TAG_REGEX = new RegExp(`^#for ([a-zA-Z_][a-zA-Z0-9_]*) in (${TEMPLATE_PATH_SEGMENT_SOURCE}(?:\\.${TEMPLATE_PATH_SEGMENT_SOURCE})*)$`);
|
|
53127
|
-
var
|
|
53207
|
+
var NUMBER_LITERAL_REGEX = /^-?(?:0|[1-9]\d*)(?:\.\d+)?$/;
|
|
53208
|
+
var COMPARISON_BLOCK_TAGS = /* @__PURE__ */ new Set(["if_eq", "if_neq", "if_in", "if_starts_with"]);
|
|
53209
|
+
var COMPARISON_ELSE_IF_TAGS = /* @__PURE__ */ new Set(["else_if_eq", "else_if_neq", "else_if_in", "else_if_starts_with"]);
|
|
53210
|
+
var COMPARISON_TAG_OPERATORS = {
|
|
53211
|
+
if_eq: "eq",
|
|
53212
|
+
else_if_eq: "eq",
|
|
53213
|
+
if_neq: "neq",
|
|
53214
|
+
else_if_neq: "neq",
|
|
53215
|
+
if_in: "in",
|
|
53216
|
+
else_if_in: "in",
|
|
53217
|
+
if_starts_with: "starts_with",
|
|
53218
|
+
else_if_starts_with: "starts_with"
|
|
53219
|
+
};
|
|
53220
|
+
var PARTIAL_ARG_ROOT_PATHS = /* @__PURE__ */ new Set([
|
|
53221
|
+
"archive",
|
|
53222
|
+
"author",
|
|
53223
|
+
"category",
|
|
53224
|
+
"collection",
|
|
53225
|
+
"collections",
|
|
53226
|
+
"currentUrl",
|
|
53227
|
+
"language",
|
|
53228
|
+
"menu",
|
|
53229
|
+
"menus",
|
|
53230
|
+
"meta",
|
|
53231
|
+
"page",
|
|
53232
|
+
"pagination",
|
|
53233
|
+
"partial",
|
|
53234
|
+
"post",
|
|
53235
|
+
"posts",
|
|
53236
|
+
"route",
|
|
53237
|
+
"site",
|
|
53238
|
+
"tag",
|
|
53239
|
+
"taxonomies",
|
|
53240
|
+
"taxonomy",
|
|
53241
|
+
"widget",
|
|
53242
|
+
"widgets"
|
|
53243
|
+
]);
|
|
53128
53244
|
var PARTIAL_ARG_KEY_REGEX = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
|
|
53129
53245
|
var SEMVER_REGEX = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
53246
|
+
var LICENSE_REF_REGEX = /^LicenseRef-[A-Za-z0-9][A-Za-z0-9.-]*$/;
|
|
53130
53247
|
var NAMESPACE_REGEX = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
53131
53248
|
var SLUG_REGEX = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
53132
53249
|
var ALLOWED_LICENSES = [
|
|
@@ -53137,7 +53254,10 @@ var ALLOWED_LICENSES = [
|
|
|
53137
53254
|
"GPL-3.0-or-later"
|
|
53138
53255
|
];
|
|
53139
53256
|
var LICENSES = new Set(ALLOWED_LICENSES);
|
|
53140
|
-
var
|
|
53257
|
+
var THEME_LINK_KEYS = /* @__PURE__ */ new Set(["homepage", "repository", "documentation", "support", "marketplace", "license"]);
|
|
53258
|
+
var THEME_LINK_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:", "mailto:"]);
|
|
53259
|
+
var DEFAULT_RUNTIME = "0.6";
|
|
53260
|
+
var THEME_RUNTIME_V0_6 = DEFAULT_RUNTIME;
|
|
53141
53261
|
var SUPPORTED_RUNTIMES = [DEFAULT_RUNTIME];
|
|
53142
53262
|
var SUPPORTED_RUNTIME_SET = new Set(SUPPORTED_RUNTIMES);
|
|
53143
53263
|
var NAMESPACE_MIN_LENGTH = 3;
|
|
@@ -53152,7 +53272,7 @@ var MENU_SLOT_ID_MAX_LENGTH = 32;
|
|
|
53152
53272
|
var MENU_SLOT_COUNT_MAX = 12;
|
|
53153
53273
|
var MENU_SLOT_TITLE_MAX_LENGTH = 80;
|
|
53154
53274
|
var MENU_SLOT_DESCRIPTION_MAX_LENGTH = 160;
|
|
53155
|
-
var SUPPORTED_THEME_FEATURES = /* @__PURE__ */ new Set(["comments", "newsletter", "
|
|
53275
|
+
var SUPPORTED_THEME_FEATURES = /* @__PURE__ */ new Set(["comments", "newsletter", "post_index"]);
|
|
53156
53276
|
var THEME_MANIFEST_KEYS = /* @__PURE__ */ new Set([
|
|
53157
53277
|
"$schema",
|
|
53158
53278
|
"name",
|
|
@@ -53164,11 +53284,12 @@ var THEME_MANIFEST_KEYS = /* @__PURE__ */ new Set([
|
|
|
53164
53284
|
"author",
|
|
53165
53285
|
"description",
|
|
53166
53286
|
"thumbnail",
|
|
53287
|
+
"links",
|
|
53167
53288
|
"features",
|
|
53168
|
-
"
|
|
53169
|
-
"
|
|
53170
|
-
"
|
|
53171
|
-
"
|
|
53289
|
+
"menu_slots",
|
|
53290
|
+
"widget_areas",
|
|
53291
|
+
"site_meta",
|
|
53292
|
+
"collection_slots"
|
|
53172
53293
|
]);
|
|
53173
53294
|
var SITE_META_KEY_REGEX = /^[a-z][a-z0-9_]*(?:-[a-z0-9_]+)*$/;
|
|
53174
53295
|
var SITE_META_KEY_MAX_LENGTH = 64;
|
|
@@ -53194,7 +53315,11 @@ function validateFeatureFlags(rawValue, errors) {
|
|
|
53194
53315
|
"INVALID_THEME_FEATURE",
|
|
53195
53316
|
`theme.json.features.${featureName}`,
|
|
53196
53317
|
`Unknown theme feature '${featureName}'`,
|
|
53197
|
-
"error"
|
|
53318
|
+
"error",
|
|
53319
|
+
{
|
|
53320
|
+
category: "theme_manifest",
|
|
53321
|
+
hint: themeFeatureHint(featureName)
|
|
53322
|
+
}
|
|
53198
53323
|
));
|
|
53199
53324
|
continue;
|
|
53200
53325
|
}
|
|
@@ -53211,6 +53336,80 @@ function validateFeatureFlags(rawValue, errors) {
|
|
|
53211
53336
|
}
|
|
53212
53337
|
return Object.keys(normalizedFeatures).length > 0 ? normalizedFeatures : void 0;
|
|
53213
53338
|
}
|
|
53339
|
+
function themeFeatureHint(featureName) {
|
|
53340
|
+
const hints = {
|
|
53341
|
+
postIndex: "ZeroPress runtime v0.6 uses snake_case keys. Use 'post_index' instead of 'postIndex'."
|
|
53342
|
+
};
|
|
53343
|
+
return hints[featureName] || "";
|
|
53344
|
+
}
|
|
53345
|
+
function themeManifestFieldHint(fieldName) {
|
|
53346
|
+
const hints = {
|
|
53347
|
+
menuSlots: "ZeroPress runtime v0.6 uses snake_case keys. Use 'menu_slots' instead of 'menuSlots'.",
|
|
53348
|
+
widgetAreas: "ZeroPress runtime v0.6 uses snake_case keys. Use 'widget_areas' instead of 'widgetAreas'.",
|
|
53349
|
+
siteMeta: "ZeroPress runtime v0.6 uses snake_case keys. Use 'site_meta' instead of 'siteMeta'.",
|
|
53350
|
+
collectionSlots: "ZeroPress runtime v0.6 uses snake_case keys. Use 'collection_slots' instead of 'collectionSlots'.",
|
|
53351
|
+
settings: "theme.json.settings was removed in runtime v0.6. Use preview-data site.meta and theme.json site_meta hints for site-level values."
|
|
53352
|
+
};
|
|
53353
|
+
return hints[fieldName] || "";
|
|
53354
|
+
}
|
|
53355
|
+
function isAllowedLicense(value) {
|
|
53356
|
+
return LICENSES.has(value) || LICENSE_REF_REGEX.test(value);
|
|
53357
|
+
}
|
|
53358
|
+
function isValidThemeLinkUrl(value) {
|
|
53359
|
+
try {
|
|
53360
|
+
const parsed = new URL(value);
|
|
53361
|
+
return THEME_LINK_PROTOCOLS.has(parsed.protocol);
|
|
53362
|
+
} catch {
|
|
53363
|
+
return false;
|
|
53364
|
+
}
|
|
53365
|
+
}
|
|
53366
|
+
function validateThemeLinks(rawValue, errors) {
|
|
53367
|
+
if (rawValue === void 0) {
|
|
53368
|
+
return void 0;
|
|
53369
|
+
}
|
|
53370
|
+
if (!rawValue || typeof rawValue !== "object" || Array.isArray(rawValue)) {
|
|
53371
|
+
errors.push(issue2(
|
|
53372
|
+
"INVALID_LINKS",
|
|
53373
|
+
"theme.json.links",
|
|
53374
|
+
"theme.json field 'links' must be an object when present",
|
|
53375
|
+
"error"
|
|
53376
|
+
));
|
|
53377
|
+
return void 0;
|
|
53378
|
+
}
|
|
53379
|
+
const normalizedLinks = {};
|
|
53380
|
+
for (const [linkKey, value] of Object.entries(rawValue)) {
|
|
53381
|
+
if (!THEME_LINK_KEYS.has(linkKey)) {
|
|
53382
|
+
errors.push(issue2(
|
|
53383
|
+
"INVALID_THEME_LINK",
|
|
53384
|
+
`theme.json.links.${linkKey}`,
|
|
53385
|
+
`Unknown theme link '${linkKey}'`,
|
|
53386
|
+
"error"
|
|
53387
|
+
));
|
|
53388
|
+
continue;
|
|
53389
|
+
}
|
|
53390
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
53391
|
+
errors.push(issue2(
|
|
53392
|
+
"INVALID_THEME_LINK_VALUE",
|
|
53393
|
+
`theme.json.links.${linkKey}`,
|
|
53394
|
+
`theme link '${linkKey}' must be a non-empty URL string`,
|
|
53395
|
+
"error"
|
|
53396
|
+
));
|
|
53397
|
+
continue;
|
|
53398
|
+
}
|
|
53399
|
+
const normalizedValue = value.trim();
|
|
53400
|
+
if (!isValidThemeLinkUrl(normalizedValue)) {
|
|
53401
|
+
errors.push(issue2(
|
|
53402
|
+
"INVALID_THEME_LINK_VALUE",
|
|
53403
|
+
`theme.json.links.${linkKey}`,
|
|
53404
|
+
`theme link '${linkKey}' must be an absolute http, https, or mailto URL`,
|
|
53405
|
+
"error"
|
|
53406
|
+
));
|
|
53407
|
+
continue;
|
|
53408
|
+
}
|
|
53409
|
+
normalizedLinks[linkKey] = normalizedValue;
|
|
53410
|
+
}
|
|
53411
|
+
return Object.keys(normalizedLinks).length > 0 ? normalizedLinks : void 0;
|
|
53412
|
+
}
|
|
53214
53413
|
function validateHelperMetadataMap(rawValue, fieldName, issueCodes, errors) {
|
|
53215
53414
|
if (rawValue === void 0) {
|
|
53216
53415
|
return void 0;
|
|
@@ -53312,7 +53511,7 @@ function validateSiteMetaMap(rawValue, errors) {
|
|
|
53312
53511
|
errors.push(issue2(
|
|
53313
53512
|
"INVALID_SITE_META",
|
|
53314
53513
|
"theme.json",
|
|
53315
|
-
"theme.json field '
|
|
53514
|
+
"theme.json field 'site_meta' must be an object when present",
|
|
53316
53515
|
"error"
|
|
53317
53516
|
));
|
|
53318
53517
|
return void 0;
|
|
@@ -53322,7 +53521,7 @@ function validateSiteMetaMap(rawValue, errors) {
|
|
|
53322
53521
|
errors.push(issue2(
|
|
53323
53522
|
"INVALID_SITE_META",
|
|
53324
53523
|
"theme.json",
|
|
53325
|
-
"theme.json field '
|
|
53524
|
+
"theme.json field 'site_meta' must not be empty",
|
|
53326
53525
|
"error"
|
|
53327
53526
|
));
|
|
53328
53527
|
}
|
|
@@ -53330,7 +53529,7 @@ function validateSiteMetaMap(rawValue, errors) {
|
|
|
53330
53529
|
errors.push(issue2(
|
|
53331
53530
|
"INVALID_SITE_META",
|
|
53332
53531
|
"theme.json",
|
|
53333
|
-
`theme.json field '
|
|
53532
|
+
`theme.json field 'site_meta' must contain at most ${SITE_META_COUNT_MAX} keys`,
|
|
53334
53533
|
"error"
|
|
53335
53534
|
));
|
|
53336
53535
|
}
|
|
@@ -53339,8 +53538,8 @@ function validateSiteMetaMap(rawValue, errors) {
|
|
|
53339
53538
|
if (!SITE_META_KEY_REGEX.test(metaKey) || metaKey.length > SITE_META_KEY_MAX_LENGTH) {
|
|
53340
53539
|
errors.push(issue2(
|
|
53341
53540
|
"INVALID_SITE_META_KEY",
|
|
53342
|
-
`theme.json.
|
|
53343
|
-
`
|
|
53541
|
+
`theme.json.site_meta.${metaKey}`,
|
|
53542
|
+
`site_meta key '${metaKey}' must start with a lowercase letter and use lowercase letters, digits, underscores, or internal hyphens only`,
|
|
53344
53543
|
"error"
|
|
53345
53544
|
));
|
|
53346
53545
|
continue;
|
|
@@ -53348,8 +53547,8 @@ function validateSiteMetaMap(rawValue, errors) {
|
|
|
53348
53547
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
53349
53548
|
errors.push(issue2(
|
|
53350
53549
|
"INVALID_SITE_META_FIELD",
|
|
53351
|
-
`theme.json.
|
|
53352
|
-
`
|
|
53550
|
+
`theme.json.site_meta.${metaKey}`,
|
|
53551
|
+
`site_meta key '${metaKey}' must be an object`,
|
|
53353
53552
|
"error"
|
|
53354
53553
|
));
|
|
53355
53554
|
continue;
|
|
@@ -53359,8 +53558,8 @@ function validateSiteMetaMap(rawValue, errors) {
|
|
|
53359
53558
|
if (!allowedKeys.has(key)) {
|
|
53360
53559
|
errors.push(issue2(
|
|
53361
53560
|
"INVALID_SITE_META_PROPERTY",
|
|
53362
|
-
`theme.json.
|
|
53363
|
-
`Unknown
|
|
53561
|
+
`theme.json.site_meta.${metaKey}.${key}`,
|
|
53562
|
+
`Unknown site_meta property '${key}' in key '${metaKey}'`,
|
|
53364
53563
|
"error"
|
|
53365
53564
|
));
|
|
53366
53565
|
}
|
|
@@ -53368,31 +53567,31 @@ function validateSiteMetaMap(rawValue, errors) {
|
|
|
53368
53567
|
if (typeof value.title !== "string" || value.title.trim() === "") {
|
|
53369
53568
|
errors.push(issue2(
|
|
53370
53569
|
"INVALID_SITE_META_TITLE",
|
|
53371
|
-
`theme.json.
|
|
53372
|
-
`
|
|
53570
|
+
`theme.json.site_meta.${metaKey}.title`,
|
|
53571
|
+
`site_meta key '${metaKey}' must define a non-empty 'title'`,
|
|
53373
53572
|
"error"
|
|
53374
53573
|
));
|
|
53375
53574
|
} else if (value.title.trim().length > MENU_SLOT_TITLE_MAX_LENGTH) {
|
|
53376
53575
|
errors.push(issue2(
|
|
53377
53576
|
"INVALID_SITE_META_TITLE",
|
|
53378
|
-
`theme.json.
|
|
53379
|
-
`
|
|
53577
|
+
`theme.json.site_meta.${metaKey}.title`,
|
|
53578
|
+
`site_meta key '${metaKey}' title must be at most ${MENU_SLOT_TITLE_MAX_LENGTH} characters`,
|
|
53380
53579
|
"error"
|
|
53381
53580
|
));
|
|
53382
53581
|
}
|
|
53383
53582
|
if (value.description !== void 0 && (typeof value.description !== "string" || value.description.trim().length > MENU_SLOT_DESCRIPTION_MAX_LENGTH)) {
|
|
53384
53583
|
errors.push(issue2(
|
|
53385
53584
|
"INVALID_SITE_META_DESCRIPTION",
|
|
53386
|
-
`theme.json.
|
|
53387
|
-
`
|
|
53585
|
+
`theme.json.site_meta.${metaKey}.description`,
|
|
53586
|
+
`site_meta key '${metaKey}' description must be a string at most ${MENU_SLOT_DESCRIPTION_MAX_LENGTH} characters`,
|
|
53388
53587
|
"error"
|
|
53389
53588
|
));
|
|
53390
53589
|
}
|
|
53391
53590
|
if (value.type !== void 0 && !SITE_META_TYPES.has(value.type)) {
|
|
53392
53591
|
errors.push(issue2(
|
|
53393
53592
|
"INVALID_SITE_META_TYPE",
|
|
53394
|
-
`theme.json.
|
|
53395
|
-
`
|
|
53593
|
+
`theme.json.site_meta.${metaKey}.type`,
|
|
53594
|
+
`site_meta key '${metaKey}' type must be one of: string, number, boolean`,
|
|
53396
53595
|
"error"
|
|
53397
53596
|
));
|
|
53398
53597
|
}
|
|
@@ -53401,15 +53600,15 @@ function validateSiteMetaMap(rawValue, errors) {
|
|
|
53401
53600
|
if (value.default !== null && defaultType !== "string" && defaultType !== "number" && defaultType !== "boolean") {
|
|
53402
53601
|
errors.push(issue2(
|
|
53403
53602
|
"INVALID_SITE_META_DEFAULT",
|
|
53404
|
-
`theme.json.
|
|
53405
|
-
`
|
|
53603
|
+
`theme.json.site_meta.${metaKey}.default`,
|
|
53604
|
+
`site_meta key '${metaKey}' default must be a string, number, boolean, or null`,
|
|
53406
53605
|
"error"
|
|
53407
53606
|
));
|
|
53408
53607
|
} else if (typeof value.type === "string" && SITE_META_TYPES.has(value.type) && value.default !== null && defaultType !== value.type) {
|
|
53409
53608
|
errors.push(issue2(
|
|
53410
53609
|
"INVALID_SITE_META_DEFAULT",
|
|
53411
|
-
`theme.json.
|
|
53412
|
-
`
|
|
53610
|
+
`theme.json.site_meta.${metaKey}.default`,
|
|
53611
|
+
`site_meta key '${metaKey}' default must match its declared type`,
|
|
53413
53612
|
"error"
|
|
53414
53613
|
));
|
|
53415
53614
|
}
|
|
@@ -53454,11 +53653,16 @@ async function validateThemeFiles(fileMap, options2 = {}) {
|
|
|
53454
53653
|
manifest = manifestResult.manifest;
|
|
53455
53654
|
errors.push(...manifestResult.errors);
|
|
53456
53655
|
} catch (error) {
|
|
53656
|
+
const rawThemeJson = getText(files.get("theme.json"));
|
|
53457
53657
|
errors.push(issue2(
|
|
53458
53658
|
"INVALID_THEME_JSON",
|
|
53459
53659
|
"theme.json",
|
|
53460
53660
|
`Invalid theme.json: ${error instanceof Error ? error.message : String(error)}`,
|
|
53461
|
-
"error"
|
|
53661
|
+
"error",
|
|
53662
|
+
{
|
|
53663
|
+
...locationForJsonParseError(error, rawThemeJson),
|
|
53664
|
+
category: "json_syntax"
|
|
53665
|
+
}
|
|
53462
53666
|
));
|
|
53463
53667
|
}
|
|
53464
53668
|
}
|
|
@@ -53524,7 +53728,11 @@ function validateManifest(themeJson) {
|
|
|
53524
53728
|
"UNKNOWN_THEME_MANIFEST_FIELD",
|
|
53525
53729
|
`theme.json.${key}`,
|
|
53526
53730
|
`Unknown theme.json field '${key}'`,
|
|
53527
|
-
"error"
|
|
53731
|
+
"error",
|
|
53732
|
+
{
|
|
53733
|
+
category: "theme_manifest",
|
|
53734
|
+
hint: themeManifestFieldHint(key)
|
|
53735
|
+
}
|
|
53528
53736
|
));
|
|
53529
53737
|
}
|
|
53530
53738
|
}
|
|
@@ -53555,13 +53763,24 @@ function validateManifest(themeJson) {
|
|
|
53555
53763
|
errors.push(issue2("INVALID_SEMVER", "theme.json", "Theme version must follow semantic versioning (e.g. 1.0.0)", "error"));
|
|
53556
53764
|
}
|
|
53557
53765
|
if (typeof themeJson.runtime === "string" && !SUPPORTED_RUNTIME_SET.has(themeJson.runtime.trim())) {
|
|
53558
|
-
errors.push(issue2(
|
|
53766
|
+
errors.push(issue2(
|
|
53767
|
+
"INVALID_RUNTIME_VERSION",
|
|
53768
|
+
"theme.json",
|
|
53769
|
+
`theme.json field 'runtime' must be one of: ${SUPPORTED_RUNTIMES.join(", ")}`,
|
|
53770
|
+
"error",
|
|
53771
|
+
{
|
|
53772
|
+
category: "theme_manifest",
|
|
53773
|
+
hint: `Update theme.json:
|
|
53774
|
+
|
|
53775
|
+
"runtime": "${THEME_RUNTIME_V0_6}"`
|
|
53776
|
+
}
|
|
53777
|
+
));
|
|
53559
53778
|
}
|
|
53560
|
-
if (typeof themeJson.license === "string" && !
|
|
53779
|
+
if (typeof themeJson.license === "string" && !isAllowedLicense(themeJson.license.trim())) {
|
|
53561
53780
|
errors.push(issue2(
|
|
53562
53781
|
"INVALID_LICENSE",
|
|
53563
53782
|
"theme.json",
|
|
53564
|
-
"theme.json field 'license' must be one of: MIT, Apache-2.0, BSD-3-Clause, GPL-3.0-only, GPL-3.0-or-later",
|
|
53783
|
+
"theme.json field 'license' must be one of: MIT, Apache-2.0, BSD-3-Clause, GPL-3.0-only, GPL-3.0-or-later, or a LicenseRef-* identifier",
|
|
53565
53784
|
"error"
|
|
53566
53785
|
));
|
|
53567
53786
|
}
|
|
@@ -53625,11 +53844,15 @@ function validateManifest(themeJson) {
|
|
|
53625
53844
|
manifest.thumbnail = themeJson.thumbnail;
|
|
53626
53845
|
}
|
|
53627
53846
|
}
|
|
53847
|
+
const links = validateThemeLinks(themeJson.links, errors);
|
|
53848
|
+
if (links) {
|
|
53849
|
+
manifest.links = links;
|
|
53850
|
+
}
|
|
53628
53851
|
const features = validateFeatureFlags(themeJson.features, errors);
|
|
53629
53852
|
if (features) {
|
|
53630
53853
|
manifest.features = features;
|
|
53631
53854
|
}
|
|
53632
|
-
const
|
|
53855
|
+
const menu_slots = validateHelperMetadataMap(themeJson.menu_slots, "menu_slots", {
|
|
53633
53856
|
itemLabel: "Menu slot",
|
|
53634
53857
|
propertyLabel: "menu slot property",
|
|
53635
53858
|
collectionLabel: "slots",
|
|
@@ -53640,10 +53863,10 @@ function validateManifest(themeJson) {
|
|
|
53640
53863
|
invalidTitleCode: "INVALID_MENU_SLOT_TITLE",
|
|
53641
53864
|
invalidDescriptionCode: "INVALID_MENU_SLOT_DESCRIPTION"
|
|
53642
53865
|
}, errors);
|
|
53643
|
-
if (
|
|
53644
|
-
manifest.
|
|
53866
|
+
if (menu_slots) {
|
|
53867
|
+
manifest.menu_slots = menu_slots;
|
|
53645
53868
|
}
|
|
53646
|
-
const
|
|
53869
|
+
const widget_areas = validateHelperMetadataMap(themeJson.widget_areas, "widget_areas", {
|
|
53647
53870
|
itemLabel: "Widget area",
|
|
53648
53871
|
propertyLabel: "widget area property",
|
|
53649
53872
|
collectionLabel: "areas",
|
|
@@ -53654,14 +53877,14 @@ function validateManifest(themeJson) {
|
|
|
53654
53877
|
invalidTitleCode: "INVALID_WIDGET_AREA_TITLE",
|
|
53655
53878
|
invalidDescriptionCode: "INVALID_WIDGET_AREA_DESCRIPTION"
|
|
53656
53879
|
}, errors);
|
|
53657
|
-
if (
|
|
53658
|
-
manifest.
|
|
53880
|
+
if (widget_areas) {
|
|
53881
|
+
manifest.widget_areas = widget_areas;
|
|
53659
53882
|
}
|
|
53660
|
-
const
|
|
53661
|
-
if (
|
|
53662
|
-
manifest.
|
|
53883
|
+
const site_meta = validateSiteMetaMap(themeJson.site_meta, errors);
|
|
53884
|
+
if (site_meta) {
|
|
53885
|
+
manifest.site_meta = site_meta;
|
|
53663
53886
|
}
|
|
53664
|
-
const
|
|
53887
|
+
const collection_slots = validateHelperMetadataMap(themeJson.collection_slots, "collection_slots", {
|
|
53665
53888
|
itemLabel: "Collection slot",
|
|
53666
53889
|
propertyLabel: "collection slot property",
|
|
53667
53890
|
collectionLabel: "slots",
|
|
@@ -53672,8 +53895,8 @@ function validateManifest(themeJson) {
|
|
|
53672
53895
|
invalidTitleCode: "INVALID_COLLECTION_SLOT_TITLE",
|
|
53673
53896
|
invalidDescriptionCode: "INVALID_COLLECTION_SLOT_DESCRIPTION"
|
|
53674
53897
|
}, errors);
|
|
53675
|
-
if (
|
|
53676
|
-
manifest.
|
|
53898
|
+
if (collection_slots) {
|
|
53899
|
+
manifest.collection_slots = collection_slots;
|
|
53677
53900
|
}
|
|
53678
53901
|
return { errors, manifest: errors.length > 0 ? void 0 : manifest };
|
|
53679
53902
|
}
|
|
@@ -53685,8 +53908,20 @@ function validateTemplateSyntax(templatePath, content, context) {
|
|
|
53685
53908
|
if (contentSlotMatches.length !== 1) {
|
|
53686
53909
|
errors.push(issue2("INVALID_LAYOUT_SLOT", "layout.html", "layout.html must contain exactly one {{slot:content}}", "error"));
|
|
53687
53910
|
}
|
|
53688
|
-
|
|
53689
|
-
|
|
53911
|
+
const scriptMatch = /<script\b/i.exec(content);
|
|
53912
|
+
if (scriptMatch) {
|
|
53913
|
+
errors.push(issue2(
|
|
53914
|
+
"LAYOUT_SCRIPT_NOT_ALLOWED",
|
|
53915
|
+
"layout.html",
|
|
53916
|
+
"layout.html must not contain <script> tags",
|
|
53917
|
+
"error",
|
|
53918
|
+
{
|
|
53919
|
+
...locationForIndex(content, scriptMatch.index),
|
|
53920
|
+
category: "theme_validation",
|
|
53921
|
+
hint: "Move shared scripts into a partial such as {{partial:content-enhancements}}, then include that partial from layout.html.",
|
|
53922
|
+
snippet: snippetForIndex(content, scriptMatch.index)
|
|
53923
|
+
}
|
|
53924
|
+
));
|
|
53690
53925
|
}
|
|
53691
53926
|
}
|
|
53692
53927
|
let match2;
|
|
@@ -53737,7 +53972,9 @@ function validateRuntimeV05TemplateSyntax(templatePath, content, errors) {
|
|
|
53737
53972
|
index = end + 2;
|
|
53738
53973
|
if (token.startsWith("partial:")) {
|
|
53739
53974
|
try {
|
|
53740
|
-
parsePartialReferenceToken(token
|
|
53975
|
+
parsePartialReferenceToken(token, {
|
|
53976
|
+
allowedSingleSegmentPaths: getPartialArgScope(stack)
|
|
53977
|
+
});
|
|
53741
53978
|
} catch (error) {
|
|
53742
53979
|
errors.push(issue2(
|
|
53743
53980
|
"INVALID_PARTIAL_REFERENCE",
|
|
@@ -53762,7 +53999,7 @@ function validateRuntimeV05TemplateSyntax(templatePath, content, errors) {
|
|
|
53762
53999
|
}
|
|
53763
54000
|
if (token === "#else") {
|
|
53764
54001
|
const current = stack[stack.length - 1];
|
|
53765
|
-
if (!current || current.tag !== "if" && current.tag
|
|
54002
|
+
if (!current || current.tag !== "if" && !COMPARISON_BLOCK_TAGS.has(current.tag)) {
|
|
53766
54003
|
errors.push(issue2("UNEXPECTED_TEMPLATE_ELSE", templatePath, `Unexpected {{#else}} in ${templatePath}`, "error"));
|
|
53767
54004
|
return;
|
|
53768
54005
|
}
|
|
@@ -53773,9 +54010,11 @@ function validateRuntimeV05TemplateSyntax(templatePath, content, errors) {
|
|
|
53773
54010
|
current.hasElse = true;
|
|
53774
54011
|
continue;
|
|
53775
54012
|
}
|
|
53776
|
-
|
|
54013
|
+
const comparisonElseIfTag = getComparisonElseIfTag(token);
|
|
54014
|
+
if (comparisonElseIfTag) {
|
|
53777
54015
|
const current = stack[stack.length - 1];
|
|
53778
|
-
|
|
54016
|
+
const expectedBlockTag = comparisonElseIfTag.replace(/^else_/, "");
|
|
54017
|
+
if (!current || current.tag !== expectedBlockTag) {
|
|
53779
54018
|
errors.push(issue2("UNEXPECTED_TEMPLATE_ELSE_IF", templatePath, `Unexpected {{${token}}} in ${templatePath}`, "error"));
|
|
53780
54019
|
return;
|
|
53781
54020
|
}
|
|
@@ -53783,13 +54022,13 @@ function validateRuntimeV05TemplateSyntax(templatePath, content, errors) {
|
|
|
53783
54022
|
errors.push(issue2("INVALID_TEMPLATE_BRANCH_ORDER", templatePath, `{{${token}}} cannot appear after {{#else}} in ${templatePath}`, "error"));
|
|
53784
54023
|
return;
|
|
53785
54024
|
}
|
|
53786
|
-
const expression = token.slice(
|
|
53787
|
-
const parsed =
|
|
54025
|
+
const expression = token.slice(`#${comparisonElseIfTag} `.length).trim();
|
|
54026
|
+
const parsed = parseComparisonExpression(expression, comparisonElseIfTag);
|
|
53788
54027
|
if (!parsed) {
|
|
53789
54028
|
errors.push(issue2("UNSUPPORTED_TEMPLATE_TAG", templatePath, `Unsupported template tag '{{${token}}}' in ${templatePath}`, "error"));
|
|
53790
54029
|
return;
|
|
53791
54030
|
}
|
|
53792
|
-
|
|
54031
|
+
validateComparisonPathUsage(parsed, templatePath, errors, stack, { isPartialFile });
|
|
53793
54032
|
continue;
|
|
53794
54033
|
}
|
|
53795
54034
|
if (token.startsWith("#else_if ")) {
|
|
@@ -53812,7 +54051,7 @@ function validateRuntimeV05TemplateSyntax(templatePath, content, errors) {
|
|
|
53812
54051
|
}
|
|
53813
54052
|
if (token.startsWith("/")) {
|
|
53814
54053
|
const closingTag = token.slice(1).trim();
|
|
53815
|
-
if (!["if", "
|
|
54054
|
+
if (!["if", "for", ...COMPARISON_BLOCK_TAGS].includes(closingTag)) {
|
|
53816
54055
|
errors.push(issue2("UNSUPPORTED_TEMPLATE_TAG", templatePath, `Unsupported template closing tag '{{${token}}}' in ${templatePath}`, "error"));
|
|
53817
54056
|
return;
|
|
53818
54057
|
}
|
|
@@ -53833,22 +54072,23 @@ function validateRuntimeV05TemplateSyntax(templatePath, content, errors) {
|
|
|
53833
54072
|
stack.push({ tag: "if", hasElse: false });
|
|
53834
54073
|
continue;
|
|
53835
54074
|
}
|
|
53836
|
-
|
|
53837
|
-
|
|
53838
|
-
const
|
|
54075
|
+
const comparisonBlockTag = getComparisonBlockTag(token);
|
|
54076
|
+
if (comparisonBlockTag) {
|
|
54077
|
+
const expression = token.slice(`#${comparisonBlockTag} `.length).trim();
|
|
54078
|
+
const parsed = parseComparisonExpression(expression, comparisonBlockTag);
|
|
53839
54079
|
if (!parsed) {
|
|
53840
54080
|
errors.push(issue2("UNSUPPORTED_TEMPLATE_TAG", templatePath, `Unsupported template tag '{{${token}}}' in ${templatePath}`, "error"));
|
|
53841
54081
|
return;
|
|
53842
54082
|
}
|
|
53843
|
-
|
|
53844
|
-
stack.push({ tag:
|
|
54083
|
+
validateComparisonPathUsage(parsed, templatePath, errors, stack, { isPartialFile });
|
|
54084
|
+
stack.push({ tag: comparisonBlockTag, hasElse: false });
|
|
53845
54085
|
continue;
|
|
53846
54086
|
}
|
|
53847
54087
|
const forMatch = FOR_TAG_REGEX.exec(token);
|
|
53848
54088
|
if (forMatch) {
|
|
53849
54089
|
const path4 = forMatch[2];
|
|
53850
54090
|
validateReservedPathUsage(path4, templatePath, errors, stack, { isPartialFile });
|
|
53851
|
-
stack.push({ tag: "for", hasElse: false });
|
|
54091
|
+
stack.push({ tag: "for", itemName: forMatch[1], hasElse: false });
|
|
53852
54092
|
continue;
|
|
53853
54093
|
}
|
|
53854
54094
|
errors.push(issue2("UNSUPPORTED_TEMPLATE_TAG", templatePath, `Unsupported template tag '{{${token}}}' in ${templatePath}`, "error"));
|
|
@@ -53881,16 +54121,124 @@ function validateReservedPathUsage(path4, templatePath, errors, stack, options2
|
|
|
53881
54121
|
));
|
|
53882
54122
|
}
|
|
53883
54123
|
}
|
|
53884
|
-
function
|
|
53885
|
-
const
|
|
53886
|
-
|
|
54124
|
+
function validateComparisonPathUsage(parsed, templatePath, errors, stack, options2) {
|
|
54125
|
+
for (const operand of [parsed.left, ...parsed.operands]) {
|
|
54126
|
+
if (operand.kind === "path") {
|
|
54127
|
+
validateReservedPathUsage(operand.path, templatePath, errors, stack, options2);
|
|
54128
|
+
}
|
|
54129
|
+
}
|
|
54130
|
+
}
|
|
54131
|
+
function getComparisonBlockTag(token) {
|
|
54132
|
+
for (const tagName of COMPARISON_BLOCK_TAGS) {
|
|
54133
|
+
if (token.startsWith(`#${tagName} `)) {
|
|
54134
|
+
return tagName;
|
|
54135
|
+
}
|
|
54136
|
+
}
|
|
54137
|
+
return "";
|
|
54138
|
+
}
|
|
54139
|
+
function getComparisonElseIfTag(token) {
|
|
54140
|
+
for (const tagName of COMPARISON_ELSE_IF_TAGS) {
|
|
54141
|
+
if (token.startsWith(`#${tagName} `)) {
|
|
54142
|
+
return tagName;
|
|
54143
|
+
}
|
|
54144
|
+
}
|
|
54145
|
+
return "";
|
|
54146
|
+
}
|
|
54147
|
+
function parseComparisonExpression(expression, tagName) {
|
|
54148
|
+
const operator = COMPARISON_TAG_OPERATORS[tagName];
|
|
54149
|
+
let tokens;
|
|
54150
|
+
try {
|
|
54151
|
+
tokens = tokenizeExpression(expression);
|
|
54152
|
+
} catch {
|
|
54153
|
+
return null;
|
|
54154
|
+
}
|
|
54155
|
+
if (!operator || operator === "in" && tokens.length < 2 || operator !== "in" && tokens.length !== 2) {
|
|
54156
|
+
return null;
|
|
54157
|
+
}
|
|
54158
|
+
const left = parsePathOperand(tokens[0]);
|
|
54159
|
+
if (!left) {
|
|
53887
54160
|
return null;
|
|
53888
54161
|
}
|
|
54162
|
+
const operands = [];
|
|
54163
|
+
for (const token of tokens.slice(1)) {
|
|
54164
|
+
const operand = parseComparisonOperand(token);
|
|
54165
|
+
if (!operand) {
|
|
54166
|
+
return null;
|
|
54167
|
+
}
|
|
54168
|
+
operands.push(operand);
|
|
54169
|
+
}
|
|
53889
54170
|
return {
|
|
53890
|
-
|
|
53891
|
-
|
|
54171
|
+
operator,
|
|
54172
|
+
left,
|
|
54173
|
+
operands
|
|
53892
54174
|
};
|
|
53893
54175
|
}
|
|
54176
|
+
function tokenizeExpression(expression) {
|
|
54177
|
+
const tokens = [];
|
|
54178
|
+
let index = 0;
|
|
54179
|
+
while (index < expression.length) {
|
|
54180
|
+
while (/\s/.test(expression[index] || "")) {
|
|
54181
|
+
index += 1;
|
|
54182
|
+
}
|
|
54183
|
+
if (index >= expression.length) {
|
|
54184
|
+
break;
|
|
54185
|
+
}
|
|
54186
|
+
if (expression[index] === '"') {
|
|
54187
|
+
const start2 = index;
|
|
54188
|
+
index += 1;
|
|
54189
|
+
let escaped = false;
|
|
54190
|
+
while (index < expression.length) {
|
|
54191
|
+
const char = expression[index];
|
|
54192
|
+
if (escaped) {
|
|
54193
|
+
escaped = false;
|
|
54194
|
+
} else if (char === "\\") {
|
|
54195
|
+
escaped = true;
|
|
54196
|
+
} else if (char === '"') {
|
|
54197
|
+
index += 1;
|
|
54198
|
+
tokens.push(expression.slice(start2, index));
|
|
54199
|
+
break;
|
|
54200
|
+
}
|
|
54201
|
+
index += 1;
|
|
54202
|
+
}
|
|
54203
|
+
if (tokens[tokens.length - 1] !== expression.slice(start2, index)) {
|
|
54204
|
+
throw new Error(`Unclosed string literal in expression: ${expression}`);
|
|
54205
|
+
}
|
|
54206
|
+
continue;
|
|
54207
|
+
}
|
|
54208
|
+
const start = index;
|
|
54209
|
+
while (index < expression.length && !/\s/.test(expression[index])) {
|
|
54210
|
+
index += 1;
|
|
54211
|
+
}
|
|
54212
|
+
tokens.push(expression.slice(start, index));
|
|
54213
|
+
}
|
|
54214
|
+
return tokens;
|
|
54215
|
+
}
|
|
54216
|
+
function parsePathOperand(token) {
|
|
54217
|
+
return TEMPLATE_PATH_REGEX.test(token) ? { kind: "path", path: token } : null;
|
|
54218
|
+
}
|
|
54219
|
+
function parseComparisonOperand(token) {
|
|
54220
|
+
if (token.startsWith('"')) {
|
|
54221
|
+
try {
|
|
54222
|
+
const value = JSON.parse(token);
|
|
54223
|
+
return typeof value === "string" ? { kind: "literal", value } : null;
|
|
54224
|
+
} catch {
|
|
54225
|
+
return null;
|
|
54226
|
+
}
|
|
54227
|
+
}
|
|
54228
|
+
if (token === "true") {
|
|
54229
|
+
return { kind: "literal", value: true };
|
|
54230
|
+
}
|
|
54231
|
+
if (token === "false") {
|
|
54232
|
+
return { kind: "literal", value: false };
|
|
54233
|
+
}
|
|
54234
|
+
if (token === "null") {
|
|
54235
|
+
return { kind: "literal", value: null };
|
|
54236
|
+
}
|
|
54237
|
+
if (NUMBER_LITERAL_REGEX.test(token)) {
|
|
54238
|
+
return { kind: "literal", value: Number(token) };
|
|
54239
|
+
}
|
|
54240
|
+
return parsePathOperand(token);
|
|
54241
|
+
}
|
|
53894
54242
|
function validatePartialReferences(templateContents, partialContents, context) {
|
|
53895
54243
|
const { errors } = context;
|
|
53896
54244
|
for (const [templatePath, content] of templateContents.entries()) {
|
|
@@ -53956,7 +54304,7 @@ function getReferencedPartialNames(content) {
|
|
|
53956
54304
|
let match2;
|
|
53957
54305
|
while ((match2 = PARTIAL_TAG_REGEX.exec(content)) !== null) {
|
|
53958
54306
|
try {
|
|
53959
|
-
const { name } = parsePartialReferenceToken(match2[1]);
|
|
54307
|
+
const { name } = parsePartialReferenceToken(match2[1], { validateArgs: false });
|
|
53960
54308
|
matches.add(name);
|
|
53961
54309
|
} catch {
|
|
53962
54310
|
}
|
|
@@ -53964,7 +54312,7 @@ function getReferencedPartialNames(content) {
|
|
|
53964
54312
|
PARTIAL_TAG_REGEX.lastIndex = 0;
|
|
53965
54313
|
return matches;
|
|
53966
54314
|
}
|
|
53967
|
-
function parsePartialReferenceToken(token) {
|
|
54315
|
+
function parsePartialReferenceToken(token, options2 = {}) {
|
|
53968
54316
|
const source = String(token || "").trim();
|
|
53969
54317
|
if (!source.startsWith("partial:")) {
|
|
53970
54318
|
throw new Error("Partial token must start with partial:");
|
|
@@ -53979,10 +54327,12 @@ function parsePartialReferenceToken(token) {
|
|
|
53979
54327
|
throw new Error(`Invalid partial name '${name}'`);
|
|
53980
54328
|
}
|
|
53981
54329
|
const argsSource = expression.slice(name.length).trim();
|
|
53982
|
-
|
|
54330
|
+
if (options2.validateArgs !== false) {
|
|
54331
|
+
parsePartialArgs(argsSource, options2);
|
|
54332
|
+
}
|
|
53983
54333
|
return { name };
|
|
53984
54334
|
}
|
|
53985
|
-
function parsePartialArgs(source) {
|
|
54335
|
+
function parsePartialArgs(source, options2 = {}) {
|
|
53986
54336
|
if (!source) {
|
|
53987
54337
|
return {};
|
|
53988
54338
|
}
|
|
@@ -54034,7 +54384,8 @@ function parsePartialArgs(source) {
|
|
|
54034
54384
|
if (cursor >= source.length || source[cursor] !== '"') {
|
|
54035
54385
|
throw new Error(`Unclosed string literal for partial argument '${key}'`);
|
|
54036
54386
|
}
|
|
54037
|
-
|
|
54387
|
+
JSON.parse(source.slice(index, cursor + 1));
|
|
54388
|
+
args[key] = true;
|
|
54038
54389
|
index = cursor + 1;
|
|
54039
54390
|
continue;
|
|
54040
54391
|
}
|
|
@@ -54044,10 +54395,25 @@ function parsePartialArgs(source) {
|
|
|
54044
54395
|
continue;
|
|
54045
54396
|
}
|
|
54046
54397
|
if (source.startsWith("false", index) && isValueBoundary(source, index + 5)) {
|
|
54047
|
-
args[key] =
|
|
54398
|
+
args[key] = true;
|
|
54048
54399
|
index += 5;
|
|
54049
54400
|
continue;
|
|
54050
54401
|
}
|
|
54402
|
+
if (source.startsWith("null", index) && isValueBoundary(source, index + 4)) {
|
|
54403
|
+
args[key] = true;
|
|
54404
|
+
index += 4;
|
|
54405
|
+
continue;
|
|
54406
|
+
}
|
|
54407
|
+
const valueMatch = /^\S+/.exec(source.slice(index));
|
|
54408
|
+
if (!valueMatch) {
|
|
54409
|
+
throw new Error(`Missing partial argument value for '${key}'`);
|
|
54410
|
+
}
|
|
54411
|
+
const valueToken = valueMatch[0];
|
|
54412
|
+
if (NUMBER_LITERAL_REGEX.test(valueToken) || TEMPLATE_PATH_REGEX.test(valueToken) && isAllowedPartialArgPath(valueToken, options2)) {
|
|
54413
|
+
args[key] = true;
|
|
54414
|
+
index += valueToken.length;
|
|
54415
|
+
continue;
|
|
54416
|
+
}
|
|
54051
54417
|
throw new Error(`Unsupported partial argument value for '${key}'`);
|
|
54052
54418
|
}
|
|
54053
54419
|
return args;
|
|
@@ -54055,6 +54421,23 @@ function parsePartialArgs(source) {
|
|
|
54055
54421
|
function isValueBoundary(source, index) {
|
|
54056
54422
|
return index >= source.length || /\s/.test(source[index]);
|
|
54057
54423
|
}
|
|
54424
|
+
function isAllowedPartialArgPath(valueToken, options2) {
|
|
54425
|
+
if (valueToken.includes(".")) {
|
|
54426
|
+
return true;
|
|
54427
|
+
}
|
|
54428
|
+
const allowedSingleSegmentPaths = options2?.allowedSingleSegmentPaths;
|
|
54429
|
+
return allowedSingleSegmentPaths instanceof Set && allowedSingleSegmentPaths.has(valueToken);
|
|
54430
|
+
}
|
|
54431
|
+
function getPartialArgScope(stack) {
|
|
54432
|
+
const scope = new Set(PARTIAL_ARG_ROOT_PATHS);
|
|
54433
|
+
for (const entry of stack) {
|
|
54434
|
+
if (entry.tag === "for" && typeof entry.itemName === "string") {
|
|
54435
|
+
scope.add(entry.itemName);
|
|
54436
|
+
scope.add("loop");
|
|
54437
|
+
}
|
|
54438
|
+
}
|
|
54439
|
+
return scope;
|
|
54440
|
+
}
|
|
54058
54441
|
function validatePathSafety(pathEntries, errors) {
|
|
54059
54442
|
for (const entry of pathEntries) {
|
|
54060
54443
|
const entryPath = normalizePath(String(entry.path || ""));
|
|
@@ -54102,13 +54485,71 @@ function normalizeAbsolutePath(value) {
|
|
|
54102
54485
|
function isPathInsideRoot(candidate, root) {
|
|
54103
54486
|
return candidate === root || candidate.startsWith(`${root}/`);
|
|
54104
54487
|
}
|
|
54105
|
-
function issue2(code2, filePath, message, severity) {
|
|
54106
|
-
|
|
54488
|
+
function issue2(code2, filePath, message, severity, details = {}) {
|
|
54489
|
+
const nextIssue = {
|
|
54107
54490
|
code: code2,
|
|
54108
54491
|
path: filePath,
|
|
54109
54492
|
message,
|
|
54110
54493
|
severity
|
|
54111
54494
|
};
|
|
54495
|
+
if (Number.isInteger(details.line) && details.line > 0) {
|
|
54496
|
+
nextIssue.line = details.line;
|
|
54497
|
+
}
|
|
54498
|
+
if (Number.isInteger(details.column) && details.column > 0) {
|
|
54499
|
+
nextIssue.column = details.column;
|
|
54500
|
+
}
|
|
54501
|
+
if (typeof details.hint === "string" && details.hint.trim()) {
|
|
54502
|
+
nextIssue.hint = details.hint;
|
|
54503
|
+
}
|
|
54504
|
+
if (typeof details.category === "string" && details.category.trim()) {
|
|
54505
|
+
nextIssue.category = details.category;
|
|
54506
|
+
}
|
|
54507
|
+
if (details.snippet && typeof details.snippet === "object" && typeof details.snippet.line === "string" && typeof details.snippet.pointer === "string") {
|
|
54508
|
+
nextIssue.snippet = {
|
|
54509
|
+
line: details.snippet.line,
|
|
54510
|
+
pointer: details.snippet.pointer
|
|
54511
|
+
};
|
|
54512
|
+
}
|
|
54513
|
+
return nextIssue;
|
|
54514
|
+
}
|
|
54515
|
+
function locationForJsonParseError(error, source) {
|
|
54516
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
54517
|
+
const lineColumnMatch = /\bline\s+(\d+)\s+column\s+(\d+)/i.exec(message);
|
|
54518
|
+
if (lineColumnMatch) {
|
|
54519
|
+
return {
|
|
54520
|
+
line: Number(lineColumnMatch[1]),
|
|
54521
|
+
column: Number(lineColumnMatch[2])
|
|
54522
|
+
};
|
|
54523
|
+
}
|
|
54524
|
+
const positionMatch = /\bposition\s+(\d+)/i.exec(message);
|
|
54525
|
+
if (positionMatch) {
|
|
54526
|
+
return locationForIndex(source, Number(positionMatch[1]));
|
|
54527
|
+
}
|
|
54528
|
+
if (/Unexpected end of JSON input/i.test(message)) {
|
|
54529
|
+
return locationForIndex(source, source.length);
|
|
54530
|
+
}
|
|
54531
|
+
return {};
|
|
54532
|
+
}
|
|
54533
|
+
function locationForIndex(source, index) {
|
|
54534
|
+
const boundedIndex = Math.max(0, Math.min(Number.isInteger(index) ? index : 0, source.length));
|
|
54535
|
+
let line = 1;
|
|
54536
|
+
let column = 1;
|
|
54537
|
+
for (let cursor = 0; cursor < boundedIndex; cursor += 1) {
|
|
54538
|
+
if (source[cursor] === "\n") {
|
|
54539
|
+
line += 1;
|
|
54540
|
+
column = 1;
|
|
54541
|
+
} else {
|
|
54542
|
+
column += 1;
|
|
54543
|
+
}
|
|
54544
|
+
}
|
|
54545
|
+
return { line, column };
|
|
54546
|
+
}
|
|
54547
|
+
function snippetForIndex(source, index) {
|
|
54548
|
+
const location = locationForIndex(source, index);
|
|
54549
|
+
const lines = String(source).split(/\r?\n/);
|
|
54550
|
+
const line = lines[location.line - 1] || "";
|
|
54551
|
+
const pointer = `${" ".repeat(Math.max(location.column - 1, 0))}^`;
|
|
54552
|
+
return { line, pointer };
|
|
54112
54553
|
}
|
|
54113
54554
|
|
|
54114
54555
|
// node_modules/@zeropress/build-core/src/assets/asset-processor.js
|
|
@@ -59574,6 +60015,10 @@ function sanitizeHtml(html) {
|
|
|
59574
60015
|
"li",
|
|
59575
60016
|
"blockquote",
|
|
59576
60017
|
"aside",
|
|
60018
|
+
"figure",
|
|
60019
|
+
"figcaption",
|
|
60020
|
+
"picture",
|
|
60021
|
+
"source",
|
|
59577
60022
|
"table",
|
|
59578
60023
|
"thead",
|
|
59579
60024
|
"tbody",
|
|
@@ -59589,9 +60034,10 @@ function sanitizeHtml(html) {
|
|
|
59589
60034
|
const allowedAttributes = {
|
|
59590
60035
|
a: /* @__PURE__ */ new Set(["href", "title", "class", "id"]),
|
|
59591
60036
|
aside: /* @__PURE__ */ new Set(["role", "class", "id"]),
|
|
59592
|
-
img: /* @__PURE__ */ new Set(["src", "alt", "title", "class", "id", "width", "height"]),
|
|
60037
|
+
img: /* @__PURE__ */ new Set(["src", "srcset", "sizes", "alt", "title", "class", "id", "width", "height", "loading", "decoding"]),
|
|
59593
60038
|
iframe: /* @__PURE__ */ new Set(["src", "width", "height", "frameborder", "allowfullscreen", "class"]),
|
|
59594
60039
|
input: /* @__PURE__ */ new Set(["type", "checked", "disabled", "class", "id"]),
|
|
60040
|
+
source: /* @__PURE__ */ new Set(["src", "srcset", "sizes", "type", "media", "width", "height", "class", "id"]),
|
|
59595
60041
|
"*": /* @__PURE__ */ new Set(["class", "id"])
|
|
59596
60042
|
};
|
|
59597
60043
|
const safeUriPattern = /^(?:(?:https?|mailto|tel):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i;
|
|
@@ -59619,13 +60065,16 @@ function sanitizeHtml(html) {
|
|
|
59619
60065
|
if ((attributeName === "href" || attributeName === "src") && !safeUriPattern.test(attributeValue)) {
|
|
59620
60066
|
continue;
|
|
59621
60067
|
}
|
|
60068
|
+
if (attributeName === "srcset" && !isSafeSrcset(attributeValue, safeUriPattern)) {
|
|
60069
|
+
continue;
|
|
60070
|
+
}
|
|
59622
60071
|
if (normalizedTag === "input" && attributeName === "type" && attributeValue !== "checkbox") {
|
|
59623
60072
|
continue;
|
|
59624
60073
|
}
|
|
59625
60074
|
filteredAttributes.push(`${attributeName}="${attributeValue}"`);
|
|
59626
60075
|
}
|
|
59627
60076
|
}
|
|
59628
|
-
const isSelfClosing = match2.endsWith("/>") || normalizedTag === "br" || normalizedTag === "hr" || normalizedTag === "img" || normalizedTag === "input";
|
|
60077
|
+
const isSelfClosing = match2.endsWith("/>") || normalizedTag === "br" || normalizedTag === "hr" || normalizedTag === "img" || normalizedTag === "input" || normalizedTag === "source";
|
|
59629
60078
|
const attributeSuffix = filteredAttributes.length > 0 ? ` ${filteredAttributes.join(" ")}` : "";
|
|
59630
60079
|
return isSelfClosing ? `<${normalizedTag}${attributeSuffix} />` : `<${normalizedTag}${attributeSuffix}>`;
|
|
59631
60080
|
});
|
|
@@ -59636,6 +60085,13 @@ function sanitizeHtml(html) {
|
|
|
59636
60085
|
return part.replace(/&(?!(?:[a-zA-Z]+|#\d+|#x[0-9a-fA-F]+);)/g, "&");
|
|
59637
60086
|
}).join("");
|
|
59638
60087
|
}
|
|
60088
|
+
function isSafeSrcset(value, safeUriPattern) {
|
|
60089
|
+
const candidates = String(value).split(",").map((candidate) => candidate.trim()).filter(Boolean);
|
|
60090
|
+
return candidates.length > 0 && candidates.every((candidate) => {
|
|
60091
|
+
const [url] = candidate.split(/\s+/);
|
|
60092
|
+
return Boolean(url) && safeUriPattern.test(url);
|
|
60093
|
+
});
|
|
60094
|
+
}
|
|
59639
60095
|
function slugify(value) {
|
|
59640
60096
|
return String(value || "").toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/[\s_-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
59641
60097
|
}
|
|
@@ -59728,6 +60184,9 @@ var VariableResolver = class _VariableResolver {
|
|
|
59728
60184
|
}
|
|
59729
60185
|
}
|
|
59730
60186
|
}
|
|
60187
|
+
if (variablePath === "data" || variablePath.startsWith("data.") || variablePath.includes(".data.")) {
|
|
60188
|
+
return false;
|
|
60189
|
+
}
|
|
59731
60190
|
const lastSegment = variablePath.split(".").pop();
|
|
59732
60191
|
if (lastSegment === "html" || lastSegment?.endsWith("_html")) {
|
|
59733
60192
|
return true;
|
|
@@ -59745,7 +60204,10 @@ var VariableResolver = class _VariableResolver {
|
|
|
59745
60204
|
// node_modules/@zeropress/build-core/src/render/partial-resolver.js
|
|
59746
60205
|
var PARTIAL_NAME_REGEX2 = /^[a-zA-Z_][a-zA-Z0-9_-]*(?:\/[a-zA-Z_][a-zA-Z0-9_-]*)*$/;
|
|
59747
60206
|
var IDENTIFIER_REGEX = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
|
|
59748
|
-
|
|
60207
|
+
var PATH_SEGMENT_SOURCE = "[a-zA-Z_][a-zA-Z0-9_]*(?:-[a-zA-Z0-9_]+)*";
|
|
60208
|
+
var PATH_REGEX = new RegExp(`^${PATH_SEGMENT_SOURCE}(?:\\.${PATH_SEGMENT_SOURCE})*$`);
|
|
60209
|
+
var NUMBER_LITERAL_REGEX2 = /^-?(?:0|[1-9]\d*)(?:\.\d+)?$/;
|
|
60210
|
+
function parsePartialToken(token, options2 = {}) {
|
|
59749
60211
|
const source = String(token || "").trim();
|
|
59750
60212
|
if (!source.startsWith("partial:")) {
|
|
59751
60213
|
throw new Error(`Invalid partial token: ${source}`);
|
|
@@ -59760,10 +60222,10 @@ function parsePartialToken(token) {
|
|
|
59760
60222
|
throw new Error(`Invalid partial name: ${name}`);
|
|
59761
60223
|
}
|
|
59762
60224
|
const argsSource = expression.slice(name.length).trim();
|
|
59763
|
-
const args = parsePartialArgs2(argsSource);
|
|
60225
|
+
const args = parsePartialArgs2(argsSource, options2);
|
|
59764
60226
|
return { name, args };
|
|
59765
60227
|
}
|
|
59766
|
-
function parsePartialArgs2(source) {
|
|
60228
|
+
function parsePartialArgs2(source, options2 = {}) {
|
|
59767
60229
|
if (!source) {
|
|
59768
60230
|
return {};
|
|
59769
60231
|
}
|
|
@@ -59815,20 +60277,40 @@ function parsePartialArgs2(source) {
|
|
|
59815
60277
|
if (cursor >= source.length || source[cursor] !== '"') {
|
|
59816
60278
|
throw new Error(`Unclosed string literal for partial argument "${key}"`);
|
|
59817
60279
|
}
|
|
59818
|
-
args[key] = JSON.parse(source.slice(index, cursor + 1));
|
|
60280
|
+
args[key] = { kind: "literal", value: JSON.parse(source.slice(index, cursor + 1)) };
|
|
59819
60281
|
index = cursor + 1;
|
|
59820
60282
|
continue;
|
|
59821
60283
|
}
|
|
59822
60284
|
if (source.startsWith("true", index) && isValueBoundary2(source, index + 4)) {
|
|
59823
|
-
args[key] = true;
|
|
60285
|
+
args[key] = { kind: "literal", value: true };
|
|
59824
60286
|
index += 4;
|
|
59825
60287
|
continue;
|
|
59826
60288
|
}
|
|
59827
60289
|
if (source.startsWith("false", index) && isValueBoundary2(source, index + 5)) {
|
|
59828
|
-
args[key] = false;
|
|
60290
|
+
args[key] = { kind: "literal", value: false };
|
|
59829
60291
|
index += 5;
|
|
59830
60292
|
continue;
|
|
59831
60293
|
}
|
|
60294
|
+
if (source.startsWith("null", index) && isValueBoundary2(source, index + 4)) {
|
|
60295
|
+
args[key] = { kind: "literal", value: null };
|
|
60296
|
+
index += 4;
|
|
60297
|
+
continue;
|
|
60298
|
+
}
|
|
60299
|
+
const valueMatch = /^\S+/.exec(source.slice(index));
|
|
60300
|
+
if (!valueMatch) {
|
|
60301
|
+
throw new Error(`Missing partial argument value for "${key}"`);
|
|
60302
|
+
}
|
|
60303
|
+
const valueToken = valueMatch[0];
|
|
60304
|
+
if (NUMBER_LITERAL_REGEX2.test(valueToken)) {
|
|
60305
|
+
args[key] = { kind: "literal", value: Number(valueToken) };
|
|
60306
|
+
index += valueToken.length;
|
|
60307
|
+
continue;
|
|
60308
|
+
}
|
|
60309
|
+
if (PATH_REGEX.test(valueToken) && isAllowedPathArgument(valueToken, options2)) {
|
|
60310
|
+
args[key] = { kind: "path", path: valueToken };
|
|
60311
|
+
index += valueToken.length;
|
|
60312
|
+
continue;
|
|
60313
|
+
}
|
|
59832
60314
|
throw new Error(`Unsupported partial argument value for "${key}"`);
|
|
59833
60315
|
}
|
|
59834
60316
|
return args;
|
|
@@ -59836,12 +60318,146 @@ function parsePartialArgs2(source) {
|
|
|
59836
60318
|
function isValueBoundary2(source, index) {
|
|
59837
60319
|
return index >= source.length || /\s/.test(source[index]);
|
|
59838
60320
|
}
|
|
60321
|
+
function isAllowedPathArgument(valueToken, options2) {
|
|
60322
|
+
if (valueToken.includes(".")) {
|
|
60323
|
+
return true;
|
|
60324
|
+
}
|
|
60325
|
+
const allowedSingleSegmentPaths = options2?.allowedSingleSegmentPaths;
|
|
60326
|
+
return allowedSingleSegmentPaths instanceof Set && allowedSingleSegmentPaths.has(valueToken);
|
|
60327
|
+
}
|
|
59839
60328
|
|
|
59840
60329
|
// node_modules/@zeropress/build-core/src/render/control-flow-renderer.js
|
|
59841
|
-
var
|
|
59842
|
-
var
|
|
59843
|
-
var FOR_EXPRESSION_REGEX = new RegExp(`^([a-zA-Z_][a-zA-Z0-9_]*)\\s+in\\s+(${
|
|
59844
|
-
var
|
|
60330
|
+
var PATH_SEGMENT_SOURCE2 = "[a-zA-Z_][a-zA-Z0-9_]*(?:-[a-zA-Z0-9_]+)*";
|
|
60331
|
+
var PATH_REGEX2 = new RegExp(`^${PATH_SEGMENT_SOURCE2}(?:\\.${PATH_SEGMENT_SOURCE2})*$`);
|
|
60332
|
+
var FOR_EXPRESSION_REGEX = new RegExp(`^([a-zA-Z_][a-zA-Z0-9_]*)\\s+in\\s+(${PATH_SEGMENT_SOURCE2}(?:\\.${PATH_SEGMENT_SOURCE2})*)$`);
|
|
60333
|
+
var NUMBER_LITERAL_REGEX3 = /^-?(?:0|[1-9]\d*)(?:\.\d+)?$/;
|
|
60334
|
+
var COMPARISON_BLOCK_TAGS2 = /* @__PURE__ */ new Set(["if_eq", "if_neq", "if_in", "if_starts_with"]);
|
|
60335
|
+
var COMPARISON_ELSE_IF_TAGS2 = /* @__PURE__ */ new Set(["else_if_eq", "else_if_neq", "else_if_in", "else_if_starts_with"]);
|
|
60336
|
+
var COMPARISON_TAG_OPERATORS2 = {
|
|
60337
|
+
if_eq: "eq",
|
|
60338
|
+
else_if_eq: "eq",
|
|
60339
|
+
if_neq: "neq",
|
|
60340
|
+
else_if_neq: "neq",
|
|
60341
|
+
if_in: "in",
|
|
60342
|
+
else_if_in: "in",
|
|
60343
|
+
if_starts_with: "starts_with",
|
|
60344
|
+
else_if_starts_with: "starts_with"
|
|
60345
|
+
};
|
|
60346
|
+
var PARTIAL_ARG_ROOT_PATHS2 = /* @__PURE__ */ new Set([
|
|
60347
|
+
"archive",
|
|
60348
|
+
"author",
|
|
60349
|
+
"category",
|
|
60350
|
+
"collection",
|
|
60351
|
+
"collections",
|
|
60352
|
+
"currentUrl",
|
|
60353
|
+
"language",
|
|
60354
|
+
"menu",
|
|
60355
|
+
"menus",
|
|
60356
|
+
"meta",
|
|
60357
|
+
"page",
|
|
60358
|
+
"pagination",
|
|
60359
|
+
"partial",
|
|
60360
|
+
"post",
|
|
60361
|
+
"posts",
|
|
60362
|
+
"route",
|
|
60363
|
+
"site",
|
|
60364
|
+
"tag",
|
|
60365
|
+
"taxonomies",
|
|
60366
|
+
"taxonomy",
|
|
60367
|
+
"widget",
|
|
60368
|
+
"widgets"
|
|
60369
|
+
]);
|
|
60370
|
+
function getComparisonBlockTag2(token) {
|
|
60371
|
+
for (const tagName of COMPARISON_BLOCK_TAGS2) {
|
|
60372
|
+
if (token.startsWith(`#${tagName} `)) {
|
|
60373
|
+
return tagName;
|
|
60374
|
+
}
|
|
60375
|
+
}
|
|
60376
|
+
return "";
|
|
60377
|
+
}
|
|
60378
|
+
function getComparisonElseIfTag2(token) {
|
|
60379
|
+
for (const tagName of COMPARISON_ELSE_IF_TAGS2) {
|
|
60380
|
+
if (token.startsWith(`#${tagName} `)) {
|
|
60381
|
+
return tagName;
|
|
60382
|
+
}
|
|
60383
|
+
}
|
|
60384
|
+
return "";
|
|
60385
|
+
}
|
|
60386
|
+
function tokenizeExpression2(expression) {
|
|
60387
|
+
const tokens = [];
|
|
60388
|
+
let index = 0;
|
|
60389
|
+
while (index < expression.length) {
|
|
60390
|
+
while (/\s/.test(expression[index] || "")) {
|
|
60391
|
+
index += 1;
|
|
60392
|
+
}
|
|
60393
|
+
if (index >= expression.length) {
|
|
60394
|
+
break;
|
|
60395
|
+
}
|
|
60396
|
+
if (expression[index] === '"') {
|
|
60397
|
+
const start2 = index;
|
|
60398
|
+
index += 1;
|
|
60399
|
+
let escaped = false;
|
|
60400
|
+
while (index < expression.length) {
|
|
60401
|
+
const char = expression[index];
|
|
60402
|
+
if (escaped) {
|
|
60403
|
+
escaped = false;
|
|
60404
|
+
} else if (char === "\\") {
|
|
60405
|
+
escaped = true;
|
|
60406
|
+
} else if (char === '"') {
|
|
60407
|
+
index += 1;
|
|
60408
|
+
tokens.push(expression.slice(start2, index));
|
|
60409
|
+
break;
|
|
60410
|
+
}
|
|
60411
|
+
index += 1;
|
|
60412
|
+
}
|
|
60413
|
+
if (tokens[tokens.length - 1] !== expression.slice(start2, index)) {
|
|
60414
|
+
throw new Error(`Unclosed string literal in expression: ${expression}`);
|
|
60415
|
+
}
|
|
60416
|
+
continue;
|
|
60417
|
+
}
|
|
60418
|
+
const start = index;
|
|
60419
|
+
while (index < expression.length && !/\s/.test(expression[index])) {
|
|
60420
|
+
index += 1;
|
|
60421
|
+
}
|
|
60422
|
+
tokens.push(expression.slice(start, index));
|
|
60423
|
+
}
|
|
60424
|
+
return tokens;
|
|
60425
|
+
}
|
|
60426
|
+
function parsePathOperand2(token, tagName, expression) {
|
|
60427
|
+
if (!PATH_REGEX2.test(token)) {
|
|
60428
|
+
throw new Error(`Invalid ${tagName} expression: ${expression}`);
|
|
60429
|
+
}
|
|
60430
|
+
return { kind: "path", path: token };
|
|
60431
|
+
}
|
|
60432
|
+
function parseComparisonOperand2(token, tagName, expression) {
|
|
60433
|
+
if (token.startsWith('"')) {
|
|
60434
|
+
try {
|
|
60435
|
+
const value = JSON.parse(token);
|
|
60436
|
+
if (typeof value !== "string") {
|
|
60437
|
+
throw new Error("Expected string literal");
|
|
60438
|
+
}
|
|
60439
|
+
return { kind: "literal", value };
|
|
60440
|
+
} catch {
|
|
60441
|
+
throw new Error(`Invalid ${tagName} expression: ${expression}`);
|
|
60442
|
+
}
|
|
60443
|
+
}
|
|
60444
|
+
if (token === "true") {
|
|
60445
|
+
return { kind: "literal", value: true };
|
|
60446
|
+
}
|
|
60447
|
+
if (token === "false") {
|
|
60448
|
+
return { kind: "literal", value: false };
|
|
60449
|
+
}
|
|
60450
|
+
if (token === "null") {
|
|
60451
|
+
return { kind: "literal", value: null };
|
|
60452
|
+
}
|
|
60453
|
+
if (NUMBER_LITERAL_REGEX3.test(token)) {
|
|
60454
|
+
return { kind: "literal", value: Number(token) };
|
|
60455
|
+
}
|
|
60456
|
+
if (PATH_REGEX2.test(token)) {
|
|
60457
|
+
return { kind: "path", path: token };
|
|
60458
|
+
}
|
|
60459
|
+
throw new Error(`Invalid ${tagName} expression: ${expression}`);
|
|
60460
|
+
}
|
|
59845
60461
|
var ControlFlowRenderer = class {
|
|
59846
60462
|
constructor(options2 = {}) {
|
|
59847
60463
|
this.resolvePath = typeof options2.resolvePath === "function" ? options2.resolvePath : ((data, path4) => path4.split(".").reduce((current, segment) => {
|
|
@@ -59864,7 +60480,7 @@ var ControlFlowRenderer = class {
|
|
|
59864
60480
|
}
|
|
59865
60481
|
parse(template) {
|
|
59866
60482
|
const source = String(template || "");
|
|
59867
|
-
const { nodes, nextIndex, stopTag } = this.parseNodes(source, 0, /* @__PURE__ */ new Set());
|
|
60483
|
+
const { nodes, nextIndex, stopTag } = this.parseNodes(source, 0, /* @__PURE__ */ new Set(), PARTIAL_ARG_ROOT_PATHS2);
|
|
59868
60484
|
if (stopTag) {
|
|
59869
60485
|
throw new Error(`Unexpected closing tag ${stopTag}`);
|
|
59870
60486
|
}
|
|
@@ -59873,7 +60489,7 @@ var ControlFlowRenderer = class {
|
|
|
59873
60489
|
}
|
|
59874
60490
|
return nodes;
|
|
59875
60491
|
}
|
|
59876
|
-
parseNodes(source, startIndex, stopTags) {
|
|
60492
|
+
parseNodes(source, startIndex, stopTags, partialArgScope) {
|
|
59877
60493
|
const nodes = [];
|
|
59878
60494
|
let index = startIndex;
|
|
59879
60495
|
while (index < source.length) {
|
|
@@ -59924,9 +60540,10 @@ var ControlFlowRenderer = class {
|
|
|
59924
60540
|
}
|
|
59925
60541
|
return { nodes, nextIndex: tokenEnd + 2, stopTag: "else" };
|
|
59926
60542
|
}
|
|
59927
|
-
|
|
59928
|
-
|
|
59929
|
-
|
|
60543
|
+
const comparisonElseIfTag = getComparisonElseIfTag2(token);
|
|
60544
|
+
if (comparisonElseIfTag) {
|
|
60545
|
+
if (!stopTags.has(comparisonElseIfTag)) {
|
|
60546
|
+
throw new Error(`Unexpected ${comparisonElseIfTag} tag`);
|
|
59930
60547
|
}
|
|
59931
60548
|
return { nodes, nextIndex: tokenEnd + 2, stopTag: token };
|
|
59932
60549
|
}
|
|
@@ -59937,21 +60554,22 @@ var ControlFlowRenderer = class {
|
|
|
59937
60554
|
return { nodes, nextIndex: tokenEnd + 2, stopTag: token };
|
|
59938
60555
|
}
|
|
59939
60556
|
if (token.startsWith("partial:")) {
|
|
59940
|
-
const { name, args } = parsePartialToken(token);
|
|
60557
|
+
const { name, args } = parsePartialToken(token, { allowedSingleSegmentPaths: partialArgScope });
|
|
59941
60558
|
nodes.push({ type: "partial", name, args });
|
|
59942
60559
|
index = tokenEnd + 2;
|
|
59943
60560
|
continue;
|
|
59944
60561
|
}
|
|
59945
|
-
|
|
59946
|
-
|
|
59947
|
-
const
|
|
60562
|
+
const comparisonBlockTag = getComparisonBlockTag2(token);
|
|
60563
|
+
if (comparisonBlockTag) {
|
|
60564
|
+
const expression = token.slice(`#${comparisonBlockTag} `.length).trim();
|
|
60565
|
+
const block2 = this.parseComparisonBlock(source, tokenEnd + 2, comparisonBlockTag, expression, partialArgScope);
|
|
59948
60566
|
nodes.push(block2.node);
|
|
59949
60567
|
index = block2.nextIndex;
|
|
59950
60568
|
continue;
|
|
59951
60569
|
}
|
|
59952
60570
|
if (token.startsWith("#if ")) {
|
|
59953
60571
|
const expression = token.slice("#if ".length).trim();
|
|
59954
|
-
const block2 = this.parseIfBlock(source, tokenEnd + 2, expression);
|
|
60572
|
+
const block2 = this.parseIfBlock(source, tokenEnd + 2, expression, partialArgScope);
|
|
59955
60573
|
nodes.push(block2.node);
|
|
59956
60574
|
index = block2.nextIndex;
|
|
59957
60575
|
continue;
|
|
@@ -59963,7 +60581,8 @@ var ControlFlowRenderer = class {
|
|
|
59963
60581
|
throw new Error(`Invalid for expression: ${expression}`);
|
|
59964
60582
|
}
|
|
59965
60583
|
const [, itemName, path4] = match2;
|
|
59966
|
-
const
|
|
60584
|
+
const forScope = /* @__PURE__ */ new Set([...partialArgScope, itemName, "loop"]);
|
|
60585
|
+
const forResult = this.parseNodes(source, tokenEnd + 2, /* @__PURE__ */ new Set(["for"]), forScope);
|
|
59967
60586
|
if (forResult.stopTag !== "for") {
|
|
59968
60587
|
throw new Error("Unclosed for block");
|
|
59969
60588
|
}
|
|
@@ -59980,8 +60599,8 @@ var ControlFlowRenderer = class {
|
|
|
59980
60599
|
}
|
|
59981
60600
|
return { nodes, nextIndex: source.length, stopTag: null };
|
|
59982
60601
|
}
|
|
59983
|
-
parseIfBlock(source, startIndex, initialPath) {
|
|
59984
|
-
if (!
|
|
60602
|
+
parseIfBlock(source, startIndex, initialPath, partialArgScope) {
|
|
60603
|
+
if (!PATH_REGEX2.test(initialPath)) {
|
|
59985
60604
|
throw new Error(`Invalid if expression: ${initialPath}`);
|
|
59986
60605
|
}
|
|
59987
60606
|
const branches = [];
|
|
@@ -59989,13 +60608,13 @@ var ControlFlowRenderer = class {
|
|
|
59989
60608
|
let nextIndex = startIndex;
|
|
59990
60609
|
let currentPath = initialPath;
|
|
59991
60610
|
while (true) {
|
|
59992
|
-
const branchResult = this.parseNodes(source, nextIndex, /* @__PURE__ */ new Set(["else", "else_if", "if"]));
|
|
60611
|
+
const branchResult = this.parseNodes(source, nextIndex, /* @__PURE__ */ new Set(["else", "else_if", "if"]), partialArgScope);
|
|
59993
60612
|
branches.push({
|
|
59994
60613
|
path: currentPath,
|
|
59995
60614
|
consequent: branchResult.nodes
|
|
59996
60615
|
});
|
|
59997
60616
|
if (branchResult.stopTag === "else") {
|
|
59998
|
-
const elseResult = this.parseNodes(source, branchResult.nextIndex, /* @__PURE__ */ new Set(["if"]));
|
|
60617
|
+
const elseResult = this.parseNodes(source, branchResult.nextIndex, /* @__PURE__ */ new Set(["if"]), partialArgScope);
|
|
59999
60618
|
if (elseResult.stopTag !== "if") {
|
|
60000
60619
|
throw new Error("Unclosed if block after else");
|
|
60001
60620
|
}
|
|
@@ -60005,7 +60624,7 @@ var ControlFlowRenderer = class {
|
|
|
60005
60624
|
}
|
|
60006
60625
|
if (typeof branchResult.stopTag === "string" && branchResult.stopTag.startsWith("#else_if ")) {
|
|
60007
60626
|
currentPath = branchResult.stopTag.slice("#else_if ".length).trim();
|
|
60008
|
-
if (!
|
|
60627
|
+
if (!PATH_REGEX2.test(currentPath)) {
|
|
60009
60628
|
throw new Error(`Invalid else_if expression: ${currentPath}`);
|
|
60010
60629
|
}
|
|
60011
60630
|
nextIndex = branchResult.nextIndex;
|
|
@@ -60026,60 +60645,65 @@ var ControlFlowRenderer = class {
|
|
|
60026
60645
|
nextIndex
|
|
60027
60646
|
};
|
|
60028
60647
|
}
|
|
60029
|
-
|
|
60030
|
-
const initialBranch = this.
|
|
60648
|
+
parseComparisonBlock(source, startIndex, tagName, expression, partialArgScope) {
|
|
60649
|
+
const initialBranch = this.parseComparisonBranchExpression(expression, tagName);
|
|
60031
60650
|
const branches = [];
|
|
60032
60651
|
let alternate = [];
|
|
60033
60652
|
let nextIndex = startIndex;
|
|
60034
60653
|
let currentBranch = initialBranch;
|
|
60654
|
+
const elseIfTag = `else_${tagName}`;
|
|
60035
60655
|
while (true) {
|
|
60036
|
-
const branchResult = this.parseNodes(source, nextIndex, /* @__PURE__ */ new Set(["else",
|
|
60656
|
+
const branchResult = this.parseNodes(source, nextIndex, /* @__PURE__ */ new Set(["else", elseIfTag, tagName]), partialArgScope);
|
|
60037
60657
|
branches.push({
|
|
60038
|
-
|
|
60039
|
-
|
|
60658
|
+
operator: currentBranch.operator,
|
|
60659
|
+
left: currentBranch.left,
|
|
60660
|
+
operands: currentBranch.operands,
|
|
60040
60661
|
consequent: branchResult.nodes
|
|
60041
60662
|
});
|
|
60042
60663
|
if (branchResult.stopTag === "else") {
|
|
60043
|
-
const elseResult = this.parseNodes(source, branchResult.nextIndex, /* @__PURE__ */ new Set([
|
|
60044
|
-
if (elseResult.stopTag !==
|
|
60045
|
-
throw new Error(
|
|
60664
|
+
const elseResult = this.parseNodes(source, branchResult.nextIndex, /* @__PURE__ */ new Set([tagName]), partialArgScope);
|
|
60665
|
+
if (elseResult.stopTag !== tagName) {
|
|
60666
|
+
throw new Error(`Unclosed ${tagName} block after else`);
|
|
60046
60667
|
}
|
|
60047
60668
|
alternate = elseResult.nodes;
|
|
60048
60669
|
nextIndex = elseResult.nextIndex;
|
|
60049
60670
|
break;
|
|
60050
60671
|
}
|
|
60051
|
-
if (typeof branchResult.stopTag === "string" && branchResult.stopTag.startsWith(
|
|
60052
|
-
currentBranch = this.
|
|
60053
|
-
branchResult.stopTag.slice(
|
|
60054
|
-
|
|
60672
|
+
if (typeof branchResult.stopTag === "string" && branchResult.stopTag.startsWith(`#${elseIfTag} `)) {
|
|
60673
|
+
currentBranch = this.parseComparisonBranchExpression(
|
|
60674
|
+
branchResult.stopTag.slice(`#${elseIfTag} `.length).trim(),
|
|
60675
|
+
elseIfTag
|
|
60055
60676
|
);
|
|
60056
60677
|
nextIndex = branchResult.nextIndex;
|
|
60057
60678
|
continue;
|
|
60058
60679
|
}
|
|
60059
|
-
if (branchResult.stopTag ===
|
|
60680
|
+
if (branchResult.stopTag === tagName) {
|
|
60060
60681
|
nextIndex = branchResult.nextIndex;
|
|
60061
60682
|
break;
|
|
60062
60683
|
}
|
|
60063
|
-
throw new Error(
|
|
60684
|
+
throw new Error(`Unclosed ${tagName} block`);
|
|
60064
60685
|
}
|
|
60065
60686
|
return {
|
|
60066
60687
|
node: {
|
|
60067
|
-
type: "
|
|
60688
|
+
type: "comparison",
|
|
60068
60689
|
branches,
|
|
60069
60690
|
alternate
|
|
60070
60691
|
},
|
|
60071
60692
|
nextIndex
|
|
60072
60693
|
};
|
|
60073
60694
|
}
|
|
60074
|
-
|
|
60075
|
-
const
|
|
60076
|
-
|
|
60695
|
+
parseComparisonBranchExpression(expression, tagName) {
|
|
60696
|
+
const operator = COMPARISON_TAG_OPERATORS2[tagName];
|
|
60697
|
+
const tokens = tokenizeExpression2(expression);
|
|
60698
|
+
if (!operator || operator === "in" && tokens.length < 2 || operator !== "in" && tokens.length !== 2) {
|
|
60077
60699
|
throw new Error(`Invalid ${tagName} expression: ${expression}`);
|
|
60078
60700
|
}
|
|
60079
|
-
const [,
|
|
60701
|
+
const left = parsePathOperand2(tokens[0], tagName, expression);
|
|
60702
|
+
const operands = tokens.slice(1).map((token) => parseComparisonOperand2(token, tagName, expression));
|
|
60080
60703
|
return {
|
|
60081
|
-
|
|
60082
|
-
|
|
60704
|
+
operator,
|
|
60705
|
+
left,
|
|
60706
|
+
operands
|
|
60083
60707
|
};
|
|
60084
60708
|
}
|
|
60085
60709
|
renderNodes(nodes, data, renderOptions) {
|
|
@@ -60093,8 +60717,8 @@ var ControlFlowRenderer = class {
|
|
|
60093
60717
|
const branch = node.branches.find((entry) => this.isTruthy(this.resolvePath(data, entry.path)));
|
|
60094
60718
|
return branch ? this.renderNodes(branch.consequent, data, renderOptions) : this.renderNodes(node.alternate, data, renderOptions);
|
|
60095
60719
|
}
|
|
60096
|
-
case "
|
|
60097
|
-
const branch = node.branches.find((entry) => this.
|
|
60720
|
+
case "comparison": {
|
|
60721
|
+
const branch = node.branches.find((entry) => this.evaluateComparison(entry, data));
|
|
60098
60722
|
return branch ? this.renderNodes(branch.consequent, data, renderOptions) : this.renderNodes(node.alternate, data, renderOptions);
|
|
60099
60723
|
}
|
|
60100
60724
|
case "for": {
|
|
@@ -60129,15 +60753,62 @@ var ControlFlowRenderer = class {
|
|
|
60129
60753
|
throw new Error(`Circular partial reference detected: ${cycle}`);
|
|
60130
60754
|
}
|
|
60131
60755
|
const partialTemplate = String(partials.get(node.name) || "");
|
|
60756
|
+
const partialArgs = this.resolvePartialArgs(node.args, data);
|
|
60132
60757
|
const partialData = {
|
|
60133
60758
|
...data,
|
|
60134
|
-
partial: {
|
|
60759
|
+
partial: {
|
|
60760
|
+
...data?.partial && typeof data.partial === "object" ? data.partial : {},
|
|
60761
|
+
...partialArgs
|
|
60762
|
+
}
|
|
60135
60763
|
};
|
|
60136
60764
|
return this.renderTemplate(partialTemplate, partialData, {
|
|
60137
60765
|
...renderOptions,
|
|
60138
60766
|
partialStack: [...activeStack, node.name]
|
|
60139
60767
|
});
|
|
60140
60768
|
}
|
|
60769
|
+
resolvePartialArgs(args, data) {
|
|
60770
|
+
const resolved = {};
|
|
60771
|
+
for (const [key, operand] of Object.entries(args || {})) {
|
|
60772
|
+
if (operand?.kind === "literal") {
|
|
60773
|
+
resolved[key] = operand.value;
|
|
60774
|
+
continue;
|
|
60775
|
+
}
|
|
60776
|
+
if (operand?.kind === "path") {
|
|
60777
|
+
resolved[key] = this.resolvePath(data, operand.path);
|
|
60778
|
+
}
|
|
60779
|
+
}
|
|
60780
|
+
return resolved;
|
|
60781
|
+
}
|
|
60782
|
+
evaluateComparison(entry, data) {
|
|
60783
|
+
const left = this.evaluateOperand(entry.left, data);
|
|
60784
|
+
const operands = entry.operands.map((operand) => this.evaluateOperand(operand, data));
|
|
60785
|
+
if (entry.operator === "eq") {
|
|
60786
|
+
const right = operands[0];
|
|
60787
|
+
return !left.missing && !right.missing && left.value === right.value;
|
|
60788
|
+
}
|
|
60789
|
+
if (entry.operator === "neq") {
|
|
60790
|
+
const right = operands[0];
|
|
60791
|
+
return left.missing || right.missing || left.value !== right.value;
|
|
60792
|
+
}
|
|
60793
|
+
if (entry.operator === "in") {
|
|
60794
|
+
if (left.missing) {
|
|
60795
|
+
return false;
|
|
60796
|
+
}
|
|
60797
|
+
return operands.some((operand) => !operand.missing && left.value === operand.value);
|
|
60798
|
+
}
|
|
60799
|
+
if (entry.operator === "starts_with") {
|
|
60800
|
+
const right = operands[0];
|
|
60801
|
+
return !left.missing && !right.missing && typeof left.value === "string" && typeof right.value === "string" && left.value.startsWith(right.value);
|
|
60802
|
+
}
|
|
60803
|
+
return false;
|
|
60804
|
+
}
|
|
60805
|
+
evaluateOperand(operand, data) {
|
|
60806
|
+
if (operand.kind === "literal") {
|
|
60807
|
+
return { value: operand.value, missing: false };
|
|
60808
|
+
}
|
|
60809
|
+
const value = this.resolvePath(data, operand.path);
|
|
60810
|
+
return { value, missing: value === void 0 };
|
|
60811
|
+
}
|
|
60141
60812
|
isTruthy(value) {
|
|
60142
60813
|
if (Array.isArray(value)) {
|
|
60143
60814
|
return value.length > 0;
|
|
@@ -60179,7 +60850,7 @@ var ZeroPressEngine = class {
|
|
|
60179
60850
|
const renderData = this.combineRenderData(data, context);
|
|
60180
60851
|
const renderedContent = this.renderTemplate(template, renderData);
|
|
60181
60852
|
const layoutWithSlots = this.slotResolver.resolve(layout, this.themePackage.partials, CONTENT_SLOT_PLACEHOLDER);
|
|
60182
|
-
return this.renderTemplate(layoutWithSlots, renderData).replaceAll(CONTENT_SLOT_PLACEHOLDER, renderedContent);
|
|
60853
|
+
return this.renderTemplate(layoutWithSlots, renderData).replaceAll(CONTENT_SLOT_PLACEHOLDER, () => renderedContent);
|
|
60183
60854
|
}
|
|
60184
60855
|
combineRenderData(data, context) {
|
|
60185
60856
|
return {
|
|
@@ -60190,7 +60861,7 @@ var ZeroPressEngine = class {
|
|
|
60190
60861
|
};
|
|
60191
60862
|
}
|
|
60192
60863
|
renderTemplate(template, data) {
|
|
60193
|
-
if (this.themePackage?.metadata?.runtime !== "0.
|
|
60864
|
+
if (this.themePackage?.metadata?.runtime !== "0.6") {
|
|
60194
60865
|
throw new Error(`Unsupported theme runtime: ${this.themePackage?.metadata?.runtime || "unknown"}`);
|
|
60195
60866
|
}
|
|
60196
60867
|
return this.controlFlowRenderer.render(template, data, {
|
|
@@ -60210,10 +60881,13 @@ var DEFAULT_OPTIONS = {
|
|
|
60210
60881
|
writeManifest: false
|
|
60211
60882
|
};
|
|
60212
60883
|
var DEFAULT_POSTS_PER_PAGE = 10;
|
|
60213
|
-
var
|
|
60214
|
-
var
|
|
60884
|
+
var DEFAULT_DATETIME_DISPLAY = "static";
|
|
60885
|
+
var DEFAULT_DATE_STYLE = "medium";
|
|
60886
|
+
var DEFAULT_TIME_STYLE = "none";
|
|
60215
60887
|
var DEFAULT_TIMEZONE = "UTC";
|
|
60216
60888
|
var DEFAULT_LOCALE = "en-US";
|
|
60889
|
+
var DATETIME_DISPLAY_MODES = /* @__PURE__ */ new Set(["static", "client"]);
|
|
60890
|
+
var DATETIME_STYLES = /* @__PURE__ */ new Set(["none", "short", "medium", "long", "full"]);
|
|
60217
60891
|
var DEFAULT_PERMALINKS = Object.freeze({
|
|
60218
60892
|
output_style: "directory",
|
|
60219
60893
|
posts: "/posts/:slug/",
|
|
@@ -60231,12 +60905,24 @@ var DEFAULT_POST_INDEX = Object.freeze({
|
|
|
60231
60905
|
});
|
|
60232
60906
|
var PERMALINK_OUTPUT_STYLES = /* @__PURE__ */ new Set(["directory", "html-extension"]);
|
|
60233
60907
|
var COMMENT_POLICY_OUTPUT_PATH = "_zeropress/comment-policy.json";
|
|
60908
|
+
var SEARCH_INDEX_OUTPUT_PATH = "_zeropress/search.json";
|
|
60909
|
+
var SEARCH_ADAPTER_OUTPUT_PATH = "_zeropress/search.js";
|
|
60234
60910
|
var OUTPUT_PATH_CONTROL_CHAR_PATTERN = /[\u0000-\u001F\u007F]/;
|
|
60235
60911
|
var SAFE_MEDIA_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:"]);
|
|
60236
60912
|
var SAFE_LINK_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:", "mailto:", "tel:"]);
|
|
60237
60913
|
var MEDIA_DELIVERY_MODES = /* @__PURE__ */ new Set(["none", "media_domain"]);
|
|
60914
|
+
var DISCOVERABILITY_VALUES = /* @__PURE__ */ new Set(["default", "noindex", "delist"]);
|
|
60238
60915
|
var RESPONSIVE_IMAGE_WIDTHS = [320, 480, 768, 1024, 1280, 1600, 1920];
|
|
60239
60916
|
var RESPONSIVE_IMAGE_EXTENSIONS = /* @__PURE__ */ new Set(["jpg", "jpeg", "png", "webp", "avif"]);
|
|
60917
|
+
var SEARCH_FIELD_WEIGHTS = Object.freeze({
|
|
60918
|
+
title: 5,
|
|
60919
|
+
headings: 3,
|
|
60920
|
+
tags: 2.5,
|
|
60921
|
+
categories: 2,
|
|
60922
|
+
excerpt: 1.5,
|
|
60923
|
+
content_text: 1
|
|
60924
|
+
});
|
|
60925
|
+
var SEARCH_RECENCY_BOOST_MAX = 0.15;
|
|
60240
60926
|
async function buildSite(input2) {
|
|
60241
60927
|
const options2 = { ...DEFAULT_OPTIONS, ...input2.options || {} };
|
|
60242
60928
|
const state = await createBuildState(input2, options2);
|
|
@@ -60279,9 +60965,17 @@ async function buildSite(input2) {
|
|
|
60279
60965
|
"application/json"
|
|
60280
60966
|
);
|
|
60281
60967
|
if (options2.generateSpecialFiles) {
|
|
60968
|
+
await writeOutput(state.writer, state.summaries, SEARCH_INDEX_OUTPUT_PATH, buildSearchIndexJson(state), "application/json");
|
|
60969
|
+
await writeOutput(state.writer, state.summaries, SEARCH_ADAPTER_OUTPUT_PATH, buildSearchAdapterJs(), "application/javascript");
|
|
60282
60970
|
await maybeRenderNotFoundPage(state);
|
|
60283
60971
|
if (hasCanonicalSiteUrl(state.previewData.site.url)) {
|
|
60284
|
-
await writeOutput(
|
|
60972
|
+
await writeOutput(
|
|
60973
|
+
state.writer,
|
|
60974
|
+
state.summaries,
|
|
60975
|
+
"sitemap.xml",
|
|
60976
|
+
buildSitemapXml(state.previewData.site, state.emitted, state.generatedAt, options2.sitemapStylesheetHref),
|
|
60977
|
+
"application/xml"
|
|
60978
|
+
);
|
|
60285
60979
|
await writeOutput(state.writer, state.summaries, "feed.xml", buildFeedXml(state.previewData.site, state.emitted, state.generatedAt), "application/rss+xml");
|
|
60286
60980
|
}
|
|
60287
60981
|
if (shouldGenerateRobotsTxt(options2)) {
|
|
@@ -60323,6 +61017,7 @@ async function createBuildState(input2, options2) {
|
|
|
60323
61017
|
customCssHref: customCssAsset ? `/${customCssAsset.path}` : "",
|
|
60324
61018
|
customHtml: previewData.custom_html,
|
|
60325
61019
|
favicon: previewData.site.favicon,
|
|
61020
|
+
exposeGenerator: previewData.site.expose_generator !== false,
|
|
60326
61021
|
commentPolicyContent: buildCommentPolicyManifest(renderData.posts),
|
|
60327
61022
|
options: options2,
|
|
60328
61023
|
generatedAt: /* @__PURE__ */ new Date(),
|
|
@@ -60432,7 +61127,8 @@ async function renderFrontPage(state, route) {
|
|
|
60432
61127
|
title: buildDocumentTitle(page.title, state.previewData.site.title),
|
|
60433
61128
|
description: page.excerpt,
|
|
60434
61129
|
ogType: "website",
|
|
60435
|
-
image: page.featured_image
|
|
61130
|
+
image: page.featured_image,
|
|
61131
|
+
robotsNoindex: shouldNoindexDocument(page)
|
|
60436
61132
|
})
|
|
60437
61133
|
},
|
|
60438
61134
|
createRenderContext(state.previewData.site, currentUrl)
|
|
@@ -60444,7 +61140,8 @@ async function renderFrontPage(state, route) {
|
|
|
60444
61140
|
url: currentUrl,
|
|
60445
61141
|
title: page.title,
|
|
60446
61142
|
description: page.excerpt,
|
|
60447
|
-
includeInFeed: false
|
|
61143
|
+
includeInFeed: false,
|
|
61144
|
+
includeInSitemap: !isDelistedDocument(page)
|
|
60448
61145
|
};
|
|
60449
61146
|
return;
|
|
60450
61147
|
}
|
|
@@ -60494,7 +61191,8 @@ async function renderPost(state, post) {
|
|
|
60494
61191
|
ogType: "article",
|
|
60495
61192
|
image: post.featured_image,
|
|
60496
61193
|
publishedTime: post.published_at_iso,
|
|
60497
|
-
modifiedTime: post.updated_at_iso
|
|
61194
|
+
modifiedTime: post.updated_at_iso,
|
|
61195
|
+
robotsNoindex: shouldNoindexDocument(post)
|
|
60498
61196
|
})
|
|
60499
61197
|
},
|
|
60500
61198
|
createRenderContext(state.previewData.site, currentUrl)
|
|
@@ -60502,14 +61200,16 @@ async function renderPost(state, post) {
|
|
|
60502
61200
|
html = state.assetProcessor.updateAssetReferences(html, state.assetMap);
|
|
60503
61201
|
html = injectSiteCustomizations(html, state);
|
|
60504
61202
|
await writeOutput(state.writer, state.summaries, routePathToOutputPath(post.url, state.previewData.site.permalinks.output_style), html, "text/html");
|
|
60505
|
-
|
|
60506
|
-
|
|
60507
|
-
|
|
60508
|
-
|
|
60509
|
-
|
|
60510
|
-
|
|
60511
|
-
|
|
60512
|
-
|
|
61203
|
+
if (!isDelistedDocument(post)) {
|
|
61204
|
+
state.emitted.posts.push({
|
|
61205
|
+
url: currentUrl,
|
|
61206
|
+
title: post.title,
|
|
61207
|
+
description: post.excerpt,
|
|
61208
|
+
publishedAt: post.published_at_iso,
|
|
61209
|
+
updatedAt: post.updated_at_iso,
|
|
61210
|
+
status: post.status
|
|
61211
|
+
});
|
|
61212
|
+
}
|
|
60513
61213
|
}
|
|
60514
61214
|
async function renderPage(state, page) {
|
|
60515
61215
|
const currentUrl = page.url;
|
|
@@ -60530,7 +61230,8 @@ async function renderPage(state, page) {
|
|
|
60530
61230
|
title: buildDocumentTitle(page.title, state.previewData.site.title),
|
|
60531
61231
|
description: page.excerpt,
|
|
60532
61232
|
ogType: "website",
|
|
60533
|
-
image: page.featured_image
|
|
61233
|
+
image: page.featured_image,
|
|
61234
|
+
robotsNoindex: shouldNoindexDocument(page)
|
|
60534
61235
|
})
|
|
60535
61236
|
},
|
|
60536
61237
|
createRenderContext(state.previewData.site, currentUrl)
|
|
@@ -60543,7 +61244,7 @@ async function renderPage(state, page) {
|
|
|
60543
61244
|
title: page.title,
|
|
60544
61245
|
description: page.excerpt,
|
|
60545
61246
|
status: page.status,
|
|
60546
|
-
includeInSitemap: page.omit_from_sitemap !== true
|
|
61247
|
+
includeInSitemap: page.omit_from_sitemap !== true && !isDelistedDocument(page)
|
|
60547
61248
|
});
|
|
60548
61249
|
}
|
|
60549
61250
|
async function maybeRenderNotFoundPage(state) {
|
|
@@ -60574,15 +61275,17 @@ async function maybeRenderNotFoundPage(state) {
|
|
|
60574
61275
|
function normalizePreviewData(previewData, options2 = {}) {
|
|
60575
61276
|
const normalizedSite = {
|
|
60576
61277
|
...previewData.site,
|
|
60577
|
-
|
|
60578
|
-
|
|
61278
|
+
media_base_url: normalizeOptionalString(previewData.site.media_base_url),
|
|
61279
|
+
media_delivery_mode: MEDIA_DELIVERY_MODES.has(previewData.site.media_delivery_mode) ? previewData.site.media_delivery_mode : "none",
|
|
60579
61280
|
favicon: normalizeSiteFavicon(previewData.site.favicon || options2.favicon),
|
|
60580
|
-
|
|
60581
|
-
|
|
60582
|
-
|
|
61281
|
+
posts_per_page: Number.isInteger(previewData.site.posts_per_page) && previewData.site.posts_per_page > 0 ? previewData.site.posts_per_page : DEFAULT_POSTS_PER_PAGE,
|
|
61282
|
+
datetime_display: DATETIME_DISPLAY_MODES.has(previewData.site.datetime_display) ? previewData.site.datetime_display : DEFAULT_DATETIME_DISPLAY,
|
|
61283
|
+
date_style: DATETIME_STYLES.has(previewData.site.date_style) ? previewData.site.date_style : DEFAULT_DATE_STYLE,
|
|
61284
|
+
time_style: DATETIME_STYLES.has(previewData.site.time_style) ? previewData.site.time_style : DEFAULT_TIME_STYLE,
|
|
60583
61285
|
timezone: normalizeNonEmptyString(previewData.site.timezone, DEFAULT_TIMEZONE),
|
|
60584
61286
|
locale: normalizeLocale(previewData.site.locale || DEFAULT_LOCALE),
|
|
60585
|
-
|
|
61287
|
+
disallow_comments: previewData.site.disallow_comments === true,
|
|
61288
|
+
expose_generator: previewData.site.expose_generator !== false,
|
|
60586
61289
|
indexing: previewData.site.indexing !== false,
|
|
60587
61290
|
permalinks: normalizePermalinks(previewData.site.permalinks),
|
|
60588
61291
|
front_page: normalizeFrontPage(previewData.site.front_page),
|
|
@@ -60596,13 +61299,13 @@ function normalizePreviewData(previewData, options2 = {}) {
|
|
|
60596
61299
|
site: normalizedSite,
|
|
60597
61300
|
menus: normalizeRecordMap(previewData.menus),
|
|
60598
61301
|
collections: normalizeCollections(previewData.collections),
|
|
60599
|
-
widgets: normalizeWidgetAreas(previewData.widgets, normalizedSite.
|
|
61302
|
+
widgets: normalizeWidgetAreas(previewData.widgets, normalizedSite.media_base_url),
|
|
60600
61303
|
custom_css: normalizeCustomCss(previewData.custom_css),
|
|
60601
61304
|
custom_html: normalizeCustomHtml(previewData.custom_html),
|
|
60602
61305
|
content: {
|
|
60603
61306
|
...previewData.content,
|
|
60604
61307
|
authors: previewData.content.authors.map((author) => {
|
|
60605
|
-
const avatar = normalizeMediaField(author.avatar, normalizedSite.
|
|
61308
|
+
const avatar = normalizeMediaField(author.avatar, normalizedSite.media_base_url);
|
|
60606
61309
|
const avatarMedia = deriveManagedMedia(avatar, mediaRegistry, normalizedSite);
|
|
60607
61310
|
return {
|
|
60608
61311
|
...author,
|
|
@@ -60611,21 +61314,23 @@ function normalizePreviewData(previewData, options2 = {}) {
|
|
|
60611
61314
|
};
|
|
60612
61315
|
}),
|
|
60613
61316
|
posts: previewData.content.posts.map((post) => {
|
|
60614
|
-
const featuredImage = normalizeMediaField(post.featured_image, normalizedSite.
|
|
61317
|
+
const featuredImage = normalizeMediaField(post.featured_image, normalizedSite.media_base_url);
|
|
60615
61318
|
const featuredMedia = deriveManagedMedia(featuredImage, mediaRegistry, normalizedSite);
|
|
60616
61319
|
return {
|
|
60617
61320
|
...post,
|
|
60618
61321
|
published_at_iso: normalizeIsoTimestamp(post.published_at_iso),
|
|
60619
61322
|
updated_at_iso: normalizeIsoTimestamp(post.updated_at_iso),
|
|
61323
|
+
discoverability: normalizeDiscoverability(post.discoverability),
|
|
60620
61324
|
featured_image: featuredImage,
|
|
60621
61325
|
...featuredMedia ? { featured_media: featuredMedia } : {}
|
|
60622
61326
|
};
|
|
60623
61327
|
}).sort((left, right) => toDate(right.published_at_iso).getTime() - toDate(left.published_at_iso).getTime()),
|
|
60624
61328
|
pages: previewData.content.pages.map((page) => {
|
|
60625
|
-
const featuredImage = normalizeMediaField(page.featured_image, normalizedSite.
|
|
61329
|
+
const featuredImage = normalizeMediaField(page.featured_image, normalizedSite.media_base_url);
|
|
60626
61330
|
const featuredMedia = deriveManagedMedia(featuredImage, mediaRegistry, normalizedSite);
|
|
60627
61331
|
return {
|
|
60628
61332
|
...page,
|
|
61333
|
+
discoverability: normalizeDiscoverability(page.discoverability),
|
|
60629
61334
|
featured_image: featuredImage,
|
|
60630
61335
|
...featuredMedia ? { featured_media: featuredMedia } : {}
|
|
60631
61336
|
};
|
|
@@ -60642,6 +61347,15 @@ function normalizeRecordMap(value) {
|
|
|
60642
61347
|
}
|
|
60643
61348
|
return { ...value };
|
|
60644
61349
|
}
|
|
61350
|
+
function normalizeDiscoverability(value) {
|
|
61351
|
+
return DISCOVERABILITY_VALUES.has(value) ? value : "default";
|
|
61352
|
+
}
|
|
61353
|
+
function isDelistedDocument(document2) {
|
|
61354
|
+
return document2?.discoverability === "delist";
|
|
61355
|
+
}
|
|
61356
|
+
function shouldNoindexDocument(document2) {
|
|
61357
|
+
return document2?.discoverability === "noindex" || document2?.discoverability === "delist";
|
|
61358
|
+
}
|
|
60645
61359
|
function normalizeContentMedia(mediaItems, site) {
|
|
60646
61360
|
if (!Array.isArray(mediaItems)) {
|
|
60647
61361
|
return [];
|
|
@@ -60650,7 +61364,7 @@ function normalizeContentMedia(mediaItems, site) {
|
|
|
60650
61364
|
if (!item || typeof item !== "object") {
|
|
60651
61365
|
return null;
|
|
60652
61366
|
}
|
|
60653
|
-
const src = normalizeMediaField(item.src, site.
|
|
61367
|
+
const src = normalizeMediaField(item.src, site.media_base_url);
|
|
60654
61368
|
const width = Number.isInteger(item.width) && item.width > 0 ? item.width : 0;
|
|
60655
61369
|
const height = Number.isInteger(item.height) && item.height > 0 ? item.height : 0;
|
|
60656
61370
|
if (!src || !width || !height) {
|
|
@@ -60688,11 +61402,11 @@ function deriveManagedMedia(src, mediaRegistry, site) {
|
|
|
60688
61402
|
};
|
|
60689
61403
|
}
|
|
60690
61404
|
function buildResponsiveImageSrcset(media, site) {
|
|
60691
|
-
if (site.
|
|
61405
|
+
if (site.media_delivery_mode !== "media_domain") {
|
|
60692
61406
|
return "";
|
|
60693
61407
|
}
|
|
60694
|
-
const
|
|
60695
|
-
if (!
|
|
61408
|
+
const media_base_url = normalizeOptionalString(site.media_base_url);
|
|
61409
|
+
if (!media_base_url || !isUrlUnderMediaBase(media.src, media_base_url) || !isResponsiveRasterImage(media.src)) {
|
|
60696
61410
|
return "";
|
|
60697
61411
|
}
|
|
60698
61412
|
const widths = RESPONSIVE_IMAGE_WIDTHS.filter((width) => width <= media.width);
|
|
@@ -60712,10 +61426,10 @@ function buildResponsiveImageVariantUrl(src, width) {
|
|
|
60712
61426
|
return src;
|
|
60713
61427
|
}
|
|
60714
61428
|
}
|
|
60715
|
-
function isUrlUnderMediaBase(src,
|
|
61429
|
+
function isUrlUnderMediaBase(src, media_base_url) {
|
|
60716
61430
|
try {
|
|
60717
61431
|
const sourceUrl = new URL(src);
|
|
60718
|
-
const baseUrl = new URL(
|
|
61432
|
+
const baseUrl = new URL(media_base_url);
|
|
60719
61433
|
const basePath = baseUrl.pathname.endsWith("/") ? baseUrl.pathname : `${baseUrl.pathname}/`;
|
|
60720
61434
|
return sourceUrl.origin === baseUrl.origin && sourceUrl.pathname.startsWith(basePath);
|
|
60721
61435
|
} catch {
|
|
@@ -60748,34 +61462,30 @@ function normalizeCollections(collections) {
|
|
|
60748
61462
|
])
|
|
60749
61463
|
);
|
|
60750
61464
|
}
|
|
60751
|
-
function normalizeWidgetAreas(
|
|
60752
|
-
if (!
|
|
61465
|
+
function normalizeWidgetAreas(widget_areas, media_base_url) {
|
|
61466
|
+
if (!widget_areas || typeof widget_areas !== "object") {
|
|
60753
61467
|
return {};
|
|
60754
61468
|
}
|
|
60755
61469
|
return Object.fromEntries(
|
|
60756
|
-
Object.entries(
|
|
61470
|
+
Object.entries(widget_areas).map(([widgetAreaId, widgetArea]) => [
|
|
60757
61471
|
widgetAreaId,
|
|
60758
61472
|
{
|
|
60759
61473
|
...widgetArea,
|
|
60760
61474
|
name: normalizeNonEmptyString(widgetArea?.name, widgetAreaId),
|
|
60761
|
-
items: Array.isArray(widgetArea?.items) ? widgetArea.items.map((item) => normalizeWidgetItem(item,
|
|
61475
|
+
items: Array.isArray(widgetArea?.items) ? widgetArea.items.map((item) => normalizeWidgetItem(item, media_base_url)) : []
|
|
60762
61476
|
}
|
|
60763
61477
|
])
|
|
60764
61478
|
);
|
|
60765
61479
|
}
|
|
60766
61480
|
function normalizeSiteFooter(footer) {
|
|
60767
61481
|
const source = footer && typeof footer === "object" && !Array.isArray(footer) ? footer : {};
|
|
60768
|
-
const attribution = source.attribution && typeof source.attribution === "object" && !Array.isArray(source.attribution) ? source.attribution : {};
|
|
60769
61482
|
return {
|
|
60770
61483
|
...source,
|
|
60771
61484
|
copyright_text: normalizeOptionalString(source.copyright_text),
|
|
60772
|
-
attribution:
|
|
60773
|
-
...attribution,
|
|
60774
|
-
enabled: attribution.enabled !== false
|
|
60775
|
-
}
|
|
61485
|
+
attribution: source.attribution !== false
|
|
60776
61486
|
};
|
|
60777
61487
|
}
|
|
60778
|
-
function normalizeWidgetItem(item,
|
|
61488
|
+
function normalizeWidgetItem(item, media_base_url) {
|
|
60779
61489
|
const normalizedItem = {
|
|
60780
61490
|
...item,
|
|
60781
61491
|
title: typeof item?.title === "string" ? item.title.trim() : ""
|
|
@@ -60785,7 +61495,7 @@ function normalizeWidgetItem(item, mediaBaseUrl) {
|
|
|
60785
61495
|
...normalizedItem,
|
|
60786
61496
|
settings: {
|
|
60787
61497
|
...item.settings,
|
|
60788
|
-
avatar: normalizeMediaField(item.settings.avatar,
|
|
61498
|
+
avatar: normalizeMediaField(item.settings.avatar, media_base_url)
|
|
60789
61499
|
}
|
|
60790
61500
|
};
|
|
60791
61501
|
}
|
|
@@ -60844,19 +61554,19 @@ function normalizeFrontPage(frontPage) {
|
|
|
60844
61554
|
...type === "standalone_html" ? { html: normalizeOptionalRawString(frontPage.html) } : {}
|
|
60845
61555
|
};
|
|
60846
61556
|
}
|
|
60847
|
-
function normalizePostIndex(
|
|
60848
|
-
if (!
|
|
61557
|
+
function normalizePostIndex(post_index) {
|
|
61558
|
+
if (!post_index || typeof post_index !== "object") {
|
|
60849
61559
|
return { ...DEFAULT_POST_INDEX };
|
|
60850
61560
|
}
|
|
60851
61561
|
return {
|
|
60852
|
-
enabled:
|
|
60853
|
-
path: normalizeNonEmptyString(
|
|
60854
|
-
paginate:
|
|
61562
|
+
enabled: post_index.enabled !== false,
|
|
61563
|
+
path: normalizeNonEmptyString(post_index.path, DEFAULT_POST_INDEX.path),
|
|
61564
|
+
paginate: post_index.paginate !== false
|
|
60855
61565
|
};
|
|
60856
61566
|
}
|
|
60857
61567
|
function createRenderData(previewData, themeMetadata = {}) {
|
|
60858
61568
|
const themeSupportsComments = themeMetadata?.features?.comments === true;
|
|
60859
|
-
const themeSupportsPostIndex = themeMetadata?.features?.
|
|
61569
|
+
const themeSupportsPostIndex = themeMetadata?.features?.post_index !== false;
|
|
60860
61570
|
const authorsById = new Map(previewData.content.authors.map((author) => [author.id, author]));
|
|
60861
61571
|
const categoriesBySlug = new Map(previewData.content.categories.map((category) => [category.slug, category]));
|
|
60862
61572
|
const tagsBySlug = new Map(previewData.content.tags.map((tag) => [tag.slug, tag]));
|
|
@@ -60864,7 +61574,8 @@ function createRenderData(previewData, themeMetadata = {}) {
|
|
|
60864
61574
|
const tagPostsBySlug = /* @__PURE__ */ new Map();
|
|
60865
61575
|
const categoryCountBySlug = /* @__PURE__ */ new Map();
|
|
60866
61576
|
const tagCountBySlug = /* @__PURE__ */ new Map();
|
|
60867
|
-
|
|
61577
|
+
const discoverableSourcePosts = previewData.content.posts.filter((post) => !isDelistedDocument(post));
|
|
61578
|
+
for (const post of discoverableSourcePosts) {
|
|
60868
61579
|
for (const slug of post.category_slugs) {
|
|
60869
61580
|
pushToSlugMap(categoryPostsBySlug, slug, post);
|
|
60870
61581
|
categoryCountBySlug.set(slug, (categoryCountBySlug.get(slug) || 0) + 1);
|
|
@@ -60875,45 +61586,54 @@ function createRenderData(previewData, themeMetadata = {}) {
|
|
|
60875
61586
|
}
|
|
60876
61587
|
}
|
|
60877
61588
|
const preparedPosts = previewData.content.posts.map((post) => preparePost(post, previewData.site, authorsById, categoriesBySlug, tagsBySlug, themeSupportsComments));
|
|
60878
|
-
const
|
|
61589
|
+
const discoverablePreparedPosts = preparedPosts.filter((post) => !isDelistedDocument(post));
|
|
61590
|
+
const adjacentPostsBySlug = new Map(
|
|
61591
|
+
discoverablePreparedPosts.map((post, index) => [post.slug, {
|
|
61592
|
+
prev: index > 0 ? buildAdjacentPostSummary(discoverablePreparedPosts[index - 1]) : null,
|
|
61593
|
+
next: index < discoverablePreparedPosts.length - 1 ? buildAdjacentPostSummary(discoverablePreparedPosts[index + 1]) : null
|
|
61594
|
+
}])
|
|
61595
|
+
);
|
|
61596
|
+
const posts = preparedPosts.map((post) => ({
|
|
60879
61597
|
...post,
|
|
60880
|
-
prev:
|
|
60881
|
-
next:
|
|
61598
|
+
prev: adjacentPostsBySlug.get(post.slug)?.prev || null,
|
|
61599
|
+
next: adjacentPostsBySlug.get(post.slug)?.next || null
|
|
60882
61600
|
}));
|
|
60883
61601
|
const pages = previewData.content.pages.map((page) => preparePage(page, previewData.site));
|
|
60884
61602
|
const postBySlug = new Map(posts.map((post) => [post.slug, post]));
|
|
60885
61603
|
const pageBySlug = new Map(pages.map((page) => [page.slug, page]));
|
|
60886
61604
|
const frontPage = previewData.site.front_page;
|
|
60887
|
-
const
|
|
60888
|
-
|
|
60889
|
-
const
|
|
60890
|
-
const
|
|
60891
|
-
|
|
61605
|
+
const collections = resolveCollections(previewData.collections, postBySlug, pageBySlug, frontPage);
|
|
61606
|
+
attachCollectionCursors(posts, pages, collections);
|
|
61607
|
+
const post_index = previewData.site.post_index;
|
|
61608
|
+
const effectivePostIndexEnabled = post_index.enabled !== false && themeSupportsPostIndex;
|
|
61609
|
+
const effectivePostIndexPaginate = effectivePostIndexEnabled && post_index.paginate !== false;
|
|
61610
|
+
const post_indexBasePath = normalizeRoutePath(post_index.path || DEFAULT_POST_INDEX.path);
|
|
61611
|
+
if (frontPage.type !== "theme_index" && effectivePostIndexEnabled && post_indexBasePath === "/") {
|
|
60892
61612
|
throw new Error('Invalid front page configuration: site.front_page occupies "/" so site.post_index.path must not be "/". Set site.post_index.path to a non-root path or disable site.post_index.');
|
|
60893
61613
|
}
|
|
60894
|
-
const frontPageRoute = buildFrontPageRoute(frontPage, pages, effectivePostIndexEnabled,
|
|
61614
|
+
const frontPageRoute = buildFrontPageRoute(frontPage, pages, effectivePostIndexEnabled, post_indexBasePath);
|
|
60895
61615
|
const pageFrontPageSlug = frontPage.type === "page" ? frontPage.page_slug : "";
|
|
60896
61616
|
const preparedPages = pageFrontPageSlug ? pages.filter((page) => page.slug !== pageFrontPageSlug) : pages;
|
|
60897
61617
|
return {
|
|
60898
61618
|
posts,
|
|
60899
61619
|
pages: preparedPages,
|
|
60900
61620
|
postBySlug,
|
|
60901
|
-
collections
|
|
61621
|
+
collections,
|
|
60902
61622
|
taxonomies: buildGlobalTaxonomies(previewData, categoryCountBySlug, tagCountBySlug),
|
|
60903
61623
|
frontPageRoute,
|
|
60904
61624
|
indexRoutes: buildPostIndexRoutes({
|
|
60905
61625
|
enabled: effectivePostIndexEnabled,
|
|
60906
61626
|
paginate: effectivePostIndexPaginate,
|
|
60907
|
-
items:
|
|
60908
|
-
|
|
60909
|
-
basePath:
|
|
61627
|
+
items: discoverableSourcePosts,
|
|
61628
|
+
posts_per_page: previewData.site.posts_per_page,
|
|
61629
|
+
basePath: post_indexBasePath,
|
|
60910
61630
|
outputStyle: previewData.site.permalinks.output_style,
|
|
60911
61631
|
postBySlug,
|
|
60912
61632
|
frontPage
|
|
60913
61633
|
}),
|
|
60914
61634
|
archiveRoutes: buildPaginatedCollection({
|
|
60915
|
-
items:
|
|
60916
|
-
|
|
61635
|
+
items: discoverableSourcePosts,
|
|
61636
|
+
posts_per_page: previewData.site.posts_per_page,
|
|
60917
61637
|
basePath: "/archive/",
|
|
60918
61638
|
outputStyle: previewData.site.permalinks.output_style
|
|
60919
61639
|
}).map((entry) => ({
|
|
@@ -60929,7 +61649,7 @@ function createRenderData(previewData, themeMetadata = {}) {
|
|
|
60929
61649
|
items: previewData.content.categories,
|
|
60930
61650
|
postsBySlug: categoryPostsBySlug,
|
|
60931
61651
|
postBySlug,
|
|
60932
|
-
|
|
61652
|
+
posts_per_page: previewData.site.posts_per_page,
|
|
60933
61653
|
outputStyle: previewData.site.permalinks.output_style,
|
|
60934
61654
|
buildBasePath: (category) => resolvePermalink(previewData.site, "categories", category).path,
|
|
60935
61655
|
renderExtras: (category) => ({
|
|
@@ -60940,7 +61660,7 @@ function createRenderData(previewData, themeMetadata = {}) {
|
|
|
60940
61660
|
items: previewData.content.tags,
|
|
60941
61661
|
postsBySlug: tagPostsBySlug,
|
|
60942
61662
|
postBySlug,
|
|
60943
|
-
|
|
61663
|
+
posts_per_page: previewData.site.posts_per_page,
|
|
60944
61664
|
outputStyle: previewData.site.permalinks.output_style,
|
|
60945
61665
|
buildBasePath: (tag) => resolvePermalink(previewData.site, "tags", tag).path,
|
|
60946
61666
|
renderExtras: (tag) => ({
|
|
@@ -60960,15 +61680,19 @@ function resolveCollections(collections, postBySlug, pageBySlug, frontPage) {
|
|
|
60960
61680
|
return {};
|
|
60961
61681
|
}
|
|
60962
61682
|
return Object.fromEntries(
|
|
60963
|
-
Object.entries(collections).map(([collectionId, collection]) =>
|
|
60964
|
-
collectionId,
|
|
60965
|
-
|
|
60966
|
-
|
|
60967
|
-
|
|
60968
|
-
|
|
60969
|
-
|
|
60970
|
-
|
|
60971
|
-
|
|
61683
|
+
Object.entries(collections).map(([collectionId, collection]) => {
|
|
61684
|
+
const items = resolveCollectionItems(collectionId, collection?.items, postBySlug, pageBySlug, frontPage);
|
|
61685
|
+
return [
|
|
61686
|
+
collectionId,
|
|
61687
|
+
{
|
|
61688
|
+
id: collectionId,
|
|
61689
|
+
title: normalizeOptionalString(collection?.title),
|
|
61690
|
+
description: normalizeOptionalString(collection?.description),
|
|
61691
|
+
count: items.length,
|
|
61692
|
+
items
|
|
61693
|
+
}
|
|
61694
|
+
];
|
|
61695
|
+
})
|
|
60972
61696
|
);
|
|
60973
61697
|
}
|
|
60974
61698
|
function resolveCollectionItems(collectionId, items, postBySlug, pageBySlug, frontPage) {
|
|
@@ -61007,12 +61731,57 @@ function buildCollectionPageSummary(page, frontPage) {
|
|
|
61007
61731
|
excerpt: page.excerpt || "",
|
|
61008
61732
|
featured_image: page.featured_image || "",
|
|
61009
61733
|
...page.featured_media ? { featured_media: { ...page.featured_media } } : {},
|
|
61010
|
-
meta: page.meta
|
|
61734
|
+
meta: page.meta,
|
|
61735
|
+
data: page.data
|
|
61736
|
+
};
|
|
61737
|
+
}
|
|
61738
|
+
function attachCollectionCursors(posts, pages, collections) {
|
|
61739
|
+
const postTargets = new Map(posts.map((post) => [post.slug, post]));
|
|
61740
|
+
const pageTargets = new Map(pages.map((page) => [page.slug, page]));
|
|
61741
|
+
for (const [collectionId, collection] of Object.entries(collections || {})) {
|
|
61742
|
+
const items = Array.isArray(collection.items) ? collection.items : [];
|
|
61743
|
+
items.forEach((item, index) => {
|
|
61744
|
+
const target = item.type === "post" ? postTargets.get(item.slug) : item.type === "page" ? pageTargets.get(item.slug) : null;
|
|
61745
|
+
if (!target) {
|
|
61746
|
+
return;
|
|
61747
|
+
}
|
|
61748
|
+
target.collection_cursors = target.collection_cursors || {};
|
|
61749
|
+
target.collection_cursors[collectionId] = buildCollectionCursor(collectionId, collection, items, index);
|
|
61750
|
+
});
|
|
61751
|
+
}
|
|
61752
|
+
}
|
|
61753
|
+
function buildCollectionCursor(collectionId, collection, items, index) {
|
|
61754
|
+
const count = items.length;
|
|
61755
|
+
return {
|
|
61756
|
+
collection_id: collectionId,
|
|
61757
|
+
collection_title: collection.title || "",
|
|
61758
|
+
index,
|
|
61759
|
+
position: index + 1,
|
|
61760
|
+
count,
|
|
61761
|
+
first: index === 0,
|
|
61762
|
+
last: index === count - 1,
|
|
61763
|
+
prev: index > 0 ? buildCollectionCursorItemSummary(items[index - 1]) : null,
|
|
61764
|
+
next: index < count - 1 ? buildCollectionCursorItemSummary(items[index + 1]) : null
|
|
61765
|
+
};
|
|
61766
|
+
}
|
|
61767
|
+
function buildCollectionCursorItemSummary(item) {
|
|
61768
|
+
if (!item) {
|
|
61769
|
+
return null;
|
|
61770
|
+
}
|
|
61771
|
+
return {
|
|
61772
|
+
type: item.type,
|
|
61773
|
+
title: item.title,
|
|
61774
|
+
slug: item.slug,
|
|
61775
|
+
url: item.url,
|
|
61776
|
+
excerpt: item.excerpt || "",
|
|
61777
|
+
featured_image: item.featured_image || "",
|
|
61778
|
+
meta: item.meta,
|
|
61779
|
+
data: item.data
|
|
61011
61780
|
};
|
|
61012
61781
|
}
|
|
61013
|
-
function buildFrontPageRoute(frontPage, pages, effectivePostIndexEnabled,
|
|
61782
|
+
function buildFrontPageRoute(frontPage, pages, effectivePostIndexEnabled, post_indexBasePath) {
|
|
61014
61783
|
if (frontPage.type === "theme_index") {
|
|
61015
|
-
if (effectivePostIndexEnabled &&
|
|
61784
|
+
if (effectivePostIndexEnabled && post_indexBasePath === "/") {
|
|
61016
61785
|
return null;
|
|
61017
61786
|
}
|
|
61018
61787
|
return {
|
|
@@ -61050,7 +61819,7 @@ function buildPostIndexRoutes(options2) {
|
|
|
61050
61819
|
return [];
|
|
61051
61820
|
}
|
|
61052
61821
|
if (!options2.paginate) {
|
|
61053
|
-
const items = options2.items.slice(0, options2.
|
|
61822
|
+
const items = options2.items.slice(0, options2.posts_per_page);
|
|
61054
61823
|
return [{
|
|
61055
61824
|
path: options2.basePath,
|
|
61056
61825
|
route_type: "post_index",
|
|
@@ -61064,7 +61833,7 @@ function buildPostIndexRoutes(options2) {
|
|
|
61064
61833
|
}
|
|
61065
61834
|
return buildPaginatedCollection({
|
|
61066
61835
|
items: options2.items,
|
|
61067
|
-
|
|
61836
|
+
posts_per_page: options2.posts_per_page,
|
|
61068
61837
|
basePath: options2.basePath,
|
|
61069
61838
|
outputStyle: options2.outputStyle
|
|
61070
61839
|
}).map((entry) => ({
|
|
@@ -61143,7 +61912,7 @@ function resolveWidgetItem(item, previewData, renderData, widgetAreaId, index) {
|
|
|
61143
61912
|
}
|
|
61144
61913
|
function resolveRecentPostsWidget(baseWidget, settings, renderData) {
|
|
61145
61914
|
const limit = clampInteger(settings?.limit, 5, 1, 20);
|
|
61146
|
-
const items = renderData.posts.slice(0, limit).map((post) => ({
|
|
61915
|
+
const items = renderData.posts.filter((post) => !isDelistedDocument(post)).slice(0, limit).map((post) => ({
|
|
61147
61916
|
title: post.title,
|
|
61148
61917
|
url: `/posts/${encodeSlugSegment(post.slug)}/`,
|
|
61149
61918
|
published_at: post.published_at,
|
|
@@ -61312,7 +62081,9 @@ function preparePost(post, site, authorsById, categoriesBySlug, tagsBySlug, them
|
|
|
61312
62081
|
featured_image: post.featured_image,
|
|
61313
62082
|
...post.featured_media ? { featured_media: { ...post.featured_media } } : {},
|
|
61314
62083
|
meta: post.meta,
|
|
62084
|
+
data: post.data,
|
|
61315
62085
|
status: post.status,
|
|
62086
|
+
discoverability: post.discoverability,
|
|
61316
62087
|
allow_comments: post.allow_comments,
|
|
61317
62088
|
category_slugs: post.category_slugs,
|
|
61318
62089
|
tag_slugs: post.tag_slugs,
|
|
@@ -61329,7 +62100,7 @@ function preparePost(post, site, authorsById, categoriesBySlug, tagsBySlug, them
|
|
|
61329
62100
|
published_at: formatTimestamp(post.published_at_iso, site),
|
|
61330
62101
|
updated_at: formatTimestamp(post.updated_at_iso, site),
|
|
61331
62102
|
reading_time: calculateReadingTime(renderedDocument.html),
|
|
61332
|
-
comments_enabled: themeSupportsComments && site.
|
|
62103
|
+
comments_enabled: themeSupportsComments && site.disallow_comments !== true && post.allow_comments === true
|
|
61333
62104
|
};
|
|
61334
62105
|
}
|
|
61335
62106
|
function buildCommentPolicyManifest(posts) {
|
|
@@ -61348,7 +62119,7 @@ function buildTaxonomyRoutes(options2) {
|
|
|
61348
62119
|
}
|
|
61349
62120
|
const paginated = buildPaginatedCollection({
|
|
61350
62121
|
items: matchedPosts,
|
|
61351
|
-
|
|
62122
|
+
posts_per_page: options2.posts_per_page,
|
|
61352
62123
|
basePath: options2.buildBasePath(item),
|
|
61353
62124
|
outputStyle: options2.outputStyle
|
|
61354
62125
|
});
|
|
@@ -61369,13 +62140,13 @@ function buildTaxonomyRoutes(options2) {
|
|
|
61369
62140
|
function buildPaginatedCollection(options2) {
|
|
61370
62141
|
const basePath = normalizePaginationBasePath(options2.basePath);
|
|
61371
62142
|
const outputStyle = PERMALINK_OUTPUT_STYLES.has(options2.outputStyle) ? options2.outputStyle : DEFAULT_PERMALINKS.output_style;
|
|
61372
|
-
const
|
|
62143
|
+
const posts_per_page = Number.isInteger(options2.posts_per_page) && options2.posts_per_page > 0 ? options2.posts_per_page : DEFAULT_POSTS_PER_PAGE;
|
|
61373
62144
|
const totalPosts = options2.items.length;
|
|
61374
|
-
const totalPages = Math.max(1, Math.ceil(totalPosts /
|
|
62145
|
+
const totalPages = Math.max(1, Math.ceil(totalPosts / posts_per_page));
|
|
61375
62146
|
const pages = [];
|
|
61376
62147
|
for (let page = 1; page <= totalPages; page += 1) {
|
|
61377
|
-
const start = (page - 1) *
|
|
61378
|
-
const end = start +
|
|
62148
|
+
const start = (page - 1) * posts_per_page;
|
|
62149
|
+
const end = start + posts_per_page;
|
|
61379
62150
|
pages.push({
|
|
61380
62151
|
path: buildPaginatedPath(basePath, page),
|
|
61381
62152
|
page,
|
|
@@ -61523,6 +62294,8 @@ function buildStructuredPostSummary(post) {
|
|
|
61523
62294
|
reading_time: post.reading_time,
|
|
61524
62295
|
featured_image: post.featured_image,
|
|
61525
62296
|
...post.featured_media ? { featured_media: { ...post.featured_media } } : {},
|
|
62297
|
+
meta: post.meta,
|
|
62298
|
+
data: post.data,
|
|
61526
62299
|
author: {
|
|
61527
62300
|
display_name: post.author?.display_name || "",
|
|
61528
62301
|
avatar: post.author?.avatar || "",
|
|
@@ -61542,7 +62315,8 @@ function buildAdjacentPostSummary(post) {
|
|
|
61542
62315
|
url: post.url,
|
|
61543
62316
|
excerpt: post.excerpt,
|
|
61544
62317
|
published_at: post.published_at,
|
|
61545
|
-
published_at_iso: post.published_at_iso
|
|
62318
|
+
published_at_iso: post.published_at_iso,
|
|
62319
|
+
data: post.data
|
|
61546
62320
|
};
|
|
61547
62321
|
}
|
|
61548
62322
|
function buildArchiveGroups(posts, postBySlug) {
|
|
@@ -61615,40 +62389,22 @@ function formatArchiveLabel(date, site) {
|
|
|
61615
62389
|
function formatTimestamp(value, site) {
|
|
61616
62390
|
const date = toDate(value);
|
|
61617
62391
|
const locale = normalizeLocale(site.locale || DEFAULT_LOCALE);
|
|
61618
|
-
const
|
|
61619
|
-
const
|
|
62392
|
+
const dateStyle = DATETIME_STYLES.has(site.date_style) ? site.date_style : DEFAULT_DATE_STYLE;
|
|
62393
|
+
const timeStyle = DATETIME_STYLES.has(site.time_style) ? site.time_style : DEFAULT_TIME_STYLE;
|
|
61620
62394
|
const siteTimezone = normalizeNonEmptyString(site.timezone, DEFAULT_TIMEZONE);
|
|
61621
|
-
|
|
61622
|
-
|
|
61623
|
-
|
|
61624
|
-
|
|
61625
|
-
|
|
61626
|
-
}
|
|
61627
|
-
|
|
61628
|
-
|
|
61629
|
-
|
|
61630
|
-
|
|
61631
|
-
|
|
61632
|
-
|
|
61633
|
-
|
|
61634
|
-
formattedDate = `${month}/${day}/${year}`;
|
|
61635
|
-
} else if (dateFormat === "MMMM D, YYYY") {
|
|
61636
|
-
formattedDate = `${month} ${String(Number(day))}, ${year}`;
|
|
61637
|
-
}
|
|
61638
|
-
if (!timeFormat) {
|
|
61639
|
-
return formattedDate;
|
|
61640
|
-
}
|
|
61641
|
-
const timeParts = new Intl.DateTimeFormat(locale, {
|
|
61642
|
-
timeZone: siteTimezone,
|
|
61643
|
-
hour: "2-digit",
|
|
61644
|
-
minute: "2-digit",
|
|
61645
|
-
hour12: timeFormat === "hh:mm A"
|
|
61646
|
-
}).formatToParts(date);
|
|
61647
|
-
const hour = timeParts.find((part) => part.type === "hour")?.value || "";
|
|
61648
|
-
const minute = timeParts.find((part) => part.type === "minute")?.value || "";
|
|
61649
|
-
const dayPeriod = (timeParts.find((part) => part.type === "dayPeriod")?.value || "").toUpperCase();
|
|
61650
|
-
const formattedTime = timeFormat === "hh:mm A" ? `${hour}:${minute}${dayPeriod ? ` ${dayPeriod}` : ""}` : `${hour}:${minute}`;
|
|
61651
|
-
return `${formattedDate} ${formattedTime}`.trim();
|
|
62395
|
+
if (dateStyle === "none" && timeStyle === "none") {
|
|
62396
|
+
return "";
|
|
62397
|
+
}
|
|
62398
|
+
const options2 = {
|
|
62399
|
+
timeZone: siteTimezone
|
|
62400
|
+
};
|
|
62401
|
+
if (dateStyle !== "none") {
|
|
62402
|
+
options2.dateStyle = dateStyle;
|
|
62403
|
+
}
|
|
62404
|
+
if (timeStyle !== "none") {
|
|
62405
|
+
options2.timeStyle = timeStyle;
|
|
62406
|
+
}
|
|
62407
|
+
return new Intl.DateTimeFormat(locale, options2).format(date);
|
|
61652
62408
|
}
|
|
61653
62409
|
function calculateReadingTime(html) {
|
|
61654
62410
|
const plainText = String(html || "").replace(/<[^>]*>/g, " ");
|
|
@@ -61729,11 +62485,12 @@ async function normalizeAndValidateThemePackage(themePackage) {
|
|
|
61729
62485
|
...themePackage.metadata.author ? { author: themePackage.metadata.author } : {},
|
|
61730
62486
|
...themePackage.metadata.description ? { description: themePackage.metadata.description } : {},
|
|
61731
62487
|
...themePackage.metadata.thumbnail ? { thumbnail: themePackage.metadata.thumbnail } : {},
|
|
62488
|
+
...themePackage.metadata.links ? { links: themePackage.metadata.links } : {},
|
|
61732
62489
|
...themePackage.metadata.features ? { features: themePackage.metadata.features } : {},
|
|
61733
|
-
...themePackage.metadata.
|
|
61734
|
-
...themePackage.metadata.
|
|
61735
|
-
...themePackage.metadata.
|
|
61736
|
-
...themePackage.metadata.
|
|
62490
|
+
...themePackage.metadata.menu_slots ? { menu_slots: themePackage.metadata.menu_slots } : {},
|
|
62491
|
+
...themePackage.metadata.widget_areas ? { widget_areas: themePackage.metadata.widget_areas } : {},
|
|
62492
|
+
...themePackage.metadata.site_meta ? { site_meta: themePackage.metadata.site_meta } : {},
|
|
62493
|
+
...themePackage.metadata.collection_slots ? { collection_slots: themePackage.metadata.collection_slots } : {}
|
|
61737
62494
|
}));
|
|
61738
62495
|
for (const [templateName, templateContent] of themePackage.templates.entries()) {
|
|
61739
62496
|
fileMap.set(`${templateName}.html`, templateContent);
|
|
@@ -61746,7 +62503,7 @@ async function normalizeAndValidateThemePackage(themePackage) {
|
|
|
61746
62503
|
}
|
|
61747
62504
|
const validation = await validateThemeFiles(fileMap);
|
|
61748
62505
|
if (!validation.ok) {
|
|
61749
|
-
throw new Error(
|
|
62506
|
+
throw new Error(formatThemeValidationFailure(validation));
|
|
61750
62507
|
}
|
|
61751
62508
|
if (!validation.manifest) {
|
|
61752
62509
|
throw new Error("Theme validation failed: normalized manifest not available");
|
|
@@ -61758,6 +62515,55 @@ async function normalizeAndValidateThemePackage(themePackage) {
|
|
|
61758
62515
|
assets: themePackage.assets
|
|
61759
62516
|
};
|
|
61760
62517
|
}
|
|
62518
|
+
function formatThemeValidationFailure(validation) {
|
|
62519
|
+
const blocks = [
|
|
62520
|
+
[
|
|
62521
|
+
"Theme validation failed",
|
|
62522
|
+
`Errors: ${validation.errors.length}`,
|
|
62523
|
+
`Checked files: ${validation.checkedFiles}`
|
|
62524
|
+
].join("\n"),
|
|
62525
|
+
...validation.errors.map((issue3) => formatThemeValidationIssue(issue3))
|
|
62526
|
+
];
|
|
62527
|
+
return blocks.join("\n\n");
|
|
62528
|
+
}
|
|
62529
|
+
function formatThemeValidationIssue(issue3) {
|
|
62530
|
+
if (!issue3) {
|
|
62531
|
+
return "Reason: Unknown error";
|
|
62532
|
+
}
|
|
62533
|
+
const lines = [`ERROR ${issue3.code || "THEME_VALIDATION_ERROR"}`];
|
|
62534
|
+
const location = splitIssuePath(issue3.path);
|
|
62535
|
+
if (location.file) {
|
|
62536
|
+
lines.push(`File: ${location.file}`);
|
|
62537
|
+
}
|
|
62538
|
+
if (location.path) {
|
|
62539
|
+
lines.push(`Path: ${location.path}`);
|
|
62540
|
+
}
|
|
62541
|
+
if (Number.isInteger(issue3.line) && Number.isInteger(issue3.column)) {
|
|
62542
|
+
lines.push(`Line: ${issue3.line}, Column: ${issue3.column}`);
|
|
62543
|
+
}
|
|
62544
|
+
if (issue3.category) {
|
|
62545
|
+
lines.push(`Category: ${issue3.category}`);
|
|
62546
|
+
}
|
|
62547
|
+
lines.push(`Reason: ${issue3.message || "Unknown error"}`);
|
|
62548
|
+
if (issue3.snippet) {
|
|
62549
|
+
const lineLabel = Number.isInteger(issue3.line) ? String(issue3.line) : "";
|
|
62550
|
+
lines.push("", `${lineLabel} | ${issue3.snippet.line}`, `${" ".repeat(lineLabel.length)} | ${issue3.snippet.pointer}`);
|
|
62551
|
+
}
|
|
62552
|
+
if (issue3.hint) {
|
|
62553
|
+
lines.push("", "Hint:", issue3.hint);
|
|
62554
|
+
}
|
|
62555
|
+
return lines.join("\n");
|
|
62556
|
+
}
|
|
62557
|
+
function splitIssuePath(issuePath) {
|
|
62558
|
+
const normalizedPath = String(issuePath || "");
|
|
62559
|
+
if (normalizedPath.startsWith("theme.json.")) {
|
|
62560
|
+
return {
|
|
62561
|
+
file: "theme.json",
|
|
62562
|
+
path: normalizedPath.slice("theme.json.".length)
|
|
62563
|
+
};
|
|
62564
|
+
}
|
|
62565
|
+
return { file: normalizedPath, path: "" };
|
|
62566
|
+
}
|
|
61761
62567
|
function normalizeThemePackageMetadata(sourceMetadata, manifest) {
|
|
61762
62568
|
return {
|
|
61763
62569
|
...manifest,
|
|
@@ -61827,6 +62633,7 @@ function buildPageMeta(site, options2 = {}) {
|
|
|
61827
62633
|
const ogType = normalizeNonEmptyString(options2.ogType, "website");
|
|
61828
62634
|
const publishedTime = normalizeOptionalString(options2.publishedTime);
|
|
61829
62635
|
const modifiedTime = normalizeOptionalString(options2.modifiedTime);
|
|
62636
|
+
const robotsNoindex = options2.robotsNoindex === true;
|
|
61830
62637
|
const meta = {
|
|
61831
62638
|
title: escapeHtml2(resolvedTitle),
|
|
61832
62639
|
description: resolvedDescription ? escapeHtml2(resolvedDescription) : "",
|
|
@@ -61838,7 +62645,8 @@ function buildPageMeta(site, options2 = {}) {
|
|
|
61838
62645
|
og_site_name: escapeHtml2(site.title),
|
|
61839
62646
|
og_image: ogImage ? escapeHtml2(ogImage) : "",
|
|
61840
62647
|
article_published_time: publishedTime ? escapeHtml2(publishedTime) : "",
|
|
61841
|
-
article_modified_time: modifiedTime ? escapeHtml2(modifiedTime) : ""
|
|
62648
|
+
article_modified_time: modifiedTime ? escapeHtml2(modifiedTime) : "",
|
|
62649
|
+
robots_noindex: robotsNoindex
|
|
61842
62650
|
};
|
|
61843
62651
|
return {
|
|
61844
62652
|
...meta,
|
|
@@ -61855,6 +62663,9 @@ function buildMetaHeadTags(meta) {
|
|
|
61855
62663
|
if (meta.description) {
|
|
61856
62664
|
tags.push(`<meta name="description" content="${meta.description}">`);
|
|
61857
62665
|
}
|
|
62666
|
+
if (meta.robots_noindex) {
|
|
62667
|
+
tags.push('<meta name="robots" content="noindex">');
|
|
62668
|
+
}
|
|
61858
62669
|
if (meta.canonical_url) {
|
|
61859
62670
|
tags.push(`<link rel="canonical" href="${meta.canonical_url}">`);
|
|
61860
62671
|
}
|
|
@@ -61895,7 +62706,7 @@ function resolveMetaImageUrl(image2) {
|
|
|
61895
62706
|
}
|
|
61896
62707
|
return "";
|
|
61897
62708
|
}
|
|
61898
|
-
function normalizeMediaField(value,
|
|
62709
|
+
function normalizeMediaField(value, media_base_url) {
|
|
61899
62710
|
if (value === void 0) {
|
|
61900
62711
|
return void 0;
|
|
61901
62712
|
}
|
|
@@ -61906,7 +62717,7 @@ function normalizeMediaField(value, mediaBaseUrl) {
|
|
|
61906
62717
|
if (isAbsoluteUrl(normalizedValue)) {
|
|
61907
62718
|
return normalizeAbsoluteUrl(normalizedValue, SAFE_MEDIA_PROTOCOLS);
|
|
61908
62719
|
}
|
|
61909
|
-
const normalizedBaseUrl = normalizeOptionalString(
|
|
62720
|
+
const normalizedBaseUrl = normalizeOptionalString(media_base_url);
|
|
61910
62721
|
if (!normalizedBaseUrl) {
|
|
61911
62722
|
return normalizedValue;
|
|
61912
62723
|
}
|
|
@@ -62112,6 +62923,7 @@ function assertPlannedOutputPathsSafe(state) {
|
|
|
62112
62923
|
COMMENT_POLICY_OUTPUT_PATH
|
|
62113
62924
|
];
|
|
62114
62925
|
if (state.options.generateSpecialFiles) {
|
|
62926
|
+
plannedPaths.push(SEARCH_INDEX_OUTPUT_PATH, SEARCH_ADAPTER_OUTPUT_PATH);
|
|
62115
62927
|
plannedPaths.push("404.html");
|
|
62116
62928
|
if (shouldGenerateRobotsTxt(state.options)) {
|
|
62117
62929
|
plannedPaths.push("robots.txt");
|
|
@@ -62191,6 +63003,7 @@ function sha256(content) {
|
|
|
62191
63003
|
}
|
|
62192
63004
|
function injectSiteCustomizations(html, state) {
|
|
62193
63005
|
let next = injectFaviconLinks(html, state.favicon);
|
|
63006
|
+
next = injectGeneratorMeta(next, state.exposeGenerator);
|
|
62194
63007
|
next = injectCustomCssAssetLink(next, state.customCssHref);
|
|
62195
63008
|
next = injectCustomHtml(next, state.customHtml);
|
|
62196
63009
|
return next;
|
|
@@ -62222,6 +63035,12 @@ function buildFaviconLinks(favicon) {
|
|
|
62222
63035
|
}
|
|
62223
63036
|
return lines.join("\n");
|
|
62224
63037
|
}
|
|
63038
|
+
function injectGeneratorMeta(html, exposeGenerator) {
|
|
63039
|
+
if (exposeGenerator === false) {
|
|
63040
|
+
return html;
|
|
63041
|
+
}
|
|
63042
|
+
return html.replace("</head>", ' <meta name="generator" content="ZeroPress">\n</head>');
|
|
63043
|
+
}
|
|
62225
63044
|
function injectCustomCssAssetLink(html, href) {
|
|
62226
63045
|
if (!normalizeOptionalString(href)) {
|
|
62227
63046
|
return html;
|
|
@@ -62243,9 +63062,383 @@ function injectCustomHtml(html, customHtml) {
|
|
|
62243
63062
|
}
|
|
62244
63063
|
return next;
|
|
62245
63064
|
}
|
|
62246
|
-
function
|
|
63065
|
+
function buildSearchIndexJson(state) {
|
|
63066
|
+
return `${JSON.stringify(buildSearchIndexItems(state), null, 2)}
|
|
63067
|
+
`;
|
|
63068
|
+
}
|
|
63069
|
+
function buildSearchIndexItems(state) {
|
|
63070
|
+
const posts = state.renderData.posts.filter((post) => post.status === "published" && !isDelistedDocument(post)).map((post) => ({
|
|
63071
|
+
id: `post:${post.slug}`,
|
|
63072
|
+
type: "post",
|
|
63073
|
+
title: post.title,
|
|
63074
|
+
url: post.url,
|
|
63075
|
+
excerpt: normalizeSearchText(post.excerpt),
|
|
63076
|
+
headings: buildSearchHeadings(post.toc),
|
|
63077
|
+
categories: Array.isArray(post.categories) ? post.categories.map((category) => category.name).filter(Boolean) : [],
|
|
63078
|
+
tags: Array.isArray(post.tags) ? post.tags.map((tag) => tag.name).filter(Boolean) : [],
|
|
63079
|
+
published_at_iso: normalizeIsoTimestamp(post.published_at_iso),
|
|
63080
|
+
updated_at_iso: normalizeIsoTimestamp(post.updated_at_iso),
|
|
63081
|
+
content_text: htmlToSearchText(post.html)
|
|
63082
|
+
}));
|
|
63083
|
+
const frontPagePage = state.renderData.frontPageRoute?.front_page_type === "page" ? state.renderData.frontPageRoute.page : null;
|
|
63084
|
+
const frontPageItems = frontPagePage && frontPagePage.status === "published" && !isDelistedDocument(frontPagePage) ? [buildSearchPageItem(frontPagePage, "/")] : [];
|
|
63085
|
+
const pageItems = state.renderData.pages.filter((page) => page.status === "published" && !isDelistedDocument(page)).map((page) => buildSearchPageItem(page, page.url));
|
|
63086
|
+
return [...posts, ...frontPageItems, ...pageItems];
|
|
63087
|
+
}
|
|
63088
|
+
function buildSearchPageItem(page, url) {
|
|
63089
|
+
return {
|
|
63090
|
+
id: `page:${page.slug}`,
|
|
63091
|
+
type: "page",
|
|
63092
|
+
title: page.title,
|
|
63093
|
+
url,
|
|
63094
|
+
excerpt: normalizeSearchText(page.excerpt),
|
|
63095
|
+
headings: buildSearchHeadings(page.toc),
|
|
63096
|
+
categories: [],
|
|
63097
|
+
tags: [],
|
|
63098
|
+
published_at_iso: "",
|
|
63099
|
+
updated_at_iso: "",
|
|
63100
|
+
content_text: htmlToSearchText(page.html)
|
|
63101
|
+
};
|
|
63102
|
+
}
|
|
63103
|
+
function buildSearchHeadings(toc) {
|
|
63104
|
+
return Array.isArray(toc) ? toc.map((item) => normalizeSearchText(item?.title)).filter(Boolean) : [];
|
|
63105
|
+
}
|
|
63106
|
+
function htmlToSearchText(html) {
|
|
63107
|
+
return normalizeSearchText(decodeHtmlEntities(
|
|
63108
|
+
String(html || "").replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, " ").replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, " ").replace(/<!--[\s\S]*?-->/g, " ").replace(/<[^>]+>/g, " ")
|
|
63109
|
+
));
|
|
63110
|
+
}
|
|
63111
|
+
function decodeHtmlEntities(value) {
|
|
63112
|
+
const namedEntities = {
|
|
63113
|
+
amp: "&",
|
|
63114
|
+
lt: "<",
|
|
63115
|
+
gt: ">",
|
|
63116
|
+
quot: '"',
|
|
63117
|
+
apos: "'",
|
|
63118
|
+
nbsp: " "
|
|
63119
|
+
};
|
|
63120
|
+
return String(value || "").replace(/&(#x[0-9a-fA-F]+|#\d+|[a-zA-Z][a-zA-Z0-9]+);/g, (match2, entity2) => {
|
|
63121
|
+
if (entity2.startsWith("#x")) {
|
|
63122
|
+
const codePoint = Number.parseInt(entity2.slice(2), 16);
|
|
63123
|
+
return Number.isFinite(codePoint) ? String.fromCodePoint(codePoint) : match2;
|
|
63124
|
+
}
|
|
63125
|
+
if (entity2.startsWith("#")) {
|
|
63126
|
+
const codePoint = Number.parseInt(entity2.slice(1), 10);
|
|
63127
|
+
return Number.isFinite(codePoint) ? String.fromCodePoint(codePoint) : match2;
|
|
63128
|
+
}
|
|
63129
|
+
return Object.prototype.hasOwnProperty.call(namedEntities, entity2) ? namedEntities[entity2] : match2;
|
|
63130
|
+
});
|
|
63131
|
+
}
|
|
63132
|
+
function normalizeSearchText(value) {
|
|
63133
|
+
return String(value || "").replace(/\s+/g, " ").trim();
|
|
63134
|
+
}
|
|
63135
|
+
function buildSearchAdapterJs() {
|
|
63136
|
+
const fieldWeightsJson = JSON.stringify(SEARCH_FIELD_WEIGHTS, null, 2);
|
|
63137
|
+
return `const FIELD_WEIGHTS = ${fieldWeightsJson};
|
|
63138
|
+
const FIELD_NAMES = Object.keys(FIELD_WEIGHTS);
|
|
63139
|
+
const RECENCY_BOOST_MAX = ${SEARCH_RECENCY_BOOST_MAX};
|
|
63140
|
+
const DEFAULT_LIMIT = 20;
|
|
63141
|
+
const BM25_K1 = 1.2;
|
|
63142
|
+
const BM25_B = 0.75;
|
|
63143
|
+
|
|
63144
|
+
let preparedIndexPromise;
|
|
63145
|
+
|
|
63146
|
+
export async function preload() {
|
|
63147
|
+
await loadPreparedIndex();
|
|
63148
|
+
}
|
|
63149
|
+
|
|
63150
|
+
export async function search(query, options = {}) {
|
|
63151
|
+
const prepared = await loadPreparedIndex();
|
|
63152
|
+
const terms = tokenize(query);
|
|
63153
|
+
const phrase = normalizeText(query);
|
|
63154
|
+
if (terms.length === 0 && !phrase) {
|
|
63155
|
+
return { results: [] };
|
|
63156
|
+
}
|
|
63157
|
+
|
|
63158
|
+
const hits = [];
|
|
63159
|
+
for (const document of prepared.documents) {
|
|
63160
|
+
const score = scoreDocument(document, terms, phrase, prepared);
|
|
63161
|
+
if (score > 0) {
|
|
63162
|
+
hits.push({ document, score });
|
|
63163
|
+
}
|
|
63164
|
+
}
|
|
63165
|
+
|
|
63166
|
+
const limit = normalizeLimit(options.limit);
|
|
63167
|
+
hits.sort((left, right) => right.score - left.score || left.document.raw.title.localeCompare(right.document.raw.title));
|
|
63168
|
+
|
|
63169
|
+
return {
|
|
63170
|
+
results: hits.slice(0, limit).map((hit) => ({
|
|
63171
|
+
id: hit.document.raw.id,
|
|
63172
|
+
score: Number(hit.score.toFixed(6)),
|
|
63173
|
+
data: async () => buildResultData(hit.document.raw, query),
|
|
63174
|
+
})),
|
|
63175
|
+
};
|
|
63176
|
+
}
|
|
63177
|
+
|
|
63178
|
+
async function loadPreparedIndex() {
|
|
63179
|
+
if (!preparedIndexPromise) {
|
|
63180
|
+
preparedIndexPromise = fetch(new URL('./search.json', import.meta.url))
|
|
63181
|
+
.then((response) => {
|
|
63182
|
+
if (!response.ok) {
|
|
63183
|
+
throw new Error('ZeroPress search index not found');
|
|
63184
|
+
}
|
|
63185
|
+
return response.json();
|
|
63186
|
+
})
|
|
63187
|
+
.then((items) => prepareIndex(Array.isArray(items) ? items : []));
|
|
63188
|
+
}
|
|
63189
|
+
|
|
63190
|
+
return preparedIndexPromise;
|
|
63191
|
+
}
|
|
63192
|
+
|
|
63193
|
+
function prepareIndex(items) {
|
|
63194
|
+
const documents = items.map((item) => prepareDocument(item));
|
|
63195
|
+
const documentFrequencies = new Map();
|
|
63196
|
+
const averageLengths = Object.fromEntries(FIELD_NAMES.map((fieldName) => [fieldName, 1]));
|
|
63197
|
+
const newestPostTime = documents.reduce((newest, document) => {
|
|
63198
|
+
if (document.raw.type !== 'post') {
|
|
63199
|
+
return newest;
|
|
63200
|
+
}
|
|
63201
|
+
return Math.max(newest, document.publishedTime || 0);
|
|
63202
|
+
}, 0);
|
|
63203
|
+
|
|
63204
|
+
for (const document of documents) {
|
|
63205
|
+
const seenTerms = new Set();
|
|
63206
|
+
for (const fieldName of FIELD_NAMES) {
|
|
63207
|
+
for (const term of document.fieldTokens[fieldName]) {
|
|
63208
|
+
seenTerms.add(term);
|
|
63209
|
+
}
|
|
63210
|
+
}
|
|
63211
|
+
for (const term of seenTerms) {
|
|
63212
|
+
documentFrequencies.set(term, (documentFrequencies.get(term) || 0) + 1);
|
|
63213
|
+
}
|
|
63214
|
+
}
|
|
63215
|
+
|
|
63216
|
+
for (const fieldName of FIELD_NAMES) {
|
|
63217
|
+
const total = documents.reduce((sum, document) => sum + document.fieldLengths[fieldName], 0);
|
|
63218
|
+
averageLengths[fieldName] = documents.length > 0 ? Math.max(1, total / documents.length) : 1;
|
|
63219
|
+
}
|
|
63220
|
+
|
|
63221
|
+
return {
|
|
63222
|
+
documents,
|
|
63223
|
+
documentFrequencies,
|
|
63224
|
+
averageLengths,
|
|
63225
|
+
documentCount: documents.length,
|
|
63226
|
+
newestPostTime,
|
|
63227
|
+
};
|
|
63228
|
+
}
|
|
63229
|
+
|
|
63230
|
+
function prepareDocument(item) {
|
|
63231
|
+
const raw = normalizeItem(item);
|
|
63232
|
+
const fields = {
|
|
63233
|
+
title: raw.title,
|
|
63234
|
+
headings: raw.headings.join(' '),
|
|
63235
|
+
tags: raw.tags.join(' '),
|
|
63236
|
+
categories: raw.categories.join(' '),
|
|
63237
|
+
excerpt: raw.excerpt,
|
|
63238
|
+
content_text: raw.content_text,
|
|
63239
|
+
};
|
|
63240
|
+
const fieldTexts = {};
|
|
63241
|
+
const fieldTokens = {};
|
|
63242
|
+
const fieldTermCounts = {};
|
|
63243
|
+
const fieldLengths = {};
|
|
63244
|
+
|
|
63245
|
+
for (const [fieldName, value] of Object.entries(fields)) {
|
|
63246
|
+
const normalizedText = normalizeText(value);
|
|
63247
|
+
const tokens = tokenize(normalizedText);
|
|
63248
|
+
fieldTexts[fieldName] = normalizedText;
|
|
63249
|
+
fieldTokens[fieldName] = tokens;
|
|
63250
|
+
fieldTermCounts[fieldName] = countTerms(tokens);
|
|
63251
|
+
fieldLengths[fieldName] = Math.max(1, tokens.length);
|
|
63252
|
+
}
|
|
63253
|
+
|
|
63254
|
+
return {
|
|
63255
|
+
raw,
|
|
63256
|
+
fieldTexts,
|
|
63257
|
+
fieldTokens,
|
|
63258
|
+
fieldTermCounts,
|
|
63259
|
+
fieldLengths,
|
|
63260
|
+
publishedTime: Date.parse(raw.published_at_iso) || 0,
|
|
63261
|
+
};
|
|
63262
|
+
}
|
|
63263
|
+
|
|
63264
|
+
function normalizeItem(item) {
|
|
63265
|
+
return {
|
|
63266
|
+
id: String(item && item.id || ''),
|
|
63267
|
+
type: item && item.type === 'page' ? 'page' : 'post',
|
|
63268
|
+
title: String(item && item.title || ''),
|
|
63269
|
+
url: String(item && item.url || ''),
|
|
63270
|
+
excerpt: String(item && item.excerpt || ''),
|
|
63271
|
+
headings: Array.isArray(item && item.headings) ? item.headings.map(String) : [],
|
|
63272
|
+
categories: Array.isArray(item && item.categories) ? item.categories.map(String) : [],
|
|
63273
|
+
tags: Array.isArray(item && item.tags) ? item.tags.map(String) : [],
|
|
63274
|
+
published_at_iso: String(item && item.published_at_iso || ''),
|
|
63275
|
+
updated_at_iso: String(item && item.updated_at_iso || ''),
|
|
63276
|
+
content_text: String(item && item.content_text || ''),
|
|
63277
|
+
};
|
|
63278
|
+
}
|
|
63279
|
+
|
|
63280
|
+
function scoreDocument(document, terms, phrase, prepared) {
|
|
63281
|
+
let score = 0;
|
|
63282
|
+
const uniqueTerms = Array.from(new Set(terms));
|
|
63283
|
+
|
|
63284
|
+
for (const term of uniqueTerms) {
|
|
63285
|
+
const documentFrequency = prepared.documentFrequencies.get(term) || 0;
|
|
63286
|
+
const idf = Math.log(1 + (prepared.documentCount - documentFrequency + 0.5) / (documentFrequency + 0.5));
|
|
63287
|
+
|
|
63288
|
+
for (const fieldName of FIELD_NAMES) {
|
|
63289
|
+
const termFrequency = document.fieldTermCounts[fieldName].get(term) || 0;
|
|
63290
|
+
if (termFrequency === 0) {
|
|
63291
|
+
continue;
|
|
63292
|
+
}
|
|
63293
|
+
|
|
63294
|
+
const fieldLength = document.fieldLengths[fieldName];
|
|
63295
|
+
const averageLength = prepared.averageLengths[fieldName];
|
|
63296
|
+
const denominator = termFrequency + BM25_K1 * (1 - BM25_B + BM25_B * (fieldLength / averageLength));
|
|
63297
|
+
score += FIELD_WEIGHTS[fieldName] * idf * ((termFrequency * (BM25_K1 + 1)) / denominator);
|
|
63298
|
+
}
|
|
63299
|
+
}
|
|
63300
|
+
|
|
63301
|
+
if (phrase && phrase.length > 1) {
|
|
63302
|
+
for (const fieldName of FIELD_NAMES) {
|
|
63303
|
+
if (document.fieldTexts[fieldName].includes(phrase)) {
|
|
63304
|
+
score += FIELD_WEIGHTS[fieldName] * 0.6;
|
|
63305
|
+
}
|
|
63306
|
+
}
|
|
63307
|
+
}
|
|
63308
|
+
|
|
63309
|
+
if (score <= 0) {
|
|
63310
|
+
return 0;
|
|
63311
|
+
}
|
|
63312
|
+
|
|
63313
|
+
return score * (1 + recencyBoost(document, prepared.newestPostTime));
|
|
63314
|
+
}
|
|
63315
|
+
|
|
63316
|
+
function recencyBoost(document, newestPostTime) {
|
|
63317
|
+
if (document.raw.type !== 'post' || !document.publishedTime || !newestPostTime) {
|
|
63318
|
+
return 0;
|
|
63319
|
+
}
|
|
63320
|
+
const ageMs = Math.max(0, newestPostTime - document.publishedTime);
|
|
63321
|
+
const halfLifeMs = 180 * 24 * 60 * 60 * 1000;
|
|
63322
|
+
return RECENCY_BOOST_MAX * Math.exp(-ageMs / halfLifeMs);
|
|
63323
|
+
}
|
|
63324
|
+
|
|
63325
|
+
function buildResultData(item, query) {
|
|
63326
|
+
const excerpt = buildExcerpt(item, query);
|
|
63327
|
+
return {
|
|
63328
|
+
url: item.url,
|
|
63329
|
+
excerpt,
|
|
63330
|
+
plain_excerpt: excerpt,
|
|
63331
|
+
meta: {
|
|
63332
|
+
title: item.title,
|
|
63333
|
+
type: item.type,
|
|
63334
|
+
published_at_iso: item.published_at_iso,
|
|
63335
|
+
updated_at_iso: item.updated_at_iso,
|
|
63336
|
+
categories: item.categories,
|
|
63337
|
+
tags: item.tags,
|
|
63338
|
+
},
|
|
63339
|
+
sub_results: [],
|
|
63340
|
+
};
|
|
63341
|
+
}
|
|
63342
|
+
|
|
63343
|
+
function buildExcerpt(item, query) {
|
|
63344
|
+
const explicitExcerpt = String(item.excerpt || '').trim();
|
|
63345
|
+
if (explicitExcerpt) {
|
|
63346
|
+
return explicitExcerpt;
|
|
63347
|
+
}
|
|
63348
|
+
|
|
63349
|
+
const text = String(item.content_text || '').replace(/\\s+/g, ' ').trim();
|
|
63350
|
+
if (!text) {
|
|
63351
|
+
return '';
|
|
63352
|
+
}
|
|
63353
|
+
|
|
63354
|
+
const normalizedText = normalizeText(text);
|
|
63355
|
+
const terms = tokenize(query);
|
|
63356
|
+
const firstMatch = terms.map((term) => normalizedText.indexOf(term)).filter((index) => index >= 0).sort((a, b) => a - b)[0];
|
|
63357
|
+
const start = Math.max(0, (firstMatch || 0) - 80);
|
|
63358
|
+
const end = Math.min(text.length, start + 180);
|
|
63359
|
+
const prefix = start > 0 ? '...' : '';
|
|
63360
|
+
const suffix = end < text.length ? '...' : '';
|
|
63361
|
+
return prefix + text.slice(start, end).trim() + suffix;
|
|
63362
|
+
}
|
|
63363
|
+
|
|
63364
|
+
function countTerms(tokens) {
|
|
63365
|
+
const counts = new Map();
|
|
63366
|
+
for (const token of tokens) {
|
|
63367
|
+
counts.set(token, (counts.get(token) || 0) + 1);
|
|
63368
|
+
}
|
|
63369
|
+
return counts;
|
|
63370
|
+
}
|
|
63371
|
+
|
|
63372
|
+
function tokenize(value) {
|
|
63373
|
+
const text = normalizeText(value);
|
|
63374
|
+
if (!text) {
|
|
63375
|
+
return [];
|
|
63376
|
+
}
|
|
63377
|
+
|
|
63378
|
+
const tokens = [];
|
|
63379
|
+
if (typeof Intl !== 'undefined' && typeof Intl.Segmenter === 'function') {
|
|
63380
|
+
try {
|
|
63381
|
+
const segmenter = new Intl.Segmenter(undefined, { granularity: 'word' });
|
|
63382
|
+
for (const part of segmenter.segment(text)) {
|
|
63383
|
+
if (part.isWordLike && isUsefulToken(part.segment)) {
|
|
63384
|
+
tokens.push(part.segment);
|
|
63385
|
+
}
|
|
63386
|
+
}
|
|
63387
|
+
} catch {
|
|
63388
|
+
// Fall through to regex tokenization.
|
|
63389
|
+
}
|
|
63390
|
+
}
|
|
63391
|
+
|
|
63392
|
+
for (const match of text.matchAll(/[\\p{Letter}\\p{Number}]+/gu)) {
|
|
63393
|
+
if (isUsefulToken(match[0])) {
|
|
63394
|
+
tokens.push(match[0]);
|
|
63395
|
+
}
|
|
63396
|
+
}
|
|
63397
|
+
|
|
63398
|
+
for (const match of text.matchAll(/[\\p{Script=Han}\\p{Script=Hiragana}\\p{Script=Katakana}\\p{Script=Hangul}]+/gu)) {
|
|
63399
|
+
tokens.push(...buildNgrams(match[0], 2));
|
|
63400
|
+
}
|
|
63401
|
+
|
|
63402
|
+
return tokens;
|
|
63403
|
+
}
|
|
63404
|
+
|
|
63405
|
+
function buildNgrams(value, size) {
|
|
63406
|
+
const normalized = Array.from(value);
|
|
63407
|
+
if (normalized.length <= size) {
|
|
63408
|
+
return isUsefulToken(value) ? [value] : [];
|
|
63409
|
+
}
|
|
63410
|
+
|
|
63411
|
+
const tokens = [];
|
|
63412
|
+
for (let index = 0; index <= normalized.length - size; index += 1) {
|
|
63413
|
+
tokens.push(normalized.slice(index, index + size).join(''));
|
|
63414
|
+
}
|
|
63415
|
+
tokens.push(value);
|
|
63416
|
+
return tokens;
|
|
63417
|
+
}
|
|
63418
|
+
|
|
63419
|
+
function isUsefulToken(value) {
|
|
63420
|
+
const token = String(value || '').trim();
|
|
63421
|
+
return token.length > 1 || /^\\d$/.test(token);
|
|
63422
|
+
}
|
|
63423
|
+
|
|
63424
|
+
function normalizeText(value) {
|
|
63425
|
+
return String(value || '')
|
|
63426
|
+
.normalize('NFKC')
|
|
63427
|
+
.toLowerCase()
|
|
63428
|
+
.replace(/[\\u2018\\u2019]/g, "'")
|
|
63429
|
+
.replace(/[_-]+/g, ' ')
|
|
63430
|
+
.replace(/\\s+/g, ' ')
|
|
63431
|
+
.trim();
|
|
63432
|
+
}
|
|
63433
|
+
|
|
63434
|
+
function normalizeLimit(value) {
|
|
63435
|
+
return Number.isInteger(value) && value > 0 ? Math.min(value, 100) : DEFAULT_LIMIT;
|
|
63436
|
+
}
|
|
63437
|
+
`;
|
|
63438
|
+
}
|
|
63439
|
+
function buildSitemapXml(site, emitted, generatedAt, stylesheetHref = "") {
|
|
62247
63440
|
const entries = [
|
|
62248
|
-
...emitted.frontPage ? [{
|
|
63441
|
+
...emitted.frontPage && emitted.frontPage.includeInSitemap !== false ? [{
|
|
62249
63442
|
url: emitted.frontPage.url,
|
|
62250
63443
|
changefreq: "daily",
|
|
62251
63444
|
priority: 1
|
|
@@ -62277,7 +63470,10 @@ function buildSitemapXml(site, emitted, generatedAt) {
|
|
|
62277
63470
|
<priority>${entry.priority.toFixed(1)}</priority>
|
|
62278
63471
|
</url>`;
|
|
62279
63472
|
}).join("\n");
|
|
62280
|
-
|
|
63473
|
+
const normalizedStylesheetHref = normalizeOptionalString(stylesheetHref);
|
|
63474
|
+
const stylesheet = normalizedStylesheetHref ? `
|
|
63475
|
+
<?xml-stylesheet type="text/xsl" href="${escapeXml(normalizedStylesheetHref)}"?>` : "";
|
|
63476
|
+
return `<?xml version="1.0" encoding="UTF-8"?>${stylesheet}
|
|
62281
63477
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
62282
63478
|
${body}
|
|
62283
63479
|
</urlset>`;
|
|
@@ -62400,7 +63596,7 @@ async function loadThemePackageFromDir(themeDir) {
|
|
|
62400
63596
|
await readThemeDir(fs4, path4, themeDir, themeDir, fileMap);
|
|
62401
63597
|
const validation = await validateThemeFiles(fileMap);
|
|
62402
63598
|
if (!validation.ok) {
|
|
62403
|
-
throw new Error(
|
|
63599
|
+
throw new Error(formatThemeValidationFailure2(validation));
|
|
62404
63600
|
}
|
|
62405
63601
|
const rawThemeJson = String(fileMap.get("theme.json"));
|
|
62406
63602
|
const themeJson = JSON.parse(rawThemeJson);
|
|
@@ -62440,6 +63636,55 @@ async function loadThemePackageFromDir(themeDir) {
|
|
|
62440
63636
|
assets
|
|
62441
63637
|
};
|
|
62442
63638
|
}
|
|
63639
|
+
function formatThemeValidationFailure2(validation) {
|
|
63640
|
+
const blocks = [
|
|
63641
|
+
[
|
|
63642
|
+
"Theme validation failed",
|
|
63643
|
+
`Errors: ${validation.errors.length}`,
|
|
63644
|
+
`Checked files: ${validation.checkedFiles}`
|
|
63645
|
+
].join("\n"),
|
|
63646
|
+
...validation.errors.map((issue3) => formatThemeValidationIssue2(issue3))
|
|
63647
|
+
];
|
|
63648
|
+
return blocks.join("\n\n");
|
|
63649
|
+
}
|
|
63650
|
+
function formatThemeValidationIssue2(issue3) {
|
|
63651
|
+
if (!issue3) {
|
|
63652
|
+
return "Reason: Unknown error";
|
|
63653
|
+
}
|
|
63654
|
+
const lines = [`ERROR ${issue3.code || "THEME_VALIDATION_ERROR"}`];
|
|
63655
|
+
const location = splitIssuePath2(issue3.path);
|
|
63656
|
+
if (location.file) {
|
|
63657
|
+
lines.push(`File: ${location.file}`);
|
|
63658
|
+
}
|
|
63659
|
+
if (location.path) {
|
|
63660
|
+
lines.push(`Path: ${location.path}`);
|
|
63661
|
+
}
|
|
63662
|
+
if (Number.isInteger(issue3.line) && Number.isInteger(issue3.column)) {
|
|
63663
|
+
lines.push(`Line: ${issue3.line}, Column: ${issue3.column}`);
|
|
63664
|
+
}
|
|
63665
|
+
if (issue3.category) {
|
|
63666
|
+
lines.push(`Category: ${issue3.category}`);
|
|
63667
|
+
}
|
|
63668
|
+
lines.push(`Reason: ${issue3.message || "Unknown error"}`);
|
|
63669
|
+
if (issue3.snippet) {
|
|
63670
|
+
const lineLabel = Number.isInteger(issue3.line) ? String(issue3.line) : "";
|
|
63671
|
+
lines.push("", `${lineLabel} | ${issue3.snippet.line}`, `${" ".repeat(lineLabel.length)} | ${issue3.snippet.pointer}`);
|
|
63672
|
+
}
|
|
63673
|
+
if (issue3.hint) {
|
|
63674
|
+
lines.push("", "Hint:", issue3.hint);
|
|
63675
|
+
}
|
|
63676
|
+
return lines.join("\n");
|
|
63677
|
+
}
|
|
63678
|
+
function splitIssuePath2(issuePath) {
|
|
63679
|
+
const normalizedPath = String(issuePath || "");
|
|
63680
|
+
if (normalizedPath.startsWith("theme.json.")) {
|
|
63681
|
+
return {
|
|
63682
|
+
file: "theme.json",
|
|
63683
|
+
path: normalizedPath.slice("theme.json.".length)
|
|
63684
|
+
};
|
|
63685
|
+
}
|
|
63686
|
+
return { file: normalizedPath, path: "" };
|
|
63687
|
+
}
|
|
62443
63688
|
async function readThemeDir(fs4, path4, rootDir, currentDir, fileMap) {
|
|
62444
63689
|
const entries = await fs4.readdir(currentDir, { withFileTypes: true });
|
|
62445
63690
|
for (const entry of entries) {
|
|
@@ -62486,6 +63731,7 @@ var PUBLIC_FAVICON_FILES = Object.freeze({
|
|
|
62486
63731
|
png: "favicon.png",
|
|
62487
63732
|
apple_touch_icon: "apple-touch-icon.png"
|
|
62488
63733
|
});
|
|
63734
|
+
var PUBLIC_SITEMAP_STYLESHEET_FILE = "sitemap.xsl";
|
|
62489
63735
|
async function assertThemeDirectory(themeDir) {
|
|
62490
63736
|
let stat;
|
|
62491
63737
|
try {
|
|
@@ -62500,14 +63746,15 @@ async function assertThemeDirectory(themeDir) {
|
|
|
62500
63746
|
throw new Error(`Theme path is not a directory: ${themeDir}`);
|
|
62501
63747
|
}
|
|
62502
63748
|
}
|
|
62503
|
-
async function runBuild(themeDir, previewData, outDir) {
|
|
62504
|
-
|
|
62505
|
-
assertPublicPathDoesNotOverlap("
|
|
63749
|
+
async function runBuild(themeDir, previewData, outDir, options2 = {}) {
|
|
63750
|
+
const publicDir = resolvePublicDir(process.cwd(), options2.publicDir);
|
|
63751
|
+
assertPublicPathDoesNotOverlap("Theme directory", themeDir, process.cwd(), publicDir);
|
|
63752
|
+
assertPublicPathDoesNotOverlap("Output directory", outDir, process.cwd(), publicDir);
|
|
62506
63753
|
await assertThemeDirectory(themeDir);
|
|
62507
63754
|
await assertEmptyOutputDirectory(outDir);
|
|
62508
|
-
const publicDir = resolvePublicDir();
|
|
62509
63755
|
const hasPublicRobotsTxt = await publicRobotsTxtExists(publicDir);
|
|
62510
63756
|
const publicFavicon = await discoverPublicFavicon(publicDir);
|
|
63757
|
+
const sitemapStylesheetHref = await discoverPublicSitemapStylesheet(publicDir);
|
|
62511
63758
|
await copyPublicDirectory(publicDir, outDir);
|
|
62512
63759
|
const writer = new GeneratedOutputWriter({ outDir });
|
|
62513
63760
|
return buildSiteFromThemeDir({
|
|
@@ -62516,6 +63763,7 @@ async function runBuild(themeDir, previewData, outDir) {
|
|
|
62516
63763
|
writer,
|
|
62517
63764
|
options: {
|
|
62518
63765
|
favicon: publicFavicon,
|
|
63766
|
+
sitemapStylesheetHref,
|
|
62519
63767
|
generateRobotsTxt: !hasPublicRobotsTxt
|
|
62520
63768
|
}
|
|
62521
63769
|
});
|
|
@@ -62555,7 +63803,10 @@ async function assertEmptyOutputDirectory(outDir) {
|
|
|
62555
63803
|
throw error;
|
|
62556
63804
|
}
|
|
62557
63805
|
}
|
|
62558
|
-
function resolvePublicDir(cwd = process.cwd()) {
|
|
63806
|
+
function resolvePublicDir(cwd = process.cwd(), publicDir) {
|
|
63807
|
+
if (publicDir) {
|
|
63808
|
+
return path.resolve(cwd, publicDir);
|
|
63809
|
+
}
|
|
62559
63810
|
const envValue = process.env[PUBLIC_DIR_ENV_NAME]?.trim();
|
|
62560
63811
|
return path.resolve(cwd, envValue || DEFAULT_PUBLIC_DIR_NAME);
|
|
62561
63812
|
}
|
|
@@ -62604,6 +63855,18 @@ async function discoverPublicFavicon(publicDir) {
|
|
|
62604
63855
|
}
|
|
62605
63856
|
return Object.keys(favicon).length ? favicon : void 0;
|
|
62606
63857
|
}
|
|
63858
|
+
async function discoverPublicSitemapStylesheet(publicDir) {
|
|
63859
|
+
let stat;
|
|
63860
|
+
try {
|
|
63861
|
+
stat = await fs.lstat(path.join(publicDir, PUBLIC_SITEMAP_STYLESHEET_FILE));
|
|
63862
|
+
} catch (error) {
|
|
63863
|
+
if (error && (error.code === "ENOENT" || error.code === "ENOTDIR")) {
|
|
63864
|
+
return void 0;
|
|
63865
|
+
}
|
|
63866
|
+
throw error;
|
|
63867
|
+
}
|
|
63868
|
+
return stat.isFile() ? `/${PUBLIC_SITEMAP_STYLESHEET_FILE}` : void 0;
|
|
63869
|
+
}
|
|
62607
63870
|
async function copyPublicEntries(sourceDir, targetDir) {
|
|
62608
63871
|
const entries = await fs.readdir(sourceDir, { withFileTypes: true });
|
|
62609
63872
|
for (const entry of entries) {
|
|
@@ -62628,8 +63891,7 @@ function shouldIgnorePublicEntry(name) {
|
|
|
62628
63891
|
const lowerName = basename.toLowerCase();
|
|
62629
63892
|
return basename.startsWith(".") || lowerName === "node_modules" || lowerName === "thumbs.db" || lowerName.endsWith(".key") || lowerName.endsWith(".pem");
|
|
62630
63893
|
}
|
|
62631
|
-
function assertPublicPathDoesNotOverlap(label, candidatePath, cwd = process.cwd()) {
|
|
62632
|
-
const publicDir = resolvePublicDir(cwd);
|
|
63894
|
+
function assertPublicPathDoesNotOverlap(label, candidatePath, cwd = process.cwd(), publicDir = resolvePublicDir(cwd)) {
|
|
62633
63895
|
const resolvedCandidate = path.resolve(cwd, candidatePath);
|
|
62634
63896
|
if (!pathsOverlap(publicDir, resolvedCandidate)) {
|
|
62635
63897
|
return;
|
|
@@ -62940,7 +64202,7 @@ try {
|
|
|
62940
64202
|
process.exitCode = 1;
|
|
62941
64203
|
}
|
|
62942
64204
|
function input(name) {
|
|
62943
|
-
return process.env[`INPUT_${name.toUpperCase()
|
|
64205
|
+
return process.env[`INPUT_${name.toUpperCase()}`]?.trim() || "";
|
|
62944
64206
|
}
|
|
62945
64207
|
function booleanInput(name, fallback) {
|
|
62946
64208
|
const value = input(name);
|