@jxsuite/parser 1.4.1 → 1.5.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.
@@ -19,12 +19,14 @@ var __toESM = (mod, isNodeMode, target) => {
19
19
  }
20
20
  target = mod != null ? __create(__getProtoOf(mod)) : {};
21
21
  const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
22
- for (let key of __getOwnPropNames(mod))
23
- if (!__hasOwnProp.call(to, key))
24
- __defProp(to, key, {
25
- get: __accessProp.bind(mod, key),
26
- enumerable: true
27
- });
22
+ if (mod && typeof mod === "object" || typeof mod === "function") {
23
+ for (let key of __getOwnPropNames(mod))
24
+ if (!__hasOwnProp.call(to, key))
25
+ __defProp(to, key, {
26
+ get: __accessProp.bind(mod, key),
27
+ enumerable: true
28
+ });
29
+ }
28
30
  if (canCache)
29
31
  cache.set(mod, to);
30
32
  return to;
@@ -80,6 +82,184 @@ function assetUrlFor(mounts, absolutePath) {
80
82
  }
81
83
  var URL_TERMINATOR = String.raw`"'\s<>()\\`;
82
84
 
85
+ // ../../packages/schema/src/locale.ts
86
+ var RTL_SCRIPTS = new Set([
87
+ "Adlm",
88
+ "Arab",
89
+ "Aran",
90
+ "Armi",
91
+ "Avst",
92
+ "Cprt",
93
+ "Egyd",
94
+ "Egyh",
95
+ "Elym",
96
+ "Gara",
97
+ "Hatr",
98
+ "Hebr",
99
+ "Hluw",
100
+ "Hung",
101
+ "Khar",
102
+ "Lydi",
103
+ "Mand",
104
+ "Mani",
105
+ "Mend",
106
+ "Merc",
107
+ "Mero",
108
+ "Narb",
109
+ "Nbat",
110
+ "Nkoo",
111
+ "Orkh",
112
+ "Palm",
113
+ "Phli",
114
+ "Phlp",
115
+ "Phnx",
116
+ "Prti",
117
+ "Rohg",
118
+ "Samr",
119
+ "Sarb",
120
+ "Sogd",
121
+ "Sogo",
122
+ "Syrc",
123
+ "Thaa",
124
+ "Todr",
125
+ "Yezi"
126
+ ]);
127
+ function canonicalizeLocale(tag) {
128
+ if (typeof tag !== "string" || tag.trim() === "") {
129
+ return null;
130
+ }
131
+ try {
132
+ return new Intl.Locale(tag.trim()).toString();
133
+ } catch {
134
+ return null;
135
+ }
136
+ }
137
+ var DEFAULT_ROUTING = "prefix-except-default";
138
+ function resolveI18n(projectConfig) {
139
+ const raw = projectConfig.i18n;
140
+ const errors = [];
141
+ if (!raw || typeof raw !== "object") {
142
+ return { errors, i18n: null };
143
+ }
144
+ const declared = Array.isArray(raw.locales) ? raw.locales : [];
145
+ const locales = [];
146
+ for (const tag of declared) {
147
+ const canonical = canonicalizeLocale(tag);
148
+ if (canonical === null) {
149
+ errors.push(`i18n.locales: "${String(tag)}" is not a well-formed BCP 47 language tag.`);
150
+ continue;
151
+ }
152
+ if (!locales.includes(canonical)) {
153
+ locales.push(canonical);
154
+ }
155
+ }
156
+ const defaultLocale = canonicalizeLocale(raw.defaultLocale) ?? locales[0] ?? null;
157
+ if (raw.defaultLocale !== undefined && canonicalizeLocale(raw.defaultLocale) === null) {
158
+ errors.push(`i18n.defaultLocale: "${String(raw.defaultLocale)}" is not a well-formed BCP 47 language tag.`);
159
+ }
160
+ if (defaultLocale === null) {
161
+ errors.push("i18n is declared with no usable locale — set `defaultLocale` or `locales`.");
162
+ return { errors, i18n: null };
163
+ }
164
+ if (!locales.includes(defaultLocale)) {
165
+ locales.unshift(defaultLocale);
166
+ }
167
+ const routing = raw.routing === "prefix-always" || raw.routing === "prefix-except-default" ? raw.routing : DEFAULT_ROUTING;
168
+ return { errors, i18n: { defaultLocale, locales, routing } };
169
+ }
170
+
171
+ // src/dates.ts
172
+ var DATE_FORMATS = ["date", "date-time"];
173
+ function isDateFormat(format) {
174
+ return typeof format === "string" && DATE_FORMATS.includes(format);
175
+ }
176
+ var DATE_ONLY = /^\d{4}-\d{2}-\d{2}$/;
177
+ var RFC_3339 = /^\d{4}-\d{2}-\d{2}[Tt ]\d{2}:\d{2}(:\d{2}(\.\d+)?)?([Zz]|[+-]\d{2}:\d{2})?$/;
178
+ function pad(n, width = 2) {
179
+ return String(n).padStart(width, "0");
180
+ }
181
+ function toDateOnly(d) {
182
+ return `${pad(d.getUTCFullYear(), 4)}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())}`;
183
+ }
184
+ function toInstant(d) {
185
+ return `${toDateOnly(d)}T${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())}:${pad(d.getUTCSeconds())}Z`;
186
+ }
187
+ function parseDateValue(value, format) {
188
+ if (value instanceof Date) {
189
+ return Number.isNaN(value.getTime()) ? null : format === "date" ? toDateOnly(value) : toInstant(value);
190
+ }
191
+ if (typeof value !== "string") {
192
+ return null;
193
+ }
194
+ const text = value.trim();
195
+ if (text === "") {
196
+ return null;
197
+ }
198
+ if (DATE_ONLY.test(text)) {
199
+ const d = new Date(`${text}T00:00:00Z`);
200
+ if (Number.isNaN(d.getTime())) {
201
+ return null;
202
+ }
203
+ return format === "date" ? text : toInstant(d);
204
+ }
205
+ if (RFC_3339.test(text)) {
206
+ const normalized = /[Zz]|[+-]\d{2}:\d{2}$/.test(text) ? text : `${text.replace(" ", "T")}Z`;
207
+ const d = new Date(normalized);
208
+ if (Number.isNaN(d.getTime())) {
209
+ return null;
210
+ }
211
+ return format === "date" ? toDateOnly(d) : toInstant(d);
212
+ }
213
+ return null;
214
+ }
215
+ function isCoercedDate(value) {
216
+ return DATE_ONLY.test(value) || RFC_3339.test(value);
217
+ }
218
+ function coerceEntryDates(entries, schema, contentTypeName) {
219
+ const warnings = [];
220
+ const properties = schema?.properties;
221
+ if (!properties) {
222
+ return warnings;
223
+ }
224
+ const dateFields = Object.entries(properties).map(([field, def]) => [field, def.format]).filter((pair) => isDateFormat(pair[1]));
225
+ if (dateFields.length === 0) {
226
+ return warnings;
227
+ }
228
+ for (const entry of entries) {
229
+ for (const [field, format] of dateFields) {
230
+ const raw = entry.data[field];
231
+ if (raw === undefined || raw === null || raw === "") {
232
+ continue;
233
+ }
234
+ const coerced = parseDateValue(raw, format);
235
+ if (coerced === null) {
236
+ warnings.push({
237
+ entryId: entry.id,
238
+ field,
239
+ message: `Content dates: "${contentTypeName}/${entry.id}" field "${field}" is ` + `${JSON.stringify(raw)}, which is not an unambiguous ${format}. Write it as ` + `${format === "date" ? "YYYY-MM-DD" : "YYYY-MM-DDTHH:MM:SSZ"} — a form like ` + `"03/04/2025" means two different days depending on who reads it, so it is left as ` + `authored rather than guessed.`,
240
+ value: raw
241
+ });
242
+ continue;
243
+ }
244
+ if (coerced !== raw) {
245
+ entry._meta ??= {};
246
+ entry._meta.rawDates ??= {};
247
+ entry._meta.rawDates[field] = raw;
248
+ }
249
+ entry.data[field] = coerced;
250
+ }
251
+ }
252
+ return warnings;
253
+ }
254
+ function parseComparable(a, b) {
255
+ const aDate = typeof a === "string" && (DATE_ONLY.test(a) || RFC_3339.test(a));
256
+ const bDate = typeof b === "string" && (DATE_ONLY.test(b) || RFC_3339.test(b));
257
+ if (aDate && bDate) {
258
+ return [a, b];
259
+ }
260
+ return [Number(a), Number(b)];
261
+ }
262
+
83
263
  // src/content-loader.ts
84
264
  function loadJSONEntries(filePath) {
85
265
  const raw = JSON.parse(readFileSync(filePath, "utf8"));
@@ -109,19 +289,53 @@ function discoverJSONFiles(resolvedSource) {
109
289
  return [];
110
290
  }
111
291
  }
292
+ var LOCALE_PLACEHOLDER = "{locale}";
293
+ function localesForExpansion(projectConfig) {
294
+ return resolveI18n(projectConfig ?? {}).i18n?.locales ?? [];
295
+ }
296
+ function localeSource(root, source, locale) {
297
+ const candidates = [locale, locale.toLowerCase()];
298
+ for (const spelling of candidates) {
299
+ const path = source.split(LOCALE_PLACEHOLDER).join(spelling);
300
+ if (existsSync(resolve(root, path))) {
301
+ return path;
302
+ }
303
+ }
304
+ const parent = resolve(root, source.slice(0, source.indexOf(LOCALE_PLACEHOLDER)));
305
+ if (existsSync(parent) && statSync(parent).isDirectory()) {
306
+ const match = readdirSync(parent).find((name) => name.toLowerCase() === locale.toLowerCase());
307
+ if (match !== undefined) {
308
+ return source.split(LOCALE_PLACEHOLDER).join(match);
309
+ }
310
+ }
311
+ return source.split(LOCALE_PLACEHOLDER).join(locale);
312
+ }
112
313
  var SECTION_KEY = "content";
113
314
  var SAFE_TYPE_NAME = /^[\w.~-]+$/;
114
315
  var ASSET_KEYS = ["src", "poster"];
115
316
  function isNonRelativeRef(value) {
116
317
  return value === "" || value.startsWith("/") || value.startsWith("#") || value.includes("${") || /^[a-z][\w+.-]*:/i.test(value);
117
318
  }
118
- function contentAssetMounts(section, root) {
319
+ function contentAssetMounts(section, root, projectConfig) {
119
320
  const mounts = [];
321
+ const locales = localesForExpansion(projectConfig);
120
322
  for (const [name, contentTypeDef] of Object.entries(section ?? {})) {
121
323
  const source = contentTypeDef?.source;
122
324
  if (!source || source.startsWith("http://") || source.startsWith("https://")) {
123
325
  continue;
124
326
  }
327
+ if (source.includes(LOCALE_PLACEHOLDER)) {
328
+ for (const locale of locales) {
329
+ if (!SAFE_TYPE_NAME.test(locale)) {
330
+ continue;
331
+ }
332
+ const dir = resolve(root, localeSource(root, source, locale)).split("\\").join("/");
333
+ if (SAFE_TYPE_NAME.test(name) && existsSync(dir) && statSync(dir).isDirectory()) {
334
+ mounts.push({ dir, urlPrefix: `/${SECTION_KEY}/${name}/${locale}` });
335
+ }
336
+ }
337
+ continue;
338
+ }
125
339
  if (!SAFE_TYPE_NAME.test(name)) {
126
340
  console.warn(`Content type "${name}": name is not URL-safe — its source directory is not published ` + `at /${SECTION_KEY}/${name}, so content-relative asset references stay unresolved.`);
127
341
  continue;
@@ -203,12 +417,35 @@ function loadContentConfig(projectRoot, projectConfig) {
203
417
  const config = { content: projectConfig?.content ?? {} };
204
418
  return { config, contentDir };
205
419
  }
206
- async function loadContentSection(section, root, formats) {
420
+ async function loadContentSection(section, root, formats, projectConfig) {
207
421
  const contentTypes = new Map;
208
- const mounts = new Map(contentAssetMounts(section, root).map((mount) => [mount.urlPrefix.split("/").pop(), mount]));
422
+ const mounts = new Map(contentAssetMounts(section, root, projectConfig).map((mount) => [
423
+ mount.urlPrefix.slice(`/${SECTION_KEY}/`.length),
424
+ mount
425
+ ]));
426
+ const locales = localesForExpansion(projectConfig);
209
427
  for (const [name, contentTypeDef] of Object.entries(section)) {
210
- const entries = await loadContentType(name, contentTypeDef, root, formats, mounts.get(name));
211
- contentTypes.set(name, entries);
428
+ const source = contentTypeDef?.source;
429
+ if (typeof source !== "string" || !source.includes(LOCALE_PLACEHOLDER)) {
430
+ const entries = await loadContentType(name, contentTypeDef, root, formats, mounts.get(name));
431
+ contentTypes.set(name, entries);
432
+ continue;
433
+ }
434
+ if (locales.length === 0) {
435
+ console.warn(`Content type "${name}": source "${source}" uses ${LOCALE_PLACEHOLDER}, but the project ` + `declares no i18n locales — nothing to expand it over, so no entries were loaded.`);
436
+ contentTypes.set(name, []);
437
+ continue;
438
+ }
439
+ const all = [];
440
+ for (const locale of locales) {
441
+ const localized = { ...contentTypeDef, source: localeSource(root, source, locale) };
442
+ const entries = await loadContentType(name, localized, root, formats, mounts.get(`${name}/${locale}`));
443
+ for (const entry of entries) {
444
+ entry._meta = { ...entry._meta, locale };
445
+ }
446
+ all.push(...entries);
447
+ }
448
+ contentTypes.set(name, all);
212
449
  }
213
450
  return contentTypes;
214
451
  }
@@ -295,6 +532,9 @@ async function loadContentType(name, contentTypeDef, projectRoot, registry, moun
295
532
  entries.push(...fileEntries);
296
533
  }
297
534
  if (schema) {
535
+ for (const warning of coerceEntryDates(entries, schema, name)) {
536
+ console.warn(warning.message);
537
+ }
298
538
  validateEntries(entries, schema, name);
299
539
  }
300
540
  return entries;
@@ -319,7 +559,9 @@ function validateEntries(entries, schema, contentTypeName) {
319
559
  if (value == null) {
320
560
  continue;
321
561
  }
322
- if (def.type === "string" && typeof value !== "string") {
562
+ if (isDateFormat(def.format) && typeof value === "string" && !isCoercedDate(value)) {
563
+ 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.`);
564
+ } else if (def.type === "string" && typeof value !== "string") {
323
565
  console.warn(`Content validation: "${contentTypeName}/${entry.id}" field "${field}" expected string, got ${typeof value}`);
324
566
  } else if (def.type === "number" && typeof value !== "number") {
325
567
  console.warn(`Content validation: "${contentTypeName}/${entry.id}" field "${field}" expected number, got ${typeof value}`);
@@ -389,12 +631,12 @@ function resolveContentTypeRefs(contentTypes, section) {
389
631
  class Content {
390
632
  static async projectData(sectionValue, ctx) {
391
633
  const section = sectionValue ?? {};
392
- const data = await loadContentSection(section, ctx.root, ctx.registry.formats);
634
+ const data = await loadContentSection(section, ctx.root, ctx.registry.formats, ctx.projectConfig);
393
635
  resolveContentTypeRefs(data, section);
394
636
  return data;
395
637
  }
396
638
  static assets(sectionValue, ctx) {
397
- return contentAssetMounts(sectionValue ?? {}, ctx.root);
639
+ return contentAssetMounts(sectionValue ?? {}, ctx.root, ctx.projectConfig);
398
640
  }
399
641
  static async resolvePaths(pathsDef, ctx) {
400
642
  const entries = ctx.data.get(pathsDef.contentType);
@@ -404,17 +646,33 @@ class Content {
404
646
  }
405
647
  const param = pathsDef.param ?? "slug";
406
648
  const field = pathsDef.field ?? "id";
407
- return entries.map((entry) => ({
408
- [param]: field === "id" ? entry.id : entry.data[field] ?? entry.id
409
- })).filter((p) => p[param]);
649
+ const localized = entries.some((entry) => entry._meta?.locale !== undefined);
650
+ const wanted = ctx.locale;
651
+ const scoped = localized && typeof wanted === "string" ? entries.filter((entry) => entry._meta?.locale === wanted) : entries;
652
+ const paths = [];
653
+ for (const entry of scoped) {
654
+ const value = field === "id" ? entry.id : entry.data[field] ?? entry.id;
655
+ if (!value) {
656
+ continue;
657
+ }
658
+ const pathEntry = { [param]: value };
659
+ if (entry._meta !== undefined) {
660
+ pathEntry._meta = entry._meta;
661
+ }
662
+ paths.push(pathEntry);
663
+ }
664
+ return paths;
410
665
  }
411
666
  }
412
667
  export {
413
- rewriteEntryAssets,
414
- resolveContentTypeRefs,
415
- loadContentSection,
416
- loadContentConfig,
417
- getContentTypeElements,
668
+ Content,
669
+ LOCALE_PLACEHOLDER,
418
670
  contentAssetMounts,
419
- Content
671
+ getContentTypeElements,
672
+ loadContentConfig,
673
+ loadContentSection,
674
+ localeSource,
675
+ localesForExpansion,
676
+ resolveContentTypeRefs,
677
+ rewriteEntryAssets
420
678
  };
package/dist/content.js CHANGED
@@ -19,12 +19,14 @@ var __toESM = (mod, isNodeMode, target) => {
19
19
  }
20
20
  target = mod != null ? __create(__getProtoOf(mod)) : {};
21
21
  const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
22
- for (let key of __getOwnPropNames(mod))
23
- if (!__hasOwnProp.call(to, key))
24
- __defProp(to, key, {
25
- get: __accessProp.bind(mod, key),
26
- enumerable: true
27
- });
22
+ if (mod && typeof mod === "object" || typeof mod === "function") {
23
+ for (let key of __getOwnPropNames(mod))
24
+ if (!__hasOwnProp.call(to, key))
25
+ __defProp(to, key, {
26
+ get: __accessProp.bind(mod, key),
27
+ enumerable: true
28
+ });
29
+ }
28
30
  if (canCache)
29
31
  cache.set(mod, to);
30
32
  return to;
@@ -46,6 +48,98 @@ var __export = (target, all) => {
46
48
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
47
49
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
48
50
 
51
+ // src/dates.ts
52
+ var DATE_FORMATS = ["date", "date-time"];
53
+ function isDateFormat(format) {
54
+ return typeof format === "string" && DATE_FORMATS.includes(format);
55
+ }
56
+ var DATE_ONLY = /^\d{4}-\d{2}-\d{2}$/;
57
+ var RFC_3339 = /^\d{4}-\d{2}-\d{2}[Tt ]\d{2}:\d{2}(:\d{2}(\.\d+)?)?([Zz]|[+-]\d{2}:\d{2})?$/;
58
+ function pad(n, width = 2) {
59
+ return String(n).padStart(width, "0");
60
+ }
61
+ function toDateOnly(d) {
62
+ return `${pad(d.getUTCFullYear(), 4)}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())}`;
63
+ }
64
+ function toInstant(d) {
65
+ return `${toDateOnly(d)}T${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())}:${pad(d.getUTCSeconds())}Z`;
66
+ }
67
+ function parseDateValue(value, format) {
68
+ if (value instanceof Date) {
69
+ return Number.isNaN(value.getTime()) ? null : format === "date" ? toDateOnly(value) : toInstant(value);
70
+ }
71
+ if (typeof value !== "string") {
72
+ return null;
73
+ }
74
+ const text = value.trim();
75
+ if (text === "") {
76
+ return null;
77
+ }
78
+ if (DATE_ONLY.test(text)) {
79
+ const d = new Date(`${text}T00:00:00Z`);
80
+ if (Number.isNaN(d.getTime())) {
81
+ return null;
82
+ }
83
+ return format === "date" ? text : toInstant(d);
84
+ }
85
+ if (RFC_3339.test(text)) {
86
+ const normalized = /[Zz]|[+-]\d{2}:\d{2}$/.test(text) ? text : `${text.replace(" ", "T")}Z`;
87
+ const d = new Date(normalized);
88
+ if (Number.isNaN(d.getTime())) {
89
+ return null;
90
+ }
91
+ return format === "date" ? toDateOnly(d) : toInstant(d);
92
+ }
93
+ return null;
94
+ }
95
+ function isCoercedDate(value) {
96
+ return DATE_ONLY.test(value) || RFC_3339.test(value);
97
+ }
98
+ function coerceEntryDates(entries, schema, contentTypeName) {
99
+ const warnings = [];
100
+ const properties = schema?.properties;
101
+ if (!properties) {
102
+ return warnings;
103
+ }
104
+ const dateFields = Object.entries(properties).map(([field, def]) => [field, def.format]).filter((pair) => isDateFormat(pair[1]));
105
+ if (dateFields.length === 0) {
106
+ return warnings;
107
+ }
108
+ for (const entry of entries) {
109
+ for (const [field, format] of dateFields) {
110
+ const raw = entry.data[field];
111
+ if (raw === undefined || raw === null || raw === "") {
112
+ continue;
113
+ }
114
+ const coerced = parseDateValue(raw, format);
115
+ if (coerced === null) {
116
+ warnings.push({
117
+ entryId: entry.id,
118
+ field,
119
+ message: `Content dates: "${contentTypeName}/${entry.id}" field "${field}" is ` + `${JSON.stringify(raw)}, which is not an unambiguous ${format}. Write it as ` + `${format === "date" ? "YYYY-MM-DD" : "YYYY-MM-DDTHH:MM:SSZ"} — a form like ` + `"03/04/2025" means two different days depending on who reads it, so it is left as ` + `authored rather than guessed.`,
120
+ value: raw
121
+ });
122
+ continue;
123
+ }
124
+ if (coerced !== raw) {
125
+ entry._meta ??= {};
126
+ entry._meta.rawDates ??= {};
127
+ entry._meta.rawDates[field] = raw;
128
+ }
129
+ entry.data[field] = coerced;
130
+ }
131
+ }
132
+ return warnings;
133
+ }
134
+ function parseComparable(a, b) {
135
+ const aDate = typeof a === "string" && (DATE_ONLY.test(a) || RFC_3339.test(a));
136
+ const bDate = typeof b === "string" && (DATE_ONLY.test(b) || RFC_3339.test(b));
137
+ if (aDate && bDate) {
138
+ return [a, b];
139
+ }
140
+ return [Number(a), Number(b)];
141
+ }
142
+
49
143
  // src/content.ts
50
144
  function evaluateFilterRule(rule, entry) {
51
145
  const actual = rule.field === "id" ? entry.id : entry.data[rule.field];
@@ -75,16 +169,20 @@ function evaluateFilterRule(rule, entry) {
75
169
  return typeof actual === "string" && !actual.includes(String(rule.value ?? ""));
76
170
  }
77
171
  case ">": {
78
- return Number(actual) > Number(rule.value);
172
+ const [a, b] = parseComparable(actual, rule.value);
173
+ return a > b;
79
174
  }
80
175
  case "<": {
81
- return Number(actual) < Number(rule.value);
176
+ const [a, b] = parseComparable(actual, rule.value);
177
+ return a < b;
82
178
  }
83
179
  case ">=": {
84
- return Number(actual) >= Number(rule.value);
180
+ const [a, b] = parseComparable(actual, rule.value);
181
+ return a >= b;
85
182
  }
86
183
  case "<=": {
87
- return Number(actual) <= Number(rule.value);
184
+ const [a, b] = parseComparable(actual, rule.value);
185
+ return a <= b;
88
186
  }
89
187
  default: {
90
188
  return true;
@@ -175,16 +273,19 @@ class ContentEntry {
175
273
  if (!resolvedId) {
176
274
  return null;
177
275
  }
276
+ const wanted = _document?.route?.locale;
277
+ const localized = entries.some((e) => e._meta?.locale !== undefined);
278
+ const scoped = localized && typeof wanted === "string" ? entries.filter((e) => e._meta?.locale === wanted) : entries;
178
279
  if (field && field !== "id") {
179
- return entries.find((e) => e.data[field] === resolvedId) ?? null;
280
+ return scoped.find((e) => e.data[field] === resolvedId) ?? null;
180
281
  }
181
- return findEntry(entries, resolvedId);
282
+ return findEntry(scoped, resolvedId);
182
283
  }
183
284
  }
184
285
  export {
185
- queryContentType,
186
- findEntry,
187
- evaluateFilterRule,
286
+ ContentCollection,
188
287
  ContentEntry,
189
- ContentCollection
288
+ evaluateFilterRule,
289
+ findEntry,
290
+ queryContentType
190
291
  };
package/dist/csv.js CHANGED
@@ -19,12 +19,14 @@ var __toESM = (mod, isNodeMode, target) => {
19
19
  }
20
20
  target = mod != null ? __create(__getProtoOf(mod)) : {};
21
21
  const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
22
- for (let key of __getOwnPropNames(mod))
23
- if (!__hasOwnProp.call(to, key))
24
- __defProp(to, key, {
25
- get: __accessProp.bind(mod, key),
26
- enumerable: true
27
- });
22
+ if (mod && typeof mod === "object" || typeof mod === "function") {
23
+ for (let key of __getOwnPropNames(mod))
24
+ if (!__hasOwnProp.call(to, key))
25
+ __defProp(to, key, {
26
+ get: __accessProp.bind(mod, key),
27
+ enumerable: true
28
+ });
29
+ }
28
30
  if (canCache)
29
31
  cache.set(mod, to);
30
32
  return to;
@@ -187,7 +189,7 @@ class Csv {
187
189
  }
188
190
  }
189
191
  export {
190
- parseCSV,
192
+ Csv,
191
193
  coerceCSVRows,
192
- Csv
194
+ parseCSV
193
195
  };