@nuasite/cli 0.49.3 → 0.50.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -22517,7 +22517,14 @@ function parseConfigSource(source, _sourcePath) {
22517
22517
  const loaderBase = loaderOptions.base;
22518
22518
  const cmsProperty = decl.properties.find((p) => p.type === "ObjectProperty" && propertyKeyName(p.key) === "cms");
22519
22519
  const layout = cmsProperty?.type === "ObjectProperty" ? parseCmsLayout(cmsProperty.value, bindings) : undefined;
22520
- const pathname = cmsProperty?.type === "ObjectProperty" ? parseCmsPathname(cmsProperty.value, bindings) : undefined;
22520
+ const declaredPathname = cmsProperty?.type === "ObjectProperty" ? parseCmsPathname(cmsProperty.value, bindings) : undefined;
22521
+ const titleField = cmsProperty?.type === "ObjectProperty" ? parseCmsTitleField(cmsProperty.value, bindings) : undefined;
22522
+ const fragment = cmsProperty?.type === "ObjectProperty" ? parseCmsFragment(cmsProperty.value, bindings) : undefined;
22523
+ const previewOf = cmsProperty?.type === "ObjectProperty" ? parseCmsPreviewOf(cmsProperty.value, bindings) : undefined;
22524
+ if (fragment && declaredPathname) {
22525
+ console.warn(`[cms] collection "${collectionName}": \`cms.fragment\` and \`cms.pathname\` are mutually exclusive \u2014 a fragment collection has no page of its own, so the \`pathname\` rule is ignored`);
22526
+ }
22527
+ const pathname = fragment ? undefined : declaredPathname;
22521
22528
  const schemaProperty = decl.properties.find((p) => p.type === "ObjectProperty" && propertyKeyName(p.key) === "schema");
22522
22529
  if (!schemaProperty || schemaProperty.type !== "ObjectProperty") {
22523
22530
  if (!loaderPattern)
@@ -22528,7 +22535,10 @@ function parseConfigSource(source, _sourcePath) {
22528
22535
  loaderPattern,
22529
22536
  loaderBase,
22530
22537
  layout,
22531
- pathname
22538
+ pathname,
22539
+ titleField,
22540
+ fragment,
22541
+ previewOf
22532
22542
  });
22533
22543
  continue;
22534
22544
  }
@@ -22542,7 +22552,10 @@ function parseConfigSource(source, _sourcePath) {
22542
22552
  loaderPattern,
22543
22553
  loaderBase,
22544
22554
  layout,
22545
- pathname
22555
+ pathname,
22556
+ titleField,
22557
+ fragment,
22558
+ previewOf
22546
22559
  });
22547
22560
  continue;
22548
22561
  }
@@ -22552,7 +22565,10 @@ function parseConfigSource(source, _sourcePath) {
22552
22565
  loaderPattern,
22553
22566
  loaderBase,
22554
22567
  layout,
22555
- pathname
22568
+ pathname,
22569
+ titleField,
22570
+ fragment,
22571
+ previewOf
22556
22572
  });
22557
22573
  }
22558
22574
  return result;
@@ -22635,6 +22651,40 @@ function parseCmsPathname(node, bindings) {
22635
22651
  }
22636
22652
  return spec.length > 0 ? spec : undefined;
22637
22653
  }
22654
+ function parseCmsTitleField(node, bindings) {
22655
+ const resolved = resolveExpression(node, bindings);
22656
+ if (resolved.type !== "ObjectExpression")
22657
+ return;
22658
+ const titleFieldProp = resolved.properties.find((p) => p.type === "ObjectProperty" && propertyKeyName(p.key) === "titleField");
22659
+ if (!titleFieldProp || titleFieldProp.type !== "ObjectProperty")
22660
+ return;
22661
+ const value = resolveExpression(titleFieldProp.value, bindings);
22662
+ if (value.type !== "StringLiteral" || value.value === "")
22663
+ return;
22664
+ return value.value;
22665
+ }
22666
+ function parseCmsFragment(node, bindings) {
22667
+ const resolved = resolveExpression(node, bindings);
22668
+ if (resolved.type !== "ObjectExpression")
22669
+ return;
22670
+ const fragmentProp = resolved.properties.find((p) => p.type === "ObjectProperty" && propertyKeyName(p.key) === "fragment");
22671
+ if (!fragmentProp || fragmentProp.type !== "ObjectProperty")
22672
+ return;
22673
+ const value = resolveExpression(fragmentProp.value, bindings);
22674
+ return value.type === "BooleanLiteral" && value.value ? true : undefined;
22675
+ }
22676
+ function parseCmsPreviewOf(node, bindings) {
22677
+ const resolved = resolveExpression(node, bindings);
22678
+ if (resolved.type !== "ObjectExpression")
22679
+ return;
22680
+ const previewOfProp = resolved.properties.find((p) => p.type === "ObjectProperty" && propertyKeyName(p.key) === "previewOf");
22681
+ if (!previewOfProp || previewOfProp.type !== "ObjectProperty")
22682
+ return;
22683
+ const value = resolveExpression(previewOfProp.value, bindings);
22684
+ if (value.type !== "StringLiteral" || value.value === "")
22685
+ return;
22686
+ return value.value;
22687
+ }
22638
22688
  function parsePathnameSegment(node) {
22639
22689
  if (node.type !== "ObjectExpression")
22640
22690
  return null;
@@ -22838,6 +22888,12 @@ function analyzeBaseCall(node, field, bindings) {
22838
22888
  field.options = options;
22839
22889
  }
22840
22890
  }
22891
+ const hintsArg = node.arguments[1];
22892
+ if (hintsArg?.type === "ObjectExpression") {
22893
+ const layout = parseFieldLayoutFromObject(hintsArg);
22894
+ if (layout)
22895
+ field.layout = layout;
22896
+ }
22841
22897
  return;
22842
22898
  }
22843
22899
  if ((ns === "z" || ns === "n") && fn === "object") {
@@ -23030,6 +23086,18 @@ import path from "path";
23030
23086
  function normalizeFieldName(name) {
23031
23087
  return name.toLowerCase().replace(/[_-]/g, "");
23032
23088
  }
23089
+ function deriveEntryTitle(data, titleField) {
23090
+ if (titleField) {
23091
+ const declared = data[titleField];
23092
+ return typeof declared === "string" && declared !== "" ? declared : undefined;
23093
+ }
23094
+ for (const key of TITLE_FALLBACK_FIELDS) {
23095
+ const value = data[key];
23096
+ if (typeof value === "string" && value !== "")
23097
+ return value;
23098
+ }
23099
+ return;
23100
+ }
23033
23101
  function extractFrontmatterBlock(content) {
23034
23102
  const match = content.match(FRONTMATTER_PATTERN);
23035
23103
  return match?.[1] ?? null;
@@ -23263,8 +23331,9 @@ async function buildCollectionDefinition(fs, basePath, sources, collectionName,
23263
23331
  sourcePath: path.join(sourceBasePath, source.relPath)
23264
23332
  };
23265
23333
  if (frontmatter) {
23266
- if (typeof frontmatter.title === "string") {
23267
- entryInfo.title = frontmatter.title;
23334
+ const title = deriveEntryTitle(frontmatter);
23335
+ if (title !== undefined) {
23336
+ entryInfo.title = title;
23268
23337
  }
23269
23338
  if (typeof frontmatter.draft === "boolean" && frontmatter.draft) {
23270
23339
  entryInfo.draft = true;
@@ -23307,7 +23376,7 @@ async function buildDataCollectionDefinition(fs, basePath, sources, collectionNa
23307
23376
  }
23308
23377
  if (!data || typeof data !== "object")
23309
23378
  continue;
23310
- const title = typeof data.name === "string" ? data.name : typeof data.title === "string" ? data.title : undefined;
23379
+ const title = deriveEntryTitle(data);
23311
23380
  entryInfos.push({
23312
23381
  slug: source.slug,
23313
23382
  title,
@@ -23389,8 +23458,25 @@ function applyParsedConfig(collections, parsed) {
23389
23458
  def.layout = parsedColl.layout;
23390
23459
  if (parsedColl.pathname)
23391
23460
  def.pathname = parsedColl.pathname;
23461
+ if (parsedColl.fragment) {
23462
+ def.fragment = parsedColl.fragment;
23463
+ if (parsedColl.previewOf)
23464
+ def.previewOf = parsedColl.previewOf;
23465
+ }
23466
+ if (parsedColl.titleField) {
23467
+ def.titleField = parsedColl.titleField;
23468
+ applyCollectionTitleField(def, parsedColl.titleField);
23469
+ }
23392
23470
  }
23393
23471
  }
23472
+ function applyCollectionTitleField(def, titleField) {
23473
+ if (!def.entries)
23474
+ return;
23475
+ for (const entry of def.entries) {
23476
+ entry.title = entry.data ? deriveEntryTitle(entry.data, titleField) : undefined;
23477
+ }
23478
+ def.entries.sort((a, b) => (a.title ?? a.slug).localeCompare(b.title ?? b.slug));
23479
+ }
23394
23480
  function applyParsedFieldLayout(field, pf) {
23395
23481
  const layout = pf.layout;
23396
23482
  if (!layout)
@@ -23413,8 +23499,10 @@ function applyParsedFieldLayout(field, pf) {
23413
23499
  function applyParsedFieldOverrides(field, pf) {
23414
23500
  if (pf.type) {
23415
23501
  field.type = pf.type;
23416
- if (pf.options)
23502
+ if (pf.options) {
23417
23503
  field.options = pf.options;
23504
+ field.optionsClosed = true;
23505
+ }
23418
23506
  }
23419
23507
  if (pf.itemType)
23420
23508
  field.itemType = pf.itemType;
@@ -23442,8 +23530,10 @@ function parsedFieldToFieldDefinition(pf) {
23442
23530
  type: pf.type ?? (pf.fields ? "object" : "text"),
23443
23531
  required: pf.required
23444
23532
  };
23445
- if (pf.options)
23533
+ if (pf.options) {
23446
23534
  fd.options = pf.options;
23535
+ fd.optionsClosed = true;
23536
+ }
23447
23537
  if (pf.itemType)
23448
23538
  fd.itemType = pf.itemType;
23449
23539
  if (pf.hints)
@@ -23679,6 +23769,26 @@ async function scanDataCollection(fs, collectionPath, collectionName, contentDir
23679
23769
  }
23680
23770
  return await buildDataCollectionDefinition(fs, collectionPath, sources, collectionName, contentDir);
23681
23771
  }
23772
+ function normalizeBasePath(basePath) {
23773
+ return path.normalize(basePath.replace(/^\.[/\\]+/, "")).replace(/[/\\]+$/, "");
23774
+ }
23775
+ function patternCoversWholeCollection(pattern, definition) {
23776
+ const match = pattern.trim().replace(/^\.[/\\]+/, "").match(WHOLE_DIRECTORY_PATTERN);
23777
+ if (!match)
23778
+ return false;
23779
+ const [, braceGroup, singleExtension] = match;
23780
+ if (braceGroup === undefined && singleExtension === undefined)
23781
+ return true;
23782
+ const patternExtensions = new Set((braceGroup !== undefined ? braceGroup.split(",") : [singleExtension]).map((ext) => ext.trim().replace(/^\./, "").toLowerCase()).filter(Boolean));
23783
+ const scannedExtensions = new Set((definition.entries ?? []).map((entry) => path.extname(entry.sourcePath).slice(1).toLowerCase()).filter(Boolean));
23784
+ if (scannedExtensions.size === 0)
23785
+ return false;
23786
+ for (const ext of scannedExtensions) {
23787
+ if (!patternExtensions.has(ext))
23788
+ return false;
23789
+ }
23790
+ return true;
23791
+ }
23682
23792
  async function scanCollections(fs, contentDir = "src/content", parseCache = new Map) {
23683
23793
  const collections = {};
23684
23794
  const entries = await fs.list(contentDir);
@@ -23695,11 +23805,29 @@ async function scanCollections(fs, contentDir = "src/content", parseCache = new
23695
23805
  });
23696
23806
  await Promise.all(scanPromises);
23697
23807
  const parsed = await parseContentConfig(fs, parseCache);
23808
+ const scannedNameByBasePath = new Map;
23809
+ for (const [name, definition] of Object.entries(collections)) {
23810
+ scannedNameByBasePath.set(normalizeBasePath(definition.path), name);
23811
+ }
23812
+ const rekeyedScannedNames = new Map;
23698
23813
  for (const [collectionName, parsedCollection] of parsed) {
23699
23814
  if (collections[collectionName])
23700
23815
  continue;
23701
23816
  if (!parsedCollection.loaderBase || !parsedCollection.loaderPattern)
23702
23817
  continue;
23818
+ const scannedName = scannedNameByBasePath.get(normalizeBasePath(parsedCollection.loaderBase));
23819
+ const scannedDefinition = scannedName ? collections[scannedName] : undefined;
23820
+ if (scannedName && scannedDefinition && patternCoversWholeCollection(parsedCollection.loaderPattern, scannedDefinition)) {
23821
+ delete collections[scannedName];
23822
+ scannedDefinition.name = collectionName;
23823
+ for (const other of Object.values(collections)) {
23824
+ if (other.parentCollection === scannedName)
23825
+ other.parentCollection = collectionName;
23826
+ }
23827
+ collections[collectionName] = scannedDefinition;
23828
+ rekeyedScannedNames.set(scannedName, collectionName);
23829
+ continue;
23830
+ }
23703
23831
  let definition;
23704
23832
  try {
23705
23833
  definition = await scanGlobCollection(fs, collectionName, parsedCollection.loaderBase, parsedCollection.loaderPattern, contentDir);
@@ -23710,8 +23838,9 @@ async function scanCollections(fs, contentDir = "src/content", parseCache = new
23710
23838
  if (!definition)
23711
23839
  continue;
23712
23840
  const baseName = parsedCollection.loaderBase.replace(/[/\\]+$/, "").split(/[/\\]/).pop();
23713
- if (baseName && baseName !== collectionName && collections[baseName]) {
23714
- definition.parentCollection = baseName;
23841
+ const parentName = !baseName ? undefined : collections[baseName] ? baseName : rekeyedScannedNames.get(baseName);
23842
+ if (parentName && parentName !== collectionName) {
23843
+ definition.parentCollection = parentName;
23715
23844
  }
23716
23845
  collections[collectionName] = definition;
23717
23846
  }
@@ -23741,7 +23870,7 @@ function warnOnPathnameCollisions(collections) {
23741
23870
  }
23742
23871
  }
23743
23872
  }
23744
- var import_yaml, DATE_PATTERN, URL_PATTERN, IMAGE_EXTENSIONS, MAX_SELECT_OPTIONS = 10, TEXTAREA_MIN_LENGTH = 200, SIDEBAR_FIELD_NAMES, DIRECTIVE_PATTERN, FREE_TEXT_FIELD_NAMES, PUBLISH_TOGGLE_NAMES, PUBLISH_DATE_NAMES, FRONTMATTER_PATTERN, MAX_NESTED_FIELD_DEPTH = 16, HREF_SUFFIXES;
23873
+ var import_yaml, DATE_PATTERN, URL_PATTERN, IMAGE_EXTENSIONS, MAX_SELECT_OPTIONS = 10, TEXTAREA_MIN_LENGTH = 200, SIDEBAR_FIELD_NAMES, DIRECTIVE_PATTERN, FREE_TEXT_FIELD_NAMES, PUBLISH_TOGGLE_NAMES, PUBLISH_DATE_NAMES, TITLE_FALLBACK_FIELDS, FRONTMATTER_PATTERN, MAX_NESTED_FIELD_DEPTH = 16, HREF_SUFFIXES, WHOLE_DIRECTORY_PATTERN;
23745
23874
  var init_collection_scanner = __esm(() => {
23746
23875
  init_content_config_ast();
23747
23876
  import_yaml = __toESM(require_dist(), 1);
@@ -23785,8 +23914,10 @@ var init_collection_scanner = __esm(() => {
23785
23914
  "publishedat",
23786
23915
  "datepublished"
23787
23916
  ]);
23917
+ TITLE_FALLBACK_FIELDS = ["title", "name", "label"];
23788
23918
  FRONTMATTER_PATTERN = /^---\r?\n([\s\S]*?)\r?\n---/;
23789
23919
  HREF_SUFFIXES = ["href", "url", "link", "slug", "path"];
23920
+ WHOLE_DIRECTORY_PATTERN = /^(?:\*\*[/\\])*\*(?:\.(?:\{([^{}/\\]*)\}|([A-Za-z0-9]+)))?$/;
23790
23921
  });
23791
23922
 
23792
23923
  // ../cms-core/src/component-registry.ts
@@ -24368,7 +24499,7 @@ var init_scan_cache = __esm(() => {
24368
24499
 
24369
24500
  // ../cms/src/shared.ts
24370
24501
  function slugify2(text) {
24371
- return text.toLowerCase().trim().replace(/[^\w\s\-/]/g, "").replace(/[\s_]+/g, "-").replace(/^[-/]+|[-/]+$/g, "");
24502
+ return text.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().trim().replace(/[^\w\s\-/]/g, "").replace(/[\s_]+/g, "-").replace(/^[-/]+|[-/]+$/g, "");
24372
24503
  }
24373
24504
 
24374
24505
  // ../cms/src/utils.ts