@jxsuite/parser 2.0.1 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/content-loader.js +620 -286
- package/dist/content.js +183 -30
- package/dist/markdown.js +641 -382
- package/dist/serialize.js +28852 -28615
- package/package.json +6 -5
- package/src/Content.class.json +2 -0
- package/src/alerts.ts +22 -7
- package/src/content-data.ts +40 -0
- package/src/content-links.ts +15 -7
- package/src/content-loader.ts +702 -223
- package/src/content-routes.ts +23 -10
- package/src/content-rules.ts +40 -29
- package/src/content.ts +108 -70
- package/src/csv.ts +18 -14
- package/src/dates.ts +18 -13
- package/src/highlight.ts +26 -6
- package/src/html-to-jx.ts +3 -3
- package/src/inert.ts +7 -5
- package/src/markdown.ts +27 -23
- package/src/md-html.ts +3 -3
- package/src/md.ts +133 -64
- package/src/serialize.ts +544 -299
- package/src/source-style.ts +236 -0
- package/src/transpile.ts +182 -152
- package/src/types.ts +43 -11
package/dist/content-loader.js
CHANGED
|
@@ -58,6 +58,77 @@ var __esm = (fn, res, err) => () => {
|
|
|
58
58
|
};
|
|
59
59
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
60
60
|
|
|
61
|
+
// ../../packages/schema/src/guards.ts
|
|
62
|
+
function isString(value) {
|
|
63
|
+
return typeof value === "string";
|
|
64
|
+
}
|
|
65
|
+
function isNumber(value) {
|
|
66
|
+
return typeof value === "number";
|
|
67
|
+
}
|
|
68
|
+
function isBoolean(value) {
|
|
69
|
+
return typeof value === "boolean";
|
|
70
|
+
}
|
|
71
|
+
function isNonNullObject(value) {
|
|
72
|
+
return typeof value === "object" && value !== null;
|
|
73
|
+
}
|
|
74
|
+
function isJsonObject(value) {
|
|
75
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
76
|
+
}
|
|
77
|
+
function isRef(value) {
|
|
78
|
+
return isJsonObject(value) && typeof value.$ref === "string";
|
|
79
|
+
}
|
|
80
|
+
function isNodeObject(value) {
|
|
81
|
+
return isJsonObject(value);
|
|
82
|
+
}
|
|
83
|
+
function isPlainTagName(tagName) {
|
|
84
|
+
return typeof tagName === "string";
|
|
85
|
+
}
|
|
86
|
+
function isTagExpression(tagName) {
|
|
87
|
+
if (typeof tagName !== "object" || tagName === null || Array.isArray(tagName) || !isJsonObject(tagName.$expression)) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
const expression = tagName.$expression;
|
|
91
|
+
if (expression.operator === "?:") {
|
|
92
|
+
return typeof expression.value === "string" && typeof expression.initial === "string";
|
|
93
|
+
}
|
|
94
|
+
if (expression.operator === "switch") {
|
|
95
|
+
return isJsonObject(expression.cases) && Object.values(expression.cases).every((tag) => isString(tag)) && typeof expression.default === "string";
|
|
96
|
+
}
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
function tagNameCandidates(tagName) {
|
|
100
|
+
if (isPlainTagName(tagName)) {
|
|
101
|
+
return [tagName];
|
|
102
|
+
}
|
|
103
|
+
if (!isTagExpression(tagName)) {
|
|
104
|
+
return [];
|
|
105
|
+
}
|
|
106
|
+
const expression = tagName.$expression;
|
|
107
|
+
if (expression.operator === "?:") {
|
|
108
|
+
return [...new Set([expression.value, expression.initial])];
|
|
109
|
+
}
|
|
110
|
+
return [...new Set([...Object.values(expression.cases), expression.default])];
|
|
111
|
+
}
|
|
112
|
+
var SCHEMA_KEYWORDS;
|
|
113
|
+
var init_guards = __esm(() => {
|
|
114
|
+
SCHEMA_KEYWORDS = new Set([
|
|
115
|
+
"type",
|
|
116
|
+
"enum",
|
|
117
|
+
"minimum",
|
|
118
|
+
"maximum",
|
|
119
|
+
"minLength",
|
|
120
|
+
"maxLength",
|
|
121
|
+
"pattern",
|
|
122
|
+
"format",
|
|
123
|
+
"items",
|
|
124
|
+
"properties",
|
|
125
|
+
"required",
|
|
126
|
+
"description",
|
|
127
|
+
"title",
|
|
128
|
+
"$comment"
|
|
129
|
+
]);
|
|
130
|
+
});
|
|
131
|
+
|
|
61
132
|
// src/alerts.ts
|
|
62
133
|
function normalizeAlerts(config, where = "alerts") {
|
|
63
134
|
if (config === false) {
|
|
@@ -68,7 +139,7 @@ function normalizeAlerts(config, where = "alerts") {
|
|
|
68
139
|
if (config === undefined || config === true) {
|
|
69
140
|
return { disabled, types };
|
|
70
141
|
}
|
|
71
|
-
if (
|
|
142
|
+
if (!isJsonObject(config)) {
|
|
72
143
|
throw new TypeError(`${where}: expected an object mapping alert types to element names, or false`);
|
|
73
144
|
}
|
|
74
145
|
for (const [type, element] of Object.entries(config)) {
|
|
@@ -81,7 +152,7 @@ function normalizeAlerts(config, where = "alerts") {
|
|
|
81
152
|
disabled.add(key);
|
|
82
153
|
} else if (element === true) {
|
|
83
154
|
types.set(key, null);
|
|
84
|
-
} else if (
|
|
155
|
+
} else if (isString(element) && TAG_NAME.test(element)) {
|
|
85
156
|
types.set(key, element);
|
|
86
157
|
} else {
|
|
87
158
|
throw new TypeError(`${where}.${type}: expected an element name such as "doc-note", true or false, got ${JSON.stringify(element)}`);
|
|
@@ -92,7 +163,7 @@ function normalizeAlerts(config, where = "alerts") {
|
|
|
92
163
|
function inlineText(nodes) {
|
|
93
164
|
let out = "";
|
|
94
165
|
for (const node of nodes) {
|
|
95
|
-
if (
|
|
166
|
+
if (node.value !== undefined) {
|
|
96
167
|
out += node.value;
|
|
97
168
|
} else if (node.children) {
|
|
98
169
|
out += inlineText(node.children);
|
|
@@ -105,7 +176,7 @@ function textNode(value) {
|
|
|
105
176
|
}
|
|
106
177
|
function markerOf(paragraph) {
|
|
107
178
|
const [first] = paragraph.children ?? [];
|
|
108
|
-
if (first?.type !== "text" ||
|
|
179
|
+
if (first?.type !== "text" || first.value === undefined) {
|
|
109
180
|
return null;
|
|
110
181
|
}
|
|
111
182
|
const match = MARKER.exec(first.value);
|
|
@@ -131,7 +202,7 @@ function splitMarker(paragraph, settings) {
|
|
|
131
202
|
const take = (node) => {
|
|
132
203
|
if (inTitle && node.type === "break") {
|
|
133
204
|
inTitle = false;
|
|
134
|
-
} else if (inTitle && node.type === "text" &&
|
|
205
|
+
} else if (inTitle && node.type === "text" && node.value !== undefined) {
|
|
135
206
|
const lineEnd = LINE_END.exec(node.value);
|
|
136
207
|
if (lineEnd === null) {
|
|
137
208
|
title.push(node);
|
|
@@ -188,6 +259,7 @@ function transformAlerts(tree, settings, onUnknown) {
|
|
|
188
259
|
}
|
|
189
260
|
var DEFAULT_ALERT_TITLES, ALERT_NODE = "jxAlert", TAG_NAME, MARKER, LINE_END;
|
|
190
261
|
var init_alerts = __esm(() => {
|
|
262
|
+
init_guards();
|
|
191
263
|
DEFAULT_ALERT_TITLES = {
|
|
192
264
|
caution: "Caution",
|
|
193
265
|
important: "Important",
|
|
@@ -334,7 +406,7 @@ function compileExclude(patterns) {
|
|
|
334
406
|
const dirs = [];
|
|
335
407
|
let everything = false;
|
|
336
408
|
for (const pattern of patterns) {
|
|
337
|
-
if (
|
|
409
|
+
if (!isString(pattern) || pattern.trim() === "") {
|
|
338
410
|
throw new TypeError(`"exclude" entries must be non-empty strings, got ${JSON.stringify(pattern)}`);
|
|
339
411
|
}
|
|
340
412
|
if (pattern.startsWith("!")) {
|
|
@@ -408,21 +480,21 @@ function readField(data, key) {
|
|
|
408
480
|
if (!key.includes(".")) {
|
|
409
481
|
return;
|
|
410
482
|
}
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
current = current[part];
|
|
483
|
+
return readPath(data, key.split("."));
|
|
484
|
+
}
|
|
485
|
+
function readPath(holder, [part, ...rest]) {
|
|
486
|
+
if (part === undefined || !isPlainObject(holder) || !Object.hasOwn(holder, part)) {
|
|
487
|
+
return;
|
|
417
488
|
}
|
|
418
|
-
|
|
489
|
+
const value = holder[part];
|
|
490
|
+
return rest.length === 0 ? value : readPath(value, rest);
|
|
419
491
|
}
|
|
420
492
|
function order(actual, operand) {
|
|
421
493
|
const a = comparable(actual);
|
|
422
|
-
if (
|
|
494
|
+
if (isNumber(a) && isNumber(operand)) {
|
|
423
495
|
return a - operand;
|
|
424
496
|
}
|
|
425
|
-
if (
|
|
497
|
+
if (isString(a) && isString(operand)) {
|
|
426
498
|
return a < operand ? -1 : a > operand ? 1 : 0;
|
|
427
499
|
}
|
|
428
500
|
return;
|
|
@@ -444,13 +516,13 @@ function operatorTest(where, op, operand) {
|
|
|
444
516
|
return op === "$in" ? hit : (actual) => !hit(actual);
|
|
445
517
|
}
|
|
446
518
|
case "$exists": {
|
|
447
|
-
if (
|
|
519
|
+
if (!isBoolean(operand)) {
|
|
448
520
|
throw new TypeError(`${where}.$exists: expected true or false, got ${JSON.stringify(operand)}`);
|
|
449
521
|
}
|
|
450
522
|
return (actual) => (actual !== undefined && actual !== null) === operand;
|
|
451
523
|
}
|
|
452
524
|
default: {
|
|
453
|
-
if (
|
|
525
|
+
if (!isString(operand) && !isNumber(operand)) {
|
|
454
526
|
throw new TypeError(`${where}.${op}: expected a string or number, got ${JSON.stringify(operand)}`);
|
|
455
527
|
}
|
|
456
528
|
const test = (diff) => op === "$gt" ? diff > 0 : op === "$gte" ? diff >= 0 : op === "$lt" ? diff < 0 : diff <= 0;
|
|
@@ -508,6 +580,7 @@ function compileWhere(where) {
|
|
|
508
580
|
}
|
|
509
581
|
var nothing = () => {}, REGEXP_SPECIAL, MAX_STAR_RUNS = 4, OPERATORS;
|
|
510
582
|
var init_content_rules = __esm(() => {
|
|
583
|
+
init_guards();
|
|
511
584
|
REGEXP_SPECIAL = /[$()*+.?[\\\]^{|}]/g;
|
|
512
585
|
OPERATORS = new Set(["$eq", "$ne", "$in", "$nin", "$exists", "$gt", "$gte", "$lt", "$lte"]);
|
|
513
586
|
});
|
|
@@ -25568,14 +25641,14 @@ var init_decode_codepoint = __esm(() => {
|
|
|
25568
25641
|
});
|
|
25569
25642
|
|
|
25570
25643
|
// ../../node_modules/parse5/node_modules/entities/dist/esm/decode.js
|
|
25571
|
-
function
|
|
25644
|
+
function isNumber2(code) {
|
|
25572
25645
|
return code >= CharCodes.ZERO && code <= CharCodes.NINE;
|
|
25573
25646
|
}
|
|
25574
25647
|
function isHexadecimalCharacter(code) {
|
|
25575
25648
|
return code >= CharCodes.UPPER_A && code <= CharCodes.UPPER_F || code >= CharCodes.LOWER_A && code <= CharCodes.LOWER_F;
|
|
25576
25649
|
}
|
|
25577
25650
|
function isAsciiAlphaNumeric(code) {
|
|
25578
|
-
return code >= CharCodes.UPPER_A && code <= CharCodes.UPPER_Z || code >= CharCodes.LOWER_A && code <= CharCodes.LOWER_Z ||
|
|
25651
|
+
return code >= CharCodes.UPPER_A && code <= CharCodes.UPPER_Z || code >= CharCodes.LOWER_A && code <= CharCodes.LOWER_Z || isNumber2(code);
|
|
25579
25652
|
}
|
|
25580
25653
|
function isEntityInAttributeInvalidEnd(code) {
|
|
25581
25654
|
return code === CharCodes.EQUALS || isAsciiAlphaNumeric(code);
|
|
@@ -25649,7 +25722,7 @@ class EntityDecoder {
|
|
|
25649
25722
|
const startIndex = offset;
|
|
25650
25723
|
while (offset < input.length) {
|
|
25651
25724
|
const char = input.charCodeAt(offset);
|
|
25652
|
-
if (
|
|
25725
|
+
if (isNumber2(char) || isHexadecimalCharacter(char)) {
|
|
25653
25726
|
offset += 1;
|
|
25654
25727
|
} else {
|
|
25655
25728
|
this.addToNumericResult(input, startIndex, offset, 16);
|
|
@@ -25663,7 +25736,7 @@ class EntityDecoder {
|
|
|
25663
25736
|
const startIndex = offset;
|
|
25664
25737
|
while (offset < input.length) {
|
|
25665
25738
|
const char = input.charCodeAt(offset);
|
|
25666
|
-
if (
|
|
25739
|
+
if (isNumber2(char)) {
|
|
25667
25740
|
offset += 1;
|
|
25668
25741
|
} else {
|
|
25669
25742
|
this.addToNumericResult(input, startIndex, offset, 10);
|
|
@@ -33099,11 +33172,11 @@ function convertHastNode(node) {
|
|
|
33099
33172
|
if (whitespace(node)) {
|
|
33100
33173
|
return null;
|
|
33101
33174
|
}
|
|
33102
|
-
return node.value
|
|
33175
|
+
return node.value;
|
|
33103
33176
|
}
|
|
33104
33177
|
if (node.type === "element") {
|
|
33105
33178
|
const el = { tagName: node.tagName };
|
|
33106
|
-
if (
|
|
33179
|
+
if (Object.keys(node.properties).length > 0) {
|
|
33107
33180
|
const { style, attrs } = hastPropsToJx(node.properties);
|
|
33108
33181
|
if (Object.keys(attrs).length > 0) {
|
|
33109
33182
|
el.attributes = attrs;
|
|
@@ -33112,8 +33185,8 @@ function convertHastNode(node) {
|
|
|
33112
33185
|
el.style = style;
|
|
33113
33186
|
}
|
|
33114
33187
|
}
|
|
33115
|
-
const kids =
|
|
33116
|
-
if (kids.length === 1 &&
|
|
33188
|
+
const kids = convertHastChildren(node.children);
|
|
33189
|
+
if (kids.length === 1 && isString(kids[0])) {
|
|
33117
33190
|
[el.textContent] = kids;
|
|
33118
33191
|
} else if (kids.length > 0) {
|
|
33119
33192
|
el.children = kids;
|
|
@@ -33131,7 +33204,7 @@ function hastPropsToJx(properties) {
|
|
|
33131
33204
|
}
|
|
33132
33205
|
const info = find(html3, key);
|
|
33133
33206
|
const name = info.attribute;
|
|
33134
|
-
if (name === "style" &&
|
|
33207
|
+
if (name === "style" && isString(value)) {
|
|
33135
33208
|
parseInlineStyle(value, style);
|
|
33136
33209
|
continue;
|
|
33137
33210
|
}
|
|
@@ -33162,6 +33235,7 @@ var init_html_to_jx = __esm(() => {
|
|
|
33162
33235
|
init_hast_util_from_html();
|
|
33163
33236
|
init_hast_util_whitespace();
|
|
33164
33237
|
init_property_information();
|
|
33238
|
+
init_guards();
|
|
33165
33239
|
});
|
|
33166
33240
|
|
|
33167
33241
|
// src/transpile.ts
|
|
@@ -33177,21 +33251,24 @@ function jxKey(key) {
|
|
|
33177
33251
|
function expandDotPaths(attrs) {
|
|
33178
33252
|
const result = {};
|
|
33179
33253
|
for (const [key, value] of Object.entries(attrs)) {
|
|
33180
|
-
const
|
|
33181
|
-
if (
|
|
33254
|
+
const lastDot = key.lastIndexOf(".");
|
|
33255
|
+
if (lastDot === -1) {
|
|
33182
33256
|
result[jxKey(key)] = value;
|
|
33183
33257
|
continue;
|
|
33184
33258
|
}
|
|
33185
|
-
const segments = key.split(".");
|
|
33186
33259
|
let target = result;
|
|
33187
|
-
for (
|
|
33188
|
-
const seg = jxKey(
|
|
33189
|
-
|
|
33190
|
-
|
|
33260
|
+
for (const segment of key.slice(0, lastDot).split(".")) {
|
|
33261
|
+
const seg = jxKey(segment);
|
|
33262
|
+
const existing = seg in target ? target[seg] : undefined;
|
|
33263
|
+
if (isNonNullObject(existing)) {
|
|
33264
|
+
target = existing;
|
|
33265
|
+
} else {
|
|
33266
|
+
const nested = {};
|
|
33267
|
+
target[seg] = nested;
|
|
33268
|
+
target = nested;
|
|
33191
33269
|
}
|
|
33192
|
-
target = target[seg];
|
|
33193
33270
|
}
|
|
33194
|
-
target[jxKey(
|
|
33271
|
+
target[jxKey(key.slice(lastDot + 1))] = value;
|
|
33195
33272
|
}
|
|
33196
33273
|
return result;
|
|
33197
33274
|
}
|
|
@@ -33212,22 +33289,34 @@ function applyStyleKeyMapping(styleObj) {
|
|
|
33212
33289
|
}
|
|
33213
33290
|
function routeAttributes(attrs) {
|
|
33214
33291
|
const expanded = expandDotPaths(attrs);
|
|
33215
|
-
|
|
33216
|
-
|
|
33292
|
+
const { style } = expanded;
|
|
33293
|
+
if (isNonNullObject(style)) {
|
|
33294
|
+
expanded.style = applyStyleKeyMapping(style);
|
|
33217
33295
|
}
|
|
33218
33296
|
const props = {};
|
|
33219
33297
|
const attributes = {};
|
|
33220
33298
|
for (const [key, value] of Object.entries(expanded)) {
|
|
33221
33299
|
if (HTML_ATTR_PATTERN.test(key)) {
|
|
33222
|
-
attributes[key] = value;
|
|
33300
|
+
attributes[key] = attributeValue(value);
|
|
33223
33301
|
} else {
|
|
33224
33302
|
props[key] = value;
|
|
33225
33303
|
}
|
|
33226
33304
|
}
|
|
33227
33305
|
return { attributes, props };
|
|
33228
33306
|
}
|
|
33307
|
+
function attributeValue(value) {
|
|
33308
|
+
return value;
|
|
33309
|
+
}
|
|
33310
|
+
function setContent(el, children) {
|
|
33311
|
+
const [only] = children;
|
|
33312
|
+
if (children.length === 1 && isString(only)) {
|
|
33313
|
+
el.textContent = only;
|
|
33314
|
+
} else if (children.length > 0) {
|
|
33315
|
+
el.children = children;
|
|
33316
|
+
}
|
|
33317
|
+
}
|
|
33229
33318
|
function mdastNodeToJx(node) {
|
|
33230
|
-
if (!node
|
|
33319
|
+
if (!node) {
|
|
33231
33320
|
return null;
|
|
33232
33321
|
}
|
|
33233
33322
|
if (node.type === "yaml" || node.type === "toml") {
|
|
@@ -33248,7 +33337,7 @@ function mdastNodeToJx(node) {
|
|
|
33248
33337
|
}
|
|
33249
33338
|
return null;
|
|
33250
33339
|
}
|
|
33251
|
-
const tagFn = JX_TAG_MAP
|
|
33340
|
+
const tagFn = JX_TAG_MAP.get(node.type);
|
|
33252
33341
|
if (!tagFn) {
|
|
33253
33342
|
return null;
|
|
33254
33343
|
}
|
|
@@ -33264,12 +33353,7 @@ function mdastNodeToJx(node) {
|
|
|
33264
33353
|
case "listItem":
|
|
33265
33354
|
case "tableRow":
|
|
33266
33355
|
case "tableCell": {
|
|
33267
|
-
|
|
33268
|
-
if (children.length === 1 && typeof children[0] === "string") {
|
|
33269
|
-
[el.textContent] = children;
|
|
33270
|
-
} else if (children.length > 0) {
|
|
33271
|
-
el.children = children;
|
|
33272
|
-
}
|
|
33356
|
+
setContent(el, convertChildren(node.children ?? []));
|
|
33273
33357
|
break;
|
|
33274
33358
|
}
|
|
33275
33359
|
case "inlineCode": {
|
|
@@ -33277,34 +33361,18 @@ function mdastNodeToJx(node) {
|
|
|
33277
33361
|
break;
|
|
33278
33362
|
}
|
|
33279
33363
|
case "link": {
|
|
33280
|
-
{
|
|
33281
|
-
|
|
33282
|
-
|
|
33283
|
-
};
|
|
33284
|
-
if (node.title) {
|
|
33285
|
-
linkAttrs.title = node.title;
|
|
33286
|
-
}
|
|
33287
|
-
el.attributes = linkAttrs;
|
|
33288
|
-
}
|
|
33289
|
-
{
|
|
33290
|
-
const children = convertChildren(node.children ?? []);
|
|
33291
|
-
if (children.length === 1 && typeof children[0] === "string") {
|
|
33292
|
-
[el.textContent] = children;
|
|
33293
|
-
} else if (children.length > 0) {
|
|
33294
|
-
el.children = children;
|
|
33295
|
-
}
|
|
33364
|
+
el.attributes = { href: node.url ?? "" };
|
|
33365
|
+
if (node.title) {
|
|
33366
|
+
el.attributes.title = node.title;
|
|
33296
33367
|
}
|
|
33368
|
+
setContent(el, convertChildren(node.children ?? []));
|
|
33297
33369
|
break;
|
|
33298
33370
|
}
|
|
33299
33371
|
case "image": {
|
|
33300
|
-
|
|
33301
|
-
alt: node.alt ?? "",
|
|
33302
|
-
src: node.url ?? ""
|
|
33303
|
-
};
|
|
33372
|
+
el.attributes = { alt: node.alt ?? "", src: node.url ?? "" };
|
|
33304
33373
|
if (node.title) {
|
|
33305
|
-
|
|
33374
|
+
el.attributes.title = node.title;
|
|
33306
33375
|
}
|
|
33307
|
-
el.attributes = imageAttrs;
|
|
33308
33376
|
break;
|
|
33309
33377
|
}
|
|
33310
33378
|
case "list": {
|
|
@@ -33317,13 +33385,11 @@ function mdastNodeToJx(node) {
|
|
|
33317
33385
|
break;
|
|
33318
33386
|
}
|
|
33319
33387
|
case "code": {
|
|
33320
|
-
|
|
33321
|
-
|
|
33322
|
-
|
|
33323
|
-
|
|
33324
|
-
|
|
33325
|
-
}
|
|
33326
|
-
];
|
|
33388
|
+
const code = { tagName: "code", textContent: node.value ?? null };
|
|
33389
|
+
if (node.lang) {
|
|
33390
|
+
code.className = `language-${node.lang}`;
|
|
33391
|
+
}
|
|
33392
|
+
el.children = [code];
|
|
33327
33393
|
break;
|
|
33328
33394
|
}
|
|
33329
33395
|
case "thematicBreak":
|
|
@@ -33333,16 +33399,21 @@ function mdastNodeToJx(node) {
|
|
|
33333
33399
|
case "table": {
|
|
33334
33400
|
const rows = convertChildren(node.children ?? []);
|
|
33335
33401
|
const [headerRow] = rows;
|
|
33336
|
-
if (headerRow &&
|
|
33402
|
+
if (isNonNullObject(headerRow) && Array.isArray(headerRow.children)) {
|
|
33337
33403
|
for (const cell of headerRow.children) {
|
|
33338
|
-
if (cell &&
|
|
33404
|
+
if (isNonNullObject(cell) && cell.tagName === "td") {
|
|
33339
33405
|
cell.tagName = "th";
|
|
33340
33406
|
}
|
|
33341
33407
|
}
|
|
33342
33408
|
}
|
|
33343
|
-
const
|
|
33344
|
-
|
|
33345
|
-
|
|
33409
|
+
const sections = [];
|
|
33410
|
+
if (headerRow !== undefined) {
|
|
33411
|
+
sections.push({ children: [headerRow], tagName: "thead" });
|
|
33412
|
+
}
|
|
33413
|
+
if (rows.length > 1) {
|
|
33414
|
+
sections.push({ children: rows.slice(1), tagName: "tbody" });
|
|
33415
|
+
}
|
|
33416
|
+
el.children = sections;
|
|
33346
33417
|
break;
|
|
33347
33418
|
}
|
|
33348
33419
|
default: {
|
|
@@ -33354,10 +33425,7 @@ function mdastNodeToJx(node) {
|
|
|
33354
33425
|
function alertToJx(node) {
|
|
33355
33426
|
const body = convertChildren(node.children ?? []);
|
|
33356
33427
|
if (node.element) {
|
|
33357
|
-
const attributes = { "data-alert": node.alert };
|
|
33358
|
-
if (node.titleNodes) {
|
|
33359
|
-
attributes["data-title"] = inlineText(node.titleNodes).trim();
|
|
33360
|
-
}
|
|
33428
|
+
const attributes = node.titleNodes ? { "data-alert": node.alert, "data-title": inlineText(node.titleNodes).trim() } : { "data-alert": node.alert };
|
|
33361
33429
|
const el = { attributes, tagName: node.element };
|
|
33362
33430
|
if (body.length > 0) {
|
|
33363
33431
|
el.children = body;
|
|
@@ -33367,8 +33435,9 @@ function alertToJx(node) {
|
|
|
33367
33435
|
const title = { className: "jx-alert-title", tagName: "p" };
|
|
33368
33436
|
if (node.titleNodes) {
|
|
33369
33437
|
const inline = convertChildren(node.titleNodes);
|
|
33370
|
-
|
|
33371
|
-
|
|
33438
|
+
const [only] = inline;
|
|
33439
|
+
if (inline.length === 1 && isString(only)) {
|
|
33440
|
+
title.textContent = only;
|
|
33372
33441
|
} else {
|
|
33373
33442
|
title.children = inline;
|
|
33374
33443
|
}
|
|
@@ -33383,13 +33452,14 @@ function alertToJx(node) {
|
|
|
33383
33452
|
};
|
|
33384
33453
|
}
|
|
33385
33454
|
function directiveToJx(node) {
|
|
33386
|
-
|
|
33387
|
-
|
|
33455
|
+
const name = node.name;
|
|
33456
|
+
if (PROTOTYPE_DIRECTIVE_NAMES.has(name)) {
|
|
33457
|
+
return prototypeDirectiveToJx(node, name);
|
|
33388
33458
|
}
|
|
33389
|
-
const el = { tagName:
|
|
33459
|
+
const el = { tagName: name };
|
|
33390
33460
|
if (node.attributes && Object.keys(node.attributes).length > 0) {
|
|
33391
33461
|
const { props, attributes } = routeAttributes(node.attributes);
|
|
33392
|
-
const isCustomElement =
|
|
33462
|
+
const isCustomElement = name.includes("-");
|
|
33393
33463
|
if (isCustomElement) {
|
|
33394
33464
|
for (const [key, value] of Object.entries(props)) {
|
|
33395
33465
|
if (key === "style" || key === "children" || key === "textContent" || key === "innerHTML" || key.startsWith("$")) {
|
|
@@ -33398,7 +33468,7 @@ function directiveToJx(node) {
|
|
|
33398
33468
|
if (!el.attributes) {
|
|
33399
33469
|
el.attributes = {};
|
|
33400
33470
|
}
|
|
33401
|
-
el.attributes[key] = value;
|
|
33471
|
+
el.attributes[key] = attributeValue(value);
|
|
33402
33472
|
}
|
|
33403
33473
|
}
|
|
33404
33474
|
} else {
|
|
@@ -33409,7 +33479,7 @@ function directiveToJx(node) {
|
|
|
33409
33479
|
if (!el.attributes) {
|
|
33410
33480
|
el.attributes = {};
|
|
33411
33481
|
}
|
|
33412
|
-
el.attributes[key] = value;
|
|
33482
|
+
el.attributes[key] = attributeValue(value);
|
|
33413
33483
|
}
|
|
33414
33484
|
}
|
|
33415
33485
|
}
|
|
@@ -33419,12 +33489,7 @@ function directiveToJx(node) {
|
|
|
33419
33489
|
}
|
|
33420
33490
|
if (node.type === "textDirective") {
|
|
33421
33491
|
if (node.children && node.children.length > 0) {
|
|
33422
|
-
|
|
33423
|
-
if (children.length === 1 && typeof children[0] === "string") {
|
|
33424
|
-
[el.textContent] = children;
|
|
33425
|
-
} else if (children.length > 0) {
|
|
33426
|
-
el.children = children;
|
|
33427
|
-
}
|
|
33492
|
+
setContent(el, convertChildren(node.children));
|
|
33428
33493
|
}
|
|
33429
33494
|
return el;
|
|
33430
33495
|
}
|
|
@@ -33433,7 +33498,7 @@ function directiveToJx(node) {
|
|
|
33433
33498
|
}
|
|
33434
33499
|
if (node.children && node.children.length > 0) {
|
|
33435
33500
|
const jxChildren = [];
|
|
33436
|
-
const isPhrasingParent = PHRASING_ELEMENTS.has(
|
|
33501
|
+
const isPhrasingParent = PHRASING_ELEMENTS.has(name);
|
|
33437
33502
|
for (const child of node.children) {
|
|
33438
33503
|
if (isPhrasingParent && child.type === "paragraph") {
|
|
33439
33504
|
for (const inline of child.children ?? []) {
|
|
@@ -33459,16 +33524,14 @@ function directiveToJx(node) {
|
|
|
33459
33524
|
}
|
|
33460
33525
|
}
|
|
33461
33526
|
}
|
|
33462
|
-
if (el.children
|
|
33463
|
-
|
|
33464
|
-
} else if (jxChildren.length > 0) {
|
|
33465
|
-
el.children = jxChildren;
|
|
33527
|
+
if (!isNonNullObject(el.children) || Array.isArray(el.children)) {
|
|
33528
|
+
setContent(el, jxChildren);
|
|
33466
33529
|
}
|
|
33467
33530
|
}
|
|
33468
33531
|
return el;
|
|
33469
33532
|
}
|
|
33470
|
-
function prototypeDirectiveToJx(node) {
|
|
33471
|
-
const el = { $prototype:
|
|
33533
|
+
function prototypeDirectiveToJx(node, name) {
|
|
33534
|
+
const el = { $prototype: name };
|
|
33472
33535
|
if (node.attributes && Object.keys(node.attributes).length > 0) {
|
|
33473
33536
|
const expanded = expandDotPaths(node.attributes);
|
|
33474
33537
|
for (const [key, value] of Object.entries(expanded)) {
|
|
@@ -33479,7 +33542,7 @@ function prototypeDirectiveToJx(node) {
|
|
|
33479
33542
|
}
|
|
33480
33543
|
}
|
|
33481
33544
|
const children = convertChildren(node.children ?? []);
|
|
33482
|
-
const template = children.find((c) => c
|
|
33545
|
+
const template = children.find((c) => !isString(c));
|
|
33483
33546
|
if (template) {
|
|
33484
33547
|
el.map = template;
|
|
33485
33548
|
}
|
|
@@ -33489,17 +33552,19 @@ function convertChildren(children) {
|
|
|
33489
33552
|
if (!children) {
|
|
33490
33553
|
return [];
|
|
33491
33554
|
}
|
|
33492
|
-
return children.flatMap((n) => mdastNodeToJx(n)
|
|
33555
|
+
return children.flatMap((n) => mdastNodeToJx(n) ?? []);
|
|
33493
33556
|
}
|
|
33494
33557
|
function transpileJxMarkdown(source) {
|
|
33495
33558
|
const processor = unified().use(remarkParse).use(remarkFrontmatter, ["yaml"]).use(import_remark_parse_frontmatter.default).use(remarkGfm).use(remarkDirective);
|
|
33496
33559
|
const tree = processor.parse(source);
|
|
33497
33560
|
const vfile = { data: {} };
|
|
33498
33561
|
processor.runSync(tree, vfile);
|
|
33499
|
-
const frontmatter = vfile.data
|
|
33562
|
+
const frontmatter = vfile.data.frontmatter ?? {};
|
|
33500
33563
|
const doc = {};
|
|
33501
|
-
|
|
33502
|
-
|
|
33564
|
+
if (!isNumber(frontmatter) && !isBoolean(frontmatter)) {
|
|
33565
|
+
for (const [key, value] of Object.entries(frontmatter)) {
|
|
33566
|
+
doc[key] = value;
|
|
33567
|
+
}
|
|
33503
33568
|
}
|
|
33504
33569
|
const bodyNodes = tree.children.filter((n) => n.type !== "yaml" && n.type !== "toml");
|
|
33505
33570
|
const children = [];
|
|
@@ -33523,10 +33588,10 @@ function slugifyHeading(text) {
|
|
|
33523
33588
|
return text.normalize("NFC").toLowerCase().replaceAll(/[^\p{L}\p{N}_\s-]/gu, "").replaceAll(/\s+/gu, "-").replaceAll(/-+/g, "-").replaceAll(/^-|-$/g, "");
|
|
33524
33589
|
}
|
|
33525
33590
|
function jxNodeText(node) {
|
|
33526
|
-
if (
|
|
33591
|
+
if (isString(node)) {
|
|
33527
33592
|
return node;
|
|
33528
33593
|
}
|
|
33529
|
-
let out =
|
|
33594
|
+
let out = isString(node.textContent) ? node.textContent : "";
|
|
33530
33595
|
if (Array.isArray(node.children)) {
|
|
33531
33596
|
for (const child of node.children) {
|
|
33532
33597
|
out += jxNodeText(child);
|
|
@@ -33539,13 +33604,13 @@ function assignHeadingIds(children) {
|
|
|
33539
33604
|
const seen = new Map;
|
|
33540
33605
|
function walk(nodes) {
|
|
33541
33606
|
for (const node of nodes) {
|
|
33542
|
-
if (
|
|
33607
|
+
if (!isNonNullObject(node)) {
|
|
33543
33608
|
continue;
|
|
33544
33609
|
}
|
|
33545
|
-
const tag =
|
|
33610
|
+
const tag = isString(node.tagName) ? node.tagName : "";
|
|
33546
33611
|
if (tag && HEADING_TAGS.has(tag)) {
|
|
33547
33612
|
const text = jxNodeText(node).trim();
|
|
33548
|
-
let id =
|
|
33613
|
+
let id = isString(node.id) && node.id.length > 0 ? node.id : "";
|
|
33549
33614
|
if (id) {
|
|
33550
33615
|
seen.set(id, (seen.get(id) ?? 0) + 1);
|
|
33551
33616
|
} else {
|
|
@@ -33575,6 +33640,7 @@ var init_transpile = __esm(() => {
|
|
|
33575
33640
|
init_remark_gfm();
|
|
33576
33641
|
init_remark_directive();
|
|
33577
33642
|
init_html_to_jx();
|
|
33643
|
+
init_guards();
|
|
33578
33644
|
init_alerts();
|
|
33579
33645
|
init_html_to_jx();
|
|
33580
33646
|
import_remark_parse_frontmatter = __toESM(require_dist2(), 1);
|
|
@@ -33642,25 +33708,25 @@ var init_transpile = __esm(() => {
|
|
|
33642
33708
|
"summary",
|
|
33643
33709
|
"dt"
|
|
33644
33710
|
]);
|
|
33645
|
-
JX_TAG_MAP =
|
|
33646
|
-
blockquote
|
|
33647
|
-
break
|
|
33648
|
-
code
|
|
33649
|
-
delete
|
|
33650
|
-
emphasis
|
|
33651
|
-
heading
|
|
33652
|
-
image
|
|
33653
|
-
inlineCode
|
|
33654
|
-
link
|
|
33655
|
-
list
|
|
33656
|
-
listItem
|
|
33657
|
-
paragraph
|
|
33658
|
-
strong
|
|
33659
|
-
table
|
|
33660
|
-
tableCell
|
|
33661
|
-
tableRow
|
|
33662
|
-
thematicBreak
|
|
33663
|
-
|
|
33711
|
+
JX_TAG_MAP = new Map([
|
|
33712
|
+
["blockquote", () => "blockquote"],
|
|
33713
|
+
["break", () => "br"],
|
|
33714
|
+
["code", () => "pre"],
|
|
33715
|
+
["delete", () => "del"],
|
|
33716
|
+
["emphasis", () => "em"],
|
|
33717
|
+
["heading", (n) => `h${n.depth}`],
|
|
33718
|
+
["image", () => "img"],
|
|
33719
|
+
["inlineCode", () => "code"],
|
|
33720
|
+
["link", () => "a"],
|
|
33721
|
+
["list", (n) => n.ordered ? "ol" : "ul"],
|
|
33722
|
+
["listItem", () => "li"],
|
|
33723
|
+
["paragraph", () => "p"],
|
|
33724
|
+
["strong", () => "strong"],
|
|
33725
|
+
["table", () => "table"],
|
|
33726
|
+
["tableCell", (n) => n.isHeader ? "th" : "td"],
|
|
33727
|
+
["tableRow", () => "tr"],
|
|
33728
|
+
["thematicBreak", () => "hr"]
|
|
33729
|
+
]);
|
|
33664
33730
|
HEADING_TAGS = new Set(["h1", "h2", "h3", "h4", "h5", "h6"]);
|
|
33665
33731
|
});
|
|
33666
33732
|
|
|
@@ -33720,10 +33786,14 @@ function walkFiles(root, accept, exclude) {
|
|
|
33720
33786
|
var init_walk = () => {};
|
|
33721
33787
|
|
|
33722
33788
|
// src/content-loader.ts
|
|
33723
|
-
import { existsSync, readFileSync, readdirSync as readdirSync2, statSync as statSync2 } from "node:fs";
|
|
33789
|
+
import { existsSync, readFileSync, readdirSync as readdirSync2, realpathSync as realpathSync2, statSync as statSync2 } from "node:fs";
|
|
33724
33790
|
import { basename, dirname, extname, relative, resolve } from "node:path";
|
|
33725
33791
|
|
|
33726
33792
|
// ../../packages/schema/src/asset-paths.ts
|
|
33793
|
+
init_guards();
|
|
33794
|
+
var CONTENT_SECTION_KEY = "content";
|
|
33795
|
+
var SAFE_CONTENT_TYPE_NAME = /^[\w.~-]+$/;
|
|
33796
|
+
var LOCALE_PLACEHOLDER = "{locale}";
|
|
33727
33797
|
function normalizeDir(value) {
|
|
33728
33798
|
const forward = value.replaceAll("\\", "/");
|
|
33729
33799
|
return forward.length > 1 && forward.endsWith("/") ? forward.slice(0, -1) : forward;
|
|
@@ -33758,6 +33828,7 @@ function assetUrlFor(mounts, absolutePath) {
|
|
|
33758
33828
|
var URL_TERMINATOR = String.raw`"'\s<>()\\`;
|
|
33759
33829
|
|
|
33760
33830
|
// ../../packages/schema/src/locale.ts
|
|
33831
|
+
init_guards();
|
|
33761
33832
|
var RTL_SCRIPTS = new Set([
|
|
33762
33833
|
"Adlm",
|
|
33763
33834
|
"Arab",
|
|
@@ -33800,7 +33871,7 @@ var RTL_SCRIPTS = new Set([
|
|
|
33800
33871
|
"Yezi"
|
|
33801
33872
|
]);
|
|
33802
33873
|
function canonicalizeLocale(tag) {
|
|
33803
|
-
if (
|
|
33874
|
+
if (!isString(tag) || tag.trim() === "") {
|
|
33804
33875
|
return null;
|
|
33805
33876
|
}
|
|
33806
33877
|
try {
|
|
@@ -33813,7 +33884,7 @@ var DEFAULT_ROUTING = "prefix-except-default";
|
|
|
33813
33884
|
function resolveI18n(projectConfig) {
|
|
33814
33885
|
const raw = projectConfig.i18n;
|
|
33815
33886
|
const errors = [];
|
|
33816
|
-
if (!raw
|
|
33887
|
+
if (!isNonNullObject(raw)) {
|
|
33817
33888
|
return { errors, i18n: null };
|
|
33818
33889
|
}
|
|
33819
33890
|
const declared = Array.isArray(raw.locales) ? raw.locales : [];
|
|
@@ -33857,9 +33928,14 @@ function localeUrlPrefix(locale, i18n) {
|
|
|
33857
33928
|
}
|
|
33858
33929
|
|
|
33859
33930
|
// src/content-loader.ts
|
|
33931
|
+
init_guards();
|
|
33860
33932
|
init_alerts();
|
|
33861
33933
|
|
|
33934
|
+
// src/content-links.ts
|
|
33935
|
+
init_guards();
|
|
33936
|
+
|
|
33862
33937
|
// src/content-routes.ts
|
|
33938
|
+
init_guards();
|
|
33863
33939
|
init_content_rules();
|
|
33864
33940
|
function slugifySegment(text) {
|
|
33865
33941
|
return text.normalize("NFKD").replaceAll(/(?<=\p{Script=Latin})\p{M}+/gu, "").normalize("NFC").replaceAll("&", " and ").replaceAll(/['’]/g, "").toLowerCase().replaceAll(/[^\p{L}\p{M}\p{N}]+/gu, "-").replaceAll(/^-+|-+$/g, "");
|
|
@@ -33874,13 +33950,13 @@ var TRANSFORMS = {
|
|
|
33874
33950
|
upper: (value) => value.toUpperCase()
|
|
33875
33951
|
};
|
|
33876
33952
|
function parseRouteTemplate(source, where) {
|
|
33877
|
-
if (
|
|
33953
|
+
if (!isString(source) || !source.startsWith("/")) {
|
|
33878
33954
|
throw new TypeError(`${where}: a route template is a site-absolute path starting with "/", got ${JSON.stringify(source)}`);
|
|
33879
33955
|
}
|
|
33880
33956
|
const tokens = [];
|
|
33881
33957
|
let last = 0;
|
|
33882
33958
|
for (const match of source.matchAll(/\{([^{}]*)\}/g)) {
|
|
33883
|
-
const index = match
|
|
33959
|
+
const { index } = match;
|
|
33884
33960
|
if (index > last) {
|
|
33885
33961
|
tokens.push({ literal: source.slice(last, index) });
|
|
33886
33962
|
}
|
|
@@ -33926,10 +34002,10 @@ function directoryOf(path) {
|
|
|
33926
34002
|
return slash === -1 ? "" : path.slice(0, slash);
|
|
33927
34003
|
}
|
|
33928
34004
|
function textOf(value) {
|
|
33929
|
-
if (
|
|
34005
|
+
if (isString(value)) {
|
|
33930
34006
|
return value.trim() === "" ? null : value;
|
|
33931
34007
|
}
|
|
33932
|
-
if (
|
|
34008
|
+
if (isNumber(value) || isBoolean(value)) {
|
|
33933
34009
|
return String(value);
|
|
33934
34010
|
}
|
|
33935
34011
|
if (value instanceof Date && !Number.isNaN(value.getTime())) {
|
|
@@ -34182,10 +34258,10 @@ function contentOf(anchor) {
|
|
|
34182
34258
|
if (Array.isArray(anchor.children)) {
|
|
34183
34259
|
return anchor.children;
|
|
34184
34260
|
}
|
|
34185
|
-
if (
|
|
34261
|
+
if (anchor.innerHTML !== undefined) {
|
|
34186
34262
|
return [{ innerHTML: anchor.innerHTML, tagName: "span" }];
|
|
34187
34263
|
}
|
|
34188
|
-
return
|
|
34264
|
+
return isString(anchor.textContent) ? [anchor.textContent] : [];
|
|
34189
34265
|
}
|
|
34190
34266
|
function rewriteLinks(nodes, from, index, report) {
|
|
34191
34267
|
for (let i = 0;i < nodes.length; i++) {
|
|
@@ -34194,11 +34270,11 @@ function rewriteLinks(nodes, from, index, report) {
|
|
|
34194
34270
|
rewriteLinks(node, from, index, report);
|
|
34195
34271
|
continue;
|
|
34196
34272
|
}
|
|
34197
|
-
if (
|
|
34273
|
+
if (!isNonNullObject(node)) {
|
|
34198
34274
|
continue;
|
|
34199
34275
|
}
|
|
34200
34276
|
const href = node.tagName === "a" ? node.attributes?.href : undefined;
|
|
34201
|
-
if (
|
|
34277
|
+
if (isString(href)) {
|
|
34202
34278
|
const resolution = resolveHref(href, from, index);
|
|
34203
34279
|
if ("problem" in resolution) {
|
|
34204
34280
|
report({ href, reason: resolution.problem });
|
|
@@ -34222,9 +34298,10 @@ function rewriteLinks(nodes, from, index, report) {
|
|
|
34222
34298
|
init_content_rules();
|
|
34223
34299
|
|
|
34224
34300
|
// src/dates.ts
|
|
34301
|
+
init_guards();
|
|
34225
34302
|
var DATE_FORMATS = ["date", "date-time"];
|
|
34226
34303
|
function isDateFormat(format) {
|
|
34227
|
-
return
|
|
34304
|
+
return DATE_FORMATS.some((candidate) => candidate === format);
|
|
34228
34305
|
}
|
|
34229
34306
|
var DATE_ONLY = /^\d{4}-\d{2}-\d{2}$/;
|
|
34230
34307
|
var RFC_3339 = /^\d{4}-\d{2}-\d{2}[Tt ]\d{2}:\d{2}(:\d{2}(\.\d+)?)?([Zz]|[+-]\d{2}:\d{2})?$/;
|
|
@@ -34241,7 +34318,7 @@ function parseDateValue(value, format) {
|
|
|
34241
34318
|
if (value instanceof Date) {
|
|
34242
34319
|
return Number.isNaN(value.getTime()) ? null : format === "date" ? toDateOnly(value) : toInstant(value);
|
|
34243
34320
|
}
|
|
34244
|
-
if (
|
|
34321
|
+
if (!isString(value)) {
|
|
34245
34322
|
return null;
|
|
34246
34323
|
}
|
|
34247
34324
|
const text = value.trim();
|
|
@@ -34274,7 +34351,7 @@ function coerceEntryDates(entries, schema, contentTypeName) {
|
|
|
34274
34351
|
if (!properties) {
|
|
34275
34352
|
return warnings;
|
|
34276
34353
|
}
|
|
34277
|
-
const dateFields = Object.entries(properties).
|
|
34354
|
+
const dateFields = Object.entries(properties).flatMap(([field, def]) => isDateFormat(def.format) ? [[field, def.format]] : []);
|
|
34278
34355
|
if (dateFields.length === 0) {
|
|
34279
34356
|
return warnings;
|
|
34280
34357
|
}
|
|
@@ -34305,9 +34382,7 @@ function coerceEntryDates(entries, schema, contentTypeName) {
|
|
|
34305
34382
|
return warnings;
|
|
34306
34383
|
}
|
|
34307
34384
|
function parseComparable(a, b) {
|
|
34308
|
-
|
|
34309
|
-
const bDate = typeof b === "string" && (DATE_ONLY.test(b) || RFC_3339.test(b));
|
|
34310
|
-
if (aDate && bDate) {
|
|
34385
|
+
if (isString(a) && isCoercedDate(a) && isString(b) && isCoercedDate(b)) {
|
|
34311
34386
|
return [a, b];
|
|
34312
34387
|
}
|
|
34313
34388
|
return [Number(a), Number(b)];
|
|
@@ -34315,23 +34390,24 @@ function parseComparable(a, b) {
|
|
|
34315
34390
|
|
|
34316
34391
|
// src/content-loader.ts
|
|
34317
34392
|
init_walk();
|
|
34393
|
+
|
|
34394
|
+
// src/content-data.ts
|
|
34395
|
+
async function entriesOf(data, name) {
|
|
34396
|
+
return await data?.load?.(name) ?? data?.get(name);
|
|
34397
|
+
}
|
|
34398
|
+
|
|
34399
|
+
// src/content-loader.ts
|
|
34318
34400
|
function loadJSONEntries(filePath) {
|
|
34319
34401
|
const raw = JSON.parse(readFileSync(filePath, "utf8"));
|
|
34320
34402
|
if (Array.isArray(raw)) {
|
|
34321
|
-
return raw.map((item, i) => ({
|
|
34322
|
-
body: null,
|
|
34323
|
-
data: item,
|
|
34324
|
-
id: item.id ?? `${basename(filePath, ".json")}-${i}`
|
|
34325
|
-
}));
|
|
34403
|
+
return raw.map((item, i) => jsonEntry(item, `${basename(filePath, ".json")}-${i}`));
|
|
34326
34404
|
}
|
|
34327
|
-
|
|
34328
|
-
|
|
34329
|
-
|
|
34330
|
-
|
|
34331
|
-
|
|
34332
|
-
|
|
34333
|
-
}
|
|
34334
|
-
];
|
|
34405
|
+
return [jsonEntry(raw, basename(filePath, ".json"))];
|
|
34406
|
+
}
|
|
34407
|
+
function jsonEntry(item, fallbackId) {
|
|
34408
|
+
const data = item;
|
|
34409
|
+
const id = data.id ?? fallbackId;
|
|
34410
|
+
return { body: null, data, id };
|
|
34335
34411
|
}
|
|
34336
34412
|
function discoverJSONFiles(resolvedSource, exclude) {
|
|
34337
34413
|
if (extname(resolvedSource)) {
|
|
@@ -34339,15 +34415,24 @@ function discoverJSONFiles(resolvedSource, exclude) {
|
|
|
34339
34415
|
}
|
|
34340
34416
|
return walkFiles(resolvedSource, (name) => name.toLowerCase().endsWith(".json"), exclude);
|
|
34341
34417
|
}
|
|
34342
|
-
var LOCALE_PLACEHOLDER = "{locale}";
|
|
34343
34418
|
function localesForExpansion(projectConfig) {
|
|
34344
34419
|
return resolveI18n(projectConfig ?? {}).i18n?.locales ?? [];
|
|
34345
34420
|
}
|
|
34421
|
+
function existsWithSpelling(root, path) {
|
|
34422
|
+
const full = resolve(root, path);
|
|
34423
|
+
if (!existsSync(full)) {
|
|
34424
|
+
return false;
|
|
34425
|
+
}
|
|
34426
|
+
const wanted = full.split(/[\\/]/).filter(Boolean);
|
|
34427
|
+
const actual = realpathSync2.native(full).split(/[\\/]/).filter(Boolean);
|
|
34428
|
+
const tail = actual.slice(-wanted.length);
|
|
34429
|
+
return wanted.every((segment, index) => segment === tail[index]);
|
|
34430
|
+
}
|
|
34346
34431
|
function localeSource(root, source, locale) {
|
|
34347
34432
|
const candidates = [locale, locale.toLowerCase()];
|
|
34348
34433
|
for (const spelling of candidates) {
|
|
34349
34434
|
const path = source.split(LOCALE_PLACEHOLDER).join(spelling);
|
|
34350
|
-
if (
|
|
34435
|
+
if (existsWithSpelling(root, path)) {
|
|
34351
34436
|
return path;
|
|
34352
34437
|
}
|
|
34353
34438
|
}
|
|
@@ -34360,8 +34445,6 @@ function localeSource(root, source, locale) {
|
|
|
34360
34445
|
}
|
|
34361
34446
|
return source.split(LOCALE_PLACEHOLDER).join(locale);
|
|
34362
34447
|
}
|
|
34363
|
-
var SECTION_KEY = "content";
|
|
34364
|
-
var SAFE_TYPE_NAME = /^[\w.~-]+$/;
|
|
34365
34448
|
var ASSET_KEYS = ["src", "poster"];
|
|
34366
34449
|
function isNonRelativeRef(value) {
|
|
34367
34450
|
return value === "" || value.startsWith("/") || value.startsWith("#") || value.includes("${") || /^[a-z][\w+.-]*:/i.test(value);
|
|
@@ -34396,28 +34479,31 @@ function contentAssetMounts(section, root, projectConfig) {
|
|
|
34396
34479
|
return filter === undefined ? {} : { filter };
|
|
34397
34480
|
};
|
|
34398
34481
|
for (const [name, contentTypeDef] of Object.entries(section ?? {})) {
|
|
34399
|
-
|
|
34482
|
+
if (!isNonNullObject(contentTypeDef)) {
|
|
34483
|
+
continue;
|
|
34484
|
+
}
|
|
34485
|
+
const { source } = contentTypeDef;
|
|
34400
34486
|
if (!source || source.startsWith("http://") || source.startsWith("https://")) {
|
|
34401
34487
|
continue;
|
|
34402
34488
|
}
|
|
34403
34489
|
if (source.includes(LOCALE_PLACEHOLDER)) {
|
|
34404
34490
|
for (const locale of locales) {
|
|
34405
|
-
if (!
|
|
34491
|
+
if (!SAFE_CONTENT_TYPE_NAME.test(locale)) {
|
|
34406
34492
|
continue;
|
|
34407
34493
|
}
|
|
34408
34494
|
const dir = resolve(root, localeSource(root, source, locale)).split("\\").join("/");
|
|
34409
|
-
if (
|
|
34495
|
+
if (SAFE_CONTENT_TYPE_NAME.test(name) && existsSync(dir) && statSync2(dir).isDirectory()) {
|
|
34410
34496
|
mounts.push({
|
|
34411
34497
|
dir,
|
|
34412
|
-
urlPrefix: `/${
|
|
34498
|
+
urlPrefix: `/${CONTENT_SECTION_KEY}/${name}/${locale}`,
|
|
34413
34499
|
...filterOf(contentTypeDef)
|
|
34414
34500
|
});
|
|
34415
34501
|
}
|
|
34416
34502
|
}
|
|
34417
34503
|
continue;
|
|
34418
34504
|
}
|
|
34419
|
-
if (!
|
|
34420
|
-
console.warn(`Content type "${name}": name is not URL-safe — its source directory is not published ` + `at /${
|
|
34505
|
+
if (!SAFE_CONTENT_TYPE_NAME.test(name)) {
|
|
34506
|
+
console.warn(`Content type "${name}": name is not URL-safe — its source directory is not published ` + `at /${CONTENT_SECTION_KEY}/${name}, so content-relative asset references stay unresolved.`);
|
|
34421
34507
|
continue;
|
|
34422
34508
|
}
|
|
34423
34509
|
const resolvedSource = resolve(root, source).split("\\").join("/");
|
|
@@ -34426,7 +34512,7 @@ function contentAssetMounts(section, root, projectConfig) {
|
|
|
34426
34512
|
}
|
|
34427
34513
|
mounts.push({
|
|
34428
34514
|
dir: resolvedSource,
|
|
34429
|
-
urlPrefix: `/${
|
|
34515
|
+
urlPrefix: `/${CONTENT_SECTION_KEY}/${name}`,
|
|
34430
34516
|
...filterOf(contentTypeDef)
|
|
34431
34517
|
});
|
|
34432
34518
|
}
|
|
@@ -34464,15 +34550,14 @@ function rewriteNodeAssets(node, entryDir, mount, onProblem) {
|
|
|
34464
34550
|
}
|
|
34465
34551
|
return;
|
|
34466
34552
|
}
|
|
34467
|
-
if (!node
|
|
34553
|
+
if (!isNonNullObject(node)) {
|
|
34468
34554
|
return;
|
|
34469
34555
|
}
|
|
34470
|
-
const
|
|
34471
|
-
const attributes = record.attributes;
|
|
34556
|
+
const { attributes } = node;
|
|
34472
34557
|
for (const key of ASSET_KEYS) {
|
|
34473
|
-
for (const holder of [
|
|
34558
|
+
for (const holder of [node, attributes]) {
|
|
34474
34559
|
const value = holder?.[key];
|
|
34475
|
-
if (
|
|
34560
|
+
if (holder && isString(value)) {
|
|
34476
34561
|
const rewritten = rewriteRef(value, entryDir, mount, onProblem);
|
|
34477
34562
|
if (rewritten) {
|
|
34478
34563
|
holder[key] = rewritten;
|
|
@@ -34480,7 +34565,7 @@ function rewriteNodeAssets(node, entryDir, mount, onProblem) {
|
|
|
34480
34565
|
}
|
|
34481
34566
|
}
|
|
34482
34567
|
}
|
|
34483
|
-
const { children } =
|
|
34568
|
+
const { children } = node;
|
|
34484
34569
|
if (Array.isArray(children)) {
|
|
34485
34570
|
for (const child of children) {
|
|
34486
34571
|
rewriteNodeAssets(child, entryDir, mount, onProblem);
|
|
@@ -34489,22 +34574,30 @@ function rewriteNodeAssets(node, entryDir, mount, onProblem) {
|
|
|
34489
34574
|
}
|
|
34490
34575
|
function rewriteEntryAssets(entries, filePath, mount, typeName, schema) {
|
|
34491
34576
|
const entryDir = dirname(filePath);
|
|
34492
|
-
const uriFields = Object.entries(schema?.properties ?? {}).
|
|
34577
|
+
const uriFields = Object.entries(schema?.properties ?? {}).flatMap(([field, def]) => isNonNullObject(def) && (def.format === "uri-reference" || def.items?.format === "uri-reference") ? [field] : []);
|
|
34493
34578
|
for (const entry of entries) {
|
|
34494
|
-
const onProblem = (
|
|
34495
|
-
|
|
34496
|
-
rewriteNodeAssets(child, entryDir, mount, onProblem);
|
|
34497
|
-
}
|
|
34579
|
+
const onProblem = assetProblemReporter(typeName, entry);
|
|
34580
|
+
rewriteBodyAssets(entry, filePath, mount, typeName);
|
|
34498
34581
|
for (const field of uriFields) {
|
|
34499
34582
|
const value = entry.data[field];
|
|
34500
|
-
if (
|
|
34583
|
+
if (isString(value)) {
|
|
34501
34584
|
entry.data[field] = rewriteRef(value, entryDir, mount, onProblem) ?? value;
|
|
34502
34585
|
} else if (Array.isArray(value)) {
|
|
34503
|
-
entry.data[field] = value.map((item) =>
|
|
34586
|
+
entry.data[field] = value.map((item) => isString(item) ? rewriteRef(item, entryDir, mount, onProblem) ?? item : item);
|
|
34504
34587
|
}
|
|
34505
34588
|
}
|
|
34506
34589
|
}
|
|
34507
34590
|
}
|
|
34591
|
+
function assetProblemReporter(typeName, entry) {
|
|
34592
|
+
return (value, problem) => console.warn(problem === "missing" ? `Content type "${typeName}": entry "${entry.id}" references missing asset "${value}"` : `Content type "${typeName}": entry "${entry.id}" references "${value}", which the ` + `collection does not publish (it is excluded, hidden or a document), so the ` + `reference is left as written`);
|
|
34593
|
+
}
|
|
34594
|
+
function rewriteBodyAssets(entry, filePath, mount, typeName) {
|
|
34595
|
+
const entryDir = dirname(filePath);
|
|
34596
|
+
const onProblem = assetProblemReporter(typeName, entry);
|
|
34597
|
+
for (const child of entry.$children ?? []) {
|
|
34598
|
+
rewriteNodeAssets(child, entryDir, mount, onProblem);
|
|
34599
|
+
}
|
|
34600
|
+
}
|
|
34508
34601
|
function loadContentConfig(projectRoot, projectConfig) {
|
|
34509
34602
|
const contentDir = resolve(projectRoot, "content");
|
|
34510
34603
|
const config = { content: projectConfig?.content ?? {} };
|
|
@@ -34512,48 +34605,63 @@ function loadContentConfig(projectRoot, projectConfig) {
|
|
|
34512
34605
|
}
|
|
34513
34606
|
async function loadContentSection(section, root, formats, projectConfig) {
|
|
34514
34607
|
const contentTypes = new Map;
|
|
34515
|
-
const mounts =
|
|
34516
|
-
|
|
34608
|
+
const mounts = sectionMounts(section, root, projectConfig);
|
|
34609
|
+
for (const name of Object.keys(section)) {
|
|
34610
|
+
contentTypes.set(name, await loadSectionType(name, { formats, mounts, projectConfig, root, section }));
|
|
34611
|
+
}
|
|
34612
|
+
return contentTypes;
|
|
34613
|
+
}
|
|
34614
|
+
function sectionMounts(section, root, projectConfig) {
|
|
34615
|
+
return new Map(contentAssetMounts(section, root, projectConfig).map((mount) => [
|
|
34616
|
+
mount.urlPrefix.slice(`/${CONTENT_SECTION_KEY}/`.length),
|
|
34517
34617
|
mount
|
|
34518
34618
|
]));
|
|
34619
|
+
}
|
|
34620
|
+
async function loadSectionType(name, source) {
|
|
34621
|
+
const { section, root, formats, projectConfig, mounts, onDeferred } = source;
|
|
34622
|
+
const contentTypeDef = section[name];
|
|
34623
|
+
if (!contentTypeDef) {
|
|
34624
|
+
return [];
|
|
34625
|
+
}
|
|
34626
|
+
const deferral = onDeferred ? { deferBody: true, onDeferred } : {};
|
|
34627
|
+
const typeSource = contentTypeDef.source;
|
|
34628
|
+
if (!isString(typeSource) || !typeSource.includes(LOCALE_PLACEHOLDER)) {
|
|
34629
|
+
return await loadContentType(name, contentTypeDef, root, formats, {
|
|
34630
|
+
mount: mounts.get(name),
|
|
34631
|
+
projectConfig,
|
|
34632
|
+
...deferral
|
|
34633
|
+
});
|
|
34634
|
+
}
|
|
34519
34635
|
const locales = localesForExpansion(projectConfig);
|
|
34520
|
-
|
|
34521
|
-
|
|
34522
|
-
|
|
34523
|
-
|
|
34524
|
-
|
|
34525
|
-
|
|
34526
|
-
|
|
34527
|
-
|
|
34528
|
-
|
|
34529
|
-
|
|
34530
|
-
|
|
34531
|
-
|
|
34532
|
-
|
|
34533
|
-
|
|
34534
|
-
|
|
34535
|
-
const all = [];
|
|
34536
|
-
for (const locale of locales) {
|
|
34537
|
-
const localized = { ...contentTypeDef, source: localeSource(root, source, locale) };
|
|
34538
|
-
const entries = await loadContentType(name, localized, root, formats, {
|
|
34539
|
-
locale,
|
|
34540
|
-
mount: mounts.get(`${name}/${locale}`),
|
|
34541
|
-
projectConfig
|
|
34542
|
-
});
|
|
34543
|
-
for (const entry of entries) {
|
|
34544
|
-
entry._meta = { ...entry._meta, locale };
|
|
34545
|
-
}
|
|
34546
|
-
all.push(...entries);
|
|
34636
|
+
if (locales.length === 0) {
|
|
34637
|
+
console.warn(`Content type "${name}": source "${typeSource}" uses ${LOCALE_PLACEHOLDER}, but the project ` + `declares no i18n locales — nothing to expand it over, so no entries were loaded.`);
|
|
34638
|
+
return [];
|
|
34639
|
+
}
|
|
34640
|
+
const all = [];
|
|
34641
|
+
for (const locale of locales) {
|
|
34642
|
+
const localized = { ...contentTypeDef, source: localeSource(root, typeSource, locale) };
|
|
34643
|
+
const entries = await loadContentType(name, localized, root, formats, {
|
|
34644
|
+
locale,
|
|
34645
|
+
mount: mounts.get(`${name}/${locale}`),
|
|
34646
|
+
projectConfig,
|
|
34647
|
+
...deferral
|
|
34648
|
+
});
|
|
34649
|
+
for (const entry of entries) {
|
|
34650
|
+
entry._meta = { ...entry._meta, locale };
|
|
34547
34651
|
}
|
|
34548
|
-
|
|
34652
|
+
all.push(...entries);
|
|
34549
34653
|
}
|
|
34550
|
-
return
|
|
34654
|
+
return all;
|
|
34551
34655
|
}
|
|
34552
34656
|
function getContentTypeElements(projectRoot, contentTypeName, projectConfig) {
|
|
34553
34657
|
const { config } = loadContentConfig(projectRoot, projectConfig);
|
|
34554
34658
|
const def = config.content[contentTypeName];
|
|
34555
34659
|
return def?.$elements;
|
|
34556
34660
|
}
|
|
34661
|
+
var LINK_MODES = ["warn", "error", "ignore"];
|
|
34662
|
+
function isLinkMode(value) {
|
|
34663
|
+
return LINK_MODES.some((mode) => mode === value);
|
|
34664
|
+
}
|
|
34557
34665
|
var KNOWN_TYPE_KEYS = [
|
|
34558
34666
|
"$elements",
|
|
34559
34667
|
"alerts",
|
|
@@ -34595,7 +34703,7 @@ function compileTypeRules(name, def) {
|
|
|
34595
34703
|
const at = `Content type "${name}"`;
|
|
34596
34704
|
try {
|
|
34597
34705
|
for (const key of Object.keys(def)) {
|
|
34598
|
-
if (KNOWN_TYPE_KEYS.
|
|
34706
|
+
if (KNOWN_TYPE_KEYS.some((known) => known === key) || key === "$comment") {
|
|
34599
34707
|
continue;
|
|
34600
34708
|
}
|
|
34601
34709
|
const suggestion = nearestOption(key);
|
|
@@ -34604,11 +34712,11 @@ function compileTypeRules(name, def) {
|
|
|
34604
34712
|
}
|
|
34605
34713
|
console.warn(`${at}: ignores the unknown option "${key}" (the options are ${KNOWN_TYPE_KEYS.join(", ")})`);
|
|
34606
34714
|
}
|
|
34607
|
-
if (def.idField !== undefined && (
|
|
34715
|
+
if (def.idField !== undefined && (!isString(def.idField) || def.idField === "")) {
|
|
34608
34716
|
throw new TypeError(`"idField" must be a field name`);
|
|
34609
34717
|
}
|
|
34610
34718
|
const links = def.links ?? "warn";
|
|
34611
|
-
if (links
|
|
34719
|
+
if (!isLinkMode(links)) {
|
|
34612
34720
|
throw new TypeError(`"links" must be "warn", "error" or "ignore", got ${JSON.stringify(links)}`);
|
|
34613
34721
|
}
|
|
34614
34722
|
normalizeAlerts(def.alerts, `"alerts"`);
|
|
@@ -34669,7 +34777,7 @@ function finishEntries(files, ctx) {
|
|
|
34669
34777
|
if (rules.idField) {
|
|
34670
34778
|
for (const entry of entries) {
|
|
34671
34779
|
const value = entry.data[rules.idField];
|
|
34672
|
-
if (
|
|
34780
|
+
if (isString(value) && value !== "" || isNumber(value)) {
|
|
34673
34781
|
const unsafe = traversalReason(String(value));
|
|
34674
34782
|
if (unsafe === null) {
|
|
34675
34783
|
entry.id = String(value);
|
|
@@ -34700,13 +34808,48 @@ function finishEntries(files, ctx) {
|
|
|
34700
34808
|
}
|
|
34701
34809
|
if (rules.route) {
|
|
34702
34810
|
assignRoutes(entries, unpublished, ctx, rules.route);
|
|
34703
|
-
|
|
34704
|
-
|
|
34705
|
-
}
|
|
34811
|
+
const links = ctx.sourceRoot ? resolveEntryLinks(kept, unpublished, ctx) : undefined;
|
|
34812
|
+
deferBodies(kept, ctx, links);
|
|
34706
34813
|
return entries.filter((entry) => entry._meta?.route !== undefined);
|
|
34707
34814
|
}
|
|
34815
|
+
deferBodies(kept, ctx);
|
|
34708
34816
|
return entries;
|
|
34709
34817
|
}
|
|
34818
|
+
function deferBodies(kept, ctx, links) {
|
|
34819
|
+
const { reload, onDeferred } = ctx;
|
|
34820
|
+
if (!reload || !onDeferred) {
|
|
34821
|
+
return;
|
|
34822
|
+
}
|
|
34823
|
+
for (const file of kept) {
|
|
34824
|
+
const [entry] = file.entries;
|
|
34825
|
+
if (file.entries.length !== 1 || !entry || entry.$children !== undefined) {
|
|
34826
|
+
continue;
|
|
34827
|
+
}
|
|
34828
|
+
onDeferred(entry, async () => {
|
|
34829
|
+
const [full] = await reload(file.filePath);
|
|
34830
|
+
if (!full) {
|
|
34831
|
+
return;
|
|
34832
|
+
}
|
|
34833
|
+
const completed = {
|
|
34834
|
+
...full,
|
|
34835
|
+
...entry,
|
|
34836
|
+
_meta: { ...full._meta, ...entry._meta }
|
|
34837
|
+
};
|
|
34838
|
+
for (const key of Object.keys(entry)) {
|
|
34839
|
+
Reflect.deleteProperty(entry, key);
|
|
34840
|
+
}
|
|
34841
|
+
Object.assign(entry, completed);
|
|
34842
|
+
if (ctx.mount) {
|
|
34843
|
+
rewriteBodyAssets(entry, file.filePath, ctx.mount, ctx.name);
|
|
34844
|
+
}
|
|
34845
|
+
if (links && file.rel !== null) {
|
|
34846
|
+
const broken = [];
|
|
34847
|
+
collectBrokenLinks(entry, file.rel, links, broken, new Set);
|
|
34848
|
+
reportBrokenLinks(broken, ctx.name, ctx.rules.links);
|
|
34849
|
+
}
|
|
34850
|
+
});
|
|
34851
|
+
}
|
|
34852
|
+
}
|
|
34710
34853
|
function settleIndexIds(name, entries) {
|
|
34711
34854
|
const indexFolders = new Set;
|
|
34712
34855
|
for (const entry of entries) {
|
|
@@ -34729,7 +34872,7 @@ function settleIndexIds(name, entries) {
|
|
|
34729
34872
|
}
|
|
34730
34873
|
function trailingSlashOf(projectConfig) {
|
|
34731
34874
|
const value = projectConfig?.build?.trailingSlash;
|
|
34732
|
-
return
|
|
34875
|
+
return isString(value) ? value : "always";
|
|
34733
34876
|
}
|
|
34734
34877
|
function localePrefixOf(ctx) {
|
|
34735
34878
|
const { i18n } = resolveI18n(ctx.projectConfig ?? {});
|
|
@@ -34777,7 +34920,21 @@ function assignRoutes(entries, unpublished, ctx, spec) {
|
|
|
34777
34920
|
}
|
|
34778
34921
|
var UNROUTED_LISTED = 3;
|
|
34779
34922
|
function resolveEntryLinks(kept, unpublished, ctx) {
|
|
34780
|
-
const
|
|
34923
|
+
const index = buildLinkIndex(kept, unpublished, ctx);
|
|
34924
|
+
const broken = [];
|
|
34925
|
+
const seen = new Set;
|
|
34926
|
+
for (const file of kept) {
|
|
34927
|
+
for (const entry of file.entries) {
|
|
34928
|
+
if (entry.$children && file.rel !== null) {
|
|
34929
|
+
collectBrokenLinks(entry, file.rel, index, broken, seen);
|
|
34930
|
+
}
|
|
34931
|
+
}
|
|
34932
|
+
}
|
|
34933
|
+
reportBrokenLinks(broken, ctx.name, ctx.rules.links);
|
|
34934
|
+
return index;
|
|
34935
|
+
}
|
|
34936
|
+
function buildLinkIndex(kept, unpublished, ctx) {
|
|
34937
|
+
const { rules, sourceRoot } = ctx;
|
|
34781
34938
|
const files = new Map;
|
|
34782
34939
|
const indexes = new Map;
|
|
34783
34940
|
const isReadme = (rel) => /^readme\./i.test(rel.slice(rel.lastIndexOf("/") + 1));
|
|
@@ -34808,7 +34965,7 @@ function resolveEntryLinks(kept, unpublished, ctx) {
|
|
|
34808
34965
|
}
|
|
34809
34966
|
}
|
|
34810
34967
|
const onDisk = (path) => resolve(sourceRoot, path);
|
|
34811
|
-
|
|
34968
|
+
return {
|
|
34812
34969
|
asset: (path) => {
|
|
34813
34970
|
const absolute = onDisk(path);
|
|
34814
34971
|
if (!ctx.mount || !existsSync(absolute) || statSync2(absolute).isDirectory()) {
|
|
@@ -34837,27 +34994,22 @@ function resolveEntryLinks(kept, unpublished, ctx) {
|
|
|
34837
34994
|
localePrefix: localePrefixOf(ctx),
|
|
34838
34995
|
trailingSlash: trailingSlashOf(ctx.projectConfig)
|
|
34839
34996
|
};
|
|
34840
|
-
|
|
34841
|
-
|
|
34842
|
-
|
|
34843
|
-
|
|
34844
|
-
|
|
34845
|
-
|
|
34846
|
-
}
|
|
34847
|
-
rewriteLinks(entry.$children, file.rel, index, (problem) => {
|
|
34848
|
-
const key = `${file.rel}\x00${problem.href}`;
|
|
34849
|
-
if (!seen.has(key)) {
|
|
34850
|
-
seen.add(key);
|
|
34851
|
-
broken.push({ from: file.rel, href: problem.href, reason: problem.reason });
|
|
34852
|
-
}
|
|
34853
|
-
});
|
|
34997
|
+
}
|
|
34998
|
+
function collectBrokenLinks(entry, rel, index, broken, seen) {
|
|
34999
|
+
rewriteLinks(entry.$children ?? [], rel, index, (problem) => {
|
|
35000
|
+
const key = `${rel}\x00${problem.href}`;
|
|
35001
|
+
if (!seen.has(key)) {
|
|
35002
|
+
seen.add(key);
|
|
35003
|
+
broken.push({ from: rel, href: problem.href, reason: problem.reason });
|
|
34854
35004
|
}
|
|
34855
|
-
}
|
|
34856
|
-
|
|
35005
|
+
});
|
|
35006
|
+
}
|
|
35007
|
+
function reportBrokenLinks(broken, name, mode) {
|
|
35008
|
+
if (mode === "ignore" || broken.length === 0) {
|
|
34857
35009
|
return;
|
|
34858
35010
|
}
|
|
34859
35011
|
const lines = broken.map(({ from, href, reason }) => `"${from}" links to "${href}", which ${reason}`);
|
|
34860
|
-
if (
|
|
35012
|
+
if (mode === "error") {
|
|
34861
35013
|
const plural = broken.length === 1 ? "" : "s";
|
|
34862
35014
|
const list = lines.map((line) => ` - ${line}`).join(`
|
|
34863
35015
|
`);
|
|
@@ -34877,8 +35029,8 @@ async function loadContentType(name, contentTypeDef, projectRoot, registry, opti
|
|
|
34877
35029
|
if (!source) {
|
|
34878
35030
|
return [];
|
|
34879
35031
|
}
|
|
34880
|
-
const { mount, projectConfig, locale } = options;
|
|
34881
|
-
const schema = contentTypeDef
|
|
35032
|
+
const { mount, projectConfig, locale, deferBody, onDeferred } = options;
|
|
35033
|
+
const { schema } = contentTypeDef;
|
|
34882
35034
|
const rules = compileTypeRules(name, contentTypeDef);
|
|
34883
35035
|
const finishContext = (extra) => ({
|
|
34884
35036
|
coerceDates: false,
|
|
@@ -34893,7 +35045,7 @@ async function loadContentType(name, contentTypeDef, projectRoot, registry, opti
|
|
|
34893
35045
|
...extra
|
|
34894
35046
|
});
|
|
34895
35047
|
const directiveOptions = contentTypeDef.$elements?.length ? {
|
|
34896
|
-
allowedNames: contentTypeDef.$elements.
|
|
35048
|
+
allowedNames: contentTypeDef.$elements.flatMap((e) => isString(e) ? [e] : isNonNullObject(e) && e.$ref ? [e.$ref] : [])
|
|
34897
35049
|
} : undefined;
|
|
34898
35050
|
const formatName = contentTypeDef.format;
|
|
34899
35051
|
let entry;
|
|
@@ -34949,25 +35101,32 @@ async function loadContentType(name, contentTypeDef, projectRoot, registry, opti
|
|
|
34949
35101
|
if (!entry) {
|
|
34950
35102
|
throw unknownFormatError(source, ext || `content type "${name}" (directory sources need an explicit "format")`);
|
|
34951
35103
|
}
|
|
34952
|
-
const
|
|
34953
|
-
|
|
34954
|
-
|
|
34955
|
-
}
|
|
35104
|
+
const discoverOptions = { baseDir: projectRoot };
|
|
35105
|
+
if (!rules.exclude.empty) {
|
|
35106
|
+
discoverOptions.exclude = contentTypeDef.exclude;
|
|
35107
|
+
}
|
|
35108
|
+
const discovered = entry.capabilities.discover ? await entry.call("discover", source, discoverOptions) : [resolvedSource];
|
|
34956
35109
|
const files = discovered.filter((file) => !isExcluded(file));
|
|
34957
35110
|
const fileExtensions = files.map((file) => extname(file).toLowerCase());
|
|
35111
|
+
const format = entry;
|
|
35112
|
+
const loadFile = (filePath, withoutBody) => {
|
|
35113
|
+
const rel = relOf(filePath);
|
|
35114
|
+
return format.call("load", filePath, {
|
|
35115
|
+
directiveOptions,
|
|
35116
|
+
schema,
|
|
35117
|
+
...sourceRoot !== undefined && { sourceRoot },
|
|
35118
|
+
...rules.alerts !== undefined && { alerts: rules.alerts },
|
|
35119
|
+
...rules.idField !== undefined && { idField: rules.idField },
|
|
35120
|
+
...withoutBody && { deferBody: true },
|
|
35121
|
+
onUnknownAlert: (type) => console.warn(`Content callouts: "${name}": "${rel ?? filePath}" has a [!${type}] callout, but ` + `"${type.toLowerCase()}" is not an enabled type, so it stays a blockquote with the ` + `marker showing. Add "alerts": { "${type.toUpperCase()}": true } to render it.`)
|
|
35122
|
+
});
|
|
35123
|
+
};
|
|
34958
35124
|
const loaded = [];
|
|
34959
35125
|
for (const filePath of files) {
|
|
34960
35126
|
const rel = relOf(filePath);
|
|
34961
35127
|
let fileEntries;
|
|
34962
35128
|
try {
|
|
34963
|
-
fileEntries = await
|
|
34964
|
-
directiveOptions,
|
|
34965
|
-
schema,
|
|
34966
|
-
...sourceRoot !== undefined && { sourceRoot },
|
|
34967
|
-
...rules.alerts !== undefined && { alerts: rules.alerts },
|
|
34968
|
-
...rules.idField !== undefined && { idField: rules.idField },
|
|
34969
|
-
onUnknownAlert: (type) => console.warn(`Content callouts: "${name}": "${rel ?? filePath}" has a [!${type}] callout, but ` + `"${type.toLowerCase()}" is not an enabled type, so it stays a blockquote with the ` + `marker showing. Add "alerts": { "${type.toUpperCase()}": true } to render it.`)
|
|
34970
|
-
});
|
|
35129
|
+
fileEntries = await loadFile(filePath, deferBody === true);
|
|
34971
35130
|
} catch (error) {
|
|
34972
35131
|
throw unreadableFile(name, rel ?? filePath, error);
|
|
34973
35132
|
}
|
|
@@ -34979,17 +35138,30 @@ async function loadContentType(name, contentTypeDef, projectRoot, registry, opti
|
|
|
34979
35138
|
return finishEntries(loaded, finishContext({
|
|
34980
35139
|
coerceDates: true,
|
|
34981
35140
|
entryExtensions: new Set([...entry.extensions, ...fileExtensions]),
|
|
34982
|
-
sourceRoot
|
|
35141
|
+
sourceRoot,
|
|
35142
|
+
...deferBody === true && {
|
|
35143
|
+
onDeferred,
|
|
35144
|
+
reload: async (filePath) => await loadFile(filePath, false)
|
|
35145
|
+
}
|
|
34983
35146
|
}));
|
|
34984
35147
|
}
|
|
34985
|
-
function unreadableFile(type, path,
|
|
34986
|
-
return new Error(`Content type "${type}": cannot read "${path}": ${errorMessage(
|
|
35148
|
+
function unreadableFile(type, path, cause) {
|
|
35149
|
+
return new Error(`Content type "${type}": cannot read "${path}": ${errorMessage(cause)}. Fix the file, or add it ` + `to "exclude" if it is not a document (a templates folder, for example).`, { cause });
|
|
34987
35150
|
}
|
|
34988
35151
|
function unknownFormatError(path, ext) {
|
|
34989
35152
|
return new Error(`No format class registered for "${ext}" (${path}). ` + `Enable an extension providing this format in project.json "extensions", ` + `e.g. "@jxsuite/parser".`);
|
|
34990
35153
|
}
|
|
34991
|
-
function errorMessage(
|
|
34992
|
-
return
|
|
35154
|
+
function errorMessage(cause) {
|
|
35155
|
+
return cause instanceof Error ? cause.message : String(cause);
|
|
35156
|
+
}
|
|
35157
|
+
function jsTypeName(value) {
|
|
35158
|
+
if (isString(value)) {
|
|
35159
|
+
return "string";
|
|
35160
|
+
}
|
|
35161
|
+
if (isNumber(value)) {
|
|
35162
|
+
return "number";
|
|
35163
|
+
}
|
|
35164
|
+
return isBoolean(value) ? "boolean" : "object";
|
|
34993
35165
|
}
|
|
34994
35166
|
function validateEntries(entries, schema, contentTypeName) {
|
|
34995
35167
|
const required = schema.required ?? [];
|
|
@@ -35005,16 +35177,16 @@ function validateEntries(entries, schema, contentTypeName) {
|
|
|
35005
35177
|
if (value == null) {
|
|
35006
35178
|
continue;
|
|
35007
35179
|
}
|
|
35008
|
-
if (isDateFormat(def.format) &&
|
|
35180
|
+
if (isDateFormat(def.format) && isString(value) && !isCoercedDate(value)) {
|
|
35009
35181
|
console.warn(`Content validation: "${contentTypeName}/${entry.id}" field "${field}" is declared ` + `${def.format} but "${value}" was not coerced — it will sort and filter as plain text.`);
|
|
35010
|
-
} else if (def.type === "string" &&
|
|
35011
|
-
console.warn(`Content validation: "${contentTypeName}/${entry.id}" field "${field}" expected string, got ${
|
|
35012
|
-
} else if (def.type === "number" &&
|
|
35013
|
-
console.warn(`Content validation: "${contentTypeName}/${entry.id}" field "${field}" expected number, got ${
|
|
35014
|
-
} else if (def.type === "boolean" &&
|
|
35015
|
-
console.warn(`Content validation: "${contentTypeName}/${entry.id}" field "${field}" expected boolean, got ${
|
|
35182
|
+
} else if (def.type === "string" && !isString(value)) {
|
|
35183
|
+
console.warn(`Content validation: "${contentTypeName}/${entry.id}" field "${field}" expected string, got ${jsTypeName(value)}`);
|
|
35184
|
+
} else if (def.type === "number" && !isNumber(value)) {
|
|
35185
|
+
console.warn(`Content validation: "${contentTypeName}/${entry.id}" field "${field}" expected number, got ${jsTypeName(value)}`);
|
|
35186
|
+
} else if (def.type === "boolean" && !isBoolean(value)) {
|
|
35187
|
+
console.warn(`Content validation: "${contentTypeName}/${entry.id}" field "${field}" expected boolean, got ${jsTypeName(value)}`);
|
|
35016
35188
|
} else if (def.type === "array" && !Array.isArray(value)) {
|
|
35017
|
-
console.warn(`Content validation: "${contentTypeName}/${entry.id}" field "${field}" expected array, got ${
|
|
35189
|
+
console.warn(`Content validation: "${contentTypeName}/${entry.id}" field "${field}" expected array, got ${jsTypeName(value)}`);
|
|
35018
35190
|
}
|
|
35019
35191
|
}
|
|
35020
35192
|
}
|
|
@@ -35026,9 +35198,19 @@ function refTargetName(ref) {
|
|
|
35026
35198
|
}
|
|
35027
35199
|
return ref.slice(CONTENT_REF_PREFIX.length);
|
|
35028
35200
|
}
|
|
35201
|
+
function referencedContentTypes(def) {
|
|
35202
|
+
const targets = new Set;
|
|
35203
|
+
for (const field of Object.values(def?.schema?.properties ?? {})) {
|
|
35204
|
+
const target = refTargetName(field.$ref) ?? refTargetName(field.items?.$ref);
|
|
35205
|
+
if (target !== undefined) {
|
|
35206
|
+
targets.add(target);
|
|
35207
|
+
}
|
|
35208
|
+
}
|
|
35209
|
+
return [...targets];
|
|
35210
|
+
}
|
|
35029
35211
|
function resolveContentTypeRefs(contentTypes, section) {
|
|
35030
35212
|
for (const [name, contentTypeDef] of Object.entries(section)) {
|
|
35031
|
-
const schema = contentTypeDef
|
|
35213
|
+
const { schema } = contentTypeDef;
|
|
35032
35214
|
if (!schema?.properties) {
|
|
35033
35215
|
continue;
|
|
35034
35216
|
}
|
|
@@ -35050,7 +35232,7 @@ function resolveContentTypeRefs(contentTypes, section) {
|
|
|
35050
35232
|
}
|
|
35051
35233
|
for (const entry of entries) {
|
|
35052
35234
|
const value = entry.data[field];
|
|
35053
|
-
if (toOne &&
|
|
35235
|
+
if (toOne && isString(value)) {
|
|
35054
35236
|
const resolved = refEntries.find((e) => e.id === value);
|
|
35055
35237
|
if (resolved) {
|
|
35056
35238
|
entry.data[field] = resolved;
|
|
@@ -35059,7 +35241,7 @@ function resolveContentTypeRefs(contentTypes, section) {
|
|
|
35059
35241
|
}
|
|
35060
35242
|
} else if (toMany && Array.isArray(value)) {
|
|
35061
35243
|
entry.data[field] = value.map((id) => {
|
|
35062
|
-
if (
|
|
35244
|
+
if (!isString(id)) {
|
|
35063
35245
|
return id;
|
|
35064
35246
|
}
|
|
35065
35247
|
const resolved = refEntries.find((e) => e.id === id);
|
|
@@ -35086,7 +35268,10 @@ function reportUnservedRoutes(contentType, entries, ctx, prefix) {
|
|
|
35086
35268
|
return;
|
|
35087
35269
|
}
|
|
35088
35270
|
const patterns = ctx.patterns.map((pattern) => withoutLocalePrefix(pattern, prefix));
|
|
35089
|
-
const unserved = entries.
|
|
35271
|
+
const unserved = entries.flatMap((entry) => {
|
|
35272
|
+
const route = entry._meta?.route;
|
|
35273
|
+
return route !== undefined && !patterns.some((pattern) => routeParams(route, pattern, []) !== null) ? [route] : [];
|
|
35274
|
+
});
|
|
35090
35275
|
if (unserved.length === 0) {
|
|
35091
35276
|
return;
|
|
35092
35277
|
}
|
|
@@ -35109,7 +35294,11 @@ function routedPaths(contentType, entries, ctx, urlPattern) {
|
|
|
35109
35294
|
example ??= route;
|
|
35110
35295
|
const params = routeParams(route, pattern, ctx.params ?? []);
|
|
35111
35296
|
if (params) {
|
|
35112
|
-
|
|
35297
|
+
const pathEntry = { ...params };
|
|
35298
|
+
if (entry._meta !== undefined) {
|
|
35299
|
+
pathEntry._meta = entry._meta;
|
|
35300
|
+
}
|
|
35301
|
+
paths.push(pathEntry);
|
|
35113
35302
|
}
|
|
35114
35303
|
}
|
|
35115
35304
|
if (paths.length === 0 && example !== undefined) {
|
|
@@ -35119,18 +35308,159 @@ function routedPaths(contentType, entries, ctx, urlPattern) {
|
|
|
35119
35308
|
return paths;
|
|
35120
35309
|
}
|
|
35121
35310
|
|
|
35311
|
+
class ContentStore extends Map {
|
|
35312
|
+
#source;
|
|
35313
|
+
#mounts;
|
|
35314
|
+
#loads = new Map;
|
|
35315
|
+
#linked = new Set;
|
|
35316
|
+
#entries = new WeakSet;
|
|
35317
|
+
#deferred = new WeakMap;
|
|
35318
|
+
#completing = new WeakMap;
|
|
35319
|
+
constructor(source) {
|
|
35320
|
+
super();
|
|
35321
|
+
this.#source = source;
|
|
35322
|
+
this.#mounts = sectionMounts(source.section, source.root, source.projectConfig);
|
|
35323
|
+
}
|
|
35324
|
+
static async whole(source) {
|
|
35325
|
+
const store = new ContentStore(source);
|
|
35326
|
+
const loaded = await loadContentSection(source.section, source.root, source.formats, source.projectConfig);
|
|
35327
|
+
for (const [name, entries] of loaded) {
|
|
35328
|
+
store.#adopt(name, entries);
|
|
35329
|
+
store.#loads.set(name, Promise.resolve());
|
|
35330
|
+
}
|
|
35331
|
+
resolveContentTypeRefs(store, source.section);
|
|
35332
|
+
for (const name of loaded.keys()) {
|
|
35333
|
+
store.#linked.add(name);
|
|
35334
|
+
}
|
|
35335
|
+
return store;
|
|
35336
|
+
}
|
|
35337
|
+
static lazy(source) {
|
|
35338
|
+
return new ContentStore(source);
|
|
35339
|
+
}
|
|
35340
|
+
async load(name) {
|
|
35341
|
+
if (!Object.hasOwn(this.#source.section, name)) {
|
|
35342
|
+
return;
|
|
35343
|
+
}
|
|
35344
|
+
const related = this.#relatedTypes(name);
|
|
35345
|
+
await Promise.all(related.map(async (type) => await this.#loadType(type)));
|
|
35346
|
+
const unlinked = related.filter((type) => !this.#linked.has(type));
|
|
35347
|
+
for (const type of unlinked) {
|
|
35348
|
+
this.#linked.add(type);
|
|
35349
|
+
}
|
|
35350
|
+
if (unlinked.length > 0) {
|
|
35351
|
+
const { section } = this.#source;
|
|
35352
|
+
resolveContentTypeRefs(this, Object.fromEntries(unlinked.flatMap((type) => section[type] ? [[type, section[type]]] : [])));
|
|
35353
|
+
}
|
|
35354
|
+
return this.get(name);
|
|
35355
|
+
}
|
|
35356
|
+
async materialize(entries) {
|
|
35357
|
+
const seen = new Set;
|
|
35358
|
+
const pending = [];
|
|
35359
|
+
const visit = (entry) => {
|
|
35360
|
+
if (seen.has(entry)) {
|
|
35361
|
+
return;
|
|
35362
|
+
}
|
|
35363
|
+
seen.add(entry);
|
|
35364
|
+
pending.push(this.#complete(entry));
|
|
35365
|
+
for (const value of Object.values(entry.data)) {
|
|
35366
|
+
for (const item of Array.isArray(value) ? value : [value]) {
|
|
35367
|
+
if (this.#isEntry(item)) {
|
|
35368
|
+
visit(item);
|
|
35369
|
+
}
|
|
35370
|
+
}
|
|
35371
|
+
}
|
|
35372
|
+
};
|
|
35373
|
+
for (const entry of entries) {
|
|
35374
|
+
if (entry) {
|
|
35375
|
+
visit(entry);
|
|
35376
|
+
}
|
|
35377
|
+
}
|
|
35378
|
+
await Promise.all(pending);
|
|
35379
|
+
}
|
|
35380
|
+
async complete() {
|
|
35381
|
+
const lists = await Promise.all(Object.keys(this.#source.section).map(async (name) => await this.load(name) ?? []));
|
|
35382
|
+
await this.materialize(lists.flat());
|
|
35383
|
+
}
|
|
35384
|
+
#relatedTypes(name) {
|
|
35385
|
+
const { section } = this.#source;
|
|
35386
|
+
const found = new Set([name]);
|
|
35387
|
+
const queue = [name];
|
|
35388
|
+
for (let type = queue.shift();type !== undefined; type = queue.shift()) {
|
|
35389
|
+
for (const target of referencedContentTypes(section[type])) {
|
|
35390
|
+
if (Object.hasOwn(section, target) && !found.has(target)) {
|
|
35391
|
+
found.add(target);
|
|
35392
|
+
queue.push(target);
|
|
35393
|
+
}
|
|
35394
|
+
}
|
|
35395
|
+
}
|
|
35396
|
+
return [...found];
|
|
35397
|
+
}
|
|
35398
|
+
#loadType(name) {
|
|
35399
|
+
let load = this.#loads.get(name);
|
|
35400
|
+
if (!load) {
|
|
35401
|
+
const { section, root, formats, projectConfig } = this.#source;
|
|
35402
|
+
load = loadSectionType(name, {
|
|
35403
|
+
formats,
|
|
35404
|
+
mounts: this.#mounts,
|
|
35405
|
+
onDeferred: (entry, completeBody) => {
|
|
35406
|
+
this.#deferred.set(entry, completeBody);
|
|
35407
|
+
},
|
|
35408
|
+
projectConfig,
|
|
35409
|
+
root,
|
|
35410
|
+
section
|
|
35411
|
+
}).then((entries) => {
|
|
35412
|
+
this.#adopt(name, entries);
|
|
35413
|
+
});
|
|
35414
|
+
load.catch(() => {
|
|
35415
|
+
this.#loads.delete(name);
|
|
35416
|
+
});
|
|
35417
|
+
this.#loads.set(name, load);
|
|
35418
|
+
}
|
|
35419
|
+
return load;
|
|
35420
|
+
}
|
|
35421
|
+
#adopt(name, entries) {
|
|
35422
|
+
for (const entry of entries) {
|
|
35423
|
+
this.#entries.add(entry);
|
|
35424
|
+
}
|
|
35425
|
+
this.set(name, entries);
|
|
35426
|
+
}
|
|
35427
|
+
#isEntry(value) {
|
|
35428
|
+
return isNonNullObject(value) && this.#entries.has(value);
|
|
35429
|
+
}
|
|
35430
|
+
#complete(entry) {
|
|
35431
|
+
let completing = this.#completing.get(entry);
|
|
35432
|
+
if (!completing) {
|
|
35433
|
+
const completeBody = this.#deferred.get(entry);
|
|
35434
|
+
if (!completeBody) {
|
|
35435
|
+
return Promise.resolve();
|
|
35436
|
+
}
|
|
35437
|
+
completing = completeBody().then(() => {
|
|
35438
|
+
this.#deferred.delete(entry);
|
|
35439
|
+
});
|
|
35440
|
+
completing.catch(() => {
|
|
35441
|
+
this.#completing.delete(entry);
|
|
35442
|
+
});
|
|
35443
|
+
this.#completing.set(entry, completing);
|
|
35444
|
+
}
|
|
35445
|
+
return completing;
|
|
35446
|
+
}
|
|
35447
|
+
}
|
|
35448
|
+
|
|
35122
35449
|
class Content {
|
|
35123
35450
|
static async projectData(sectionValue, ctx) {
|
|
35124
|
-
const
|
|
35125
|
-
|
|
35126
|
-
|
|
35127
|
-
|
|
35451
|
+
const source = {
|
|
35452
|
+
formats: ctx.registry.formats,
|
|
35453
|
+
projectConfig: ctx.projectConfig,
|
|
35454
|
+
root: ctx.root,
|
|
35455
|
+
section: sectionValue ?? {}
|
|
35456
|
+
};
|
|
35457
|
+
return ctx.lazy === true ? ContentStore.lazy(source) : await ContentStore.whole(source);
|
|
35128
35458
|
}
|
|
35129
35459
|
static assets(sectionValue, ctx) {
|
|
35130
35460
|
return contentAssetMounts(sectionValue ?? {}, ctx.root, ctx.projectConfig);
|
|
35131
35461
|
}
|
|
35132
35462
|
static async resolvePaths(pathsDef, ctx) {
|
|
35133
|
-
const entries = ctx.data
|
|
35463
|
+
const entries = await entriesOf(ctx.data, pathsDef.contentType);
|
|
35134
35464
|
if (!entries || entries.length === 0) {
|
|
35135
35465
|
console.warn(`Warning: $paths references content type "${pathsDef.contentType}" but it has no entries`);
|
|
35136
35466
|
return [];
|
|
@@ -35139,7 +35469,7 @@ class Content {
|
|
|
35139
35469
|
const field = pathsDef.field ?? "id";
|
|
35140
35470
|
const localized = entries.some((entry) => entry._meta?.locale !== undefined);
|
|
35141
35471
|
const wanted = ctx.locale;
|
|
35142
|
-
const scoped = localized &&
|
|
35472
|
+
const scoped = localized && isString(wanted) ? entries.filter((entry) => entry._meta?.locale === wanted) : entries;
|
|
35143
35473
|
if (pathsDef.param === undefined && pathsDef.field === undefined && ctx.urlPattern !== undefined && scoped.some((entry) => entry._meta?.route !== undefined)) {
|
|
35144
35474
|
return routedPaths(pathsDef.contentType, scoped, ctx, ctx.urlPattern);
|
|
35145
35475
|
}
|
|
@@ -35165,13 +35495,17 @@ class Content {
|
|
|
35165
35495
|
}
|
|
35166
35496
|
export {
|
|
35167
35497
|
Content,
|
|
35498
|
+
ContentStore,
|
|
35168
35499
|
LOCALE_PLACEHOLDER,
|
|
35169
35500
|
contentAssetMounts,
|
|
35170
35501
|
getContentTypeElements,
|
|
35171
35502
|
loadContentConfig,
|
|
35172
35503
|
loadContentSection,
|
|
35504
|
+
loadSectionType,
|
|
35173
35505
|
localeSource,
|
|
35174
35506
|
localesForExpansion,
|
|
35507
|
+
referencedContentTypes,
|
|
35175
35508
|
resolveContentTypeRefs,
|
|
35176
|
-
rewriteEntryAssets
|
|
35509
|
+
rewriteEntryAssets,
|
|
35510
|
+
sectionMounts
|
|
35177
35511
|
};
|