@zeropress/build-pages 0.5.6 → 0.6.2
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 +105 -24
- package/action.yml +3 -0
- package/dist/action.js +1814 -334
- package/dist/prebuild.js +157 -24
- package/package.json +2 -2
- package/schemas/zeropress-build-pages.config.v0.1.schema.json +33 -12
- package/src/action.js +2 -1
- package/src/index.js +154 -3
- package/src/prebuild.js +178 -23
- package/themes/docs/assets/style.css +212 -0
- package/themes/docs/assets/theme.js +121 -0
- package/themes/docs/layout.html +20 -4
- package/themes/docs/page.html +2 -2
- package/themes/docs/partials/theme-scripts.html +1 -0
- package/themes/docs/post.html +1 -1
- package/themes/docs/theme.json +5 -6
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,18 @@ 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",
|
|
52321
|
+
"search",
|
|
52313
52322
|
"locale",
|
|
52314
|
-
"
|
|
52315
|
-
"
|
|
52316
|
-
"
|
|
52323
|
+
"posts_per_page",
|
|
52324
|
+
"datetime_display",
|
|
52325
|
+
"date_style",
|
|
52326
|
+
"time_style",
|
|
52317
52327
|
"timezone",
|
|
52318
|
-
"
|
|
52328
|
+
"disallow_comments",
|
|
52319
52329
|
"indexing",
|
|
52320
52330
|
"permalinks",
|
|
52321
52331
|
"front_page",
|
|
@@ -52329,19 +52339,26 @@ function validateSite(site, path4, errors) {
|
|
|
52329
52339
|
validateNonEmptyString(site.title, `${path4}.title`, "INVALID_SITE_TITLE", errors);
|
|
52330
52340
|
validateString(site.description, `${path4}.description`, "INVALID_SITE_DESCRIPTION", errors);
|
|
52331
52341
|
validateSiteUri(site.url, `${path4}.url`, "INVALID_SITE_URL", errors);
|
|
52332
|
-
validateSiteUri(site.
|
|
52333
|
-
if (site.
|
|
52334
|
-
validateEnum(site.
|
|
52342
|
+
validateSiteUri(site.media_base_url, `${path4}.media_base_url`, "INVALID_SITE_MEDIA_BASE_URL", errors);
|
|
52343
|
+
if (site.media_delivery_mode !== void 0) {
|
|
52344
|
+
validateEnum(site.media_delivery_mode, `${path4}.media_delivery_mode`, "INVALID_SITE_MEDIA_DELIVERY_MODE", errors, PREVIEW_MEDIA_DELIVERY_MODES);
|
|
52335
52345
|
}
|
|
52336
52346
|
if (site.favicon !== void 0) {
|
|
52337
52347
|
validateSiteFavicon(site.favicon, `${path4}.favicon`, errors);
|
|
52338
52348
|
}
|
|
52349
|
+
if (site.expose_generator !== void 0) {
|
|
52350
|
+
validateBoolean(site.expose_generator, `${path4}.expose_generator`, "INVALID_SITE_EXPOSE_GENERATOR", errors);
|
|
52351
|
+
}
|
|
52352
|
+
if (site.search !== void 0) {
|
|
52353
|
+
validateBoolean(site.search, `${path4}.search`, "INVALID_SITE_SEARCH", errors);
|
|
52354
|
+
}
|
|
52339
52355
|
validateNonEmptyString(site.locale, `${path4}.locale`, "INVALID_SITE_LOCALE", errors);
|
|
52340
|
-
validateInteger(site.
|
|
52341
|
-
|
|
52342
|
-
|
|
52356
|
+
validateInteger(site.posts_per_page, `${path4}.posts_per_page`, "INVALID_SITE_POSTS_PER_PAGE", errors, { minimum: 1 });
|
|
52357
|
+
validateEnum(site.datetime_display, `${path4}.datetime_display`, "INVALID_SITE_DATETIME_DISPLAY", errors, PREVIEW_DATETIME_DISPLAY_MODES);
|
|
52358
|
+
validateEnum(site.date_style, `${path4}.date_style`, "INVALID_SITE_DATE_STYLE", errors, PREVIEW_DATETIME_STYLES);
|
|
52359
|
+
validateEnum(site.time_style, `${path4}.time_style`, "INVALID_SITE_TIME_STYLE", errors, PREVIEW_DATETIME_STYLES);
|
|
52343
52360
|
validateNonEmptyString(site.timezone, `${path4}.timezone`, "INVALID_SITE_TIMEZONE", errors);
|
|
52344
|
-
validateBoolean(site.
|
|
52361
|
+
validateBoolean(site.disallow_comments, `${path4}.disallow_comments`, "INVALID_SITE_DISALLOW_COMMENTS", errors);
|
|
52345
52362
|
if (site.indexing !== void 0) {
|
|
52346
52363
|
validateBoolean(site.indexing, `${path4}.indexing`, "INVALID_SITE_INDEXING", errors);
|
|
52347
52364
|
}
|
|
@@ -52357,7 +52374,6 @@ function validateSite(site, path4, errors) {
|
|
|
52357
52374
|
"site_description",
|
|
52358
52375
|
"site_url",
|
|
52359
52376
|
"metadata",
|
|
52360
|
-
"media_delivery_mode",
|
|
52361
52377
|
"media_delivery_base_url",
|
|
52362
52378
|
"language",
|
|
52363
52379
|
"siteLocale",
|
|
@@ -52395,10 +52411,7 @@ function validateSiteFooter(footer, path4, errors) {
|
|
|
52395
52411
|
validateNonEmptyString(footer.copyright_text, `${path4}.copyright_text`, "INVALID_SITE_FOOTER_COPYRIGHT_TEXT", errors);
|
|
52396
52412
|
}
|
|
52397
52413
|
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
|
-
}
|
|
52414
|
+
validateBoolean(footer.attribution, `${path4}.attribution`, "INVALID_SITE_FOOTER_ATTRIBUTION", errors);
|
|
52402
52415
|
}
|
|
52403
52416
|
}
|
|
52404
52417
|
function validateMenus(menus, path4, errors) {
|
|
@@ -52424,7 +52437,7 @@ function validatePreviewMenu(menu, path4, errors) {
|
|
|
52424
52437
|
});
|
|
52425
52438
|
}
|
|
52426
52439
|
function validatePreviewMenuItem(item, path4, errors) {
|
|
52427
|
-
validateClosedObject(item, path4, errors, ["title", "url", "type", "target", "children"]);
|
|
52440
|
+
validateClosedObject(item, path4, errors, ["title", "url", "type", "target", "meta", "children"]);
|
|
52428
52441
|
if (!isObject(item)) {
|
|
52429
52442
|
return;
|
|
52430
52443
|
}
|
|
@@ -52432,6 +52445,7 @@ function validatePreviewMenuItem(item, path4, errors) {
|
|
|
52432
52445
|
validateUrlLike(item.url, `${path4}.url`, "INVALID_MENU_ITEM_URL", errors);
|
|
52433
52446
|
validateEnum(item.type, `${path4}.type`, "INVALID_MENU_ITEM_TYPE", errors, PREVIEW_MENU_ITEM_TYPES);
|
|
52434
52447
|
validateEnum(item.target, `${path4}.target`, "INVALID_MENU_ITEM_TARGET", errors, PREVIEW_MENU_TARGETS);
|
|
52448
|
+
validatePreviewMeta(item.meta, `${path4}.meta`, errors);
|
|
52435
52449
|
validateArray(item.children, `${path4}.children`, "INVALID_MENU_ITEM_CHILDREN", errors, (entry, index) => {
|
|
52436
52450
|
validatePreviewMenuItem(entry, `${path4}.children[${index}]`, errors);
|
|
52437
52451
|
});
|
|
@@ -52637,7 +52651,9 @@ function validatePreviewPost(post, path4, errors, authorIds) {
|
|
|
52637
52651
|
"author_id",
|
|
52638
52652
|
"featured_image",
|
|
52639
52653
|
"meta",
|
|
52654
|
+
"data",
|
|
52640
52655
|
"status",
|
|
52656
|
+
"discoverability",
|
|
52641
52657
|
"allow_comments",
|
|
52642
52658
|
"category_slugs",
|
|
52643
52659
|
"tag_slugs"
|
|
@@ -52655,6 +52671,9 @@ function validatePreviewPost(post, path4, errors, authorIds) {
|
|
|
52655
52671
|
validateDateTimeString(post.updated_at_iso, `${path4}.updated_at_iso`, "INVALID_POST_UPDATED_AT_ISO", errors);
|
|
52656
52672
|
validateNonEmptyString(post.author_id, `${path4}.author_id`, "INVALID_POST_AUTHOR_ID", errors);
|
|
52657
52673
|
validateEnum(post.status, `${path4}.status`, "INVALID_POST_STATUS", errors, ["published", "draft"]);
|
|
52674
|
+
if (post.discoverability !== void 0) {
|
|
52675
|
+
validateEnum(post.discoverability, `${path4}.discoverability`, "INVALID_POST_DISCOVERABILITY", errors, PREVIEW_DISCOVERABILITY_VALUES);
|
|
52676
|
+
}
|
|
52658
52677
|
validateBoolean(post.allow_comments, `${path4}.allow_comments`, "INVALID_POST_ALLOW_COMMENTS", errors);
|
|
52659
52678
|
validateSlugArray(post.category_slugs, `${path4}.category_slugs`, "INVALID_POST_CATEGORY_SLUGS", errors);
|
|
52660
52679
|
validateSlugArray(post.tag_slugs, `${path4}.tag_slugs`, "INVALID_POST_TAG_SLUGS", errors);
|
|
@@ -52662,12 +52681,13 @@ function validatePreviewPost(post, path4, errors, authorIds) {
|
|
|
52662
52681
|
validateUrlLike(post.featured_image, `${path4}.featured_image`, "INVALID_POST_FEATURED_IMAGE", errors);
|
|
52663
52682
|
}
|
|
52664
52683
|
validatePreviewMeta(post.meta, `${path4}.meta`, errors);
|
|
52684
|
+
validatePreviewStructuredData(post.data, `${path4}.data`, errors);
|
|
52665
52685
|
if (typeof post.author_id === "string" && post.author_id.trim() !== "" && !authorIds.has(post.author_id)) {
|
|
52666
52686
|
errors.push(issue("INVALID_POST_AUTHOR_REFERENCE", `${path4}.author_id`, "Referenced author_id does not exist"));
|
|
52667
52687
|
}
|
|
52668
52688
|
}
|
|
52669
52689
|
function validatePreviewPage(page, path4, errors) {
|
|
52670
|
-
validateClosedObject(page, path4, errors, ["title", "slug", "path", "content", "document_type", "excerpt", "featured_image", "meta", "status"]);
|
|
52690
|
+
validateClosedObject(page, path4, errors, ["title", "slug", "path", "content", "document_type", "excerpt", "featured_image", "meta", "data", "status", "discoverability"]);
|
|
52671
52691
|
if (!isObject(page)) {
|
|
52672
52692
|
return;
|
|
52673
52693
|
}
|
|
@@ -52683,7 +52703,11 @@ function validatePreviewPage(page, path4, errors) {
|
|
|
52683
52703
|
validateUrlLike(page.featured_image, `${path4}.featured_image`, "INVALID_PAGE_FEATURED_IMAGE", errors);
|
|
52684
52704
|
}
|
|
52685
52705
|
validatePreviewMeta(page.meta, `${path4}.meta`, errors);
|
|
52706
|
+
validatePreviewStructuredData(page.data, `${path4}.data`, errors);
|
|
52686
52707
|
validateEnum(page.status, `${path4}.status`, "INVALID_PAGE_STATUS", errors, ["published", "draft"]);
|
|
52708
|
+
if (page.discoverability !== void 0) {
|
|
52709
|
+
validateEnum(page.discoverability, `${path4}.discoverability`, "INVALID_PAGE_DISCOVERABILITY", errors, PREVIEW_DISCOVERABILITY_VALUES);
|
|
52710
|
+
}
|
|
52687
52711
|
}
|
|
52688
52712
|
function validatePreviewMeta(meta, path4, errors) {
|
|
52689
52713
|
if (meta === void 0) {
|
|
@@ -52700,6 +52724,66 @@ function validatePreviewMeta(meta, path4, errors) {
|
|
|
52700
52724
|
errors.push(issue("INVALID_META_VALUE", `${path4}.${key}`, "meta values must be strings, numbers, booleans, or null"));
|
|
52701
52725
|
}
|
|
52702
52726
|
}
|
|
52727
|
+
function validatePreviewStructuredData(data, path4, errors) {
|
|
52728
|
+
if (data === void 0) {
|
|
52729
|
+
return;
|
|
52730
|
+
}
|
|
52731
|
+
if (!isObject(data)) {
|
|
52732
|
+
errors.push(issue("INVALID_DATA", path4, "data must be an object"));
|
|
52733
|
+
return;
|
|
52734
|
+
}
|
|
52735
|
+
validatePreviewDataObject(data, path4, errors, 0);
|
|
52736
|
+
}
|
|
52737
|
+
function validatePreviewDataValue(value, path4, errors, depth) {
|
|
52738
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") {
|
|
52739
|
+
return;
|
|
52740
|
+
}
|
|
52741
|
+
if (typeof value === "number") {
|
|
52742
|
+
if (!Number.isFinite(value)) {
|
|
52743
|
+
errors.push(issue("INVALID_DATA_VALUE", path4, "data numbers must be finite"));
|
|
52744
|
+
}
|
|
52745
|
+
return;
|
|
52746
|
+
}
|
|
52747
|
+
if (Array.isArray(value)) {
|
|
52748
|
+
validatePreviewDataArray(value, path4, errors, depth);
|
|
52749
|
+
return;
|
|
52750
|
+
}
|
|
52751
|
+
if (isObject(value)) {
|
|
52752
|
+
validatePreviewDataObject(value, path4, errors, depth);
|
|
52753
|
+
return;
|
|
52754
|
+
}
|
|
52755
|
+
errors.push(issue("INVALID_DATA_VALUE", path4, "data values must be JSON-safe strings, numbers, booleans, null, arrays, or objects"));
|
|
52756
|
+
}
|
|
52757
|
+
function validatePreviewDataObject(object, path4, errors, depth) {
|
|
52758
|
+
if (depth > PREVIEW_DATA_MAX_DEPTH) {
|
|
52759
|
+
errors.push(issue("INVALID_DATA_DEPTH", path4, `data nesting must not exceed ${PREVIEW_DATA_MAX_DEPTH} container levels`));
|
|
52760
|
+
return;
|
|
52761
|
+
}
|
|
52762
|
+
const entries = Object.entries(object);
|
|
52763
|
+
if (entries.length > PREVIEW_DATA_MAX_KEYS) {
|
|
52764
|
+
errors.push(issue("INVALID_DATA_OBJECT_SIZE", path4, `data objects must not contain more than ${PREVIEW_DATA_MAX_KEYS} keys`));
|
|
52765
|
+
}
|
|
52766
|
+
for (const [key, value] of entries) {
|
|
52767
|
+
const childPath = `${path4}.${key}`;
|
|
52768
|
+
if (!PREVIEW_DATA_KEY_PATTERN.test(key)) {
|
|
52769
|
+
errors.push(issue("INVALID_DATA_KEY", childPath, "data keys must be valid template path segments"));
|
|
52770
|
+
continue;
|
|
52771
|
+
}
|
|
52772
|
+
validatePreviewDataValue(value, childPath, errors, depth + 1);
|
|
52773
|
+
}
|
|
52774
|
+
}
|
|
52775
|
+
function validatePreviewDataArray(array, path4, errors, depth) {
|
|
52776
|
+
if (depth > PREVIEW_DATA_MAX_DEPTH) {
|
|
52777
|
+
errors.push(issue("INVALID_DATA_DEPTH", path4, `data nesting must not exceed ${PREVIEW_DATA_MAX_DEPTH} container levels`));
|
|
52778
|
+
return;
|
|
52779
|
+
}
|
|
52780
|
+
if (array.length > PREVIEW_DATA_MAX_ARRAY_LENGTH) {
|
|
52781
|
+
errors.push(issue("INVALID_DATA_ARRAY_SIZE", path4, `data arrays must not contain more than ${PREVIEW_DATA_MAX_ARRAY_LENGTH} items`));
|
|
52782
|
+
}
|
|
52783
|
+
array.forEach((value, index) => {
|
|
52784
|
+
validatePreviewDataValue(value, `${path4}[${index}]`, errors, depth + 1);
|
|
52785
|
+
});
|
|
52786
|
+
}
|
|
52703
52787
|
function validatePermalinks(permalinks, path4, errors) {
|
|
52704
52788
|
if (permalinks === void 0) {
|
|
52705
52789
|
return;
|
|
@@ -52930,7 +53014,7 @@ function isOptionalKey(path4, key) {
|
|
|
52930
53014
|
return key === "head_end" || key === "body_end";
|
|
52931
53015
|
}
|
|
52932
53016
|
if (path4 === "site") {
|
|
52933
|
-
return key === "
|
|
53017
|
+
return key === "media_delivery_mode" || key === "favicon" || key === "expose_generator" || key === "search" || key === "indexing" || key === "permalinks" || key === "front_page" || key === "post_index" || key === "footer" || key === "meta";
|
|
52934
53018
|
}
|
|
52935
53019
|
if (path4 === "site.favicon") {
|
|
52936
53020
|
return key === "icon" || key === "svg" || key === "png" || key === "apple_touch_icon";
|
|
@@ -52938,9 +53022,6 @@ function isOptionalKey(path4, key) {
|
|
|
52938
53022
|
if (path4 === "site.footer") {
|
|
52939
53023
|
return key === "copyright_text" || key === "attribution";
|
|
52940
53024
|
}
|
|
52941
|
-
if (path4 === "site.footer.attribution") {
|
|
52942
|
-
return key === "enabled";
|
|
52943
|
-
}
|
|
52944
53025
|
if (path4 === "site.front_page") {
|
|
52945
53026
|
return key === "page_slug" || key === "html";
|
|
52946
53027
|
}
|
|
@@ -52959,6 +53040,9 @@ function isOptionalKey(path4, key) {
|
|
|
52959
53040
|
if (path4.startsWith("content.media[")) {
|
|
52960
53041
|
return key === "alt";
|
|
52961
53042
|
}
|
|
53043
|
+
if (path4.startsWith("menus.") && (path4.includes(".items[") || path4.includes(".children["))) {
|
|
53044
|
+
return key === "meta";
|
|
53045
|
+
}
|
|
52962
53046
|
if (path4.startsWith("widgets.") && path4.includes(".items[")) {
|
|
52963
53047
|
return key === "settings";
|
|
52964
53048
|
}
|
|
@@ -52966,10 +53050,10 @@ function isOptionalKey(path4, key) {
|
|
|
52966
53050
|
return key === "title" || key === "description";
|
|
52967
53051
|
}
|
|
52968
53052
|
if (path4.startsWith("content.posts[")) {
|
|
52969
|
-
return key === "id" || key === "featured_image" || key === "meta";
|
|
53053
|
+
return key === "id" || key === "featured_image" || key === "meta" || key === "data" || key === "discoverability";
|
|
52970
53054
|
}
|
|
52971
53055
|
if (path4.startsWith("content.pages[")) {
|
|
52972
|
-
return key === "path" || key === "excerpt" || key === "featured_image" || key === "meta";
|
|
53056
|
+
return key === "path" || key === "excerpt" || key === "featured_image" || key === "meta" || key === "data" || key === "discoverability";
|
|
52973
53057
|
}
|
|
52974
53058
|
if (path4.startsWith("content.categories[") || path4.startsWith("content.tags[")) {
|
|
52975
53059
|
return key === "description";
|
|
@@ -53014,7 +53098,7 @@ function mapSlugValidationMessage(issueCode) {
|
|
|
53014
53098
|
function rejectLegacyKeys(value, path4, errors, keys, code2) {
|
|
53015
53099
|
for (const key of keys) {
|
|
53016
53100
|
if (key in value) {
|
|
53017
|
-
errors.push(issue(code2, `${path4}.${key}`, "Legacy field is not allowed in preview-data v0.
|
|
53101
|
+
errors.push(issue(code2, `${path4}.${key}`, "Legacy field is not allowed in preview-data v0.6"));
|
|
53018
53102
|
}
|
|
53019
53103
|
}
|
|
53020
53104
|
}
|
|
@@ -53124,9 +53208,46 @@ var PARTIAL_TAG_REGEX = /\{\{(partial:[^}]+)\}\}/g;
|
|
|
53124
53208
|
var TEMPLATE_PATH_SEGMENT_SOURCE = "[a-zA-Z_][a-zA-Z0-9_]*(?:-[a-zA-Z0-9_]+)*";
|
|
53125
53209
|
var TEMPLATE_PATH_REGEX = new RegExp(`^${TEMPLATE_PATH_SEGMENT_SOURCE}(?:\\.${TEMPLATE_PATH_SEGMENT_SOURCE})*$`);
|
|
53126
53210
|
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
|
|
53211
|
+
var NUMBER_LITERAL_REGEX = /^-?(?:0|[1-9]\d*)(?:\.\d+)?$/;
|
|
53212
|
+
var COMPARISON_BLOCK_TAGS = /* @__PURE__ */ new Set(["if_eq", "if_neq", "if_in", "if_starts_with"]);
|
|
53213
|
+
var COMPARISON_ELSE_IF_TAGS = /* @__PURE__ */ new Set(["else_if_eq", "else_if_neq", "else_if_in", "else_if_starts_with"]);
|
|
53214
|
+
var COMPARISON_TAG_OPERATORS = {
|
|
53215
|
+
if_eq: "eq",
|
|
53216
|
+
else_if_eq: "eq",
|
|
53217
|
+
if_neq: "neq",
|
|
53218
|
+
else_if_neq: "neq",
|
|
53219
|
+
if_in: "in",
|
|
53220
|
+
else_if_in: "in",
|
|
53221
|
+
if_starts_with: "starts_with",
|
|
53222
|
+
else_if_starts_with: "starts_with"
|
|
53223
|
+
};
|
|
53224
|
+
var PARTIAL_ARG_ROOT_PATHS = /* @__PURE__ */ new Set([
|
|
53225
|
+
"archive",
|
|
53226
|
+
"author",
|
|
53227
|
+
"category",
|
|
53228
|
+
"collection",
|
|
53229
|
+
"collections",
|
|
53230
|
+
"currentUrl",
|
|
53231
|
+
"language",
|
|
53232
|
+
"menu",
|
|
53233
|
+
"menus",
|
|
53234
|
+
"meta",
|
|
53235
|
+
"page",
|
|
53236
|
+
"pagination",
|
|
53237
|
+
"partial",
|
|
53238
|
+
"post",
|
|
53239
|
+
"posts",
|
|
53240
|
+
"route",
|
|
53241
|
+
"site",
|
|
53242
|
+
"tag",
|
|
53243
|
+
"taxonomies",
|
|
53244
|
+
"taxonomy",
|
|
53245
|
+
"widget",
|
|
53246
|
+
"widgets"
|
|
53247
|
+
]);
|
|
53128
53248
|
var PARTIAL_ARG_KEY_REGEX = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
|
|
53129
53249
|
var SEMVER_REGEX = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
53250
|
+
var LICENSE_REF_REGEX = /^LicenseRef-[A-Za-z0-9][A-Za-z0-9.-]*$/;
|
|
53130
53251
|
var NAMESPACE_REGEX = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
53131
53252
|
var SLUG_REGEX = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
53132
53253
|
var ALLOWED_LICENSES = [
|
|
@@ -53137,7 +53258,10 @@ var ALLOWED_LICENSES = [
|
|
|
53137
53258
|
"GPL-3.0-or-later"
|
|
53138
53259
|
];
|
|
53139
53260
|
var LICENSES = new Set(ALLOWED_LICENSES);
|
|
53140
|
-
var
|
|
53261
|
+
var THEME_LINK_KEYS = /* @__PURE__ */ new Set(["homepage", "repository", "documentation", "support", "marketplace", "license"]);
|
|
53262
|
+
var THEME_LINK_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:", "mailto:"]);
|
|
53263
|
+
var DEFAULT_RUNTIME = "0.6";
|
|
53264
|
+
var THEME_RUNTIME_V0_6 = DEFAULT_RUNTIME;
|
|
53141
53265
|
var SUPPORTED_RUNTIMES = [DEFAULT_RUNTIME];
|
|
53142
53266
|
var SUPPORTED_RUNTIME_SET = new Set(SUPPORTED_RUNTIMES);
|
|
53143
53267
|
var NAMESPACE_MIN_LENGTH = 3;
|
|
@@ -53152,7 +53276,7 @@ var MENU_SLOT_ID_MAX_LENGTH = 32;
|
|
|
53152
53276
|
var MENU_SLOT_COUNT_MAX = 12;
|
|
53153
53277
|
var MENU_SLOT_TITLE_MAX_LENGTH = 80;
|
|
53154
53278
|
var MENU_SLOT_DESCRIPTION_MAX_LENGTH = 160;
|
|
53155
|
-
var SUPPORTED_THEME_FEATURES = /* @__PURE__ */ new Set(["comments", "newsletter", "
|
|
53279
|
+
var SUPPORTED_THEME_FEATURES = /* @__PURE__ */ new Set(["comments", "newsletter", "post_index", "search"]);
|
|
53156
53280
|
var THEME_MANIFEST_KEYS = /* @__PURE__ */ new Set([
|
|
53157
53281
|
"$schema",
|
|
53158
53282
|
"name",
|
|
@@ -53164,11 +53288,12 @@ var THEME_MANIFEST_KEYS = /* @__PURE__ */ new Set([
|
|
|
53164
53288
|
"author",
|
|
53165
53289
|
"description",
|
|
53166
53290
|
"thumbnail",
|
|
53291
|
+
"links",
|
|
53167
53292
|
"features",
|
|
53168
|
-
"
|
|
53169
|
-
"
|
|
53170
|
-
"
|
|
53171
|
-
"
|
|
53293
|
+
"menu_slots",
|
|
53294
|
+
"widget_areas",
|
|
53295
|
+
"site_meta",
|
|
53296
|
+
"collection_slots"
|
|
53172
53297
|
]);
|
|
53173
53298
|
var SITE_META_KEY_REGEX = /^[a-z][a-z0-9_]*(?:-[a-z0-9_]+)*$/;
|
|
53174
53299
|
var SITE_META_KEY_MAX_LENGTH = 64;
|
|
@@ -53194,7 +53319,11 @@ function validateFeatureFlags(rawValue, errors) {
|
|
|
53194
53319
|
"INVALID_THEME_FEATURE",
|
|
53195
53320
|
`theme.json.features.${featureName}`,
|
|
53196
53321
|
`Unknown theme feature '${featureName}'`,
|
|
53197
|
-
"error"
|
|
53322
|
+
"error",
|
|
53323
|
+
{
|
|
53324
|
+
category: "theme_manifest",
|
|
53325
|
+
hint: themeFeatureHint(featureName)
|
|
53326
|
+
}
|
|
53198
53327
|
));
|
|
53199
53328
|
continue;
|
|
53200
53329
|
}
|
|
@@ -53211,6 +53340,80 @@ function validateFeatureFlags(rawValue, errors) {
|
|
|
53211
53340
|
}
|
|
53212
53341
|
return Object.keys(normalizedFeatures).length > 0 ? normalizedFeatures : void 0;
|
|
53213
53342
|
}
|
|
53343
|
+
function themeFeatureHint(featureName) {
|
|
53344
|
+
const hints = {
|
|
53345
|
+
postIndex: "ZeroPress runtime v0.6 uses snake_case keys. Use 'post_index' instead of 'postIndex'."
|
|
53346
|
+
};
|
|
53347
|
+
return hints[featureName] || "";
|
|
53348
|
+
}
|
|
53349
|
+
function themeManifestFieldHint(fieldName) {
|
|
53350
|
+
const hints = {
|
|
53351
|
+
menuSlots: "ZeroPress runtime v0.6 uses snake_case keys. Use 'menu_slots' instead of 'menuSlots'.",
|
|
53352
|
+
widgetAreas: "ZeroPress runtime v0.6 uses snake_case keys. Use 'widget_areas' instead of 'widgetAreas'.",
|
|
53353
|
+
siteMeta: "ZeroPress runtime v0.6 uses snake_case keys. Use 'site_meta' instead of 'siteMeta'.",
|
|
53354
|
+
collectionSlots: "ZeroPress runtime v0.6 uses snake_case keys. Use 'collection_slots' instead of 'collectionSlots'.",
|
|
53355
|
+
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."
|
|
53356
|
+
};
|
|
53357
|
+
return hints[fieldName] || "";
|
|
53358
|
+
}
|
|
53359
|
+
function isAllowedLicense(value) {
|
|
53360
|
+
return LICENSES.has(value) || LICENSE_REF_REGEX.test(value);
|
|
53361
|
+
}
|
|
53362
|
+
function isValidThemeLinkUrl(value) {
|
|
53363
|
+
try {
|
|
53364
|
+
const parsed = new URL(value);
|
|
53365
|
+
return THEME_LINK_PROTOCOLS.has(parsed.protocol);
|
|
53366
|
+
} catch {
|
|
53367
|
+
return false;
|
|
53368
|
+
}
|
|
53369
|
+
}
|
|
53370
|
+
function validateThemeLinks(rawValue, errors) {
|
|
53371
|
+
if (rawValue === void 0) {
|
|
53372
|
+
return void 0;
|
|
53373
|
+
}
|
|
53374
|
+
if (!rawValue || typeof rawValue !== "object" || Array.isArray(rawValue)) {
|
|
53375
|
+
errors.push(issue2(
|
|
53376
|
+
"INVALID_LINKS",
|
|
53377
|
+
"theme.json.links",
|
|
53378
|
+
"theme.json field 'links' must be an object when present",
|
|
53379
|
+
"error"
|
|
53380
|
+
));
|
|
53381
|
+
return void 0;
|
|
53382
|
+
}
|
|
53383
|
+
const normalizedLinks = {};
|
|
53384
|
+
for (const [linkKey, value] of Object.entries(rawValue)) {
|
|
53385
|
+
if (!THEME_LINK_KEYS.has(linkKey)) {
|
|
53386
|
+
errors.push(issue2(
|
|
53387
|
+
"INVALID_THEME_LINK",
|
|
53388
|
+
`theme.json.links.${linkKey}`,
|
|
53389
|
+
`Unknown theme link '${linkKey}'`,
|
|
53390
|
+
"error"
|
|
53391
|
+
));
|
|
53392
|
+
continue;
|
|
53393
|
+
}
|
|
53394
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
53395
|
+
errors.push(issue2(
|
|
53396
|
+
"INVALID_THEME_LINK_VALUE",
|
|
53397
|
+
`theme.json.links.${linkKey}`,
|
|
53398
|
+
`theme link '${linkKey}' must be a non-empty URL string`,
|
|
53399
|
+
"error"
|
|
53400
|
+
));
|
|
53401
|
+
continue;
|
|
53402
|
+
}
|
|
53403
|
+
const normalizedValue = value.trim();
|
|
53404
|
+
if (!isValidThemeLinkUrl(normalizedValue)) {
|
|
53405
|
+
errors.push(issue2(
|
|
53406
|
+
"INVALID_THEME_LINK_VALUE",
|
|
53407
|
+
`theme.json.links.${linkKey}`,
|
|
53408
|
+
`theme link '${linkKey}' must be an absolute http, https, or mailto URL`,
|
|
53409
|
+
"error"
|
|
53410
|
+
));
|
|
53411
|
+
continue;
|
|
53412
|
+
}
|
|
53413
|
+
normalizedLinks[linkKey] = normalizedValue;
|
|
53414
|
+
}
|
|
53415
|
+
return Object.keys(normalizedLinks).length > 0 ? normalizedLinks : void 0;
|
|
53416
|
+
}
|
|
53214
53417
|
function validateHelperMetadataMap(rawValue, fieldName, issueCodes, errors) {
|
|
53215
53418
|
if (rawValue === void 0) {
|
|
53216
53419
|
return void 0;
|
|
@@ -53312,7 +53515,7 @@ function validateSiteMetaMap(rawValue, errors) {
|
|
|
53312
53515
|
errors.push(issue2(
|
|
53313
53516
|
"INVALID_SITE_META",
|
|
53314
53517
|
"theme.json",
|
|
53315
|
-
"theme.json field '
|
|
53518
|
+
"theme.json field 'site_meta' must be an object when present",
|
|
53316
53519
|
"error"
|
|
53317
53520
|
));
|
|
53318
53521
|
return void 0;
|
|
@@ -53322,7 +53525,7 @@ function validateSiteMetaMap(rawValue, errors) {
|
|
|
53322
53525
|
errors.push(issue2(
|
|
53323
53526
|
"INVALID_SITE_META",
|
|
53324
53527
|
"theme.json",
|
|
53325
|
-
"theme.json field '
|
|
53528
|
+
"theme.json field 'site_meta' must not be empty",
|
|
53326
53529
|
"error"
|
|
53327
53530
|
));
|
|
53328
53531
|
}
|
|
@@ -53330,7 +53533,7 @@ function validateSiteMetaMap(rawValue, errors) {
|
|
|
53330
53533
|
errors.push(issue2(
|
|
53331
53534
|
"INVALID_SITE_META",
|
|
53332
53535
|
"theme.json",
|
|
53333
|
-
`theme.json field '
|
|
53536
|
+
`theme.json field 'site_meta' must contain at most ${SITE_META_COUNT_MAX} keys`,
|
|
53334
53537
|
"error"
|
|
53335
53538
|
));
|
|
53336
53539
|
}
|
|
@@ -53339,8 +53542,8 @@ function validateSiteMetaMap(rawValue, errors) {
|
|
|
53339
53542
|
if (!SITE_META_KEY_REGEX.test(metaKey) || metaKey.length > SITE_META_KEY_MAX_LENGTH) {
|
|
53340
53543
|
errors.push(issue2(
|
|
53341
53544
|
"INVALID_SITE_META_KEY",
|
|
53342
|
-
`theme.json.
|
|
53343
|
-
`
|
|
53545
|
+
`theme.json.site_meta.${metaKey}`,
|
|
53546
|
+
`site_meta key '${metaKey}' must start with a lowercase letter and use lowercase letters, digits, underscores, or internal hyphens only`,
|
|
53344
53547
|
"error"
|
|
53345
53548
|
));
|
|
53346
53549
|
continue;
|
|
@@ -53348,8 +53551,8 @@ function validateSiteMetaMap(rawValue, errors) {
|
|
|
53348
53551
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
53349
53552
|
errors.push(issue2(
|
|
53350
53553
|
"INVALID_SITE_META_FIELD",
|
|
53351
|
-
`theme.json.
|
|
53352
|
-
`
|
|
53554
|
+
`theme.json.site_meta.${metaKey}`,
|
|
53555
|
+
`site_meta key '${metaKey}' must be an object`,
|
|
53353
53556
|
"error"
|
|
53354
53557
|
));
|
|
53355
53558
|
continue;
|
|
@@ -53359,8 +53562,8 @@ function validateSiteMetaMap(rawValue, errors) {
|
|
|
53359
53562
|
if (!allowedKeys.has(key)) {
|
|
53360
53563
|
errors.push(issue2(
|
|
53361
53564
|
"INVALID_SITE_META_PROPERTY",
|
|
53362
|
-
`theme.json.
|
|
53363
|
-
`Unknown
|
|
53565
|
+
`theme.json.site_meta.${metaKey}.${key}`,
|
|
53566
|
+
`Unknown site_meta property '${key}' in key '${metaKey}'`,
|
|
53364
53567
|
"error"
|
|
53365
53568
|
));
|
|
53366
53569
|
}
|
|
@@ -53368,31 +53571,31 @@ function validateSiteMetaMap(rawValue, errors) {
|
|
|
53368
53571
|
if (typeof value.title !== "string" || value.title.trim() === "") {
|
|
53369
53572
|
errors.push(issue2(
|
|
53370
53573
|
"INVALID_SITE_META_TITLE",
|
|
53371
|
-
`theme.json.
|
|
53372
|
-
`
|
|
53574
|
+
`theme.json.site_meta.${metaKey}.title`,
|
|
53575
|
+
`site_meta key '${metaKey}' must define a non-empty 'title'`,
|
|
53373
53576
|
"error"
|
|
53374
53577
|
));
|
|
53375
53578
|
} else if (value.title.trim().length > MENU_SLOT_TITLE_MAX_LENGTH) {
|
|
53376
53579
|
errors.push(issue2(
|
|
53377
53580
|
"INVALID_SITE_META_TITLE",
|
|
53378
|
-
`theme.json.
|
|
53379
|
-
`
|
|
53581
|
+
`theme.json.site_meta.${metaKey}.title`,
|
|
53582
|
+
`site_meta key '${metaKey}' title must be at most ${MENU_SLOT_TITLE_MAX_LENGTH} characters`,
|
|
53380
53583
|
"error"
|
|
53381
53584
|
));
|
|
53382
53585
|
}
|
|
53383
53586
|
if (value.description !== void 0 && (typeof value.description !== "string" || value.description.trim().length > MENU_SLOT_DESCRIPTION_MAX_LENGTH)) {
|
|
53384
53587
|
errors.push(issue2(
|
|
53385
53588
|
"INVALID_SITE_META_DESCRIPTION",
|
|
53386
|
-
`theme.json.
|
|
53387
|
-
`
|
|
53589
|
+
`theme.json.site_meta.${metaKey}.description`,
|
|
53590
|
+
`site_meta key '${metaKey}' description must be a string at most ${MENU_SLOT_DESCRIPTION_MAX_LENGTH} characters`,
|
|
53388
53591
|
"error"
|
|
53389
53592
|
));
|
|
53390
53593
|
}
|
|
53391
53594
|
if (value.type !== void 0 && !SITE_META_TYPES.has(value.type)) {
|
|
53392
53595
|
errors.push(issue2(
|
|
53393
53596
|
"INVALID_SITE_META_TYPE",
|
|
53394
|
-
`theme.json.
|
|
53395
|
-
`
|
|
53597
|
+
`theme.json.site_meta.${metaKey}.type`,
|
|
53598
|
+
`site_meta key '${metaKey}' type must be one of: string, number, boolean`,
|
|
53396
53599
|
"error"
|
|
53397
53600
|
));
|
|
53398
53601
|
}
|
|
@@ -53401,15 +53604,15 @@ function validateSiteMetaMap(rawValue, errors) {
|
|
|
53401
53604
|
if (value.default !== null && defaultType !== "string" && defaultType !== "number" && defaultType !== "boolean") {
|
|
53402
53605
|
errors.push(issue2(
|
|
53403
53606
|
"INVALID_SITE_META_DEFAULT",
|
|
53404
|
-
`theme.json.
|
|
53405
|
-
`
|
|
53607
|
+
`theme.json.site_meta.${metaKey}.default`,
|
|
53608
|
+
`site_meta key '${metaKey}' default must be a string, number, boolean, or null`,
|
|
53406
53609
|
"error"
|
|
53407
53610
|
));
|
|
53408
53611
|
} else if (typeof value.type === "string" && SITE_META_TYPES.has(value.type) && value.default !== null && defaultType !== value.type) {
|
|
53409
53612
|
errors.push(issue2(
|
|
53410
53613
|
"INVALID_SITE_META_DEFAULT",
|
|
53411
|
-
`theme.json.
|
|
53412
|
-
`
|
|
53614
|
+
`theme.json.site_meta.${metaKey}.default`,
|
|
53615
|
+
`site_meta key '${metaKey}' default must match its declared type`,
|
|
53413
53616
|
"error"
|
|
53414
53617
|
));
|
|
53415
53618
|
}
|
|
@@ -53454,11 +53657,16 @@ async function validateThemeFiles(fileMap, options2 = {}) {
|
|
|
53454
53657
|
manifest = manifestResult.manifest;
|
|
53455
53658
|
errors.push(...manifestResult.errors);
|
|
53456
53659
|
} catch (error) {
|
|
53660
|
+
const rawThemeJson = getText(files.get("theme.json"));
|
|
53457
53661
|
errors.push(issue2(
|
|
53458
53662
|
"INVALID_THEME_JSON",
|
|
53459
53663
|
"theme.json",
|
|
53460
53664
|
`Invalid theme.json: ${error instanceof Error ? error.message : String(error)}`,
|
|
53461
|
-
"error"
|
|
53665
|
+
"error",
|
|
53666
|
+
{
|
|
53667
|
+
...locationForJsonParseError(error, rawThemeJson),
|
|
53668
|
+
category: "json_syntax"
|
|
53669
|
+
}
|
|
53462
53670
|
));
|
|
53463
53671
|
}
|
|
53464
53672
|
}
|
|
@@ -53524,7 +53732,11 @@ function validateManifest(themeJson) {
|
|
|
53524
53732
|
"UNKNOWN_THEME_MANIFEST_FIELD",
|
|
53525
53733
|
`theme.json.${key}`,
|
|
53526
53734
|
`Unknown theme.json field '${key}'`,
|
|
53527
|
-
"error"
|
|
53735
|
+
"error",
|
|
53736
|
+
{
|
|
53737
|
+
category: "theme_manifest",
|
|
53738
|
+
hint: themeManifestFieldHint(key)
|
|
53739
|
+
}
|
|
53528
53740
|
));
|
|
53529
53741
|
}
|
|
53530
53742
|
}
|
|
@@ -53555,13 +53767,24 @@ function validateManifest(themeJson) {
|
|
|
53555
53767
|
errors.push(issue2("INVALID_SEMVER", "theme.json", "Theme version must follow semantic versioning (e.g. 1.0.0)", "error"));
|
|
53556
53768
|
}
|
|
53557
53769
|
if (typeof themeJson.runtime === "string" && !SUPPORTED_RUNTIME_SET.has(themeJson.runtime.trim())) {
|
|
53558
|
-
errors.push(issue2(
|
|
53770
|
+
errors.push(issue2(
|
|
53771
|
+
"INVALID_RUNTIME_VERSION",
|
|
53772
|
+
"theme.json",
|
|
53773
|
+
`theme.json field 'runtime' must be one of: ${SUPPORTED_RUNTIMES.join(", ")}`,
|
|
53774
|
+
"error",
|
|
53775
|
+
{
|
|
53776
|
+
category: "theme_manifest",
|
|
53777
|
+
hint: `Update theme.json:
|
|
53778
|
+
|
|
53779
|
+
"runtime": "${THEME_RUNTIME_V0_6}"`
|
|
53780
|
+
}
|
|
53781
|
+
));
|
|
53559
53782
|
}
|
|
53560
|
-
if (typeof themeJson.license === "string" && !
|
|
53783
|
+
if (typeof themeJson.license === "string" && !isAllowedLicense(themeJson.license.trim())) {
|
|
53561
53784
|
errors.push(issue2(
|
|
53562
53785
|
"INVALID_LICENSE",
|
|
53563
53786
|
"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",
|
|
53787
|
+
"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
53788
|
"error"
|
|
53566
53789
|
));
|
|
53567
53790
|
}
|
|
@@ -53625,11 +53848,15 @@ function validateManifest(themeJson) {
|
|
|
53625
53848
|
manifest.thumbnail = themeJson.thumbnail;
|
|
53626
53849
|
}
|
|
53627
53850
|
}
|
|
53851
|
+
const links = validateThemeLinks(themeJson.links, errors);
|
|
53852
|
+
if (links) {
|
|
53853
|
+
manifest.links = links;
|
|
53854
|
+
}
|
|
53628
53855
|
const features = validateFeatureFlags(themeJson.features, errors);
|
|
53629
53856
|
if (features) {
|
|
53630
53857
|
manifest.features = features;
|
|
53631
53858
|
}
|
|
53632
|
-
const
|
|
53859
|
+
const menu_slots = validateHelperMetadataMap(themeJson.menu_slots, "menu_slots", {
|
|
53633
53860
|
itemLabel: "Menu slot",
|
|
53634
53861
|
propertyLabel: "menu slot property",
|
|
53635
53862
|
collectionLabel: "slots",
|
|
@@ -53640,10 +53867,10 @@ function validateManifest(themeJson) {
|
|
|
53640
53867
|
invalidTitleCode: "INVALID_MENU_SLOT_TITLE",
|
|
53641
53868
|
invalidDescriptionCode: "INVALID_MENU_SLOT_DESCRIPTION"
|
|
53642
53869
|
}, errors);
|
|
53643
|
-
if (
|
|
53644
|
-
manifest.
|
|
53870
|
+
if (menu_slots) {
|
|
53871
|
+
manifest.menu_slots = menu_slots;
|
|
53645
53872
|
}
|
|
53646
|
-
const
|
|
53873
|
+
const widget_areas = validateHelperMetadataMap(themeJson.widget_areas, "widget_areas", {
|
|
53647
53874
|
itemLabel: "Widget area",
|
|
53648
53875
|
propertyLabel: "widget area property",
|
|
53649
53876
|
collectionLabel: "areas",
|
|
@@ -53654,14 +53881,14 @@ function validateManifest(themeJson) {
|
|
|
53654
53881
|
invalidTitleCode: "INVALID_WIDGET_AREA_TITLE",
|
|
53655
53882
|
invalidDescriptionCode: "INVALID_WIDGET_AREA_DESCRIPTION"
|
|
53656
53883
|
}, errors);
|
|
53657
|
-
if (
|
|
53658
|
-
manifest.
|
|
53884
|
+
if (widget_areas) {
|
|
53885
|
+
manifest.widget_areas = widget_areas;
|
|
53659
53886
|
}
|
|
53660
|
-
const
|
|
53661
|
-
if (
|
|
53662
|
-
manifest.
|
|
53887
|
+
const site_meta = validateSiteMetaMap(themeJson.site_meta, errors);
|
|
53888
|
+
if (site_meta) {
|
|
53889
|
+
manifest.site_meta = site_meta;
|
|
53663
53890
|
}
|
|
53664
|
-
const
|
|
53891
|
+
const collection_slots = validateHelperMetadataMap(themeJson.collection_slots, "collection_slots", {
|
|
53665
53892
|
itemLabel: "Collection slot",
|
|
53666
53893
|
propertyLabel: "collection slot property",
|
|
53667
53894
|
collectionLabel: "slots",
|
|
@@ -53672,8 +53899,8 @@ function validateManifest(themeJson) {
|
|
|
53672
53899
|
invalidTitleCode: "INVALID_COLLECTION_SLOT_TITLE",
|
|
53673
53900
|
invalidDescriptionCode: "INVALID_COLLECTION_SLOT_DESCRIPTION"
|
|
53674
53901
|
}, errors);
|
|
53675
|
-
if (
|
|
53676
|
-
manifest.
|
|
53902
|
+
if (collection_slots) {
|
|
53903
|
+
manifest.collection_slots = collection_slots;
|
|
53677
53904
|
}
|
|
53678
53905
|
return { errors, manifest: errors.length > 0 ? void 0 : manifest };
|
|
53679
53906
|
}
|
|
@@ -53685,8 +53912,20 @@ function validateTemplateSyntax(templatePath, content, context) {
|
|
|
53685
53912
|
if (contentSlotMatches.length !== 1) {
|
|
53686
53913
|
errors.push(issue2("INVALID_LAYOUT_SLOT", "layout.html", "layout.html must contain exactly one {{slot:content}}", "error"));
|
|
53687
53914
|
}
|
|
53688
|
-
|
|
53689
|
-
|
|
53915
|
+
const scriptMatch = /<script\b/i.exec(content);
|
|
53916
|
+
if (scriptMatch) {
|
|
53917
|
+
errors.push(issue2(
|
|
53918
|
+
"LAYOUT_SCRIPT_NOT_ALLOWED",
|
|
53919
|
+
"layout.html",
|
|
53920
|
+
"layout.html must not contain <script> tags",
|
|
53921
|
+
"error",
|
|
53922
|
+
{
|
|
53923
|
+
...locationForIndex(content, scriptMatch.index),
|
|
53924
|
+
category: "theme_validation",
|
|
53925
|
+
hint: "Move shared scripts into a partial such as {{partial:content-enhancements}}, then include that partial from layout.html.",
|
|
53926
|
+
snippet: snippetForIndex(content, scriptMatch.index)
|
|
53927
|
+
}
|
|
53928
|
+
));
|
|
53690
53929
|
}
|
|
53691
53930
|
}
|
|
53692
53931
|
let match2;
|
|
@@ -53737,7 +53976,9 @@ function validateRuntimeV05TemplateSyntax(templatePath, content, errors) {
|
|
|
53737
53976
|
index = end + 2;
|
|
53738
53977
|
if (token.startsWith("partial:")) {
|
|
53739
53978
|
try {
|
|
53740
|
-
parsePartialReferenceToken(token
|
|
53979
|
+
parsePartialReferenceToken(token, {
|
|
53980
|
+
allowedSingleSegmentPaths: getPartialArgScope(stack)
|
|
53981
|
+
});
|
|
53741
53982
|
} catch (error) {
|
|
53742
53983
|
errors.push(issue2(
|
|
53743
53984
|
"INVALID_PARTIAL_REFERENCE",
|
|
@@ -53762,7 +54003,7 @@ function validateRuntimeV05TemplateSyntax(templatePath, content, errors) {
|
|
|
53762
54003
|
}
|
|
53763
54004
|
if (token === "#else") {
|
|
53764
54005
|
const current = stack[stack.length - 1];
|
|
53765
|
-
if (!current || current.tag !== "if" && current.tag
|
|
54006
|
+
if (!current || current.tag !== "if" && !COMPARISON_BLOCK_TAGS.has(current.tag)) {
|
|
53766
54007
|
errors.push(issue2("UNEXPECTED_TEMPLATE_ELSE", templatePath, `Unexpected {{#else}} in ${templatePath}`, "error"));
|
|
53767
54008
|
return;
|
|
53768
54009
|
}
|
|
@@ -53773,9 +54014,11 @@ function validateRuntimeV05TemplateSyntax(templatePath, content, errors) {
|
|
|
53773
54014
|
current.hasElse = true;
|
|
53774
54015
|
continue;
|
|
53775
54016
|
}
|
|
53776
|
-
|
|
54017
|
+
const comparisonElseIfTag = getComparisonElseIfTag(token);
|
|
54018
|
+
if (comparisonElseIfTag) {
|
|
53777
54019
|
const current = stack[stack.length - 1];
|
|
53778
|
-
|
|
54020
|
+
const expectedBlockTag = comparisonElseIfTag.replace(/^else_/, "");
|
|
54021
|
+
if (!current || current.tag !== expectedBlockTag) {
|
|
53779
54022
|
errors.push(issue2("UNEXPECTED_TEMPLATE_ELSE_IF", templatePath, `Unexpected {{${token}}} in ${templatePath}`, "error"));
|
|
53780
54023
|
return;
|
|
53781
54024
|
}
|
|
@@ -53783,13 +54026,13 @@ function validateRuntimeV05TemplateSyntax(templatePath, content, errors) {
|
|
|
53783
54026
|
errors.push(issue2("INVALID_TEMPLATE_BRANCH_ORDER", templatePath, `{{${token}}} cannot appear after {{#else}} in ${templatePath}`, "error"));
|
|
53784
54027
|
return;
|
|
53785
54028
|
}
|
|
53786
|
-
const expression = token.slice(
|
|
53787
|
-
const parsed =
|
|
54029
|
+
const expression = token.slice(`#${comparisonElseIfTag} `.length).trim();
|
|
54030
|
+
const parsed = parseComparisonExpression(expression, comparisonElseIfTag);
|
|
53788
54031
|
if (!parsed) {
|
|
53789
54032
|
errors.push(issue2("UNSUPPORTED_TEMPLATE_TAG", templatePath, `Unsupported template tag '{{${token}}}' in ${templatePath}`, "error"));
|
|
53790
54033
|
return;
|
|
53791
54034
|
}
|
|
53792
|
-
|
|
54035
|
+
validateComparisonPathUsage(parsed, templatePath, errors, stack, { isPartialFile });
|
|
53793
54036
|
continue;
|
|
53794
54037
|
}
|
|
53795
54038
|
if (token.startsWith("#else_if ")) {
|
|
@@ -53812,7 +54055,7 @@ function validateRuntimeV05TemplateSyntax(templatePath, content, errors) {
|
|
|
53812
54055
|
}
|
|
53813
54056
|
if (token.startsWith("/")) {
|
|
53814
54057
|
const closingTag = token.slice(1).trim();
|
|
53815
|
-
if (!["if", "
|
|
54058
|
+
if (!["if", "for", ...COMPARISON_BLOCK_TAGS].includes(closingTag)) {
|
|
53816
54059
|
errors.push(issue2("UNSUPPORTED_TEMPLATE_TAG", templatePath, `Unsupported template closing tag '{{${token}}}' in ${templatePath}`, "error"));
|
|
53817
54060
|
return;
|
|
53818
54061
|
}
|
|
@@ -53833,22 +54076,23 @@ function validateRuntimeV05TemplateSyntax(templatePath, content, errors) {
|
|
|
53833
54076
|
stack.push({ tag: "if", hasElse: false });
|
|
53834
54077
|
continue;
|
|
53835
54078
|
}
|
|
53836
|
-
|
|
53837
|
-
|
|
53838
|
-
const
|
|
54079
|
+
const comparisonBlockTag = getComparisonBlockTag(token);
|
|
54080
|
+
if (comparisonBlockTag) {
|
|
54081
|
+
const expression = token.slice(`#${comparisonBlockTag} `.length).trim();
|
|
54082
|
+
const parsed = parseComparisonExpression(expression, comparisonBlockTag);
|
|
53839
54083
|
if (!parsed) {
|
|
53840
54084
|
errors.push(issue2("UNSUPPORTED_TEMPLATE_TAG", templatePath, `Unsupported template tag '{{${token}}}' in ${templatePath}`, "error"));
|
|
53841
54085
|
return;
|
|
53842
54086
|
}
|
|
53843
|
-
|
|
53844
|
-
stack.push({ tag:
|
|
54087
|
+
validateComparisonPathUsage(parsed, templatePath, errors, stack, { isPartialFile });
|
|
54088
|
+
stack.push({ tag: comparisonBlockTag, hasElse: false });
|
|
53845
54089
|
continue;
|
|
53846
54090
|
}
|
|
53847
54091
|
const forMatch = FOR_TAG_REGEX.exec(token);
|
|
53848
54092
|
if (forMatch) {
|
|
53849
54093
|
const path4 = forMatch[2];
|
|
53850
54094
|
validateReservedPathUsage(path4, templatePath, errors, stack, { isPartialFile });
|
|
53851
|
-
stack.push({ tag: "for", hasElse: false });
|
|
54095
|
+
stack.push({ tag: "for", itemName: forMatch[1], hasElse: false });
|
|
53852
54096
|
continue;
|
|
53853
54097
|
}
|
|
53854
54098
|
errors.push(issue2("UNSUPPORTED_TEMPLATE_TAG", templatePath, `Unsupported template tag '{{${token}}}' in ${templatePath}`, "error"));
|
|
@@ -53881,16 +54125,124 @@ function validateReservedPathUsage(path4, templatePath, errors, stack, options2
|
|
|
53881
54125
|
));
|
|
53882
54126
|
}
|
|
53883
54127
|
}
|
|
53884
|
-
function
|
|
53885
|
-
const
|
|
53886
|
-
|
|
54128
|
+
function validateComparisonPathUsage(parsed, templatePath, errors, stack, options2) {
|
|
54129
|
+
for (const operand of [parsed.left, ...parsed.operands]) {
|
|
54130
|
+
if (operand.kind === "path") {
|
|
54131
|
+
validateReservedPathUsage(operand.path, templatePath, errors, stack, options2);
|
|
54132
|
+
}
|
|
54133
|
+
}
|
|
54134
|
+
}
|
|
54135
|
+
function getComparisonBlockTag(token) {
|
|
54136
|
+
for (const tagName of COMPARISON_BLOCK_TAGS) {
|
|
54137
|
+
if (token.startsWith(`#${tagName} `)) {
|
|
54138
|
+
return tagName;
|
|
54139
|
+
}
|
|
54140
|
+
}
|
|
54141
|
+
return "";
|
|
54142
|
+
}
|
|
54143
|
+
function getComparisonElseIfTag(token) {
|
|
54144
|
+
for (const tagName of COMPARISON_ELSE_IF_TAGS) {
|
|
54145
|
+
if (token.startsWith(`#${tagName} `)) {
|
|
54146
|
+
return tagName;
|
|
54147
|
+
}
|
|
54148
|
+
}
|
|
54149
|
+
return "";
|
|
54150
|
+
}
|
|
54151
|
+
function parseComparisonExpression(expression, tagName) {
|
|
54152
|
+
const operator = COMPARISON_TAG_OPERATORS[tagName];
|
|
54153
|
+
let tokens;
|
|
54154
|
+
try {
|
|
54155
|
+
tokens = tokenizeExpression(expression);
|
|
54156
|
+
} catch {
|
|
54157
|
+
return null;
|
|
54158
|
+
}
|
|
54159
|
+
if (!operator || operator === "in" && tokens.length < 2 || operator !== "in" && tokens.length !== 2) {
|
|
54160
|
+
return null;
|
|
54161
|
+
}
|
|
54162
|
+
const left = parsePathOperand(tokens[0]);
|
|
54163
|
+
if (!left) {
|
|
53887
54164
|
return null;
|
|
53888
54165
|
}
|
|
54166
|
+
const operands = [];
|
|
54167
|
+
for (const token of tokens.slice(1)) {
|
|
54168
|
+
const operand = parseComparisonOperand(token);
|
|
54169
|
+
if (!operand) {
|
|
54170
|
+
return null;
|
|
54171
|
+
}
|
|
54172
|
+
operands.push(operand);
|
|
54173
|
+
}
|
|
53889
54174
|
return {
|
|
53890
|
-
|
|
53891
|
-
|
|
54175
|
+
operator,
|
|
54176
|
+
left,
|
|
54177
|
+
operands
|
|
53892
54178
|
};
|
|
53893
54179
|
}
|
|
54180
|
+
function tokenizeExpression(expression) {
|
|
54181
|
+
const tokens = [];
|
|
54182
|
+
let index = 0;
|
|
54183
|
+
while (index < expression.length) {
|
|
54184
|
+
while (/\s/.test(expression[index] || "")) {
|
|
54185
|
+
index += 1;
|
|
54186
|
+
}
|
|
54187
|
+
if (index >= expression.length) {
|
|
54188
|
+
break;
|
|
54189
|
+
}
|
|
54190
|
+
if (expression[index] === '"') {
|
|
54191
|
+
const start2 = index;
|
|
54192
|
+
index += 1;
|
|
54193
|
+
let escaped = false;
|
|
54194
|
+
while (index < expression.length) {
|
|
54195
|
+
const char = expression[index];
|
|
54196
|
+
if (escaped) {
|
|
54197
|
+
escaped = false;
|
|
54198
|
+
} else if (char === "\\") {
|
|
54199
|
+
escaped = true;
|
|
54200
|
+
} else if (char === '"') {
|
|
54201
|
+
index += 1;
|
|
54202
|
+
tokens.push(expression.slice(start2, index));
|
|
54203
|
+
break;
|
|
54204
|
+
}
|
|
54205
|
+
index += 1;
|
|
54206
|
+
}
|
|
54207
|
+
if (tokens[tokens.length - 1] !== expression.slice(start2, index)) {
|
|
54208
|
+
throw new Error(`Unclosed string literal in expression: ${expression}`);
|
|
54209
|
+
}
|
|
54210
|
+
continue;
|
|
54211
|
+
}
|
|
54212
|
+
const start = index;
|
|
54213
|
+
while (index < expression.length && !/\s/.test(expression[index])) {
|
|
54214
|
+
index += 1;
|
|
54215
|
+
}
|
|
54216
|
+
tokens.push(expression.slice(start, index));
|
|
54217
|
+
}
|
|
54218
|
+
return tokens;
|
|
54219
|
+
}
|
|
54220
|
+
function parsePathOperand(token) {
|
|
54221
|
+
return TEMPLATE_PATH_REGEX.test(token) ? { kind: "path", path: token } : null;
|
|
54222
|
+
}
|
|
54223
|
+
function parseComparisonOperand(token) {
|
|
54224
|
+
if (token.startsWith('"')) {
|
|
54225
|
+
try {
|
|
54226
|
+
const value = JSON.parse(token);
|
|
54227
|
+
return typeof value === "string" ? { kind: "literal", value } : null;
|
|
54228
|
+
} catch {
|
|
54229
|
+
return null;
|
|
54230
|
+
}
|
|
54231
|
+
}
|
|
54232
|
+
if (token === "true") {
|
|
54233
|
+
return { kind: "literal", value: true };
|
|
54234
|
+
}
|
|
54235
|
+
if (token === "false") {
|
|
54236
|
+
return { kind: "literal", value: false };
|
|
54237
|
+
}
|
|
54238
|
+
if (token === "null") {
|
|
54239
|
+
return { kind: "literal", value: null };
|
|
54240
|
+
}
|
|
54241
|
+
if (NUMBER_LITERAL_REGEX.test(token)) {
|
|
54242
|
+
return { kind: "literal", value: Number(token) };
|
|
54243
|
+
}
|
|
54244
|
+
return parsePathOperand(token);
|
|
54245
|
+
}
|
|
53894
54246
|
function validatePartialReferences(templateContents, partialContents, context) {
|
|
53895
54247
|
const { errors } = context;
|
|
53896
54248
|
for (const [templatePath, content] of templateContents.entries()) {
|
|
@@ -53956,7 +54308,7 @@ function getReferencedPartialNames(content) {
|
|
|
53956
54308
|
let match2;
|
|
53957
54309
|
while ((match2 = PARTIAL_TAG_REGEX.exec(content)) !== null) {
|
|
53958
54310
|
try {
|
|
53959
|
-
const { name } = parsePartialReferenceToken(match2[1]);
|
|
54311
|
+
const { name } = parsePartialReferenceToken(match2[1], { validateArgs: false });
|
|
53960
54312
|
matches.add(name);
|
|
53961
54313
|
} catch {
|
|
53962
54314
|
}
|
|
@@ -53964,7 +54316,7 @@ function getReferencedPartialNames(content) {
|
|
|
53964
54316
|
PARTIAL_TAG_REGEX.lastIndex = 0;
|
|
53965
54317
|
return matches;
|
|
53966
54318
|
}
|
|
53967
|
-
function parsePartialReferenceToken(token) {
|
|
54319
|
+
function parsePartialReferenceToken(token, options2 = {}) {
|
|
53968
54320
|
const source = String(token || "").trim();
|
|
53969
54321
|
if (!source.startsWith("partial:")) {
|
|
53970
54322
|
throw new Error("Partial token must start with partial:");
|
|
@@ -53979,10 +54331,12 @@ function parsePartialReferenceToken(token) {
|
|
|
53979
54331
|
throw new Error(`Invalid partial name '${name}'`);
|
|
53980
54332
|
}
|
|
53981
54333
|
const argsSource = expression.slice(name.length).trim();
|
|
53982
|
-
|
|
54334
|
+
if (options2.validateArgs !== false) {
|
|
54335
|
+
parsePartialArgs(argsSource, options2);
|
|
54336
|
+
}
|
|
53983
54337
|
return { name };
|
|
53984
54338
|
}
|
|
53985
|
-
function parsePartialArgs(source) {
|
|
54339
|
+
function parsePartialArgs(source, options2 = {}) {
|
|
53986
54340
|
if (!source) {
|
|
53987
54341
|
return {};
|
|
53988
54342
|
}
|
|
@@ -54034,7 +54388,8 @@ function parsePartialArgs(source) {
|
|
|
54034
54388
|
if (cursor >= source.length || source[cursor] !== '"') {
|
|
54035
54389
|
throw new Error(`Unclosed string literal for partial argument '${key}'`);
|
|
54036
54390
|
}
|
|
54037
|
-
|
|
54391
|
+
JSON.parse(source.slice(index, cursor + 1));
|
|
54392
|
+
args[key] = true;
|
|
54038
54393
|
index = cursor + 1;
|
|
54039
54394
|
continue;
|
|
54040
54395
|
}
|
|
@@ -54044,10 +54399,25 @@ function parsePartialArgs(source) {
|
|
|
54044
54399
|
continue;
|
|
54045
54400
|
}
|
|
54046
54401
|
if (source.startsWith("false", index) && isValueBoundary(source, index + 5)) {
|
|
54047
|
-
args[key] =
|
|
54402
|
+
args[key] = true;
|
|
54048
54403
|
index += 5;
|
|
54049
54404
|
continue;
|
|
54050
54405
|
}
|
|
54406
|
+
if (source.startsWith("null", index) && isValueBoundary(source, index + 4)) {
|
|
54407
|
+
args[key] = true;
|
|
54408
|
+
index += 4;
|
|
54409
|
+
continue;
|
|
54410
|
+
}
|
|
54411
|
+
const valueMatch = /^\S+/.exec(source.slice(index));
|
|
54412
|
+
if (!valueMatch) {
|
|
54413
|
+
throw new Error(`Missing partial argument value for '${key}'`);
|
|
54414
|
+
}
|
|
54415
|
+
const valueToken = valueMatch[0];
|
|
54416
|
+
if (NUMBER_LITERAL_REGEX.test(valueToken) || TEMPLATE_PATH_REGEX.test(valueToken) && isAllowedPartialArgPath(valueToken, options2)) {
|
|
54417
|
+
args[key] = true;
|
|
54418
|
+
index += valueToken.length;
|
|
54419
|
+
continue;
|
|
54420
|
+
}
|
|
54051
54421
|
throw new Error(`Unsupported partial argument value for '${key}'`);
|
|
54052
54422
|
}
|
|
54053
54423
|
return args;
|
|
@@ -54055,6 +54425,23 @@ function parsePartialArgs(source) {
|
|
|
54055
54425
|
function isValueBoundary(source, index) {
|
|
54056
54426
|
return index >= source.length || /\s/.test(source[index]);
|
|
54057
54427
|
}
|
|
54428
|
+
function isAllowedPartialArgPath(valueToken, options2) {
|
|
54429
|
+
if (valueToken.includes(".")) {
|
|
54430
|
+
return true;
|
|
54431
|
+
}
|
|
54432
|
+
const allowedSingleSegmentPaths = options2?.allowedSingleSegmentPaths;
|
|
54433
|
+
return allowedSingleSegmentPaths instanceof Set && allowedSingleSegmentPaths.has(valueToken);
|
|
54434
|
+
}
|
|
54435
|
+
function getPartialArgScope(stack) {
|
|
54436
|
+
const scope = new Set(PARTIAL_ARG_ROOT_PATHS);
|
|
54437
|
+
for (const entry of stack) {
|
|
54438
|
+
if (entry.tag === "for" && typeof entry.itemName === "string") {
|
|
54439
|
+
scope.add(entry.itemName);
|
|
54440
|
+
scope.add("loop");
|
|
54441
|
+
}
|
|
54442
|
+
}
|
|
54443
|
+
return scope;
|
|
54444
|
+
}
|
|
54058
54445
|
function validatePathSafety(pathEntries, errors) {
|
|
54059
54446
|
for (const entry of pathEntries) {
|
|
54060
54447
|
const entryPath = normalizePath(String(entry.path || ""));
|
|
@@ -54102,13 +54489,71 @@ function normalizeAbsolutePath(value) {
|
|
|
54102
54489
|
function isPathInsideRoot(candidate, root) {
|
|
54103
54490
|
return candidate === root || candidate.startsWith(`${root}/`);
|
|
54104
54491
|
}
|
|
54105
|
-
function issue2(code2, filePath, message, severity) {
|
|
54106
|
-
|
|
54492
|
+
function issue2(code2, filePath, message, severity, details = {}) {
|
|
54493
|
+
const nextIssue = {
|
|
54107
54494
|
code: code2,
|
|
54108
54495
|
path: filePath,
|
|
54109
54496
|
message,
|
|
54110
54497
|
severity
|
|
54111
54498
|
};
|
|
54499
|
+
if (Number.isInteger(details.line) && details.line > 0) {
|
|
54500
|
+
nextIssue.line = details.line;
|
|
54501
|
+
}
|
|
54502
|
+
if (Number.isInteger(details.column) && details.column > 0) {
|
|
54503
|
+
nextIssue.column = details.column;
|
|
54504
|
+
}
|
|
54505
|
+
if (typeof details.hint === "string" && details.hint.trim()) {
|
|
54506
|
+
nextIssue.hint = details.hint;
|
|
54507
|
+
}
|
|
54508
|
+
if (typeof details.category === "string" && details.category.trim()) {
|
|
54509
|
+
nextIssue.category = details.category;
|
|
54510
|
+
}
|
|
54511
|
+
if (details.snippet && typeof details.snippet === "object" && typeof details.snippet.line === "string" && typeof details.snippet.pointer === "string") {
|
|
54512
|
+
nextIssue.snippet = {
|
|
54513
|
+
line: details.snippet.line,
|
|
54514
|
+
pointer: details.snippet.pointer
|
|
54515
|
+
};
|
|
54516
|
+
}
|
|
54517
|
+
return nextIssue;
|
|
54518
|
+
}
|
|
54519
|
+
function locationForJsonParseError(error, source) {
|
|
54520
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
54521
|
+
const lineColumnMatch = /\bline\s+(\d+)\s+column\s+(\d+)/i.exec(message);
|
|
54522
|
+
if (lineColumnMatch) {
|
|
54523
|
+
return {
|
|
54524
|
+
line: Number(lineColumnMatch[1]),
|
|
54525
|
+
column: Number(lineColumnMatch[2])
|
|
54526
|
+
};
|
|
54527
|
+
}
|
|
54528
|
+
const positionMatch = /\bposition\s+(\d+)/i.exec(message);
|
|
54529
|
+
if (positionMatch) {
|
|
54530
|
+
return locationForIndex(source, Number(positionMatch[1]));
|
|
54531
|
+
}
|
|
54532
|
+
if (/Unexpected end of JSON input/i.test(message)) {
|
|
54533
|
+
return locationForIndex(source, source.length);
|
|
54534
|
+
}
|
|
54535
|
+
return {};
|
|
54536
|
+
}
|
|
54537
|
+
function locationForIndex(source, index) {
|
|
54538
|
+
const boundedIndex = Math.max(0, Math.min(Number.isInteger(index) ? index : 0, source.length));
|
|
54539
|
+
let line = 1;
|
|
54540
|
+
let column = 1;
|
|
54541
|
+
for (let cursor = 0; cursor < boundedIndex; cursor += 1) {
|
|
54542
|
+
if (source[cursor] === "\n") {
|
|
54543
|
+
line += 1;
|
|
54544
|
+
column = 1;
|
|
54545
|
+
} else {
|
|
54546
|
+
column += 1;
|
|
54547
|
+
}
|
|
54548
|
+
}
|
|
54549
|
+
return { line, column };
|
|
54550
|
+
}
|
|
54551
|
+
function snippetForIndex(source, index) {
|
|
54552
|
+
const location = locationForIndex(source, index);
|
|
54553
|
+
const lines = String(source).split(/\r?\n/);
|
|
54554
|
+
const line = lines[location.line - 1] || "";
|
|
54555
|
+
const pointer = `${" ".repeat(Math.max(location.column - 1, 0))}^`;
|
|
54556
|
+
return { line, pointer };
|
|
54112
54557
|
}
|
|
54113
54558
|
|
|
54114
54559
|
// node_modules/@zeropress/build-core/src/assets/asset-processor.js
|
|
@@ -59574,6 +60019,10 @@ function sanitizeHtml(html) {
|
|
|
59574
60019
|
"li",
|
|
59575
60020
|
"blockquote",
|
|
59576
60021
|
"aside",
|
|
60022
|
+
"figure",
|
|
60023
|
+
"figcaption",
|
|
60024
|
+
"picture",
|
|
60025
|
+
"source",
|
|
59577
60026
|
"table",
|
|
59578
60027
|
"thead",
|
|
59579
60028
|
"tbody",
|
|
@@ -59589,9 +60038,10 @@ function sanitizeHtml(html) {
|
|
|
59589
60038
|
const allowedAttributes = {
|
|
59590
60039
|
a: /* @__PURE__ */ new Set(["href", "title", "class", "id"]),
|
|
59591
60040
|
aside: /* @__PURE__ */ new Set(["role", "class", "id"]),
|
|
59592
|
-
img: /* @__PURE__ */ new Set(["src", "alt", "title", "class", "id", "width", "height"]),
|
|
60041
|
+
img: /* @__PURE__ */ new Set(["src", "srcset", "sizes", "alt", "title", "class", "id", "width", "height", "loading", "decoding"]),
|
|
59593
60042
|
iframe: /* @__PURE__ */ new Set(["src", "width", "height", "frameborder", "allowfullscreen", "class"]),
|
|
59594
60043
|
input: /* @__PURE__ */ new Set(["type", "checked", "disabled", "class", "id"]),
|
|
60044
|
+
source: /* @__PURE__ */ new Set(["src", "srcset", "sizes", "type", "media", "width", "height", "class", "id"]),
|
|
59595
60045
|
"*": /* @__PURE__ */ new Set(["class", "id"])
|
|
59596
60046
|
};
|
|
59597
60047
|
const safeUriPattern = /^(?:(?:https?|mailto|tel):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i;
|
|
@@ -59619,13 +60069,16 @@ function sanitizeHtml(html) {
|
|
|
59619
60069
|
if ((attributeName === "href" || attributeName === "src") && !safeUriPattern.test(attributeValue)) {
|
|
59620
60070
|
continue;
|
|
59621
60071
|
}
|
|
60072
|
+
if (attributeName === "srcset" && !isSafeSrcset(attributeValue, safeUriPattern)) {
|
|
60073
|
+
continue;
|
|
60074
|
+
}
|
|
59622
60075
|
if (normalizedTag === "input" && attributeName === "type" && attributeValue !== "checkbox") {
|
|
59623
60076
|
continue;
|
|
59624
60077
|
}
|
|
59625
60078
|
filteredAttributes.push(`${attributeName}="${attributeValue}"`);
|
|
59626
60079
|
}
|
|
59627
60080
|
}
|
|
59628
|
-
const isSelfClosing = match2.endsWith("/>") || normalizedTag === "br" || normalizedTag === "hr" || normalizedTag === "img" || normalizedTag === "input";
|
|
60081
|
+
const isSelfClosing = match2.endsWith("/>") || normalizedTag === "br" || normalizedTag === "hr" || normalizedTag === "img" || normalizedTag === "input" || normalizedTag === "source";
|
|
59629
60082
|
const attributeSuffix = filteredAttributes.length > 0 ? ` ${filteredAttributes.join(" ")}` : "";
|
|
59630
60083
|
return isSelfClosing ? `<${normalizedTag}${attributeSuffix} />` : `<${normalizedTag}${attributeSuffix}>`;
|
|
59631
60084
|
});
|
|
@@ -59636,6 +60089,13 @@ function sanitizeHtml(html) {
|
|
|
59636
60089
|
return part.replace(/&(?!(?:[a-zA-Z]+|#\d+|#x[0-9a-fA-F]+);)/g, "&");
|
|
59637
60090
|
}).join("");
|
|
59638
60091
|
}
|
|
60092
|
+
function isSafeSrcset(value, safeUriPattern) {
|
|
60093
|
+
const candidates = String(value).split(",").map((candidate) => candidate.trim()).filter(Boolean);
|
|
60094
|
+
return candidates.length > 0 && candidates.every((candidate) => {
|
|
60095
|
+
const [url] = candidate.split(/\s+/);
|
|
60096
|
+
return Boolean(url) && safeUriPattern.test(url);
|
|
60097
|
+
});
|
|
60098
|
+
}
|
|
59639
60099
|
function slugify(value) {
|
|
59640
60100
|
return String(value || "").toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/[\s_-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
59641
60101
|
}
|
|
@@ -59728,6 +60188,9 @@ var VariableResolver = class _VariableResolver {
|
|
|
59728
60188
|
}
|
|
59729
60189
|
}
|
|
59730
60190
|
}
|
|
60191
|
+
if (variablePath === "data" || variablePath.startsWith("data.") || variablePath.includes(".data.")) {
|
|
60192
|
+
return false;
|
|
60193
|
+
}
|
|
59731
60194
|
const lastSegment = variablePath.split(".").pop();
|
|
59732
60195
|
if (lastSegment === "html" || lastSegment?.endsWith("_html")) {
|
|
59733
60196
|
return true;
|
|
@@ -59745,7 +60208,10 @@ var VariableResolver = class _VariableResolver {
|
|
|
59745
60208
|
// node_modules/@zeropress/build-core/src/render/partial-resolver.js
|
|
59746
60209
|
var PARTIAL_NAME_REGEX2 = /^[a-zA-Z_][a-zA-Z0-9_-]*(?:\/[a-zA-Z_][a-zA-Z0-9_-]*)*$/;
|
|
59747
60210
|
var IDENTIFIER_REGEX = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
|
|
59748
|
-
|
|
60211
|
+
var PATH_SEGMENT_SOURCE = "[a-zA-Z_][a-zA-Z0-9_]*(?:-[a-zA-Z0-9_]+)*";
|
|
60212
|
+
var PATH_REGEX = new RegExp(`^${PATH_SEGMENT_SOURCE}(?:\\.${PATH_SEGMENT_SOURCE})*$`);
|
|
60213
|
+
var NUMBER_LITERAL_REGEX2 = /^-?(?:0|[1-9]\d*)(?:\.\d+)?$/;
|
|
60214
|
+
function parsePartialToken(token, options2 = {}) {
|
|
59749
60215
|
const source = String(token || "").trim();
|
|
59750
60216
|
if (!source.startsWith("partial:")) {
|
|
59751
60217
|
throw new Error(`Invalid partial token: ${source}`);
|
|
@@ -59760,10 +60226,10 @@ function parsePartialToken(token) {
|
|
|
59760
60226
|
throw new Error(`Invalid partial name: ${name}`);
|
|
59761
60227
|
}
|
|
59762
60228
|
const argsSource = expression.slice(name.length).trim();
|
|
59763
|
-
const args = parsePartialArgs2(argsSource);
|
|
60229
|
+
const args = parsePartialArgs2(argsSource, options2);
|
|
59764
60230
|
return { name, args };
|
|
59765
60231
|
}
|
|
59766
|
-
function parsePartialArgs2(source) {
|
|
60232
|
+
function parsePartialArgs2(source, options2 = {}) {
|
|
59767
60233
|
if (!source) {
|
|
59768
60234
|
return {};
|
|
59769
60235
|
}
|
|
@@ -59815,20 +60281,40 @@ function parsePartialArgs2(source) {
|
|
|
59815
60281
|
if (cursor >= source.length || source[cursor] !== '"') {
|
|
59816
60282
|
throw new Error(`Unclosed string literal for partial argument "${key}"`);
|
|
59817
60283
|
}
|
|
59818
|
-
args[key] = JSON.parse(source.slice(index, cursor + 1));
|
|
60284
|
+
args[key] = { kind: "literal", value: JSON.parse(source.slice(index, cursor + 1)) };
|
|
59819
60285
|
index = cursor + 1;
|
|
59820
60286
|
continue;
|
|
59821
60287
|
}
|
|
59822
60288
|
if (source.startsWith("true", index) && isValueBoundary2(source, index + 4)) {
|
|
59823
|
-
args[key] = true;
|
|
60289
|
+
args[key] = { kind: "literal", value: true };
|
|
59824
60290
|
index += 4;
|
|
59825
60291
|
continue;
|
|
59826
60292
|
}
|
|
59827
60293
|
if (source.startsWith("false", index) && isValueBoundary2(source, index + 5)) {
|
|
59828
|
-
args[key] = false;
|
|
60294
|
+
args[key] = { kind: "literal", value: false };
|
|
59829
60295
|
index += 5;
|
|
59830
60296
|
continue;
|
|
59831
60297
|
}
|
|
60298
|
+
if (source.startsWith("null", index) && isValueBoundary2(source, index + 4)) {
|
|
60299
|
+
args[key] = { kind: "literal", value: null };
|
|
60300
|
+
index += 4;
|
|
60301
|
+
continue;
|
|
60302
|
+
}
|
|
60303
|
+
const valueMatch = /^\S+/.exec(source.slice(index));
|
|
60304
|
+
if (!valueMatch) {
|
|
60305
|
+
throw new Error(`Missing partial argument value for "${key}"`);
|
|
60306
|
+
}
|
|
60307
|
+
const valueToken = valueMatch[0];
|
|
60308
|
+
if (NUMBER_LITERAL_REGEX2.test(valueToken)) {
|
|
60309
|
+
args[key] = { kind: "literal", value: Number(valueToken) };
|
|
60310
|
+
index += valueToken.length;
|
|
60311
|
+
continue;
|
|
60312
|
+
}
|
|
60313
|
+
if (PATH_REGEX.test(valueToken) && isAllowedPathArgument(valueToken, options2)) {
|
|
60314
|
+
args[key] = { kind: "path", path: valueToken };
|
|
60315
|
+
index += valueToken.length;
|
|
60316
|
+
continue;
|
|
60317
|
+
}
|
|
59832
60318
|
throw new Error(`Unsupported partial argument value for "${key}"`);
|
|
59833
60319
|
}
|
|
59834
60320
|
return args;
|
|
@@ -59836,50 +60322,184 @@ function parsePartialArgs2(source) {
|
|
|
59836
60322
|
function isValueBoundary2(source, index) {
|
|
59837
60323
|
return index >= source.length || /\s/.test(source[index]);
|
|
59838
60324
|
}
|
|
60325
|
+
function isAllowedPathArgument(valueToken, options2) {
|
|
60326
|
+
if (valueToken.includes(".")) {
|
|
60327
|
+
return true;
|
|
60328
|
+
}
|
|
60329
|
+
const allowedSingleSegmentPaths = options2?.allowedSingleSegmentPaths;
|
|
60330
|
+
return allowedSingleSegmentPaths instanceof Set && allowedSingleSegmentPaths.has(valueToken);
|
|
60331
|
+
}
|
|
59839
60332
|
|
|
59840
60333
|
// 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
|
|
59845
|
-
var
|
|
59846
|
-
|
|
59847
|
-
|
|
59848
|
-
|
|
59849
|
-
|
|
59850
|
-
|
|
59851
|
-
|
|
59852
|
-
|
|
59853
|
-
|
|
59854
|
-
|
|
59855
|
-
|
|
59856
|
-
|
|
59857
|
-
|
|
59858
|
-
|
|
59859
|
-
|
|
60334
|
+
var PATH_SEGMENT_SOURCE2 = "[a-zA-Z_][a-zA-Z0-9_]*(?:-[a-zA-Z0-9_]+)*";
|
|
60335
|
+
var PATH_REGEX2 = new RegExp(`^${PATH_SEGMENT_SOURCE2}(?:\\.${PATH_SEGMENT_SOURCE2})*$`);
|
|
60336
|
+
var FOR_EXPRESSION_REGEX = new RegExp(`^([a-zA-Z_][a-zA-Z0-9_]*)\\s+in\\s+(${PATH_SEGMENT_SOURCE2}(?:\\.${PATH_SEGMENT_SOURCE2})*)$`);
|
|
60337
|
+
var NUMBER_LITERAL_REGEX3 = /^-?(?:0|[1-9]\d*)(?:\.\d+)?$/;
|
|
60338
|
+
var COMPARISON_BLOCK_TAGS2 = /* @__PURE__ */ new Set(["if_eq", "if_neq", "if_in", "if_starts_with"]);
|
|
60339
|
+
var COMPARISON_ELSE_IF_TAGS2 = /* @__PURE__ */ new Set(["else_if_eq", "else_if_neq", "else_if_in", "else_if_starts_with"]);
|
|
60340
|
+
var COMPARISON_TAG_OPERATORS2 = {
|
|
60341
|
+
if_eq: "eq",
|
|
60342
|
+
else_if_eq: "eq",
|
|
60343
|
+
if_neq: "neq",
|
|
60344
|
+
else_if_neq: "neq",
|
|
60345
|
+
if_in: "in",
|
|
60346
|
+
else_if_in: "in",
|
|
60347
|
+
if_starts_with: "starts_with",
|
|
60348
|
+
else_if_starts_with: "starts_with"
|
|
60349
|
+
};
|
|
60350
|
+
var PARTIAL_ARG_ROOT_PATHS2 = /* @__PURE__ */ new Set([
|
|
60351
|
+
"archive",
|
|
60352
|
+
"author",
|
|
60353
|
+
"category",
|
|
60354
|
+
"collection",
|
|
60355
|
+
"collections",
|
|
60356
|
+
"currentUrl",
|
|
60357
|
+
"language",
|
|
60358
|
+
"menu",
|
|
60359
|
+
"menus",
|
|
60360
|
+
"meta",
|
|
60361
|
+
"page",
|
|
60362
|
+
"pagination",
|
|
60363
|
+
"partial",
|
|
60364
|
+
"post",
|
|
60365
|
+
"posts",
|
|
60366
|
+
"route",
|
|
60367
|
+
"site",
|
|
60368
|
+
"tag",
|
|
60369
|
+
"taxonomies",
|
|
60370
|
+
"taxonomy",
|
|
60371
|
+
"widget",
|
|
60372
|
+
"widgets"
|
|
60373
|
+
]);
|
|
60374
|
+
function getComparisonBlockTag2(token) {
|
|
60375
|
+
for (const tagName of COMPARISON_BLOCK_TAGS2) {
|
|
60376
|
+
if (token.startsWith(`#${tagName} `)) {
|
|
60377
|
+
return tagName;
|
|
60378
|
+
}
|
|
59860
60379
|
}
|
|
59861
|
-
|
|
59862
|
-
|
|
59863
|
-
|
|
60380
|
+
return "";
|
|
60381
|
+
}
|
|
60382
|
+
function getComparisonElseIfTag2(token) {
|
|
60383
|
+
for (const tagName of COMPARISON_ELSE_IF_TAGS2) {
|
|
60384
|
+
if (token.startsWith(`#${tagName} `)) {
|
|
60385
|
+
return tagName;
|
|
60386
|
+
}
|
|
59864
60387
|
}
|
|
59865
|
-
|
|
59866
|
-
|
|
59867
|
-
|
|
59868
|
-
|
|
59869
|
-
|
|
60388
|
+
return "";
|
|
60389
|
+
}
|
|
60390
|
+
function tokenizeExpression2(expression) {
|
|
60391
|
+
const tokens = [];
|
|
60392
|
+
let index = 0;
|
|
60393
|
+
while (index < expression.length) {
|
|
60394
|
+
while (/\s/.test(expression[index] || "")) {
|
|
60395
|
+
index += 1;
|
|
59870
60396
|
}
|
|
59871
|
-
if (
|
|
59872
|
-
|
|
60397
|
+
if (index >= expression.length) {
|
|
60398
|
+
break;
|
|
59873
60399
|
}
|
|
59874
|
-
|
|
59875
|
-
|
|
59876
|
-
|
|
59877
|
-
|
|
59878
|
-
|
|
59879
|
-
|
|
59880
|
-
|
|
59881
|
-
|
|
59882
|
-
|
|
60400
|
+
if (expression[index] === '"') {
|
|
60401
|
+
const start2 = index;
|
|
60402
|
+
index += 1;
|
|
60403
|
+
let escaped = false;
|
|
60404
|
+
while (index < expression.length) {
|
|
60405
|
+
const char = expression[index];
|
|
60406
|
+
if (escaped) {
|
|
60407
|
+
escaped = false;
|
|
60408
|
+
} else if (char === "\\") {
|
|
60409
|
+
escaped = true;
|
|
60410
|
+
} else if (char === '"') {
|
|
60411
|
+
index += 1;
|
|
60412
|
+
tokens.push(expression.slice(start2, index));
|
|
60413
|
+
break;
|
|
60414
|
+
}
|
|
60415
|
+
index += 1;
|
|
60416
|
+
}
|
|
60417
|
+
if (tokens[tokens.length - 1] !== expression.slice(start2, index)) {
|
|
60418
|
+
throw new Error(`Unclosed string literal in expression: ${expression}`);
|
|
60419
|
+
}
|
|
60420
|
+
continue;
|
|
60421
|
+
}
|
|
60422
|
+
const start = index;
|
|
60423
|
+
while (index < expression.length && !/\s/.test(expression[index])) {
|
|
60424
|
+
index += 1;
|
|
60425
|
+
}
|
|
60426
|
+
tokens.push(expression.slice(start, index));
|
|
60427
|
+
}
|
|
60428
|
+
return tokens;
|
|
60429
|
+
}
|
|
60430
|
+
function parsePathOperand2(token, tagName, expression) {
|
|
60431
|
+
if (!PATH_REGEX2.test(token)) {
|
|
60432
|
+
throw new Error(`Invalid ${tagName} expression: ${expression}`);
|
|
60433
|
+
}
|
|
60434
|
+
return { kind: "path", path: token };
|
|
60435
|
+
}
|
|
60436
|
+
function parseComparisonOperand2(token, tagName, expression) {
|
|
60437
|
+
if (token.startsWith('"')) {
|
|
60438
|
+
try {
|
|
60439
|
+
const value = JSON.parse(token);
|
|
60440
|
+
if (typeof value !== "string") {
|
|
60441
|
+
throw new Error("Expected string literal");
|
|
60442
|
+
}
|
|
60443
|
+
return { kind: "literal", value };
|
|
60444
|
+
} catch {
|
|
60445
|
+
throw new Error(`Invalid ${tagName} expression: ${expression}`);
|
|
60446
|
+
}
|
|
60447
|
+
}
|
|
60448
|
+
if (token === "true") {
|
|
60449
|
+
return { kind: "literal", value: true };
|
|
60450
|
+
}
|
|
60451
|
+
if (token === "false") {
|
|
60452
|
+
return { kind: "literal", value: false };
|
|
60453
|
+
}
|
|
60454
|
+
if (token === "null") {
|
|
60455
|
+
return { kind: "literal", value: null };
|
|
60456
|
+
}
|
|
60457
|
+
if (NUMBER_LITERAL_REGEX3.test(token)) {
|
|
60458
|
+
return { kind: "literal", value: Number(token) };
|
|
60459
|
+
}
|
|
60460
|
+
if (PATH_REGEX2.test(token)) {
|
|
60461
|
+
return { kind: "path", path: token };
|
|
60462
|
+
}
|
|
60463
|
+
throw new Error(`Invalid ${tagName} expression: ${expression}`);
|
|
60464
|
+
}
|
|
60465
|
+
var ControlFlowRenderer = class {
|
|
60466
|
+
constructor(options2 = {}) {
|
|
60467
|
+
this.resolvePath = typeof options2.resolvePath === "function" ? options2.resolvePath : ((data, path4) => path4.split(".").reduce((current, segment) => {
|
|
60468
|
+
if (current == null || typeof current !== "object") {
|
|
60469
|
+
return void 0;
|
|
60470
|
+
}
|
|
60471
|
+
return current[segment];
|
|
60472
|
+
}, data));
|
|
60473
|
+
this.renderText = typeof options2.renderText === "function" ? options2.renderText : ((value) => value);
|
|
60474
|
+
}
|
|
60475
|
+
render(template, data, renderOptions = {}) {
|
|
60476
|
+
return this.renderTemplate(template, data, {
|
|
60477
|
+
...renderOptions,
|
|
60478
|
+
partialStack: Array.isArray(renderOptions.partialStack) ? renderOptions.partialStack : []
|
|
60479
|
+
});
|
|
60480
|
+
}
|
|
60481
|
+
renderTemplate(template, data, renderOptions) {
|
|
60482
|
+
const nodes = this.parse(template);
|
|
60483
|
+
return this.renderNodes(nodes, data, renderOptions);
|
|
60484
|
+
}
|
|
60485
|
+
parse(template) {
|
|
60486
|
+
const source = String(template || "");
|
|
60487
|
+
const { nodes, nextIndex, stopTag } = this.parseNodes(source, 0, /* @__PURE__ */ new Set(), PARTIAL_ARG_ROOT_PATHS2);
|
|
60488
|
+
if (stopTag) {
|
|
60489
|
+
throw new Error(`Unexpected closing tag ${stopTag}`);
|
|
60490
|
+
}
|
|
60491
|
+
if (nextIndex !== source.length) {
|
|
60492
|
+
throw new Error("Unexpected parser termination");
|
|
60493
|
+
}
|
|
60494
|
+
return nodes;
|
|
60495
|
+
}
|
|
60496
|
+
parseNodes(source, startIndex, stopTags, partialArgScope) {
|
|
60497
|
+
const nodes = [];
|
|
60498
|
+
let index = startIndex;
|
|
60499
|
+
while (index < source.length) {
|
|
60500
|
+
const nextDelimiter = source.indexOf("{{", index);
|
|
60501
|
+
if (nextDelimiter === -1) {
|
|
60502
|
+
nodes.push({ type: "text", value: source.slice(index) });
|
|
59883
60503
|
return { nodes, nextIndex: source.length, stopTag: null };
|
|
59884
60504
|
}
|
|
59885
60505
|
if (nextDelimiter > index) {
|
|
@@ -59924,9 +60544,10 @@ var ControlFlowRenderer = class {
|
|
|
59924
60544
|
}
|
|
59925
60545
|
return { nodes, nextIndex: tokenEnd + 2, stopTag: "else" };
|
|
59926
60546
|
}
|
|
59927
|
-
|
|
59928
|
-
|
|
59929
|
-
|
|
60547
|
+
const comparisonElseIfTag = getComparisonElseIfTag2(token);
|
|
60548
|
+
if (comparisonElseIfTag) {
|
|
60549
|
+
if (!stopTags.has(comparisonElseIfTag)) {
|
|
60550
|
+
throw new Error(`Unexpected ${comparisonElseIfTag} tag`);
|
|
59930
60551
|
}
|
|
59931
60552
|
return { nodes, nextIndex: tokenEnd + 2, stopTag: token };
|
|
59932
60553
|
}
|
|
@@ -59937,21 +60558,22 @@ var ControlFlowRenderer = class {
|
|
|
59937
60558
|
return { nodes, nextIndex: tokenEnd + 2, stopTag: token };
|
|
59938
60559
|
}
|
|
59939
60560
|
if (token.startsWith("partial:")) {
|
|
59940
|
-
const { name, args } = parsePartialToken(token);
|
|
60561
|
+
const { name, args } = parsePartialToken(token, { allowedSingleSegmentPaths: partialArgScope });
|
|
59941
60562
|
nodes.push({ type: "partial", name, args });
|
|
59942
60563
|
index = tokenEnd + 2;
|
|
59943
60564
|
continue;
|
|
59944
60565
|
}
|
|
59945
|
-
|
|
59946
|
-
|
|
59947
|
-
const
|
|
60566
|
+
const comparisonBlockTag = getComparisonBlockTag2(token);
|
|
60567
|
+
if (comparisonBlockTag) {
|
|
60568
|
+
const expression = token.slice(`#${comparisonBlockTag} `.length).trim();
|
|
60569
|
+
const block2 = this.parseComparisonBlock(source, tokenEnd + 2, comparisonBlockTag, expression, partialArgScope);
|
|
59948
60570
|
nodes.push(block2.node);
|
|
59949
60571
|
index = block2.nextIndex;
|
|
59950
60572
|
continue;
|
|
59951
60573
|
}
|
|
59952
60574
|
if (token.startsWith("#if ")) {
|
|
59953
60575
|
const expression = token.slice("#if ".length).trim();
|
|
59954
|
-
const block2 = this.parseIfBlock(source, tokenEnd + 2, expression);
|
|
60576
|
+
const block2 = this.parseIfBlock(source, tokenEnd + 2, expression, partialArgScope);
|
|
59955
60577
|
nodes.push(block2.node);
|
|
59956
60578
|
index = block2.nextIndex;
|
|
59957
60579
|
continue;
|
|
@@ -59963,7 +60585,8 @@ var ControlFlowRenderer = class {
|
|
|
59963
60585
|
throw new Error(`Invalid for expression: ${expression}`);
|
|
59964
60586
|
}
|
|
59965
60587
|
const [, itemName, path4] = match2;
|
|
59966
|
-
const
|
|
60588
|
+
const forScope = /* @__PURE__ */ new Set([...partialArgScope, itemName, "loop"]);
|
|
60589
|
+
const forResult = this.parseNodes(source, tokenEnd + 2, /* @__PURE__ */ new Set(["for"]), forScope);
|
|
59967
60590
|
if (forResult.stopTag !== "for") {
|
|
59968
60591
|
throw new Error("Unclosed for block");
|
|
59969
60592
|
}
|
|
@@ -59980,8 +60603,8 @@ var ControlFlowRenderer = class {
|
|
|
59980
60603
|
}
|
|
59981
60604
|
return { nodes, nextIndex: source.length, stopTag: null };
|
|
59982
60605
|
}
|
|
59983
|
-
parseIfBlock(source, startIndex, initialPath) {
|
|
59984
|
-
if (!
|
|
60606
|
+
parseIfBlock(source, startIndex, initialPath, partialArgScope) {
|
|
60607
|
+
if (!PATH_REGEX2.test(initialPath)) {
|
|
59985
60608
|
throw new Error(`Invalid if expression: ${initialPath}`);
|
|
59986
60609
|
}
|
|
59987
60610
|
const branches = [];
|
|
@@ -59989,13 +60612,13 @@ var ControlFlowRenderer = class {
|
|
|
59989
60612
|
let nextIndex = startIndex;
|
|
59990
60613
|
let currentPath = initialPath;
|
|
59991
60614
|
while (true) {
|
|
59992
|
-
const branchResult = this.parseNodes(source, nextIndex, /* @__PURE__ */ new Set(["else", "else_if", "if"]));
|
|
60615
|
+
const branchResult = this.parseNodes(source, nextIndex, /* @__PURE__ */ new Set(["else", "else_if", "if"]), partialArgScope);
|
|
59993
60616
|
branches.push({
|
|
59994
60617
|
path: currentPath,
|
|
59995
60618
|
consequent: branchResult.nodes
|
|
59996
60619
|
});
|
|
59997
60620
|
if (branchResult.stopTag === "else") {
|
|
59998
|
-
const elseResult = this.parseNodes(source, branchResult.nextIndex, /* @__PURE__ */ new Set(["if"]));
|
|
60621
|
+
const elseResult = this.parseNodes(source, branchResult.nextIndex, /* @__PURE__ */ new Set(["if"]), partialArgScope);
|
|
59999
60622
|
if (elseResult.stopTag !== "if") {
|
|
60000
60623
|
throw new Error("Unclosed if block after else");
|
|
60001
60624
|
}
|
|
@@ -60005,7 +60628,7 @@ var ControlFlowRenderer = class {
|
|
|
60005
60628
|
}
|
|
60006
60629
|
if (typeof branchResult.stopTag === "string" && branchResult.stopTag.startsWith("#else_if ")) {
|
|
60007
60630
|
currentPath = branchResult.stopTag.slice("#else_if ".length).trim();
|
|
60008
|
-
if (!
|
|
60631
|
+
if (!PATH_REGEX2.test(currentPath)) {
|
|
60009
60632
|
throw new Error(`Invalid else_if expression: ${currentPath}`);
|
|
60010
60633
|
}
|
|
60011
60634
|
nextIndex = branchResult.nextIndex;
|
|
@@ -60026,60 +60649,65 @@ var ControlFlowRenderer = class {
|
|
|
60026
60649
|
nextIndex
|
|
60027
60650
|
};
|
|
60028
60651
|
}
|
|
60029
|
-
|
|
60030
|
-
const initialBranch = this.
|
|
60652
|
+
parseComparisonBlock(source, startIndex, tagName, expression, partialArgScope) {
|
|
60653
|
+
const initialBranch = this.parseComparisonBranchExpression(expression, tagName);
|
|
60031
60654
|
const branches = [];
|
|
60032
60655
|
let alternate = [];
|
|
60033
60656
|
let nextIndex = startIndex;
|
|
60034
60657
|
let currentBranch = initialBranch;
|
|
60658
|
+
const elseIfTag = `else_${tagName}`;
|
|
60035
60659
|
while (true) {
|
|
60036
|
-
const branchResult = this.parseNodes(source, nextIndex, /* @__PURE__ */ new Set(["else",
|
|
60660
|
+
const branchResult = this.parseNodes(source, nextIndex, /* @__PURE__ */ new Set(["else", elseIfTag, tagName]), partialArgScope);
|
|
60037
60661
|
branches.push({
|
|
60038
|
-
|
|
60039
|
-
|
|
60662
|
+
operator: currentBranch.operator,
|
|
60663
|
+
left: currentBranch.left,
|
|
60664
|
+
operands: currentBranch.operands,
|
|
60040
60665
|
consequent: branchResult.nodes
|
|
60041
60666
|
});
|
|
60042
60667
|
if (branchResult.stopTag === "else") {
|
|
60043
|
-
const elseResult = this.parseNodes(source, branchResult.nextIndex, /* @__PURE__ */ new Set([
|
|
60044
|
-
if (elseResult.stopTag !==
|
|
60045
|
-
throw new Error(
|
|
60668
|
+
const elseResult = this.parseNodes(source, branchResult.nextIndex, /* @__PURE__ */ new Set([tagName]), partialArgScope);
|
|
60669
|
+
if (elseResult.stopTag !== tagName) {
|
|
60670
|
+
throw new Error(`Unclosed ${tagName} block after else`);
|
|
60046
60671
|
}
|
|
60047
60672
|
alternate = elseResult.nodes;
|
|
60048
60673
|
nextIndex = elseResult.nextIndex;
|
|
60049
60674
|
break;
|
|
60050
60675
|
}
|
|
60051
|
-
if (typeof branchResult.stopTag === "string" && branchResult.stopTag.startsWith(
|
|
60052
|
-
currentBranch = this.
|
|
60053
|
-
branchResult.stopTag.slice(
|
|
60054
|
-
|
|
60676
|
+
if (typeof branchResult.stopTag === "string" && branchResult.stopTag.startsWith(`#${elseIfTag} `)) {
|
|
60677
|
+
currentBranch = this.parseComparisonBranchExpression(
|
|
60678
|
+
branchResult.stopTag.slice(`#${elseIfTag} `.length).trim(),
|
|
60679
|
+
elseIfTag
|
|
60055
60680
|
);
|
|
60056
60681
|
nextIndex = branchResult.nextIndex;
|
|
60057
60682
|
continue;
|
|
60058
60683
|
}
|
|
60059
|
-
if (branchResult.stopTag ===
|
|
60684
|
+
if (branchResult.stopTag === tagName) {
|
|
60060
60685
|
nextIndex = branchResult.nextIndex;
|
|
60061
60686
|
break;
|
|
60062
60687
|
}
|
|
60063
|
-
throw new Error(
|
|
60688
|
+
throw new Error(`Unclosed ${tagName} block`);
|
|
60064
60689
|
}
|
|
60065
60690
|
return {
|
|
60066
60691
|
node: {
|
|
60067
|
-
type: "
|
|
60692
|
+
type: "comparison",
|
|
60068
60693
|
branches,
|
|
60069
60694
|
alternate
|
|
60070
60695
|
},
|
|
60071
60696
|
nextIndex
|
|
60072
60697
|
};
|
|
60073
60698
|
}
|
|
60074
|
-
|
|
60075
|
-
const
|
|
60076
|
-
|
|
60699
|
+
parseComparisonBranchExpression(expression, tagName) {
|
|
60700
|
+
const operator = COMPARISON_TAG_OPERATORS2[tagName];
|
|
60701
|
+
const tokens = tokenizeExpression2(expression);
|
|
60702
|
+
if (!operator || operator === "in" && tokens.length < 2 || operator !== "in" && tokens.length !== 2) {
|
|
60077
60703
|
throw new Error(`Invalid ${tagName} expression: ${expression}`);
|
|
60078
60704
|
}
|
|
60079
|
-
const [,
|
|
60705
|
+
const left = parsePathOperand2(tokens[0], tagName, expression);
|
|
60706
|
+
const operands = tokens.slice(1).map((token) => parseComparisonOperand2(token, tagName, expression));
|
|
60080
60707
|
return {
|
|
60081
|
-
|
|
60082
|
-
|
|
60708
|
+
operator,
|
|
60709
|
+
left,
|
|
60710
|
+
operands
|
|
60083
60711
|
};
|
|
60084
60712
|
}
|
|
60085
60713
|
renderNodes(nodes, data, renderOptions) {
|
|
@@ -60093,8 +60721,8 @@ var ControlFlowRenderer = class {
|
|
|
60093
60721
|
const branch = node.branches.find((entry) => this.isTruthy(this.resolvePath(data, entry.path)));
|
|
60094
60722
|
return branch ? this.renderNodes(branch.consequent, data, renderOptions) : this.renderNodes(node.alternate, data, renderOptions);
|
|
60095
60723
|
}
|
|
60096
|
-
case "
|
|
60097
|
-
const branch = node.branches.find((entry) => this.
|
|
60724
|
+
case "comparison": {
|
|
60725
|
+
const branch = node.branches.find((entry) => this.evaluateComparison(entry, data));
|
|
60098
60726
|
return branch ? this.renderNodes(branch.consequent, data, renderOptions) : this.renderNodes(node.alternate, data, renderOptions);
|
|
60099
60727
|
}
|
|
60100
60728
|
case "for": {
|
|
@@ -60129,15 +60757,62 @@ var ControlFlowRenderer = class {
|
|
|
60129
60757
|
throw new Error(`Circular partial reference detected: ${cycle}`);
|
|
60130
60758
|
}
|
|
60131
60759
|
const partialTemplate = String(partials.get(node.name) || "");
|
|
60760
|
+
const partialArgs = this.resolvePartialArgs(node.args, data);
|
|
60132
60761
|
const partialData = {
|
|
60133
60762
|
...data,
|
|
60134
|
-
partial: {
|
|
60763
|
+
partial: {
|
|
60764
|
+
...data?.partial && typeof data.partial === "object" ? data.partial : {},
|
|
60765
|
+
...partialArgs
|
|
60766
|
+
}
|
|
60135
60767
|
};
|
|
60136
60768
|
return this.renderTemplate(partialTemplate, partialData, {
|
|
60137
60769
|
...renderOptions,
|
|
60138
60770
|
partialStack: [...activeStack, node.name]
|
|
60139
60771
|
});
|
|
60140
60772
|
}
|
|
60773
|
+
resolvePartialArgs(args, data) {
|
|
60774
|
+
const resolved = {};
|
|
60775
|
+
for (const [key, operand] of Object.entries(args || {})) {
|
|
60776
|
+
if (operand?.kind === "literal") {
|
|
60777
|
+
resolved[key] = operand.value;
|
|
60778
|
+
continue;
|
|
60779
|
+
}
|
|
60780
|
+
if (operand?.kind === "path") {
|
|
60781
|
+
resolved[key] = this.resolvePath(data, operand.path);
|
|
60782
|
+
}
|
|
60783
|
+
}
|
|
60784
|
+
return resolved;
|
|
60785
|
+
}
|
|
60786
|
+
evaluateComparison(entry, data) {
|
|
60787
|
+
const left = this.evaluateOperand(entry.left, data);
|
|
60788
|
+
const operands = entry.operands.map((operand) => this.evaluateOperand(operand, data));
|
|
60789
|
+
if (entry.operator === "eq") {
|
|
60790
|
+
const right = operands[0];
|
|
60791
|
+
return !left.missing && !right.missing && left.value === right.value;
|
|
60792
|
+
}
|
|
60793
|
+
if (entry.operator === "neq") {
|
|
60794
|
+
const right = operands[0];
|
|
60795
|
+
return left.missing || right.missing || left.value !== right.value;
|
|
60796
|
+
}
|
|
60797
|
+
if (entry.operator === "in") {
|
|
60798
|
+
if (left.missing) {
|
|
60799
|
+
return false;
|
|
60800
|
+
}
|
|
60801
|
+
return operands.some((operand) => !operand.missing && left.value === operand.value);
|
|
60802
|
+
}
|
|
60803
|
+
if (entry.operator === "starts_with") {
|
|
60804
|
+
const right = operands[0];
|
|
60805
|
+
return !left.missing && !right.missing && typeof left.value === "string" && typeof right.value === "string" && left.value.startsWith(right.value);
|
|
60806
|
+
}
|
|
60807
|
+
return false;
|
|
60808
|
+
}
|
|
60809
|
+
evaluateOperand(operand, data) {
|
|
60810
|
+
if (operand.kind === "literal") {
|
|
60811
|
+
return { value: operand.value, missing: false };
|
|
60812
|
+
}
|
|
60813
|
+
const value = this.resolvePath(data, operand.path);
|
|
60814
|
+
return { value, missing: value === void 0 };
|
|
60815
|
+
}
|
|
60141
60816
|
isTruthy(value) {
|
|
60142
60817
|
if (Array.isArray(value)) {
|
|
60143
60818
|
return value.length > 0;
|
|
@@ -60179,7 +60854,7 @@ var ZeroPressEngine = class {
|
|
|
60179
60854
|
const renderData = this.combineRenderData(data, context);
|
|
60180
60855
|
const renderedContent = this.renderTemplate(template, renderData);
|
|
60181
60856
|
const layoutWithSlots = this.slotResolver.resolve(layout, this.themePackage.partials, CONTENT_SLOT_PLACEHOLDER);
|
|
60182
|
-
return this.renderTemplate(layoutWithSlots, renderData).replaceAll(CONTENT_SLOT_PLACEHOLDER, renderedContent);
|
|
60857
|
+
return this.renderTemplate(layoutWithSlots, renderData).replaceAll(CONTENT_SLOT_PLACEHOLDER, () => renderedContent);
|
|
60183
60858
|
}
|
|
60184
60859
|
combineRenderData(data, context) {
|
|
60185
60860
|
return {
|
|
@@ -60190,7 +60865,7 @@ var ZeroPressEngine = class {
|
|
|
60190
60865
|
};
|
|
60191
60866
|
}
|
|
60192
60867
|
renderTemplate(template, data) {
|
|
60193
|
-
if (this.themePackage?.metadata?.runtime !== "0.
|
|
60868
|
+
if (this.themePackage?.metadata?.runtime !== "0.6") {
|
|
60194
60869
|
throw new Error(`Unsupported theme runtime: ${this.themePackage?.metadata?.runtime || "unknown"}`);
|
|
60195
60870
|
}
|
|
60196
60871
|
return this.controlFlowRenderer.render(template, data, {
|
|
@@ -60210,10 +60885,13 @@ var DEFAULT_OPTIONS = {
|
|
|
60210
60885
|
writeManifest: false
|
|
60211
60886
|
};
|
|
60212
60887
|
var DEFAULT_POSTS_PER_PAGE = 10;
|
|
60213
|
-
var
|
|
60214
|
-
var
|
|
60888
|
+
var DEFAULT_DATETIME_DISPLAY = "static";
|
|
60889
|
+
var DEFAULT_DATE_STYLE = "medium";
|
|
60890
|
+
var DEFAULT_TIME_STYLE = "none";
|
|
60215
60891
|
var DEFAULT_TIMEZONE = "UTC";
|
|
60216
60892
|
var DEFAULT_LOCALE = "en-US";
|
|
60893
|
+
var DATETIME_DISPLAY_MODES = /* @__PURE__ */ new Set(["static", "client"]);
|
|
60894
|
+
var DATETIME_STYLES = /* @__PURE__ */ new Set(["none", "short", "medium", "long", "full"]);
|
|
60217
60895
|
var DEFAULT_PERMALINKS = Object.freeze({
|
|
60218
60896
|
output_style: "directory",
|
|
60219
60897
|
posts: "/posts/:slug/",
|
|
@@ -60231,12 +60909,25 @@ var DEFAULT_POST_INDEX = Object.freeze({
|
|
|
60231
60909
|
});
|
|
60232
60910
|
var PERMALINK_OUTPUT_STYLES = /* @__PURE__ */ new Set(["directory", "html-extension"]);
|
|
60233
60911
|
var COMMENT_POLICY_OUTPUT_PATH = "_zeropress/comment-policy.json";
|
|
60912
|
+
var SEARCH_INDEX_OUTPUT_PATH = "_zeropress/search.json";
|
|
60913
|
+
var SEARCH_ADAPTER_OUTPUT_PATH = "_zeropress/search.js";
|
|
60914
|
+
var SEARCH_PAGEFIND_ADAPTER_OUTPUT_PATH = "_zeropress/search_pagefind.js";
|
|
60234
60915
|
var OUTPUT_PATH_CONTROL_CHAR_PATTERN = /[\u0000-\u001F\u007F]/;
|
|
60235
60916
|
var SAFE_MEDIA_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:"]);
|
|
60236
60917
|
var SAFE_LINK_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:", "mailto:", "tel:"]);
|
|
60237
60918
|
var MEDIA_DELIVERY_MODES = /* @__PURE__ */ new Set(["none", "media_domain"]);
|
|
60919
|
+
var DISCOVERABILITY_VALUES = /* @__PURE__ */ new Set(["default", "noindex", "delist"]);
|
|
60238
60920
|
var RESPONSIVE_IMAGE_WIDTHS = [320, 480, 768, 1024, 1280, 1600, 1920];
|
|
60239
60921
|
var RESPONSIVE_IMAGE_EXTENSIONS = /* @__PURE__ */ new Set(["jpg", "jpeg", "png", "webp", "avif"]);
|
|
60922
|
+
var SEARCH_FIELD_WEIGHTS = Object.freeze({
|
|
60923
|
+
title: 5,
|
|
60924
|
+
headings: 3,
|
|
60925
|
+
tags: 2.5,
|
|
60926
|
+
categories: 2,
|
|
60927
|
+
excerpt: 1.5,
|
|
60928
|
+
content_text: 1
|
|
60929
|
+
});
|
|
60930
|
+
var SEARCH_RECENCY_BOOST_MAX = 0.15;
|
|
60240
60931
|
async function buildSite(input2) {
|
|
60241
60932
|
const options2 = { ...DEFAULT_OPTIONS, ...input2.options || {} };
|
|
60242
60933
|
const state = await createBuildState(input2, options2);
|
|
@@ -60278,10 +60969,21 @@ async function buildSite(input2) {
|
|
|
60278
60969
|
state.commentPolicyContent,
|
|
60279
60970
|
"application/json"
|
|
60280
60971
|
);
|
|
60972
|
+
if (shouldGenerateSearchArtifacts(state, options2)) {
|
|
60973
|
+
await writeOutput(state.writer, state.summaries, SEARCH_INDEX_OUTPUT_PATH, buildSearchIndexJson(state), "application/json");
|
|
60974
|
+
await writeOutput(state.writer, state.summaries, SEARCH_ADAPTER_OUTPUT_PATH, buildSearchAdapterJs(), "application/javascript");
|
|
60975
|
+
await writeOutput(state.writer, state.summaries, SEARCH_PAGEFIND_ADAPTER_OUTPUT_PATH, buildSearchPagefindAdapterJs(), "application/javascript");
|
|
60976
|
+
}
|
|
60281
60977
|
if (options2.generateSpecialFiles) {
|
|
60282
60978
|
await maybeRenderNotFoundPage(state);
|
|
60283
60979
|
if (hasCanonicalSiteUrl(state.previewData.site.url)) {
|
|
60284
|
-
await writeOutput(
|
|
60980
|
+
await writeOutput(
|
|
60981
|
+
state.writer,
|
|
60982
|
+
state.summaries,
|
|
60983
|
+
"sitemap.xml",
|
|
60984
|
+
buildSitemapXml(state.previewData.site, state.emitted, state.generatedAt, options2.sitemapStylesheetHref),
|
|
60985
|
+
"application/xml"
|
|
60986
|
+
);
|
|
60285
60987
|
await writeOutput(state.writer, state.summaries, "feed.xml", buildFeedXml(state.previewData.site, state.emitted, state.generatedAt), "application/rss+xml");
|
|
60286
60988
|
}
|
|
60287
60989
|
if (shouldGenerateRobotsTxt(options2)) {
|
|
@@ -60323,6 +61025,7 @@ async function createBuildState(input2, options2) {
|
|
|
60323
61025
|
customCssHref: customCssAsset ? `/${customCssAsset.path}` : "",
|
|
60324
61026
|
customHtml: previewData.custom_html,
|
|
60325
61027
|
favicon: previewData.site.favicon,
|
|
61028
|
+
exposeGenerator: previewData.site.expose_generator !== false,
|
|
60326
61029
|
commentPolicyContent: buildCommentPolicyManifest(renderData.posts),
|
|
60327
61030
|
options: options2,
|
|
60328
61031
|
generatedAt: /* @__PURE__ */ new Date(),
|
|
@@ -60432,7 +61135,8 @@ async function renderFrontPage(state, route) {
|
|
|
60432
61135
|
title: buildDocumentTitle(page.title, state.previewData.site.title),
|
|
60433
61136
|
description: page.excerpt,
|
|
60434
61137
|
ogType: "website",
|
|
60435
|
-
image: page.featured_image
|
|
61138
|
+
image: page.featured_image,
|
|
61139
|
+
robotsNoindex: shouldNoindexDocument(page)
|
|
60436
61140
|
})
|
|
60437
61141
|
},
|
|
60438
61142
|
createRenderContext(state.previewData.site, currentUrl)
|
|
@@ -60444,7 +61148,8 @@ async function renderFrontPage(state, route) {
|
|
|
60444
61148
|
url: currentUrl,
|
|
60445
61149
|
title: page.title,
|
|
60446
61150
|
description: page.excerpt,
|
|
60447
|
-
includeInFeed: false
|
|
61151
|
+
includeInFeed: false,
|
|
61152
|
+
includeInSitemap: !isDelistedDocument(page)
|
|
60448
61153
|
};
|
|
60449
61154
|
return;
|
|
60450
61155
|
}
|
|
@@ -60494,7 +61199,8 @@ async function renderPost(state, post) {
|
|
|
60494
61199
|
ogType: "article",
|
|
60495
61200
|
image: post.featured_image,
|
|
60496
61201
|
publishedTime: post.published_at_iso,
|
|
60497
|
-
modifiedTime: post.updated_at_iso
|
|
61202
|
+
modifiedTime: post.updated_at_iso,
|
|
61203
|
+
robotsNoindex: shouldNoindexDocument(post)
|
|
60498
61204
|
})
|
|
60499
61205
|
},
|
|
60500
61206
|
createRenderContext(state.previewData.site, currentUrl)
|
|
@@ -60502,14 +61208,16 @@ async function renderPost(state, post) {
|
|
|
60502
61208
|
html = state.assetProcessor.updateAssetReferences(html, state.assetMap);
|
|
60503
61209
|
html = injectSiteCustomizations(html, state);
|
|
60504
61210
|
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
|
-
|
|
61211
|
+
if (!isDelistedDocument(post)) {
|
|
61212
|
+
state.emitted.posts.push({
|
|
61213
|
+
url: currentUrl,
|
|
61214
|
+
title: post.title,
|
|
61215
|
+
description: post.excerpt,
|
|
61216
|
+
publishedAt: post.published_at_iso,
|
|
61217
|
+
updatedAt: post.updated_at_iso,
|
|
61218
|
+
status: post.status
|
|
61219
|
+
});
|
|
61220
|
+
}
|
|
60513
61221
|
}
|
|
60514
61222
|
async function renderPage(state, page) {
|
|
60515
61223
|
const currentUrl = page.url;
|
|
@@ -60530,7 +61238,8 @@ async function renderPage(state, page) {
|
|
|
60530
61238
|
title: buildDocumentTitle(page.title, state.previewData.site.title),
|
|
60531
61239
|
description: page.excerpt,
|
|
60532
61240
|
ogType: "website",
|
|
60533
|
-
image: page.featured_image
|
|
61241
|
+
image: page.featured_image,
|
|
61242
|
+
robotsNoindex: shouldNoindexDocument(page)
|
|
60534
61243
|
})
|
|
60535
61244
|
},
|
|
60536
61245
|
createRenderContext(state.previewData.site, currentUrl)
|
|
@@ -60543,7 +61252,7 @@ async function renderPage(state, page) {
|
|
|
60543
61252
|
title: page.title,
|
|
60544
61253
|
description: page.excerpt,
|
|
60545
61254
|
status: page.status,
|
|
60546
|
-
includeInSitemap: page.omit_from_sitemap !== true
|
|
61255
|
+
includeInSitemap: page.omit_from_sitemap !== true && !isDelistedDocument(page)
|
|
60547
61256
|
});
|
|
60548
61257
|
}
|
|
60549
61258
|
async function maybeRenderNotFoundPage(state) {
|
|
@@ -60574,15 +61283,18 @@ async function maybeRenderNotFoundPage(state) {
|
|
|
60574
61283
|
function normalizePreviewData(previewData, options2 = {}) {
|
|
60575
61284
|
const normalizedSite = {
|
|
60576
61285
|
...previewData.site,
|
|
60577
|
-
|
|
60578
|
-
|
|
61286
|
+
media_base_url: normalizeOptionalString(previewData.site.media_base_url),
|
|
61287
|
+
media_delivery_mode: MEDIA_DELIVERY_MODES.has(previewData.site.media_delivery_mode) ? previewData.site.media_delivery_mode : "none",
|
|
60579
61288
|
favicon: normalizeSiteFavicon(previewData.site.favicon || options2.favicon),
|
|
60580
|
-
|
|
60581
|
-
|
|
60582
|
-
|
|
61289
|
+
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,
|
|
61290
|
+
datetime_display: DATETIME_DISPLAY_MODES.has(previewData.site.datetime_display) ? previewData.site.datetime_display : DEFAULT_DATETIME_DISPLAY,
|
|
61291
|
+
date_style: DATETIME_STYLES.has(previewData.site.date_style) ? previewData.site.date_style : DEFAULT_DATE_STYLE,
|
|
61292
|
+
time_style: DATETIME_STYLES.has(previewData.site.time_style) ? previewData.site.time_style : DEFAULT_TIME_STYLE,
|
|
60583
61293
|
timezone: normalizeNonEmptyString(previewData.site.timezone, DEFAULT_TIMEZONE),
|
|
60584
61294
|
locale: normalizeLocale(previewData.site.locale || DEFAULT_LOCALE),
|
|
60585
|
-
|
|
61295
|
+
disallow_comments: previewData.site.disallow_comments === true,
|
|
61296
|
+
expose_generator: previewData.site.expose_generator !== false,
|
|
61297
|
+
search: previewData.site.search !== false,
|
|
60586
61298
|
indexing: previewData.site.indexing !== false,
|
|
60587
61299
|
permalinks: normalizePermalinks(previewData.site.permalinks),
|
|
60588
61300
|
front_page: normalizeFrontPage(previewData.site.front_page),
|
|
@@ -60596,13 +61308,13 @@ function normalizePreviewData(previewData, options2 = {}) {
|
|
|
60596
61308
|
site: normalizedSite,
|
|
60597
61309
|
menus: normalizeRecordMap(previewData.menus),
|
|
60598
61310
|
collections: normalizeCollections(previewData.collections),
|
|
60599
|
-
widgets: normalizeWidgetAreas(previewData.widgets, normalizedSite.
|
|
61311
|
+
widgets: normalizeWidgetAreas(previewData.widgets, normalizedSite.media_base_url),
|
|
60600
61312
|
custom_css: normalizeCustomCss(previewData.custom_css),
|
|
60601
61313
|
custom_html: normalizeCustomHtml(previewData.custom_html),
|
|
60602
61314
|
content: {
|
|
60603
61315
|
...previewData.content,
|
|
60604
61316
|
authors: previewData.content.authors.map((author) => {
|
|
60605
|
-
const avatar = normalizeMediaField(author.avatar, normalizedSite.
|
|
61317
|
+
const avatar = normalizeMediaField(author.avatar, normalizedSite.media_base_url);
|
|
60606
61318
|
const avatarMedia = deriveManagedMedia(avatar, mediaRegistry, normalizedSite);
|
|
60607
61319
|
return {
|
|
60608
61320
|
...author,
|
|
@@ -60611,21 +61323,23 @@ function normalizePreviewData(previewData, options2 = {}) {
|
|
|
60611
61323
|
};
|
|
60612
61324
|
}),
|
|
60613
61325
|
posts: previewData.content.posts.map((post) => {
|
|
60614
|
-
const featuredImage = normalizeMediaField(post.featured_image, normalizedSite.
|
|
61326
|
+
const featuredImage = normalizeMediaField(post.featured_image, normalizedSite.media_base_url);
|
|
60615
61327
|
const featuredMedia = deriveManagedMedia(featuredImage, mediaRegistry, normalizedSite);
|
|
60616
61328
|
return {
|
|
60617
61329
|
...post,
|
|
60618
61330
|
published_at_iso: normalizeIsoTimestamp(post.published_at_iso),
|
|
60619
61331
|
updated_at_iso: normalizeIsoTimestamp(post.updated_at_iso),
|
|
61332
|
+
discoverability: normalizeDiscoverability(post.discoverability),
|
|
60620
61333
|
featured_image: featuredImage,
|
|
60621
61334
|
...featuredMedia ? { featured_media: featuredMedia } : {}
|
|
60622
61335
|
};
|
|
60623
61336
|
}).sort((left, right) => toDate(right.published_at_iso).getTime() - toDate(left.published_at_iso).getTime()),
|
|
60624
61337
|
pages: previewData.content.pages.map((page) => {
|
|
60625
|
-
const featuredImage = normalizeMediaField(page.featured_image, normalizedSite.
|
|
61338
|
+
const featuredImage = normalizeMediaField(page.featured_image, normalizedSite.media_base_url);
|
|
60626
61339
|
const featuredMedia = deriveManagedMedia(featuredImage, mediaRegistry, normalizedSite);
|
|
60627
61340
|
return {
|
|
60628
61341
|
...page,
|
|
61342
|
+
discoverability: normalizeDiscoverability(page.discoverability),
|
|
60629
61343
|
featured_image: featuredImage,
|
|
60630
61344
|
...featuredMedia ? { featured_media: featuredMedia } : {}
|
|
60631
61345
|
};
|
|
@@ -60642,6 +61356,15 @@ function normalizeRecordMap(value) {
|
|
|
60642
61356
|
}
|
|
60643
61357
|
return { ...value };
|
|
60644
61358
|
}
|
|
61359
|
+
function normalizeDiscoverability(value) {
|
|
61360
|
+
return DISCOVERABILITY_VALUES.has(value) ? value : "default";
|
|
61361
|
+
}
|
|
61362
|
+
function isDelistedDocument(document2) {
|
|
61363
|
+
return document2?.discoverability === "delist";
|
|
61364
|
+
}
|
|
61365
|
+
function shouldNoindexDocument(document2) {
|
|
61366
|
+
return document2?.discoverability === "noindex" || document2?.discoverability === "delist";
|
|
61367
|
+
}
|
|
60645
61368
|
function normalizeContentMedia(mediaItems, site) {
|
|
60646
61369
|
if (!Array.isArray(mediaItems)) {
|
|
60647
61370
|
return [];
|
|
@@ -60650,7 +61373,7 @@ function normalizeContentMedia(mediaItems, site) {
|
|
|
60650
61373
|
if (!item || typeof item !== "object") {
|
|
60651
61374
|
return null;
|
|
60652
61375
|
}
|
|
60653
|
-
const src = normalizeMediaField(item.src, site.
|
|
61376
|
+
const src = normalizeMediaField(item.src, site.media_base_url);
|
|
60654
61377
|
const width = Number.isInteger(item.width) && item.width > 0 ? item.width : 0;
|
|
60655
61378
|
const height = Number.isInteger(item.height) && item.height > 0 ? item.height : 0;
|
|
60656
61379
|
if (!src || !width || !height) {
|
|
@@ -60688,11 +61411,11 @@ function deriveManagedMedia(src, mediaRegistry, site) {
|
|
|
60688
61411
|
};
|
|
60689
61412
|
}
|
|
60690
61413
|
function buildResponsiveImageSrcset(media, site) {
|
|
60691
|
-
if (site.
|
|
61414
|
+
if (site.media_delivery_mode !== "media_domain") {
|
|
60692
61415
|
return "";
|
|
60693
61416
|
}
|
|
60694
|
-
const
|
|
60695
|
-
if (!
|
|
61417
|
+
const media_base_url = normalizeOptionalString(site.media_base_url);
|
|
61418
|
+
if (!media_base_url || !isUrlUnderMediaBase(media.src, media_base_url) || !isResponsiveRasterImage(media.src)) {
|
|
60696
61419
|
return "";
|
|
60697
61420
|
}
|
|
60698
61421
|
const widths = RESPONSIVE_IMAGE_WIDTHS.filter((width) => width <= media.width);
|
|
@@ -60712,10 +61435,10 @@ function buildResponsiveImageVariantUrl(src, width) {
|
|
|
60712
61435
|
return src;
|
|
60713
61436
|
}
|
|
60714
61437
|
}
|
|
60715
|
-
function isUrlUnderMediaBase(src,
|
|
61438
|
+
function isUrlUnderMediaBase(src, media_base_url) {
|
|
60716
61439
|
try {
|
|
60717
61440
|
const sourceUrl = new URL(src);
|
|
60718
|
-
const baseUrl = new URL(
|
|
61441
|
+
const baseUrl = new URL(media_base_url);
|
|
60719
61442
|
const basePath = baseUrl.pathname.endsWith("/") ? baseUrl.pathname : `${baseUrl.pathname}/`;
|
|
60720
61443
|
return sourceUrl.origin === baseUrl.origin && sourceUrl.pathname.startsWith(basePath);
|
|
60721
61444
|
} catch {
|
|
@@ -60748,34 +61471,30 @@ function normalizeCollections(collections) {
|
|
|
60748
61471
|
])
|
|
60749
61472
|
);
|
|
60750
61473
|
}
|
|
60751
|
-
function normalizeWidgetAreas(
|
|
60752
|
-
if (!
|
|
61474
|
+
function normalizeWidgetAreas(widget_areas, media_base_url) {
|
|
61475
|
+
if (!widget_areas || typeof widget_areas !== "object") {
|
|
60753
61476
|
return {};
|
|
60754
61477
|
}
|
|
60755
61478
|
return Object.fromEntries(
|
|
60756
|
-
Object.entries(
|
|
61479
|
+
Object.entries(widget_areas).map(([widgetAreaId, widgetArea]) => [
|
|
60757
61480
|
widgetAreaId,
|
|
60758
61481
|
{
|
|
60759
61482
|
...widgetArea,
|
|
60760
61483
|
name: normalizeNonEmptyString(widgetArea?.name, widgetAreaId),
|
|
60761
|
-
items: Array.isArray(widgetArea?.items) ? widgetArea.items.map((item) => normalizeWidgetItem(item,
|
|
61484
|
+
items: Array.isArray(widgetArea?.items) ? widgetArea.items.map((item) => normalizeWidgetItem(item, media_base_url)) : []
|
|
60762
61485
|
}
|
|
60763
61486
|
])
|
|
60764
61487
|
);
|
|
60765
61488
|
}
|
|
60766
61489
|
function normalizeSiteFooter(footer) {
|
|
60767
61490
|
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
61491
|
return {
|
|
60770
61492
|
...source,
|
|
60771
61493
|
copyright_text: normalizeOptionalString(source.copyright_text),
|
|
60772
|
-
attribution:
|
|
60773
|
-
...attribution,
|
|
60774
|
-
enabled: attribution.enabled !== false
|
|
60775
|
-
}
|
|
61494
|
+
attribution: source.attribution !== false
|
|
60776
61495
|
};
|
|
60777
61496
|
}
|
|
60778
|
-
function normalizeWidgetItem(item,
|
|
61497
|
+
function normalizeWidgetItem(item, media_base_url) {
|
|
60779
61498
|
const normalizedItem = {
|
|
60780
61499
|
...item,
|
|
60781
61500
|
title: typeof item?.title === "string" ? item.title.trim() : ""
|
|
@@ -60785,7 +61504,7 @@ function normalizeWidgetItem(item, mediaBaseUrl) {
|
|
|
60785
61504
|
...normalizedItem,
|
|
60786
61505
|
settings: {
|
|
60787
61506
|
...item.settings,
|
|
60788
|
-
avatar: normalizeMediaField(item.settings.avatar,
|
|
61507
|
+
avatar: normalizeMediaField(item.settings.avatar, media_base_url)
|
|
60789
61508
|
}
|
|
60790
61509
|
};
|
|
60791
61510
|
}
|
|
@@ -60844,19 +61563,21 @@ function normalizeFrontPage(frontPage) {
|
|
|
60844
61563
|
...type === "standalone_html" ? { html: normalizeOptionalRawString(frontPage.html) } : {}
|
|
60845
61564
|
};
|
|
60846
61565
|
}
|
|
60847
|
-
function normalizePostIndex(
|
|
60848
|
-
if (!
|
|
61566
|
+
function normalizePostIndex(post_index) {
|
|
61567
|
+
if (!post_index || typeof post_index !== "object") {
|
|
60849
61568
|
return { ...DEFAULT_POST_INDEX };
|
|
60850
61569
|
}
|
|
60851
61570
|
return {
|
|
60852
|
-
enabled:
|
|
60853
|
-
path: normalizeNonEmptyString(
|
|
60854
|
-
paginate:
|
|
61571
|
+
enabled: post_index.enabled !== false,
|
|
61572
|
+
path: normalizeNonEmptyString(post_index.path, DEFAULT_POST_INDEX.path),
|
|
61573
|
+
paginate: post_index.paginate !== false
|
|
60855
61574
|
};
|
|
60856
61575
|
}
|
|
60857
61576
|
function createRenderData(previewData, themeMetadata = {}) {
|
|
60858
61577
|
const themeSupportsComments = themeMetadata?.features?.comments === true;
|
|
60859
|
-
const themeSupportsPostIndex = themeMetadata?.features?.
|
|
61578
|
+
const themeSupportsPostIndex = themeMetadata?.features?.post_index !== false;
|
|
61579
|
+
const themeSupportsSearch = themeMetadata?.features?.search === true;
|
|
61580
|
+
previewData.site.search = previewData.site.search !== false && themeSupportsSearch;
|
|
60860
61581
|
const authorsById = new Map(previewData.content.authors.map((author) => [author.id, author]));
|
|
60861
61582
|
const categoriesBySlug = new Map(previewData.content.categories.map((category) => [category.slug, category]));
|
|
60862
61583
|
const tagsBySlug = new Map(previewData.content.tags.map((tag) => [tag.slug, tag]));
|
|
@@ -60864,7 +61585,8 @@ function createRenderData(previewData, themeMetadata = {}) {
|
|
|
60864
61585
|
const tagPostsBySlug = /* @__PURE__ */ new Map();
|
|
60865
61586
|
const categoryCountBySlug = /* @__PURE__ */ new Map();
|
|
60866
61587
|
const tagCountBySlug = /* @__PURE__ */ new Map();
|
|
60867
|
-
|
|
61588
|
+
const discoverableSourcePosts = previewData.content.posts.filter((post) => !isDelistedDocument(post));
|
|
61589
|
+
for (const post of discoverableSourcePosts) {
|
|
60868
61590
|
for (const slug of post.category_slugs) {
|
|
60869
61591
|
pushToSlugMap(categoryPostsBySlug, slug, post);
|
|
60870
61592
|
categoryCountBySlug.set(slug, (categoryCountBySlug.get(slug) || 0) + 1);
|
|
@@ -60875,45 +61597,54 @@ function createRenderData(previewData, themeMetadata = {}) {
|
|
|
60875
61597
|
}
|
|
60876
61598
|
}
|
|
60877
61599
|
const preparedPosts = previewData.content.posts.map((post) => preparePost(post, previewData.site, authorsById, categoriesBySlug, tagsBySlug, themeSupportsComments));
|
|
60878
|
-
const
|
|
61600
|
+
const discoverablePreparedPosts = preparedPosts.filter((post) => !isDelistedDocument(post));
|
|
61601
|
+
const adjacentPostsBySlug = new Map(
|
|
61602
|
+
discoverablePreparedPosts.map((post, index) => [post.slug, {
|
|
61603
|
+
prev: index > 0 ? buildAdjacentPostSummary(discoverablePreparedPosts[index - 1]) : null,
|
|
61604
|
+
next: index < discoverablePreparedPosts.length - 1 ? buildAdjacentPostSummary(discoverablePreparedPosts[index + 1]) : null
|
|
61605
|
+
}])
|
|
61606
|
+
);
|
|
61607
|
+
const posts = preparedPosts.map((post) => ({
|
|
60879
61608
|
...post,
|
|
60880
|
-
prev:
|
|
60881
|
-
next:
|
|
61609
|
+
prev: adjacentPostsBySlug.get(post.slug)?.prev || null,
|
|
61610
|
+
next: adjacentPostsBySlug.get(post.slug)?.next || null
|
|
60882
61611
|
}));
|
|
60883
61612
|
const pages = previewData.content.pages.map((page) => preparePage(page, previewData.site));
|
|
60884
61613
|
const postBySlug = new Map(posts.map((post) => [post.slug, post]));
|
|
60885
61614
|
const pageBySlug = new Map(pages.map((page) => [page.slug, page]));
|
|
60886
61615
|
const frontPage = previewData.site.front_page;
|
|
60887
|
-
const
|
|
60888
|
-
|
|
60889
|
-
const
|
|
60890
|
-
const
|
|
60891
|
-
|
|
61616
|
+
const collections = resolveCollections(previewData.collections, postBySlug, pageBySlug, frontPage);
|
|
61617
|
+
attachCollectionCursors(posts, pages, collections);
|
|
61618
|
+
const post_index = previewData.site.post_index;
|
|
61619
|
+
const effectivePostIndexEnabled = post_index.enabled !== false && themeSupportsPostIndex;
|
|
61620
|
+
const effectivePostIndexPaginate = effectivePostIndexEnabled && post_index.paginate !== false;
|
|
61621
|
+
const post_indexBasePath = normalizeRoutePath(post_index.path || DEFAULT_POST_INDEX.path);
|
|
61622
|
+
if (frontPage.type !== "theme_index" && effectivePostIndexEnabled && post_indexBasePath === "/") {
|
|
60892
61623
|
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
61624
|
}
|
|
60894
|
-
const frontPageRoute = buildFrontPageRoute(frontPage, pages, effectivePostIndexEnabled,
|
|
61625
|
+
const frontPageRoute = buildFrontPageRoute(frontPage, pages, effectivePostIndexEnabled, post_indexBasePath);
|
|
60895
61626
|
const pageFrontPageSlug = frontPage.type === "page" ? frontPage.page_slug : "";
|
|
60896
61627
|
const preparedPages = pageFrontPageSlug ? pages.filter((page) => page.slug !== pageFrontPageSlug) : pages;
|
|
60897
61628
|
return {
|
|
60898
61629
|
posts,
|
|
60899
61630
|
pages: preparedPages,
|
|
60900
61631
|
postBySlug,
|
|
60901
|
-
collections
|
|
61632
|
+
collections,
|
|
60902
61633
|
taxonomies: buildGlobalTaxonomies(previewData, categoryCountBySlug, tagCountBySlug),
|
|
60903
61634
|
frontPageRoute,
|
|
60904
61635
|
indexRoutes: buildPostIndexRoutes({
|
|
60905
61636
|
enabled: effectivePostIndexEnabled,
|
|
60906
61637
|
paginate: effectivePostIndexPaginate,
|
|
60907
|
-
items:
|
|
60908
|
-
|
|
60909
|
-
basePath:
|
|
61638
|
+
items: discoverableSourcePosts,
|
|
61639
|
+
posts_per_page: previewData.site.posts_per_page,
|
|
61640
|
+
basePath: post_indexBasePath,
|
|
60910
61641
|
outputStyle: previewData.site.permalinks.output_style,
|
|
60911
61642
|
postBySlug,
|
|
60912
61643
|
frontPage
|
|
60913
61644
|
}),
|
|
60914
61645
|
archiveRoutes: buildPaginatedCollection({
|
|
60915
|
-
items:
|
|
60916
|
-
|
|
61646
|
+
items: discoverableSourcePosts,
|
|
61647
|
+
posts_per_page: previewData.site.posts_per_page,
|
|
60917
61648
|
basePath: "/archive/",
|
|
60918
61649
|
outputStyle: previewData.site.permalinks.output_style
|
|
60919
61650
|
}).map((entry) => ({
|
|
@@ -60929,7 +61660,7 @@ function createRenderData(previewData, themeMetadata = {}) {
|
|
|
60929
61660
|
items: previewData.content.categories,
|
|
60930
61661
|
postsBySlug: categoryPostsBySlug,
|
|
60931
61662
|
postBySlug,
|
|
60932
|
-
|
|
61663
|
+
posts_per_page: previewData.site.posts_per_page,
|
|
60933
61664
|
outputStyle: previewData.site.permalinks.output_style,
|
|
60934
61665
|
buildBasePath: (category) => resolvePermalink(previewData.site, "categories", category).path,
|
|
60935
61666
|
renderExtras: (category) => ({
|
|
@@ -60940,7 +61671,7 @@ function createRenderData(previewData, themeMetadata = {}) {
|
|
|
60940
61671
|
items: previewData.content.tags,
|
|
60941
61672
|
postsBySlug: tagPostsBySlug,
|
|
60942
61673
|
postBySlug,
|
|
60943
|
-
|
|
61674
|
+
posts_per_page: previewData.site.posts_per_page,
|
|
60944
61675
|
outputStyle: previewData.site.permalinks.output_style,
|
|
60945
61676
|
buildBasePath: (tag) => resolvePermalink(previewData.site, "tags", tag).path,
|
|
60946
61677
|
renderExtras: (tag) => ({
|
|
@@ -60960,15 +61691,19 @@ function resolveCollections(collections, postBySlug, pageBySlug, frontPage) {
|
|
|
60960
61691
|
return {};
|
|
60961
61692
|
}
|
|
60962
61693
|
return Object.fromEntries(
|
|
60963
|
-
Object.entries(collections).map(([collectionId, collection]) =>
|
|
60964
|
-
collectionId,
|
|
60965
|
-
|
|
60966
|
-
|
|
60967
|
-
|
|
60968
|
-
|
|
60969
|
-
|
|
60970
|
-
|
|
60971
|
-
|
|
61694
|
+
Object.entries(collections).map(([collectionId, collection]) => {
|
|
61695
|
+
const items = resolveCollectionItems(collectionId, collection?.items, postBySlug, pageBySlug, frontPage);
|
|
61696
|
+
return [
|
|
61697
|
+
collectionId,
|
|
61698
|
+
{
|
|
61699
|
+
id: collectionId,
|
|
61700
|
+
title: normalizeOptionalString(collection?.title),
|
|
61701
|
+
description: normalizeOptionalString(collection?.description),
|
|
61702
|
+
count: items.length,
|
|
61703
|
+
items
|
|
61704
|
+
}
|
|
61705
|
+
];
|
|
61706
|
+
})
|
|
60972
61707
|
);
|
|
60973
61708
|
}
|
|
60974
61709
|
function resolveCollectionItems(collectionId, items, postBySlug, pageBySlug, frontPage) {
|
|
@@ -61007,12 +61742,57 @@ function buildCollectionPageSummary(page, frontPage) {
|
|
|
61007
61742
|
excerpt: page.excerpt || "",
|
|
61008
61743
|
featured_image: page.featured_image || "",
|
|
61009
61744
|
...page.featured_media ? { featured_media: { ...page.featured_media } } : {},
|
|
61010
|
-
meta: page.meta
|
|
61745
|
+
meta: page.meta,
|
|
61746
|
+
data: page.data
|
|
61747
|
+
};
|
|
61748
|
+
}
|
|
61749
|
+
function attachCollectionCursors(posts, pages, collections) {
|
|
61750
|
+
const postTargets = new Map(posts.map((post) => [post.slug, post]));
|
|
61751
|
+
const pageTargets = new Map(pages.map((page) => [page.slug, page]));
|
|
61752
|
+
for (const [collectionId, collection] of Object.entries(collections || {})) {
|
|
61753
|
+
const items = Array.isArray(collection.items) ? collection.items : [];
|
|
61754
|
+
items.forEach((item, index) => {
|
|
61755
|
+
const target = item.type === "post" ? postTargets.get(item.slug) : item.type === "page" ? pageTargets.get(item.slug) : null;
|
|
61756
|
+
if (!target) {
|
|
61757
|
+
return;
|
|
61758
|
+
}
|
|
61759
|
+
target.collection_cursors = target.collection_cursors || {};
|
|
61760
|
+
target.collection_cursors[collectionId] = buildCollectionCursor(collectionId, collection, items, index);
|
|
61761
|
+
});
|
|
61762
|
+
}
|
|
61763
|
+
}
|
|
61764
|
+
function buildCollectionCursor(collectionId, collection, items, index) {
|
|
61765
|
+
const count = items.length;
|
|
61766
|
+
return {
|
|
61767
|
+
collection_id: collectionId,
|
|
61768
|
+
collection_title: collection.title || "",
|
|
61769
|
+
index,
|
|
61770
|
+
position: index + 1,
|
|
61771
|
+
count,
|
|
61772
|
+
first: index === 0,
|
|
61773
|
+
last: index === count - 1,
|
|
61774
|
+
prev: index > 0 ? buildCollectionCursorItemSummary(items[index - 1]) : null,
|
|
61775
|
+
next: index < count - 1 ? buildCollectionCursorItemSummary(items[index + 1]) : null
|
|
61011
61776
|
};
|
|
61012
61777
|
}
|
|
61013
|
-
function
|
|
61778
|
+
function buildCollectionCursorItemSummary(item) {
|
|
61779
|
+
if (!item) {
|
|
61780
|
+
return null;
|
|
61781
|
+
}
|
|
61782
|
+
return {
|
|
61783
|
+
type: item.type,
|
|
61784
|
+
title: item.title,
|
|
61785
|
+
slug: item.slug,
|
|
61786
|
+
url: item.url,
|
|
61787
|
+
excerpt: item.excerpt || "",
|
|
61788
|
+
featured_image: item.featured_image || "",
|
|
61789
|
+
meta: item.meta,
|
|
61790
|
+
data: item.data
|
|
61791
|
+
};
|
|
61792
|
+
}
|
|
61793
|
+
function buildFrontPageRoute(frontPage, pages, effectivePostIndexEnabled, post_indexBasePath) {
|
|
61014
61794
|
if (frontPage.type === "theme_index") {
|
|
61015
|
-
if (effectivePostIndexEnabled &&
|
|
61795
|
+
if (effectivePostIndexEnabled && post_indexBasePath === "/") {
|
|
61016
61796
|
return null;
|
|
61017
61797
|
}
|
|
61018
61798
|
return {
|
|
@@ -61050,7 +61830,7 @@ function buildPostIndexRoutes(options2) {
|
|
|
61050
61830
|
return [];
|
|
61051
61831
|
}
|
|
61052
61832
|
if (!options2.paginate) {
|
|
61053
|
-
const items = options2.items.slice(0, options2.
|
|
61833
|
+
const items = options2.items.slice(0, options2.posts_per_page);
|
|
61054
61834
|
return [{
|
|
61055
61835
|
path: options2.basePath,
|
|
61056
61836
|
route_type: "post_index",
|
|
@@ -61064,7 +61844,7 @@ function buildPostIndexRoutes(options2) {
|
|
|
61064
61844
|
}
|
|
61065
61845
|
return buildPaginatedCollection({
|
|
61066
61846
|
items: options2.items,
|
|
61067
|
-
|
|
61847
|
+
posts_per_page: options2.posts_per_page,
|
|
61068
61848
|
basePath: options2.basePath,
|
|
61069
61849
|
outputStyle: options2.outputStyle
|
|
61070
61850
|
}).map((entry) => ({
|
|
@@ -61143,7 +61923,7 @@ function resolveWidgetItem(item, previewData, renderData, widgetAreaId, index) {
|
|
|
61143
61923
|
}
|
|
61144
61924
|
function resolveRecentPostsWidget(baseWidget, settings, renderData) {
|
|
61145
61925
|
const limit = clampInteger(settings?.limit, 5, 1, 20);
|
|
61146
|
-
const items = renderData.posts.slice(0, limit).map((post) => ({
|
|
61926
|
+
const items = renderData.posts.filter((post) => !isDelistedDocument(post)).slice(0, limit).map((post) => ({
|
|
61147
61927
|
title: post.title,
|
|
61148
61928
|
url: `/posts/${encodeSlugSegment(post.slug)}/`,
|
|
61149
61929
|
published_at: post.published_at,
|
|
@@ -61312,7 +62092,9 @@ function preparePost(post, site, authorsById, categoriesBySlug, tagsBySlug, them
|
|
|
61312
62092
|
featured_image: post.featured_image,
|
|
61313
62093
|
...post.featured_media ? { featured_media: { ...post.featured_media } } : {},
|
|
61314
62094
|
meta: post.meta,
|
|
62095
|
+
data: post.data,
|
|
61315
62096
|
status: post.status,
|
|
62097
|
+
discoverability: post.discoverability,
|
|
61316
62098
|
allow_comments: post.allow_comments,
|
|
61317
62099
|
category_slugs: post.category_slugs,
|
|
61318
62100
|
tag_slugs: post.tag_slugs,
|
|
@@ -61329,7 +62111,7 @@ function preparePost(post, site, authorsById, categoriesBySlug, tagsBySlug, them
|
|
|
61329
62111
|
published_at: formatTimestamp(post.published_at_iso, site),
|
|
61330
62112
|
updated_at: formatTimestamp(post.updated_at_iso, site),
|
|
61331
62113
|
reading_time: calculateReadingTime(renderedDocument.html),
|
|
61332
|
-
comments_enabled: themeSupportsComments && site.
|
|
62114
|
+
comments_enabled: themeSupportsComments && site.disallow_comments !== true && post.allow_comments === true
|
|
61333
62115
|
};
|
|
61334
62116
|
}
|
|
61335
62117
|
function buildCommentPolicyManifest(posts) {
|
|
@@ -61348,7 +62130,7 @@ function buildTaxonomyRoutes(options2) {
|
|
|
61348
62130
|
}
|
|
61349
62131
|
const paginated = buildPaginatedCollection({
|
|
61350
62132
|
items: matchedPosts,
|
|
61351
|
-
|
|
62133
|
+
posts_per_page: options2.posts_per_page,
|
|
61352
62134
|
basePath: options2.buildBasePath(item),
|
|
61353
62135
|
outputStyle: options2.outputStyle
|
|
61354
62136
|
});
|
|
@@ -61369,13 +62151,13 @@ function buildTaxonomyRoutes(options2) {
|
|
|
61369
62151
|
function buildPaginatedCollection(options2) {
|
|
61370
62152
|
const basePath = normalizePaginationBasePath(options2.basePath);
|
|
61371
62153
|
const outputStyle = PERMALINK_OUTPUT_STYLES.has(options2.outputStyle) ? options2.outputStyle : DEFAULT_PERMALINKS.output_style;
|
|
61372
|
-
const
|
|
62154
|
+
const posts_per_page = Number.isInteger(options2.posts_per_page) && options2.posts_per_page > 0 ? options2.posts_per_page : DEFAULT_POSTS_PER_PAGE;
|
|
61373
62155
|
const totalPosts = options2.items.length;
|
|
61374
|
-
const totalPages = Math.max(1, Math.ceil(totalPosts /
|
|
62156
|
+
const totalPages = Math.max(1, Math.ceil(totalPosts / posts_per_page));
|
|
61375
62157
|
const pages = [];
|
|
61376
62158
|
for (let page = 1; page <= totalPages; page += 1) {
|
|
61377
|
-
const start = (page - 1) *
|
|
61378
|
-
const end = start +
|
|
62159
|
+
const start = (page - 1) * posts_per_page;
|
|
62160
|
+
const end = start + posts_per_page;
|
|
61379
62161
|
pages.push({
|
|
61380
62162
|
path: buildPaginatedPath(basePath, page),
|
|
61381
62163
|
page,
|
|
@@ -61523,6 +62305,8 @@ function buildStructuredPostSummary(post) {
|
|
|
61523
62305
|
reading_time: post.reading_time,
|
|
61524
62306
|
featured_image: post.featured_image,
|
|
61525
62307
|
...post.featured_media ? { featured_media: { ...post.featured_media } } : {},
|
|
62308
|
+
meta: post.meta,
|
|
62309
|
+
data: post.data,
|
|
61526
62310
|
author: {
|
|
61527
62311
|
display_name: post.author?.display_name || "",
|
|
61528
62312
|
avatar: post.author?.avatar || "",
|
|
@@ -61542,7 +62326,8 @@ function buildAdjacentPostSummary(post) {
|
|
|
61542
62326
|
url: post.url,
|
|
61543
62327
|
excerpt: post.excerpt,
|
|
61544
62328
|
published_at: post.published_at,
|
|
61545
|
-
published_at_iso: post.published_at_iso
|
|
62329
|
+
published_at_iso: post.published_at_iso,
|
|
62330
|
+
data: post.data
|
|
61546
62331
|
};
|
|
61547
62332
|
}
|
|
61548
62333
|
function buildArchiveGroups(posts, postBySlug) {
|
|
@@ -61615,40 +62400,22 @@ function formatArchiveLabel(date, site) {
|
|
|
61615
62400
|
function formatTimestamp(value, site) {
|
|
61616
62401
|
const date = toDate(value);
|
|
61617
62402
|
const locale = normalizeLocale(site.locale || DEFAULT_LOCALE);
|
|
61618
|
-
const
|
|
61619
|
-
const
|
|
62403
|
+
const dateStyle = DATETIME_STYLES.has(site.date_style) ? site.date_style : DEFAULT_DATE_STYLE;
|
|
62404
|
+
const timeStyle = DATETIME_STYLES.has(site.time_style) ? site.time_style : DEFAULT_TIME_STYLE;
|
|
61620
62405
|
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();
|
|
62406
|
+
if (dateStyle === "none" && timeStyle === "none") {
|
|
62407
|
+
return "";
|
|
62408
|
+
}
|
|
62409
|
+
const options2 = {
|
|
62410
|
+
timeZone: siteTimezone
|
|
62411
|
+
};
|
|
62412
|
+
if (dateStyle !== "none") {
|
|
62413
|
+
options2.dateStyle = dateStyle;
|
|
62414
|
+
}
|
|
62415
|
+
if (timeStyle !== "none") {
|
|
62416
|
+
options2.timeStyle = timeStyle;
|
|
62417
|
+
}
|
|
62418
|
+
return new Intl.DateTimeFormat(locale, options2).format(date);
|
|
61652
62419
|
}
|
|
61653
62420
|
function calculateReadingTime(html) {
|
|
61654
62421
|
const plainText = String(html || "").replace(/<[^>]*>/g, " ");
|
|
@@ -61729,11 +62496,12 @@ async function normalizeAndValidateThemePackage(themePackage) {
|
|
|
61729
62496
|
...themePackage.metadata.author ? { author: themePackage.metadata.author } : {},
|
|
61730
62497
|
...themePackage.metadata.description ? { description: themePackage.metadata.description } : {},
|
|
61731
62498
|
...themePackage.metadata.thumbnail ? { thumbnail: themePackage.metadata.thumbnail } : {},
|
|
62499
|
+
...themePackage.metadata.links ? { links: themePackage.metadata.links } : {},
|
|
61732
62500
|
...themePackage.metadata.features ? { features: themePackage.metadata.features } : {},
|
|
61733
|
-
...themePackage.metadata.
|
|
61734
|
-
...themePackage.metadata.
|
|
61735
|
-
...themePackage.metadata.
|
|
61736
|
-
...themePackage.metadata.
|
|
62501
|
+
...themePackage.metadata.menu_slots ? { menu_slots: themePackage.metadata.menu_slots } : {},
|
|
62502
|
+
...themePackage.metadata.widget_areas ? { widget_areas: themePackage.metadata.widget_areas } : {},
|
|
62503
|
+
...themePackage.metadata.site_meta ? { site_meta: themePackage.metadata.site_meta } : {},
|
|
62504
|
+
...themePackage.metadata.collection_slots ? { collection_slots: themePackage.metadata.collection_slots } : {}
|
|
61737
62505
|
}));
|
|
61738
62506
|
for (const [templateName, templateContent] of themePackage.templates.entries()) {
|
|
61739
62507
|
fileMap.set(`${templateName}.html`, templateContent);
|
|
@@ -61746,7 +62514,7 @@ async function normalizeAndValidateThemePackage(themePackage) {
|
|
|
61746
62514
|
}
|
|
61747
62515
|
const validation = await validateThemeFiles(fileMap);
|
|
61748
62516
|
if (!validation.ok) {
|
|
61749
|
-
throw new Error(
|
|
62517
|
+
throw new Error(formatThemeValidationFailure(validation));
|
|
61750
62518
|
}
|
|
61751
62519
|
if (!validation.manifest) {
|
|
61752
62520
|
throw new Error("Theme validation failed: normalized manifest not available");
|
|
@@ -61758,6 +62526,55 @@ async function normalizeAndValidateThemePackage(themePackage) {
|
|
|
61758
62526
|
assets: themePackage.assets
|
|
61759
62527
|
};
|
|
61760
62528
|
}
|
|
62529
|
+
function formatThemeValidationFailure(validation) {
|
|
62530
|
+
const blocks = [
|
|
62531
|
+
[
|
|
62532
|
+
"Theme validation failed",
|
|
62533
|
+
`Errors: ${validation.errors.length}`,
|
|
62534
|
+
`Checked files: ${validation.checkedFiles}`
|
|
62535
|
+
].join("\n"),
|
|
62536
|
+
...validation.errors.map((issue3) => formatThemeValidationIssue(issue3))
|
|
62537
|
+
];
|
|
62538
|
+
return blocks.join("\n\n");
|
|
62539
|
+
}
|
|
62540
|
+
function formatThemeValidationIssue(issue3) {
|
|
62541
|
+
if (!issue3) {
|
|
62542
|
+
return "Reason: Unknown error";
|
|
62543
|
+
}
|
|
62544
|
+
const lines = [`ERROR ${issue3.code || "THEME_VALIDATION_ERROR"}`];
|
|
62545
|
+
const location = splitIssuePath(issue3.path);
|
|
62546
|
+
if (location.file) {
|
|
62547
|
+
lines.push(`File: ${location.file}`);
|
|
62548
|
+
}
|
|
62549
|
+
if (location.path) {
|
|
62550
|
+
lines.push(`Path: ${location.path}`);
|
|
62551
|
+
}
|
|
62552
|
+
if (Number.isInteger(issue3.line) && Number.isInteger(issue3.column)) {
|
|
62553
|
+
lines.push(`Line: ${issue3.line}, Column: ${issue3.column}`);
|
|
62554
|
+
}
|
|
62555
|
+
if (issue3.category) {
|
|
62556
|
+
lines.push(`Category: ${issue3.category}`);
|
|
62557
|
+
}
|
|
62558
|
+
lines.push(`Reason: ${issue3.message || "Unknown error"}`);
|
|
62559
|
+
if (issue3.snippet) {
|
|
62560
|
+
const lineLabel = Number.isInteger(issue3.line) ? String(issue3.line) : "";
|
|
62561
|
+
lines.push("", `${lineLabel} | ${issue3.snippet.line}`, `${" ".repeat(lineLabel.length)} | ${issue3.snippet.pointer}`);
|
|
62562
|
+
}
|
|
62563
|
+
if (issue3.hint) {
|
|
62564
|
+
lines.push("", "Hint:", issue3.hint);
|
|
62565
|
+
}
|
|
62566
|
+
return lines.join("\n");
|
|
62567
|
+
}
|
|
62568
|
+
function splitIssuePath(issuePath) {
|
|
62569
|
+
const normalizedPath = String(issuePath || "");
|
|
62570
|
+
if (normalizedPath.startsWith("theme.json.")) {
|
|
62571
|
+
return {
|
|
62572
|
+
file: "theme.json",
|
|
62573
|
+
path: normalizedPath.slice("theme.json.".length)
|
|
62574
|
+
};
|
|
62575
|
+
}
|
|
62576
|
+
return { file: normalizedPath, path: "" };
|
|
62577
|
+
}
|
|
61761
62578
|
function normalizeThemePackageMetadata(sourceMetadata, manifest) {
|
|
61762
62579
|
return {
|
|
61763
62580
|
...manifest,
|
|
@@ -61827,6 +62644,7 @@ function buildPageMeta(site, options2 = {}) {
|
|
|
61827
62644
|
const ogType = normalizeNonEmptyString(options2.ogType, "website");
|
|
61828
62645
|
const publishedTime = normalizeOptionalString(options2.publishedTime);
|
|
61829
62646
|
const modifiedTime = normalizeOptionalString(options2.modifiedTime);
|
|
62647
|
+
const robotsNoindex = options2.robotsNoindex === true;
|
|
61830
62648
|
const meta = {
|
|
61831
62649
|
title: escapeHtml2(resolvedTitle),
|
|
61832
62650
|
description: resolvedDescription ? escapeHtml2(resolvedDescription) : "",
|
|
@@ -61838,7 +62656,8 @@ function buildPageMeta(site, options2 = {}) {
|
|
|
61838
62656
|
og_site_name: escapeHtml2(site.title),
|
|
61839
62657
|
og_image: ogImage ? escapeHtml2(ogImage) : "",
|
|
61840
62658
|
article_published_time: publishedTime ? escapeHtml2(publishedTime) : "",
|
|
61841
|
-
article_modified_time: modifiedTime ? escapeHtml2(modifiedTime) : ""
|
|
62659
|
+
article_modified_time: modifiedTime ? escapeHtml2(modifiedTime) : "",
|
|
62660
|
+
robots_noindex: robotsNoindex
|
|
61842
62661
|
};
|
|
61843
62662
|
return {
|
|
61844
62663
|
...meta,
|
|
@@ -61855,6 +62674,9 @@ function buildMetaHeadTags(meta) {
|
|
|
61855
62674
|
if (meta.description) {
|
|
61856
62675
|
tags.push(`<meta name="description" content="${meta.description}">`);
|
|
61857
62676
|
}
|
|
62677
|
+
if (meta.robots_noindex) {
|
|
62678
|
+
tags.push('<meta name="robots" content="noindex">');
|
|
62679
|
+
}
|
|
61858
62680
|
if (meta.canonical_url) {
|
|
61859
62681
|
tags.push(`<link rel="canonical" href="${meta.canonical_url}">`);
|
|
61860
62682
|
}
|
|
@@ -61895,7 +62717,7 @@ function resolveMetaImageUrl(image2) {
|
|
|
61895
62717
|
}
|
|
61896
62718
|
return "";
|
|
61897
62719
|
}
|
|
61898
|
-
function normalizeMediaField(value,
|
|
62720
|
+
function normalizeMediaField(value, media_base_url) {
|
|
61899
62721
|
if (value === void 0) {
|
|
61900
62722
|
return void 0;
|
|
61901
62723
|
}
|
|
@@ -61906,7 +62728,7 @@ function normalizeMediaField(value, mediaBaseUrl) {
|
|
|
61906
62728
|
if (isAbsoluteUrl(normalizedValue)) {
|
|
61907
62729
|
return normalizeAbsoluteUrl(normalizedValue, SAFE_MEDIA_PROTOCOLS);
|
|
61908
62730
|
}
|
|
61909
|
-
const normalizedBaseUrl = normalizeOptionalString(
|
|
62731
|
+
const normalizedBaseUrl = normalizeOptionalString(media_base_url);
|
|
61910
62732
|
if (!normalizedBaseUrl) {
|
|
61911
62733
|
return normalizedValue;
|
|
61912
62734
|
}
|
|
@@ -62111,6 +62933,9 @@ function assertPlannedOutputPathsSafe(state) {
|
|
|
62111
62933
|
...state.assetOutputs.map((assetOutput) => assetOutput.path),
|
|
62112
62934
|
COMMENT_POLICY_OUTPUT_PATH
|
|
62113
62935
|
];
|
|
62936
|
+
if (shouldGenerateSearchArtifacts(state, state.options)) {
|
|
62937
|
+
plannedPaths.push(SEARCH_INDEX_OUTPUT_PATH, SEARCH_ADAPTER_OUTPUT_PATH, SEARCH_PAGEFIND_ADAPTER_OUTPUT_PATH);
|
|
62938
|
+
}
|
|
62114
62939
|
if (state.options.generateSpecialFiles) {
|
|
62115
62940
|
plannedPaths.push("404.html");
|
|
62116
62941
|
if (shouldGenerateRobotsTxt(state.options)) {
|
|
@@ -62191,6 +63016,7 @@ function sha256(content) {
|
|
|
62191
63016
|
}
|
|
62192
63017
|
function injectSiteCustomizations(html, state) {
|
|
62193
63018
|
let next = injectFaviconLinks(html, state.favicon);
|
|
63019
|
+
next = injectGeneratorMeta(next, state.exposeGenerator);
|
|
62194
63020
|
next = injectCustomCssAssetLink(next, state.customCssHref);
|
|
62195
63021
|
next = injectCustomHtml(next, state.customHtml);
|
|
62196
63022
|
return next;
|
|
@@ -62222,6 +63048,12 @@ function buildFaviconLinks(favicon) {
|
|
|
62222
63048
|
}
|
|
62223
63049
|
return lines.join("\n");
|
|
62224
63050
|
}
|
|
63051
|
+
function injectGeneratorMeta(html, exposeGenerator) {
|
|
63052
|
+
if (exposeGenerator === false) {
|
|
63053
|
+
return html;
|
|
63054
|
+
}
|
|
63055
|
+
return html.replace("</head>", ' <meta name="generator" content="ZeroPress">\n</head>');
|
|
63056
|
+
}
|
|
62225
63057
|
function injectCustomCssAssetLink(html, href) {
|
|
62226
63058
|
if (!normalizeOptionalString(href)) {
|
|
62227
63059
|
return html;
|
|
@@ -62243,9 +63075,464 @@ function injectCustomHtml(html, customHtml) {
|
|
|
62243
63075
|
}
|
|
62244
63076
|
return next;
|
|
62245
63077
|
}
|
|
62246
|
-
function
|
|
63078
|
+
function buildSearchIndexJson(state) {
|
|
63079
|
+
return `${JSON.stringify(buildSearchIndexItems(state), null, 2)}
|
|
63080
|
+
`;
|
|
63081
|
+
}
|
|
63082
|
+
function buildSearchIndexItems(state) {
|
|
63083
|
+
const posts = state.renderData.posts.filter((post) => post.status === "published" && !isDelistedDocument(post)).map((post) => ({
|
|
63084
|
+
id: `post:${post.slug}`,
|
|
63085
|
+
type: "post",
|
|
63086
|
+
title: post.title,
|
|
63087
|
+
url: post.url,
|
|
63088
|
+
excerpt: normalizeSearchText(post.excerpt),
|
|
63089
|
+
headings: buildSearchHeadings(post.toc),
|
|
63090
|
+
categories: Array.isArray(post.categories) ? post.categories.map((category) => category.name).filter(Boolean) : [],
|
|
63091
|
+
tags: Array.isArray(post.tags) ? post.tags.map((tag) => tag.name).filter(Boolean) : [],
|
|
63092
|
+
published_at_iso: normalizeIsoTimestamp(post.published_at_iso),
|
|
63093
|
+
updated_at_iso: normalizeIsoTimestamp(post.updated_at_iso),
|
|
63094
|
+
content_text: htmlToSearchText(post.html)
|
|
63095
|
+
}));
|
|
63096
|
+
const frontPagePage = state.renderData.frontPageRoute?.front_page_type === "page" ? state.renderData.frontPageRoute.page : null;
|
|
63097
|
+
const frontPageItems = frontPagePage && frontPagePage.status === "published" && !isDelistedDocument(frontPagePage) ? [buildSearchPageItem(frontPagePage, "/")] : [];
|
|
63098
|
+
const pageItems = state.renderData.pages.filter((page) => page.status === "published" && !isDelistedDocument(page)).map((page) => buildSearchPageItem(page, page.url));
|
|
63099
|
+
return [...posts, ...frontPageItems, ...pageItems];
|
|
63100
|
+
}
|
|
63101
|
+
function buildSearchPageItem(page, url) {
|
|
63102
|
+
return {
|
|
63103
|
+
id: `page:${page.slug}`,
|
|
63104
|
+
type: "page",
|
|
63105
|
+
title: page.title,
|
|
63106
|
+
url,
|
|
63107
|
+
excerpt: normalizeSearchText(page.excerpt),
|
|
63108
|
+
headings: buildSearchHeadings(page.toc),
|
|
63109
|
+
categories: [],
|
|
63110
|
+
tags: [],
|
|
63111
|
+
published_at_iso: "",
|
|
63112
|
+
updated_at_iso: "",
|
|
63113
|
+
content_text: htmlToSearchText(page.html)
|
|
63114
|
+
};
|
|
63115
|
+
}
|
|
63116
|
+
function buildSearchHeadings(toc) {
|
|
63117
|
+
return Array.isArray(toc) ? toc.map((item) => normalizeSearchText(item?.title)).filter(Boolean) : [];
|
|
63118
|
+
}
|
|
63119
|
+
function htmlToSearchText(html) {
|
|
63120
|
+
return normalizeSearchText(decodeHtmlEntities(
|
|
63121
|
+
String(html || "").replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, " ").replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, " ").replace(/<!--[\s\S]*?-->/g, " ").replace(/<[^>]+>/g, " ")
|
|
63122
|
+
));
|
|
63123
|
+
}
|
|
63124
|
+
function decodeHtmlEntities(value) {
|
|
63125
|
+
const namedEntities = {
|
|
63126
|
+
amp: "&",
|
|
63127
|
+
lt: "<",
|
|
63128
|
+
gt: ">",
|
|
63129
|
+
quot: '"',
|
|
63130
|
+
apos: "'",
|
|
63131
|
+
nbsp: " "
|
|
63132
|
+
};
|
|
63133
|
+
return String(value || "").replace(/&(#x[0-9a-fA-F]+|#\d+|[a-zA-Z][a-zA-Z0-9]+);/g, (match2, entity2) => {
|
|
63134
|
+
if (entity2.startsWith("#x")) {
|
|
63135
|
+
const codePoint = Number.parseInt(entity2.slice(2), 16);
|
|
63136
|
+
return Number.isFinite(codePoint) ? String.fromCodePoint(codePoint) : match2;
|
|
63137
|
+
}
|
|
63138
|
+
if (entity2.startsWith("#")) {
|
|
63139
|
+
const codePoint = Number.parseInt(entity2.slice(1), 10);
|
|
63140
|
+
return Number.isFinite(codePoint) ? String.fromCodePoint(codePoint) : match2;
|
|
63141
|
+
}
|
|
63142
|
+
return Object.prototype.hasOwnProperty.call(namedEntities, entity2) ? namedEntities[entity2] : match2;
|
|
63143
|
+
});
|
|
63144
|
+
}
|
|
63145
|
+
function normalizeSearchText(value) {
|
|
63146
|
+
return String(value || "").replace(/\s+/g, " ").trim();
|
|
63147
|
+
}
|
|
63148
|
+
function buildSearchAdapterJs() {
|
|
63149
|
+
const fieldWeightsJson = JSON.stringify(SEARCH_FIELD_WEIGHTS, null, 2);
|
|
63150
|
+
return `const FIELD_WEIGHTS = ${fieldWeightsJson};
|
|
63151
|
+
const FIELD_NAMES = Object.keys(FIELD_WEIGHTS);
|
|
63152
|
+
const RECENCY_BOOST_MAX = ${SEARCH_RECENCY_BOOST_MAX};
|
|
63153
|
+
const DEFAULT_LIMIT = 20;
|
|
63154
|
+
const BM25_K1 = 1.2;
|
|
63155
|
+
const BM25_B = 0.75;
|
|
63156
|
+
|
|
63157
|
+
let preparedIndexPromise;
|
|
63158
|
+
|
|
63159
|
+
export async function preload() {
|
|
63160
|
+
await loadPreparedIndex();
|
|
63161
|
+
}
|
|
63162
|
+
|
|
63163
|
+
export async function search(query, options = {}) {
|
|
63164
|
+
const prepared = await loadPreparedIndex();
|
|
63165
|
+
const terms = tokenize(query);
|
|
63166
|
+
const phrase = normalizeText(query);
|
|
63167
|
+
if (terms.length === 0 && !phrase) {
|
|
63168
|
+
return { results: [] };
|
|
63169
|
+
}
|
|
63170
|
+
|
|
63171
|
+
const hits = [];
|
|
63172
|
+
for (const document of prepared.documents) {
|
|
63173
|
+
const score = scoreDocument(document, terms, phrase, prepared);
|
|
63174
|
+
if (score > 0) {
|
|
63175
|
+
hits.push({ document, score });
|
|
63176
|
+
}
|
|
63177
|
+
}
|
|
63178
|
+
|
|
63179
|
+
const limit = normalizeLimit(options.limit);
|
|
63180
|
+
hits.sort((left, right) => right.score - left.score || left.document.raw.title.localeCompare(right.document.raw.title));
|
|
63181
|
+
|
|
63182
|
+
return {
|
|
63183
|
+
results: hits.slice(0, limit).map((hit) => ({
|
|
63184
|
+
id: hit.document.raw.id,
|
|
63185
|
+
score: Number(hit.score.toFixed(6)),
|
|
63186
|
+
data: async () => buildResultData(hit.document.raw, query),
|
|
63187
|
+
})),
|
|
63188
|
+
};
|
|
63189
|
+
}
|
|
63190
|
+
|
|
63191
|
+
async function loadPreparedIndex() {
|
|
63192
|
+
if (!preparedIndexPromise) {
|
|
63193
|
+
preparedIndexPromise = fetch(new URL('./search.json', import.meta.url))
|
|
63194
|
+
.then((response) => {
|
|
63195
|
+
if (!response.ok) {
|
|
63196
|
+
throw new Error('ZeroPress search index not found');
|
|
63197
|
+
}
|
|
63198
|
+
return response.json();
|
|
63199
|
+
})
|
|
63200
|
+
.then((items) => prepareIndex(Array.isArray(items) ? items : []));
|
|
63201
|
+
}
|
|
63202
|
+
|
|
63203
|
+
return preparedIndexPromise;
|
|
63204
|
+
}
|
|
63205
|
+
|
|
63206
|
+
function prepareIndex(items) {
|
|
63207
|
+
const documents = items.map((item) => prepareDocument(item));
|
|
63208
|
+
const documentFrequencies = new Map();
|
|
63209
|
+
const averageLengths = Object.fromEntries(FIELD_NAMES.map((fieldName) => [fieldName, 1]));
|
|
63210
|
+
const newestPostTime = documents.reduce((newest, document) => {
|
|
63211
|
+
if (document.raw.type !== 'post') {
|
|
63212
|
+
return newest;
|
|
63213
|
+
}
|
|
63214
|
+
return Math.max(newest, document.publishedTime || 0);
|
|
63215
|
+
}, 0);
|
|
63216
|
+
|
|
63217
|
+
for (const document of documents) {
|
|
63218
|
+
const seenTerms = new Set();
|
|
63219
|
+
for (const fieldName of FIELD_NAMES) {
|
|
63220
|
+
for (const term of document.fieldTokens[fieldName]) {
|
|
63221
|
+
seenTerms.add(term);
|
|
63222
|
+
}
|
|
63223
|
+
}
|
|
63224
|
+
for (const term of seenTerms) {
|
|
63225
|
+
documentFrequencies.set(term, (documentFrequencies.get(term) || 0) + 1);
|
|
63226
|
+
}
|
|
63227
|
+
}
|
|
63228
|
+
|
|
63229
|
+
for (const fieldName of FIELD_NAMES) {
|
|
63230
|
+
const total = documents.reduce((sum, document) => sum + document.fieldLengths[fieldName], 0);
|
|
63231
|
+
averageLengths[fieldName] = documents.length > 0 ? Math.max(1, total / documents.length) : 1;
|
|
63232
|
+
}
|
|
63233
|
+
|
|
63234
|
+
return {
|
|
63235
|
+
documents,
|
|
63236
|
+
documentFrequencies,
|
|
63237
|
+
averageLengths,
|
|
63238
|
+
documentCount: documents.length,
|
|
63239
|
+
newestPostTime,
|
|
63240
|
+
};
|
|
63241
|
+
}
|
|
63242
|
+
|
|
63243
|
+
function prepareDocument(item) {
|
|
63244
|
+
const raw = normalizeItem(item);
|
|
63245
|
+
const fields = {
|
|
63246
|
+
title: raw.title,
|
|
63247
|
+
headings: raw.headings.join(' '),
|
|
63248
|
+
tags: raw.tags.join(' '),
|
|
63249
|
+
categories: raw.categories.join(' '),
|
|
63250
|
+
excerpt: raw.excerpt,
|
|
63251
|
+
content_text: raw.content_text,
|
|
63252
|
+
};
|
|
63253
|
+
const fieldTexts = {};
|
|
63254
|
+
const fieldTokens = {};
|
|
63255
|
+
const fieldTermCounts = {};
|
|
63256
|
+
const fieldLengths = {};
|
|
63257
|
+
|
|
63258
|
+
for (const [fieldName, value] of Object.entries(fields)) {
|
|
63259
|
+
const normalizedText = normalizeText(value);
|
|
63260
|
+
const tokens = tokenize(normalizedText);
|
|
63261
|
+
fieldTexts[fieldName] = normalizedText;
|
|
63262
|
+
fieldTokens[fieldName] = tokens;
|
|
63263
|
+
fieldTermCounts[fieldName] = countTerms(tokens);
|
|
63264
|
+
fieldLengths[fieldName] = Math.max(1, tokens.length);
|
|
63265
|
+
}
|
|
63266
|
+
|
|
63267
|
+
return {
|
|
63268
|
+
raw,
|
|
63269
|
+
fieldTexts,
|
|
63270
|
+
fieldTokens,
|
|
63271
|
+
fieldTermCounts,
|
|
63272
|
+
fieldLengths,
|
|
63273
|
+
publishedTime: Date.parse(raw.published_at_iso) || 0,
|
|
63274
|
+
};
|
|
63275
|
+
}
|
|
63276
|
+
|
|
63277
|
+
function normalizeItem(item) {
|
|
63278
|
+
return {
|
|
63279
|
+
id: String(item && item.id || ''),
|
|
63280
|
+
type: item && item.type === 'page' ? 'page' : 'post',
|
|
63281
|
+
title: String(item && item.title || ''),
|
|
63282
|
+
url: String(item && item.url || ''),
|
|
63283
|
+
excerpt: String(item && item.excerpt || ''),
|
|
63284
|
+
headings: Array.isArray(item && item.headings) ? item.headings.map(String) : [],
|
|
63285
|
+
categories: Array.isArray(item && item.categories) ? item.categories.map(String) : [],
|
|
63286
|
+
tags: Array.isArray(item && item.tags) ? item.tags.map(String) : [],
|
|
63287
|
+
published_at_iso: String(item && item.published_at_iso || ''),
|
|
63288
|
+
updated_at_iso: String(item && item.updated_at_iso || ''),
|
|
63289
|
+
content_text: String(item && item.content_text || ''),
|
|
63290
|
+
};
|
|
63291
|
+
}
|
|
63292
|
+
|
|
63293
|
+
function scoreDocument(document, terms, phrase, prepared) {
|
|
63294
|
+
let score = 0;
|
|
63295
|
+
const uniqueTerms = Array.from(new Set(terms));
|
|
63296
|
+
|
|
63297
|
+
for (const term of uniqueTerms) {
|
|
63298
|
+
const documentFrequency = prepared.documentFrequencies.get(term) || 0;
|
|
63299
|
+
const idf = Math.log(1 + (prepared.documentCount - documentFrequency + 0.5) / (documentFrequency + 0.5));
|
|
63300
|
+
|
|
63301
|
+
for (const fieldName of FIELD_NAMES) {
|
|
63302
|
+
const termFrequency = document.fieldTermCounts[fieldName].get(term) || 0;
|
|
63303
|
+
if (termFrequency === 0) {
|
|
63304
|
+
continue;
|
|
63305
|
+
}
|
|
63306
|
+
|
|
63307
|
+
const fieldLength = document.fieldLengths[fieldName];
|
|
63308
|
+
const averageLength = prepared.averageLengths[fieldName];
|
|
63309
|
+
const denominator = termFrequency + BM25_K1 * (1 - BM25_B + BM25_B * (fieldLength / averageLength));
|
|
63310
|
+
score += FIELD_WEIGHTS[fieldName] * idf * ((termFrequency * (BM25_K1 + 1)) / denominator);
|
|
63311
|
+
}
|
|
63312
|
+
}
|
|
63313
|
+
|
|
63314
|
+
if (phrase && phrase.length > 1) {
|
|
63315
|
+
for (const fieldName of FIELD_NAMES) {
|
|
63316
|
+
if (document.fieldTexts[fieldName].includes(phrase)) {
|
|
63317
|
+
score += FIELD_WEIGHTS[fieldName] * 0.6;
|
|
63318
|
+
}
|
|
63319
|
+
}
|
|
63320
|
+
}
|
|
63321
|
+
|
|
63322
|
+
if (score <= 0) {
|
|
63323
|
+
return 0;
|
|
63324
|
+
}
|
|
63325
|
+
|
|
63326
|
+
return score * (1 + recencyBoost(document, prepared.newestPostTime));
|
|
63327
|
+
}
|
|
63328
|
+
|
|
63329
|
+
function recencyBoost(document, newestPostTime) {
|
|
63330
|
+
if (document.raw.type !== 'post' || !document.publishedTime || !newestPostTime) {
|
|
63331
|
+
return 0;
|
|
63332
|
+
}
|
|
63333
|
+
const ageMs = Math.max(0, newestPostTime - document.publishedTime);
|
|
63334
|
+
const halfLifeMs = 180 * 24 * 60 * 60 * 1000;
|
|
63335
|
+
return RECENCY_BOOST_MAX * Math.exp(-ageMs / halfLifeMs);
|
|
63336
|
+
}
|
|
63337
|
+
|
|
63338
|
+
function buildResultData(item, query) {
|
|
63339
|
+
const excerpt = buildExcerpt(item, query);
|
|
63340
|
+
return {
|
|
63341
|
+
url: item.url,
|
|
63342
|
+
excerpt,
|
|
63343
|
+
plain_excerpt: excerpt,
|
|
63344
|
+
meta: {
|
|
63345
|
+
title: item.title,
|
|
63346
|
+
type: item.type,
|
|
63347
|
+
published_at_iso: item.published_at_iso,
|
|
63348
|
+
updated_at_iso: item.updated_at_iso,
|
|
63349
|
+
categories: item.categories,
|
|
63350
|
+
tags: item.tags,
|
|
63351
|
+
},
|
|
63352
|
+
sub_results: [],
|
|
63353
|
+
};
|
|
63354
|
+
}
|
|
63355
|
+
|
|
63356
|
+
function buildExcerpt(item, query) {
|
|
63357
|
+
const explicitExcerpt = String(item.excerpt || '').trim();
|
|
63358
|
+
if (explicitExcerpt) {
|
|
63359
|
+
return explicitExcerpt;
|
|
63360
|
+
}
|
|
63361
|
+
|
|
63362
|
+
const text = String(item.content_text || '').replace(/\\s+/g, ' ').trim();
|
|
63363
|
+
if (!text) {
|
|
63364
|
+
return '';
|
|
63365
|
+
}
|
|
63366
|
+
|
|
63367
|
+
const normalizedText = normalizeText(text);
|
|
63368
|
+
const terms = tokenize(query);
|
|
63369
|
+
const firstMatch = terms.map((term) => normalizedText.indexOf(term)).filter((index) => index >= 0).sort((a, b) => a - b)[0];
|
|
63370
|
+
const start = Math.max(0, (firstMatch || 0) - 80);
|
|
63371
|
+
const end = Math.min(text.length, start + 180);
|
|
63372
|
+
const prefix = start > 0 ? '...' : '';
|
|
63373
|
+
const suffix = end < text.length ? '...' : '';
|
|
63374
|
+
return prefix + text.slice(start, end).trim() + suffix;
|
|
63375
|
+
}
|
|
63376
|
+
|
|
63377
|
+
function countTerms(tokens) {
|
|
63378
|
+
const counts = new Map();
|
|
63379
|
+
for (const token of tokens) {
|
|
63380
|
+
counts.set(token, (counts.get(token) || 0) + 1);
|
|
63381
|
+
}
|
|
63382
|
+
return counts;
|
|
63383
|
+
}
|
|
63384
|
+
|
|
63385
|
+
function tokenize(value) {
|
|
63386
|
+
const text = normalizeText(value);
|
|
63387
|
+
if (!text) {
|
|
63388
|
+
return [];
|
|
63389
|
+
}
|
|
63390
|
+
|
|
63391
|
+
const tokens = [];
|
|
63392
|
+
if (typeof Intl !== 'undefined' && typeof Intl.Segmenter === 'function') {
|
|
63393
|
+
try {
|
|
63394
|
+
const segmenter = new Intl.Segmenter(undefined, { granularity: 'word' });
|
|
63395
|
+
for (const part of segmenter.segment(text)) {
|
|
63396
|
+
if (part.isWordLike && isUsefulToken(part.segment)) {
|
|
63397
|
+
tokens.push(part.segment);
|
|
63398
|
+
}
|
|
63399
|
+
}
|
|
63400
|
+
} catch {
|
|
63401
|
+
// Fall through to regex tokenization.
|
|
63402
|
+
}
|
|
63403
|
+
}
|
|
63404
|
+
|
|
63405
|
+
for (const match of text.matchAll(/[\\p{Letter}\\p{Number}]+/gu)) {
|
|
63406
|
+
if (isUsefulToken(match[0])) {
|
|
63407
|
+
tokens.push(match[0]);
|
|
63408
|
+
}
|
|
63409
|
+
}
|
|
63410
|
+
|
|
63411
|
+
for (const match of text.matchAll(/[\\p{Script=Han}\\p{Script=Hiragana}\\p{Script=Katakana}\\p{Script=Hangul}]+/gu)) {
|
|
63412
|
+
tokens.push(...buildNgrams(match[0], 2));
|
|
63413
|
+
}
|
|
63414
|
+
|
|
63415
|
+
return tokens;
|
|
63416
|
+
}
|
|
63417
|
+
|
|
63418
|
+
function buildNgrams(value, size) {
|
|
63419
|
+
const normalized = Array.from(value);
|
|
63420
|
+
if (normalized.length <= size) {
|
|
63421
|
+
return isUsefulToken(value) ? [value] : [];
|
|
63422
|
+
}
|
|
63423
|
+
|
|
63424
|
+
const tokens = [];
|
|
63425
|
+
for (let index = 0; index <= normalized.length - size; index += 1) {
|
|
63426
|
+
tokens.push(normalized.slice(index, index + size).join(''));
|
|
63427
|
+
}
|
|
63428
|
+
tokens.push(value);
|
|
63429
|
+
return tokens;
|
|
63430
|
+
}
|
|
63431
|
+
|
|
63432
|
+
function isUsefulToken(value) {
|
|
63433
|
+
const token = String(value || '').trim();
|
|
63434
|
+
return token.length > 1 || /^\\d$/.test(token);
|
|
63435
|
+
}
|
|
63436
|
+
|
|
63437
|
+
function normalizeText(value) {
|
|
63438
|
+
return String(value || '')
|
|
63439
|
+
.normalize('NFKC')
|
|
63440
|
+
.toLowerCase()
|
|
63441
|
+
.replace(/[\\u2018\\u2019]/g, "'")
|
|
63442
|
+
.replace(/[_-]+/g, ' ')
|
|
63443
|
+
.replace(/\\s+/g, ' ')
|
|
63444
|
+
.trim();
|
|
63445
|
+
}
|
|
63446
|
+
|
|
63447
|
+
function normalizeLimit(value) {
|
|
63448
|
+
return Number.isInteger(value) && value > 0 ? Math.min(value, 100) : DEFAULT_LIMIT;
|
|
63449
|
+
}
|
|
63450
|
+
`;
|
|
63451
|
+
}
|
|
63452
|
+
function buildSearchPagefindAdapterJs() {
|
|
63453
|
+
return `let pagefindPromise;
|
|
63454
|
+
|
|
63455
|
+
export async function preload() {
|
|
63456
|
+
if (!pagefindPromise) {
|
|
63457
|
+
pagefindPromise = import(new URL('./pagefind/pagefind.js', import.meta.url).href).then(async (pagefind) => {
|
|
63458
|
+
if (typeof pagefind.options === 'function') {
|
|
63459
|
+
await pagefind.options({ baseUrl: '/' });
|
|
63460
|
+
}
|
|
63461
|
+
return pagefind;
|
|
63462
|
+
});
|
|
63463
|
+
}
|
|
63464
|
+
|
|
63465
|
+
return pagefindPromise;
|
|
63466
|
+
}
|
|
63467
|
+
|
|
63468
|
+
export async function search(query, options = {}) {
|
|
63469
|
+
const pagefind = await preload();
|
|
63470
|
+
const result = await pagefind.search(query, options);
|
|
63471
|
+
const limit = normalizeLimit(options.limit);
|
|
63472
|
+
if (!Array.isArray(result?.results)) {
|
|
63473
|
+
return result;
|
|
63474
|
+
}
|
|
63475
|
+
|
|
63476
|
+
const results = result.results.map(normalizeResult);
|
|
63477
|
+
return {
|
|
63478
|
+
...result,
|
|
63479
|
+
results: limit ? results.slice(0, limit) : results,
|
|
63480
|
+
};
|
|
63481
|
+
}
|
|
63482
|
+
|
|
63483
|
+
function normalizeResult(result) {
|
|
63484
|
+
if (!result || typeof result.data !== 'function') {
|
|
63485
|
+
return result;
|
|
63486
|
+
}
|
|
63487
|
+
|
|
63488
|
+
return {
|
|
63489
|
+
...result,
|
|
63490
|
+
data: async () => normalizeResultData(await result.data()),
|
|
63491
|
+
};
|
|
63492
|
+
}
|
|
63493
|
+
|
|
63494
|
+
function normalizeResultData(data) {
|
|
63495
|
+
if (!data || typeof data !== 'object') {
|
|
63496
|
+
return data;
|
|
63497
|
+
}
|
|
63498
|
+
|
|
63499
|
+
return {
|
|
63500
|
+
...data,
|
|
63501
|
+
url: normalizeUrl(data.url),
|
|
63502
|
+
sub_results: Array.isArray(data.sub_results)
|
|
63503
|
+
? data.sub_results.map((item) => ({ ...item, url: normalizeUrl(item.url) }))
|
|
63504
|
+
: data.sub_results,
|
|
63505
|
+
};
|
|
63506
|
+
}
|
|
63507
|
+
|
|
63508
|
+
function normalizeUrl(value) {
|
|
63509
|
+
const url = String(value || '');
|
|
63510
|
+
if (url.startsWith('/_zeropress/') && !url.startsWith('/_zeropress/pagefind/')) {
|
|
63511
|
+
return url.replace(/^\\/_zeropress/, '') || '/';
|
|
63512
|
+
}
|
|
63513
|
+
if (url.startsWith('_zeropress/') && !url.startsWith('_zeropress/pagefind/')) {
|
|
63514
|
+
return url.replace(/^_zeropress/, '') || '/';
|
|
63515
|
+
}
|
|
63516
|
+
return url;
|
|
63517
|
+
}
|
|
63518
|
+
|
|
63519
|
+
function normalizeLimit(value) {
|
|
63520
|
+
if (value === undefined || value === null) {
|
|
63521
|
+
return null;
|
|
63522
|
+
}
|
|
63523
|
+
|
|
63524
|
+
const limit = Number(value);
|
|
63525
|
+
if (!Number.isFinite(limit) || limit <= 0) {
|
|
63526
|
+
return null;
|
|
63527
|
+
}
|
|
63528
|
+
|
|
63529
|
+
return Math.floor(limit);
|
|
63530
|
+
}
|
|
63531
|
+
`;
|
|
63532
|
+
}
|
|
63533
|
+
function buildSitemapXml(site, emitted, generatedAt, stylesheetHref = "") {
|
|
62247
63534
|
const entries = [
|
|
62248
|
-
...emitted.frontPage ? [{
|
|
63535
|
+
...emitted.frontPage && emitted.frontPage.includeInSitemap !== false ? [{
|
|
62249
63536
|
url: emitted.frontPage.url,
|
|
62250
63537
|
changefreq: "daily",
|
|
62251
63538
|
priority: 1
|
|
@@ -62277,7 +63564,10 @@ function buildSitemapXml(site, emitted, generatedAt) {
|
|
|
62277
63564
|
<priority>${entry.priority.toFixed(1)}</priority>
|
|
62278
63565
|
</url>`;
|
|
62279
63566
|
}).join("\n");
|
|
62280
|
-
|
|
63567
|
+
const normalizedStylesheetHref = normalizeOptionalString(stylesheetHref);
|
|
63568
|
+
const stylesheet = normalizedStylesheetHref ? `
|
|
63569
|
+
<?xml-stylesheet type="text/xsl" href="${escapeXml(normalizedStylesheetHref)}"?>` : "";
|
|
63570
|
+
return `<?xml version="1.0" encoding="UTF-8"?>${stylesheet}
|
|
62281
63571
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
62282
63572
|
${body}
|
|
62283
63573
|
</urlset>`;
|
|
@@ -62325,6 +63615,9 @@ function buildRobotsTxt(site) {
|
|
|
62325
63615
|
function shouldGenerateRobotsTxt(options2) {
|
|
62326
63616
|
return options2.generateSpecialFiles && options2.generateRobotsTxt !== false;
|
|
62327
63617
|
}
|
|
63618
|
+
function shouldGenerateSearchArtifacts(state, options2) {
|
|
63619
|
+
return options2.generateSpecialFiles && state.previewData.site.search === true;
|
|
63620
|
+
}
|
|
62328
63621
|
function getContentType(assetPath) {
|
|
62329
63622
|
const ext = assetPath.split(".").pop()?.toLowerCase();
|
|
62330
63623
|
const contentTypes = {
|
|
@@ -62400,7 +63693,7 @@ async function loadThemePackageFromDir(themeDir) {
|
|
|
62400
63693
|
await readThemeDir(fs4, path4, themeDir, themeDir, fileMap);
|
|
62401
63694
|
const validation = await validateThemeFiles(fileMap);
|
|
62402
63695
|
if (!validation.ok) {
|
|
62403
|
-
throw new Error(
|
|
63696
|
+
throw new Error(formatThemeValidationFailure2(validation));
|
|
62404
63697
|
}
|
|
62405
63698
|
const rawThemeJson = String(fileMap.get("theme.json"));
|
|
62406
63699
|
const themeJson = JSON.parse(rawThemeJson);
|
|
@@ -62440,6 +63733,55 @@ async function loadThemePackageFromDir(themeDir) {
|
|
|
62440
63733
|
assets
|
|
62441
63734
|
};
|
|
62442
63735
|
}
|
|
63736
|
+
function formatThemeValidationFailure2(validation) {
|
|
63737
|
+
const blocks = [
|
|
63738
|
+
[
|
|
63739
|
+
"Theme validation failed",
|
|
63740
|
+
`Errors: ${validation.errors.length}`,
|
|
63741
|
+
`Checked files: ${validation.checkedFiles}`
|
|
63742
|
+
].join("\n"),
|
|
63743
|
+
...validation.errors.map((issue3) => formatThemeValidationIssue2(issue3))
|
|
63744
|
+
];
|
|
63745
|
+
return blocks.join("\n\n");
|
|
63746
|
+
}
|
|
63747
|
+
function formatThemeValidationIssue2(issue3) {
|
|
63748
|
+
if (!issue3) {
|
|
63749
|
+
return "Reason: Unknown error";
|
|
63750
|
+
}
|
|
63751
|
+
const lines = [`ERROR ${issue3.code || "THEME_VALIDATION_ERROR"}`];
|
|
63752
|
+
const location = splitIssuePath2(issue3.path);
|
|
63753
|
+
if (location.file) {
|
|
63754
|
+
lines.push(`File: ${location.file}`);
|
|
63755
|
+
}
|
|
63756
|
+
if (location.path) {
|
|
63757
|
+
lines.push(`Path: ${location.path}`);
|
|
63758
|
+
}
|
|
63759
|
+
if (Number.isInteger(issue3.line) && Number.isInteger(issue3.column)) {
|
|
63760
|
+
lines.push(`Line: ${issue3.line}, Column: ${issue3.column}`);
|
|
63761
|
+
}
|
|
63762
|
+
if (issue3.category) {
|
|
63763
|
+
lines.push(`Category: ${issue3.category}`);
|
|
63764
|
+
}
|
|
63765
|
+
lines.push(`Reason: ${issue3.message || "Unknown error"}`);
|
|
63766
|
+
if (issue3.snippet) {
|
|
63767
|
+
const lineLabel = Number.isInteger(issue3.line) ? String(issue3.line) : "";
|
|
63768
|
+
lines.push("", `${lineLabel} | ${issue3.snippet.line}`, `${" ".repeat(lineLabel.length)} | ${issue3.snippet.pointer}`);
|
|
63769
|
+
}
|
|
63770
|
+
if (issue3.hint) {
|
|
63771
|
+
lines.push("", "Hint:", issue3.hint);
|
|
63772
|
+
}
|
|
63773
|
+
return lines.join("\n");
|
|
63774
|
+
}
|
|
63775
|
+
function splitIssuePath2(issuePath) {
|
|
63776
|
+
const normalizedPath = String(issuePath || "");
|
|
63777
|
+
if (normalizedPath.startsWith("theme.json.")) {
|
|
63778
|
+
return {
|
|
63779
|
+
file: "theme.json",
|
|
63780
|
+
path: normalizedPath.slice("theme.json.".length)
|
|
63781
|
+
};
|
|
63782
|
+
}
|
|
63783
|
+
return { file: normalizedPath, path: "" };
|
|
63784
|
+
}
|
|
62443
63785
|
async function readThemeDir(fs4, path4, rootDir, currentDir, fileMap) {
|
|
62444
63786
|
const entries = await fs4.readdir(currentDir, { withFileTypes: true });
|
|
62445
63787
|
for (const entry of entries) {
|
|
@@ -62486,6 +63828,7 @@ var PUBLIC_FAVICON_FILES = Object.freeze({
|
|
|
62486
63828
|
png: "favicon.png",
|
|
62487
63829
|
apple_touch_icon: "apple-touch-icon.png"
|
|
62488
63830
|
});
|
|
63831
|
+
var PUBLIC_SITEMAP_STYLESHEET_FILE = "sitemap.xsl";
|
|
62489
63832
|
async function assertThemeDirectory(themeDir) {
|
|
62490
63833
|
let stat;
|
|
62491
63834
|
try {
|
|
@@ -62500,14 +63843,15 @@ async function assertThemeDirectory(themeDir) {
|
|
|
62500
63843
|
throw new Error(`Theme path is not a directory: ${themeDir}`);
|
|
62501
63844
|
}
|
|
62502
63845
|
}
|
|
62503
|
-
async function runBuild(themeDir, previewData, outDir) {
|
|
62504
|
-
|
|
62505
|
-
assertPublicPathDoesNotOverlap("
|
|
63846
|
+
async function runBuild(themeDir, previewData, outDir, options2 = {}) {
|
|
63847
|
+
const publicDir = resolvePublicDir(process.cwd(), options2.publicDir);
|
|
63848
|
+
assertPublicPathDoesNotOverlap("Theme directory", themeDir, process.cwd(), publicDir);
|
|
63849
|
+
assertPublicPathDoesNotOverlap("Output directory", outDir, process.cwd(), publicDir);
|
|
62506
63850
|
await assertThemeDirectory(themeDir);
|
|
62507
63851
|
await assertEmptyOutputDirectory(outDir);
|
|
62508
|
-
const publicDir = resolvePublicDir();
|
|
62509
63852
|
const hasPublicRobotsTxt = await publicRobotsTxtExists(publicDir);
|
|
62510
63853
|
const publicFavicon = await discoverPublicFavicon(publicDir);
|
|
63854
|
+
const sitemapStylesheetHref = await discoverPublicSitemapStylesheet(publicDir);
|
|
62511
63855
|
await copyPublicDirectory(publicDir, outDir);
|
|
62512
63856
|
const writer = new GeneratedOutputWriter({ outDir });
|
|
62513
63857
|
return buildSiteFromThemeDir({
|
|
@@ -62516,6 +63860,7 @@ async function runBuild(themeDir, previewData, outDir) {
|
|
|
62516
63860
|
writer,
|
|
62517
63861
|
options: {
|
|
62518
63862
|
favicon: publicFavicon,
|
|
63863
|
+
sitemapStylesheetHref,
|
|
62519
63864
|
generateRobotsTxt: !hasPublicRobotsTxt
|
|
62520
63865
|
}
|
|
62521
63866
|
});
|
|
@@ -62555,7 +63900,10 @@ async function assertEmptyOutputDirectory(outDir) {
|
|
|
62555
63900
|
throw error;
|
|
62556
63901
|
}
|
|
62557
63902
|
}
|
|
62558
|
-
function resolvePublicDir(cwd = process.cwd()) {
|
|
63903
|
+
function resolvePublicDir(cwd = process.cwd(), publicDir) {
|
|
63904
|
+
if (publicDir) {
|
|
63905
|
+
return path.resolve(cwd, publicDir);
|
|
63906
|
+
}
|
|
62559
63907
|
const envValue = process.env[PUBLIC_DIR_ENV_NAME]?.trim();
|
|
62560
63908
|
return path.resolve(cwd, envValue || DEFAULT_PUBLIC_DIR_NAME);
|
|
62561
63909
|
}
|
|
@@ -62604,6 +63952,18 @@ async function discoverPublicFavicon(publicDir) {
|
|
|
62604
63952
|
}
|
|
62605
63953
|
return Object.keys(favicon).length ? favicon : void 0;
|
|
62606
63954
|
}
|
|
63955
|
+
async function discoverPublicSitemapStylesheet(publicDir) {
|
|
63956
|
+
let stat;
|
|
63957
|
+
try {
|
|
63958
|
+
stat = await fs.lstat(path.join(publicDir, PUBLIC_SITEMAP_STYLESHEET_FILE));
|
|
63959
|
+
} catch (error) {
|
|
63960
|
+
if (error && (error.code === "ENOENT" || error.code === "ENOTDIR")) {
|
|
63961
|
+
return void 0;
|
|
63962
|
+
}
|
|
63963
|
+
throw error;
|
|
63964
|
+
}
|
|
63965
|
+
return stat.isFile() ? `/${PUBLIC_SITEMAP_STYLESHEET_FILE}` : void 0;
|
|
63966
|
+
}
|
|
62607
63967
|
async function copyPublicEntries(sourceDir, targetDir) {
|
|
62608
63968
|
const entries = await fs.readdir(sourceDir, { withFileTypes: true });
|
|
62609
63969
|
for (const entry of entries) {
|
|
@@ -62628,8 +63988,7 @@ function shouldIgnorePublicEntry(name) {
|
|
|
62628
63988
|
const lowerName = basename.toLowerCase();
|
|
62629
63989
|
return basename.startsWith(".") || lowerName === "node_modules" || lowerName === "thumbs.db" || lowerName.endsWith(".key") || lowerName.endsWith(".pem");
|
|
62630
63990
|
}
|
|
62631
|
-
function assertPublicPathDoesNotOverlap(label, candidatePath, cwd = process.cwd()) {
|
|
62632
|
-
const publicDir = resolvePublicDir(cwd);
|
|
63991
|
+
function assertPublicPathDoesNotOverlap(label, candidatePath, cwd = process.cwd(), publicDir = resolvePublicDir(cwd)) {
|
|
62633
63992
|
const resolvedCandidate = path.resolve(cwd, candidatePath);
|
|
62634
63993
|
if (!pathsOverlap(publicDir, resolvedCandidate)) {
|
|
62635
63994
|
return;
|
|
@@ -62755,6 +64114,8 @@ async function runBuildPages(options2) {
|
|
|
62755
64114
|
const cwd = path3.resolve(options2.cwd || process.cwd());
|
|
62756
64115
|
const copyMarkdownSource = options2.copyMarkdownSource !== false;
|
|
62757
64116
|
const sourceDir = path3.resolve(cwd, options2.source);
|
|
64117
|
+
const publicDirExplicit = hasExplicitPublicDir(options2);
|
|
64118
|
+
const publicDir = publicDirExplicit ? path3.resolve(cwd, options2.publicDir) : sourceDir;
|
|
62758
64119
|
const destinationDir = path3.resolve(cwd, options2.destination);
|
|
62759
64120
|
const generatedDir = path3.join(cwd, ".zeropress");
|
|
62760
64121
|
const stagingDir = path3.join(cwd, STAGING_DIR);
|
|
@@ -62763,17 +64124,22 @@ async function runBuildPages(options2) {
|
|
|
62763
64124
|
assertBuildPagesPathLayout({
|
|
62764
64125
|
cwd,
|
|
62765
64126
|
sourceDir,
|
|
64127
|
+
publicDir,
|
|
64128
|
+
publicDirExplicit,
|
|
62766
64129
|
destinationDir,
|
|
62767
64130
|
themeDir,
|
|
62768
64131
|
generatedDir
|
|
62769
64132
|
});
|
|
62770
64133
|
await assertDirectory(sourceDir, "Source directory");
|
|
64134
|
+
await assertPublicDirectory(publicDir, publicDirExplicit);
|
|
64135
|
+
await assertDestinationPath(destinationDir);
|
|
62771
64136
|
await fs3.rm(generatedDir, { recursive: true, force: true });
|
|
62772
64137
|
await fs3.mkdir(generatedDir, { recursive: true });
|
|
62773
64138
|
const env = {
|
|
62774
64139
|
...process.env,
|
|
62775
64140
|
ZEROPRESS_BUILD_PAGES_SOURCE: sourceDir,
|
|
62776
|
-
|
|
64141
|
+
ZEROPRESS_BUILD_PAGES_PUBLIC_DIR: publicDir,
|
|
64142
|
+
ZEROPRESS_PUBLIC_DIR: publicDir,
|
|
62777
64143
|
ZEROPRESS_SKIP_UNTITLED_MARKDOWN: String(Boolean(options2.skipUntitledMarkdown)),
|
|
62778
64144
|
ZEROPRESS_COPY_MARKDOWN_SOURCE: String(copyMarkdownSource)
|
|
62779
64145
|
};
|
|
@@ -62797,10 +64163,13 @@ async function runBuildPages(options2) {
|
|
|
62797
64163
|
await fs3.rm(destinationDir, { recursive: true, force: true });
|
|
62798
64164
|
await fs3.rm(stagingDir, { recursive: true, force: true });
|
|
62799
64165
|
await fs3.mkdir(stagingDir, { recursive: true });
|
|
62800
|
-
await copyPublicStaging(
|
|
64166
|
+
await copyPublicStaging(publicDir, stagingDir, {
|
|
62801
64167
|
excludePaths: [destinationDir, themeDir, generatedDir],
|
|
62802
64168
|
copyMarkdownSource
|
|
62803
64169
|
});
|
|
64170
|
+
if (copyMarkdownSource) {
|
|
64171
|
+
await copySourceMarkdownFiles(sourceDir, stagingDir, previewData);
|
|
64172
|
+
}
|
|
62804
64173
|
const previousPublicDir = process.env.ZEROPRESS_PUBLIC_DIR;
|
|
62805
64174
|
process.env.ZEROPRESS_PUBLIC_DIR = stagingDir;
|
|
62806
64175
|
try {
|
|
@@ -62835,6 +64204,9 @@ function resolveThemeDir(cwd, options2) {
|
|
|
62835
64204
|
}
|
|
62836
64205
|
throw new Error(`Unknown bundled theme: ${options2.theme}`);
|
|
62837
64206
|
}
|
|
64207
|
+
function hasExplicitPublicDir(options2) {
|
|
64208
|
+
return typeof options2.publicDir === "string" && Boolean(options2.publicDir.trim());
|
|
64209
|
+
}
|
|
62838
64210
|
async function assertDirectory(dir, label) {
|
|
62839
64211
|
let stat;
|
|
62840
64212
|
try {
|
|
@@ -62849,17 +64221,78 @@ async function assertDirectory(dir, label) {
|
|
|
62849
64221
|
throw new Error(`${label} is not a directory: ${dir}`);
|
|
62850
64222
|
}
|
|
62851
64223
|
}
|
|
62852
|
-
function
|
|
64224
|
+
async function assertPublicDirectory(publicDir, explicit) {
|
|
64225
|
+
if (!explicit) {
|
|
64226
|
+
return;
|
|
64227
|
+
}
|
|
64228
|
+
let stat;
|
|
64229
|
+
try {
|
|
64230
|
+
stat = await fs3.lstat(publicDir);
|
|
64231
|
+
} catch (error) {
|
|
64232
|
+
if (error?.code === "ENOENT") {
|
|
64233
|
+
throw new Error(`Public directory not found: ${publicDir}`);
|
|
64234
|
+
}
|
|
64235
|
+
throw error;
|
|
64236
|
+
}
|
|
64237
|
+
if (stat.isSymbolicLink()) {
|
|
64238
|
+
throw new Error(`Public directory must not be a symbolic link: ${publicDir}`);
|
|
64239
|
+
}
|
|
64240
|
+
if (!stat.isDirectory()) {
|
|
64241
|
+
throw new Error(`Public path is not a directory: ${publicDir}`);
|
|
64242
|
+
}
|
|
64243
|
+
}
|
|
64244
|
+
async function assertDestinationPath(destinationDir) {
|
|
64245
|
+
let stat;
|
|
64246
|
+
try {
|
|
64247
|
+
stat = await fs3.lstat(destinationDir);
|
|
64248
|
+
} catch (error) {
|
|
64249
|
+
if (error?.code === "ENOENT") {
|
|
64250
|
+
return;
|
|
64251
|
+
}
|
|
64252
|
+
throw error;
|
|
64253
|
+
}
|
|
64254
|
+
if (!stat.isDirectory()) {
|
|
64255
|
+
throw new Error(`Destination path is not a directory: ${destinationDir}`);
|
|
64256
|
+
}
|
|
64257
|
+
}
|
|
64258
|
+
function assertBuildPagesPathLayout({
|
|
64259
|
+
cwd,
|
|
64260
|
+
sourceDir,
|
|
64261
|
+
publicDir,
|
|
64262
|
+
publicDirExplicit,
|
|
64263
|
+
destinationDir,
|
|
64264
|
+
themeDir,
|
|
64265
|
+
generatedDir
|
|
64266
|
+
}) {
|
|
62853
64267
|
if (samePath(sourceDir, cwd)) {
|
|
62854
64268
|
throw new Error(
|
|
62855
64269
|
`Source directory must be a dedicated content directory, not the current working directory. Received: ${formatPath(cwd, sourceDir)}`
|
|
62856
64270
|
);
|
|
62857
64271
|
}
|
|
64272
|
+
if (publicDirExplicit && samePath(publicDir, cwd)) {
|
|
64273
|
+
throw new Error(
|
|
64274
|
+
`Public directory must be a dedicated asset directory, not the current working directory. Received: ${formatPath(cwd, publicDir)}`
|
|
64275
|
+
);
|
|
64276
|
+
}
|
|
62858
64277
|
assertNoPathOverlap(cwd, "Source directory", sourceDir, "internal .zeropress working directory", generatedDir);
|
|
62859
64278
|
assertNoPathOverlap(cwd, "Destination directory", destinationDir, "internal .zeropress working directory", generatedDir);
|
|
62860
64279
|
assertNoPathOverlap(cwd, "Theme directory", themeDir, "internal .zeropress working directory", generatedDir);
|
|
64280
|
+
if (!samePath(publicDir, sourceDir)) {
|
|
64281
|
+
assertNoPathOverlap(cwd, "Public directory", publicDir, "internal .zeropress working directory", generatedDir);
|
|
64282
|
+
assertNoPathOverlap(cwd, "Public directory", publicDir, "destination directory", destinationDir);
|
|
64283
|
+
assertNoPathOverlap(cwd, "Public directory", publicDir, "theme directory", themeDir);
|
|
64284
|
+
}
|
|
62861
64285
|
assertNoPathOverlap(cwd, "Source directory", sourceDir, "destination directory", destinationDir);
|
|
62862
64286
|
assertNoPathOverlap(cwd, "Source directory", sourceDir, "theme directory", themeDir);
|
|
64287
|
+
assertSourceIsNotInsidePublicDirectory(cwd, sourceDir, publicDir);
|
|
64288
|
+
}
|
|
64289
|
+
function assertSourceIsNotInsidePublicDirectory(cwd, sourceDir, publicDir) {
|
|
64290
|
+
if (samePath(sourceDir, publicDir) || !isPathInside2(publicDir, sourceDir)) {
|
|
64291
|
+
return;
|
|
64292
|
+
}
|
|
64293
|
+
throw new Error(
|
|
64294
|
+
`Source directory must not be inside the public directory. Source directory: ${formatPath(cwd, sourceDir)}; Public directory: ${formatPath(cwd, publicDir)}`
|
|
64295
|
+
);
|
|
62863
64296
|
}
|
|
62864
64297
|
function assertNoPathOverlap(cwd, firstLabel, firstPath, secondLabel, secondPath) {
|
|
62865
64298
|
if (!pathsOverlap2(firstPath, secondPath)) {
|
|
@@ -62895,6 +64328,52 @@ async function copyPublicStaging(sourceDir, targetDir, options2) {
|
|
|
62895
64328
|
await fs3.copyFile(sourcePath, targetPath);
|
|
62896
64329
|
}
|
|
62897
64330
|
}
|
|
64331
|
+
async function copySourceMarkdownFiles(sourceDir, targetDir, previewData) {
|
|
64332
|
+
const markdownUrls = /* @__PURE__ */ new Set();
|
|
64333
|
+
for (const page of previewData?.content?.pages || []) {
|
|
64334
|
+
const sourceMarkdownUrl = page?.meta?.source_markdown_url;
|
|
64335
|
+
if (typeof sourceMarkdownUrl === "string" && sourceMarkdownUrl) {
|
|
64336
|
+
markdownUrls.add(sourceMarkdownUrl);
|
|
64337
|
+
}
|
|
64338
|
+
}
|
|
64339
|
+
for (const sourceMarkdownUrl of markdownUrls) {
|
|
64340
|
+
const relativePath = sourceMarkdownUrlToRelativePath(sourceMarkdownUrl);
|
|
64341
|
+
if (!relativePath) {
|
|
64342
|
+
continue;
|
|
64343
|
+
}
|
|
64344
|
+
const sourcePath = path3.join(sourceDir, relativePath);
|
|
64345
|
+
if (!isPathInside2(sourceDir, sourcePath)) {
|
|
64346
|
+
continue;
|
|
64347
|
+
}
|
|
64348
|
+
const targetPath = path3.join(targetDir, relativePath);
|
|
64349
|
+
await fs3.mkdir(path3.dirname(targetPath), { recursive: true });
|
|
64350
|
+
await fs3.copyFile(sourcePath, targetPath);
|
|
64351
|
+
}
|
|
64352
|
+
}
|
|
64353
|
+
function sourceMarkdownUrlToRelativePath(sourceMarkdownUrl) {
|
|
64354
|
+
if (!sourceMarkdownUrl.startsWith("/") || sourceMarkdownUrl.includes("?") || sourceMarkdownUrl.includes("#")) {
|
|
64355
|
+
return "";
|
|
64356
|
+
}
|
|
64357
|
+
const rawSegments = sourceMarkdownUrl.slice(1).split("/");
|
|
64358
|
+
const segments = [];
|
|
64359
|
+
for (const rawSegment of rawSegments) {
|
|
64360
|
+
if (!rawSegment) {
|
|
64361
|
+
return "";
|
|
64362
|
+
}
|
|
64363
|
+
let segment;
|
|
64364
|
+
try {
|
|
64365
|
+
segment = decodeURIComponent(rawSegment);
|
|
64366
|
+
} catch {
|
|
64367
|
+
return "";
|
|
64368
|
+
}
|
|
64369
|
+
if (!segment || segment === "." || segment === ".." || segment.includes("/") || segment.includes("\\")) {
|
|
64370
|
+
return "";
|
|
64371
|
+
}
|
|
64372
|
+
segments.push(segment);
|
|
64373
|
+
}
|
|
64374
|
+
const relativePath = segments.join("/");
|
|
64375
|
+
return relativePath.toLowerCase().endsWith(".md") ? relativePath : "";
|
|
64376
|
+
}
|
|
62898
64377
|
function shouldIgnorePublicEntry2(name) {
|
|
62899
64378
|
const basename = String(name || "");
|
|
62900
64379
|
const lowerName = basename.toLowerCase();
|
|
@@ -62923,6 +64402,7 @@ function formatPath(cwd, targetPath) {
|
|
|
62923
64402
|
// src/action.js
|
|
62924
64403
|
var options = {
|
|
62925
64404
|
source: input("source") || "./docs",
|
|
64405
|
+
publicDir: input("public-dir"),
|
|
62926
64406
|
destination: input("destination") || "./_site",
|
|
62927
64407
|
theme: input("theme") || "docs",
|
|
62928
64408
|
themePath: input("theme-path"),
|
|
@@ -62940,7 +64420,7 @@ try {
|
|
|
62940
64420
|
process.exitCode = 1;
|
|
62941
64421
|
}
|
|
62942
64422
|
function input(name) {
|
|
62943
|
-
return process.env[`INPUT_${name.toUpperCase()
|
|
64423
|
+
return process.env[`INPUT_${name.toUpperCase()}`]?.trim() || "";
|
|
62944
64424
|
}
|
|
62945
64425
|
function booleanInput(name, fallback) {
|
|
62946
64426
|
const value = input(name);
|