wp-typia 0.24.0 → 0.24.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.
@@ -36337,29 +36337,13 @@ function suggestCloseId(input, candidates, options = {}) {
36337
36337
  return bestCandidate && bestCandidate.distance <= maxDistance ? bestCandidate.id : null;
36338
36338
  }
36339
36339
 
36340
- // ../wp-typia-project-tools/src/runtime/pattern-catalog.ts
36341
- import fs8 from "fs";
36342
- import path11 from "path";
36340
+ // ../wp-typia-project-tools/src/runtime/pattern-catalog-section-roles.ts
36343
36341
  import {
36344
36342
  validateBlockPatternContentNesting
36345
36343
  } from "@wp-typia/block-runtime/metadata-core";
36346
36344
  function createPatternCatalogDiagnostic(diagnostic) {
36347
36345
  return diagnostic;
36348
36346
  }
36349
- function isPatternCatalogScope(value2) {
36350
- return PATTERN_CATALOG_SCOPE_IDS.includes(value2);
36351
- }
36352
- function isSafeRelativePath(value2) {
36353
- return value2.length > 0 && !path11.isAbsolute(value2) && !value2.includes("\\") && !value2.split(/[\\/]+/u).includes("..") && !/[<>:"|?*\u0000-\u001F]/u.test(value2);
36354
- }
36355
- function isPatternContentFilePath(value2) {
36356
- if (!isSafeRelativePath(value2) || !value2.startsWith(PATTERN_CONTENT_FILE_ROOT) || !value2.endsWith(".php")) {
36357
- return false;
36358
- }
36359
- const patternRelativePath = value2.slice(PATTERN_CONTENT_FILE_ROOT.length);
36360
- const segments = patternRelativePath.split("/");
36361
- return (segments.length === 1 || segments.length === 2) && segments.every((segment) => segment.length > 0);
36362
- }
36363
36347
  function normalizeSectionRoleConventionInput(convention = {}) {
36364
36348
  return {
36365
36349
  baseClassName: convention.baseClassName ?? DEFAULT_SECTION_ROLE_CONVENTION.baseClassName,
@@ -36379,7 +36363,7 @@ function createRoleClassNamePattern(pattern) {
36379
36363
  }
36380
36364
  return new RegExp(`^${escapeRegExp2(parts[0] ?? "")}(?<role>\\S*)${escapeRegExp2(parts[1] ?? "")}$`, "u");
36381
36365
  }
36382
- function normalizeSectionRoleConvention(convention = {}) {
36366
+ function normalizePatternCatalogSectionRoleConvention(convention = {}) {
36383
36367
  const normalized = normalizeSectionRoleConventionInput(convention);
36384
36368
  return {
36385
36369
  ...normalized,
@@ -36441,7 +36425,7 @@ function collectSectionRoleMatches(blocks, convention, pathSegments = []) {
36441
36425
  `${block.blockName}[${index}]`
36442
36426
  ];
36443
36427
  const blockPath = blockPathSegments.join(" > ");
36444
- const roles = extractPatternSectionRolesFromAttributes(block.attributes, convention);
36428
+ const roles = extractPatternSectionRolesFromNormalizedAttributes(block.attributes, convention);
36445
36429
  const matches = isSectionWrapperCandidate(block, roles, convention) ? [
36446
36430
  {
36447
36431
  blockName: block.blockName,
@@ -36464,27 +36448,12 @@ function unescapeSerializedBlockCommentJsonQuotes(content) {
36464
36448
  return `<!--${body.replace(/\\"/gu, '"')}-->`;
36465
36449
  });
36466
36450
  }
36467
- function extractPatternSectionRolesFromAttributes(attributes, convention = {}) {
36468
- const normalized = normalizeSectionRoleConvention(convention);
36451
+ function extractPatternSectionRolesFromNormalizedAttributes(attributes, normalized) {
36469
36452
  const classRoles = getClassNameTokens(attributes).map((token) => normalized.roleClassNamePatternRegExp.exec(token)?.groups?.role).filter((role) => typeof role === "string");
36470
36453
  const attributeRoles = normalized.roleAttributePaths.flatMap((pathName) => collectStringValues(getAttributePathValue(attributes, pathName)));
36471
36454
  return uniqueValues([...classRoles, ...attributeRoles]);
36472
36455
  }
36473
- function isValidPatternThumbnailUrl(value2) {
36474
- if (value2.length === 0) {
36475
- return false;
36476
- }
36477
- try {
36478
- const url2 = new URL(value2);
36479
- return url2.protocol === "http:" || url2.protocol === "https:";
36480
- } catch {
36481
- return isSafeRelativePath(value2);
36482
- }
36483
- }
36484
- function resolvePatternCatalogContentFile(pattern) {
36485
- return pattern.contentFile ?? pattern.file;
36486
- }
36487
- function createKnownSectionRoleSet(patterns) {
36456
+ function collectKnownPatternSectionRoles(patterns) {
36488
36457
  return new Set(patterns.map((pattern) => pattern.sectionRole).filter((sectionRole) => typeof sectionRole === "string" && PATTERN_SECTION_ROLE_PATTERN.test(sectionRole)));
36489
36458
  }
36490
36459
  function validatePatternContentSectionRoles({
@@ -36576,26 +36545,72 @@ function validatePatternContentSectionRoles({
36576
36545
  }
36577
36546
  return diagnostics;
36578
36547
  }
36548
+ var PATTERN_SECTION_ROLE_PATTERN, DEFAULT_SECTION_ROLE_CONVENTION;
36549
+ var init_pattern_catalog_section_roles = __esm(() => {
36550
+ PATTERN_SECTION_ROLE_PATTERN = /^[a-z][a-z0-9-]*$/u;
36551
+ DEFAULT_SECTION_ROLE_CONVENTION = {
36552
+ baseClassName: "section",
36553
+ requireUniqueFullPatternRoles: false,
36554
+ roleAttributePaths: ["metadata.sectionRole"],
36555
+ roleClassNamePattern: "section--{role}",
36556
+ wrapperBlockName: "core/group"
36557
+ };
36558
+ });
36559
+
36560
+ // ../wp-typia-project-tools/src/runtime/pattern-catalog.ts
36561
+ import fs8 from "fs";
36562
+ import path11 from "path";
36563
+ function createPatternCatalogDiagnostic2(diagnostic) {
36564
+ return diagnostic;
36565
+ }
36566
+ function isPatternCatalogScope(value2) {
36567
+ return PATTERN_CATALOG_SCOPE_IDS.includes(value2);
36568
+ }
36569
+ function isSafeRelativePath(value2) {
36570
+ return value2.length > 0 && !path11.isAbsolute(value2) && !value2.includes("\\") && !value2.split(/[\\/]+/u).includes("..") && !/[<>:"|?*\u0000-\u001F]/u.test(value2);
36571
+ }
36572
+ function isPatternContentFilePath(value2) {
36573
+ if (!isSafeRelativePath(value2) || !value2.startsWith(PATTERN_CONTENT_FILE_ROOT) || !value2.endsWith(".php")) {
36574
+ return false;
36575
+ }
36576
+ const patternRelativePath = value2.slice(PATTERN_CONTENT_FILE_ROOT.length);
36577
+ const segments = patternRelativePath.split("/");
36578
+ return (segments.length === 1 || segments.length === 2) && segments.every((segment) => segment.length > 0);
36579
+ }
36580
+ function isValidPatternThumbnailUrl(value2) {
36581
+ if (value2.length === 0) {
36582
+ return false;
36583
+ }
36584
+ try {
36585
+ const url2 = new URL(value2);
36586
+ return url2.protocol === "http:" || url2.protocol === "https:";
36587
+ } catch {
36588
+ return isSafeRelativePath(value2);
36589
+ }
36590
+ }
36591
+ function resolvePatternCatalogContentFile(pattern) {
36592
+ return pattern.contentFile ?? pattern.file;
36593
+ }
36579
36594
  function validatePatternCatalog(patterns, options = {}) {
36580
36595
  const diagnostics = [];
36581
36596
  const seenSlugs = new Map;
36582
36597
  let sectionRoleConvention = null;
36583
36598
  if (options.sectionRoleConvention !== false) {
36584
36599
  try {
36585
- sectionRoleConvention = normalizeSectionRoleConvention(options.sectionRoleConvention);
36600
+ sectionRoleConvention = normalizePatternCatalogSectionRoleConvention(options.sectionRoleConvention);
36586
36601
  } catch (error48) {
36587
- diagnostics.push(createPatternCatalogDiagnostic({
36602
+ diagnostics.push(createPatternCatalogDiagnostic2({
36588
36603
  code: "invalid-pattern-section-role-convention",
36589
36604
  message: `sectionRoleConvention.roleClassNamePattern is invalid: ${error48 instanceof Error ? error48.message : String(error48)}`,
36590
36605
  severity: "error"
36591
36606
  }));
36592
36607
  }
36593
36608
  }
36594
- const knownSectionRoles = createKnownSectionRoleSet(patterns);
36609
+ const knownSectionRoles = collectKnownPatternSectionRoles(patterns);
36595
36610
  for (const [index, pattern] of patterns.entries()) {
36596
36611
  const label = pattern.slug || `PATTERNS[${index}]`;
36597
36612
  if (!PATTERN_SLUG_PATTERN.test(pattern.slug)) {
36598
- diagnostics.push(createPatternCatalogDiagnostic({
36613
+ diagnostics.push(createPatternCatalogDiagnostic2({
36599
36614
  code: "invalid-pattern-slug",
36600
36615
  message: `${label}: slug must start with a lowercase letter and contain only lowercase letters, numbers, and hyphens.`,
36601
36616
  patternSlug: pattern.slug,
@@ -36604,7 +36619,7 @@ function validatePatternCatalog(patterns, options = {}) {
36604
36619
  }
36605
36620
  const previousIndex = seenSlugs.get(pattern.slug);
36606
36621
  if (previousIndex !== undefined) {
36607
- diagnostics.push(createPatternCatalogDiagnostic({
36622
+ diagnostics.push(createPatternCatalogDiagnostic2({
36608
36623
  code: "duplicate-pattern-slug",
36609
36624
  message: `${label}: duplicate slug already declared at PATTERNS[${previousIndex}].`,
36610
36625
  patternSlug: pattern.slug,
@@ -36615,7 +36630,7 @@ function validatePatternCatalog(patterns, options = {}) {
36615
36630
  }
36616
36631
  const scope = pattern.scope ?? "full";
36617
36632
  if (!isPatternCatalogScope(scope)) {
36618
- diagnostics.push(createPatternCatalogDiagnostic({
36633
+ diagnostics.push(createPatternCatalogDiagnostic2({
36619
36634
  code: "invalid-pattern-scope",
36620
36635
  message: `${label}: scope must be one of ${PATTERN_CATALOG_SCOPE_IDS.join(", ")}.`,
36621
36636
  patternSlug: pattern.slug,
@@ -36623,7 +36638,7 @@ function validatePatternCatalog(patterns, options = {}) {
36623
36638
  }));
36624
36639
  }
36625
36640
  if (scope === "section" && !pattern.sectionRole) {
36626
- diagnostics.push(createPatternCatalogDiagnostic({
36641
+ diagnostics.push(createPatternCatalogDiagnostic2({
36627
36642
  code: "missing-pattern-section-role",
36628
36643
  message: `${label}: section-scoped patterns must declare sectionRole.`,
36629
36644
  patternSlug: pattern.slug,
@@ -36631,7 +36646,7 @@ function validatePatternCatalog(patterns, options = {}) {
36631
36646
  }));
36632
36647
  }
36633
36648
  if (pattern.sectionRole !== undefined && !PATTERN_SECTION_ROLE_PATTERN.test(pattern.sectionRole)) {
36634
- diagnostics.push(createPatternCatalogDiagnostic({
36649
+ diagnostics.push(createPatternCatalogDiagnostic2({
36635
36650
  code: "invalid-pattern-section-role",
36636
36651
  message: `${label}: sectionRole must start with a lowercase letter and contain only lowercase letters, numbers, and hyphens.`,
36637
36652
  patternSlug: pattern.slug,
@@ -36640,7 +36655,7 @@ function validatePatternCatalog(patterns, options = {}) {
36640
36655
  }
36641
36656
  for (const [tagIndex, tag] of (pattern.tags ?? []).entries()) {
36642
36657
  if (!PATTERN_TAG_PATTERN.test(tag)) {
36643
- diagnostics.push(createPatternCatalogDiagnostic({
36658
+ diagnostics.push(createPatternCatalogDiagnostic2({
36644
36659
  code: "invalid-pattern-tag",
36645
36660
  message: `${label}: tags[${tagIndex}] must contain only lowercase letters, numbers, and hyphens.`,
36646
36661
  patternSlug: pattern.slug,
@@ -36649,7 +36664,7 @@ function validatePatternCatalog(patterns, options = {}) {
36649
36664
  }
36650
36665
  }
36651
36666
  if (pattern.thumbnailUrl !== undefined && !isValidPatternThumbnailUrl(pattern.thumbnailUrl)) {
36652
- diagnostics.push(createPatternCatalogDiagnostic({
36667
+ diagnostics.push(createPatternCatalogDiagnostic2({
36653
36668
  code: "invalid-pattern-thumbnail-url",
36654
36669
  message: `${label}: thumbnailUrl must be an http(s) URL or safe relative project path.`,
36655
36670
  patternSlug: pattern.slug,
@@ -36658,7 +36673,7 @@ function validatePatternCatalog(patterns, options = {}) {
36658
36673
  }
36659
36674
  const contentFile = resolvePatternCatalogContentFile(pattern);
36660
36675
  if (!contentFile) {
36661
- diagnostics.push(createPatternCatalogDiagnostic({
36676
+ diagnostics.push(createPatternCatalogDiagnostic2({
36662
36677
  code: "missing-pattern-content-file",
36663
36678
  message: `${label}: contentFile or legacy file must point at the pattern PHP file.`,
36664
36679
  patternSlug: pattern.slug,
@@ -36667,7 +36682,7 @@ function validatePatternCatalog(patterns, options = {}) {
36667
36682
  continue;
36668
36683
  }
36669
36684
  if (!isPatternContentFilePath(contentFile)) {
36670
- diagnostics.push(createPatternCatalogDiagnostic({
36685
+ diagnostics.push(createPatternCatalogDiagnostic2({
36671
36686
  code: "invalid-pattern-content-file",
36672
36687
  message: `${label}: contentFile must be a safe relative project path directly under src/patterns/ or one nested directory under src/patterns/ and end in .php.`,
36673
36688
  patternSlug: pattern.slug,
@@ -36680,7 +36695,7 @@ function validatePatternCatalog(patterns, options = {}) {
36680
36695
  }
36681
36696
  const absoluteContentFile = path11.join(options.projectDir, contentFile);
36682
36697
  if (!fs8.existsSync(absoluteContentFile)) {
36683
- diagnostics.push(createPatternCatalogDiagnostic({
36698
+ diagnostics.push(createPatternCatalogDiagnostic2({
36684
36699
  code: "missing-pattern-content-file",
36685
36700
  message: `${label}: missing pattern content file ${contentFile}.`,
36686
36701
  patternSlug: pattern.slug,
@@ -36693,7 +36708,7 @@ function validatePatternCatalog(patterns, options = {}) {
36693
36708
  try {
36694
36709
  content = fs8.readFileSync(absoluteContentFile, "utf8");
36695
36710
  } catch (error48) {
36696
- diagnostics.push(createPatternCatalogDiagnostic({
36711
+ diagnostics.push(createPatternCatalogDiagnostic2({
36697
36712
  code: "invalid-pattern-content-file",
36698
36713
  message: `${label}: failed to read pattern content file ${contentFile}: ${error48 instanceof Error ? error48.message : String(error48)}.`,
36699
36714
  patternSlug: pattern.slug,
@@ -36723,19 +36738,13 @@ function formatPatternCatalogDiagnostics(diagnostics) {
36723
36738
  return diagnostics.map((diagnostic) => `- [${diagnostic.code}] ${diagnostic.message}`).join(`
36724
36739
  `);
36725
36740
  }
36726
- var PATTERN_CATALOG_SCOPE_IDS, PATTERN_SLUG_PATTERN, PATTERN_SECTION_ROLE_PATTERN, PATTERN_TAG_PATTERN, PATTERN_CONTENT_FILE_ROOT = "src/patterns/", DEFAULT_SECTION_ROLE_CONVENTION;
36741
+ var PATTERN_CATALOG_SCOPE_IDS, PATTERN_SLUG_PATTERN, PATTERN_TAG_PATTERN, PATTERN_CONTENT_FILE_ROOT = "src/patterns/";
36727
36742
  var init_pattern_catalog = __esm(() => {
36743
+ init_pattern_catalog_section_roles();
36744
+ init_pattern_catalog_section_roles();
36728
36745
  PATTERN_CATALOG_SCOPE_IDS = ["full", "section"];
36729
36746
  PATTERN_SLUG_PATTERN = /^[a-z][a-z0-9-]*$/u;
36730
- PATTERN_SECTION_ROLE_PATTERN = PATTERN_SLUG_PATTERN;
36731
36747
  PATTERN_TAG_PATTERN = /^[a-z0-9][a-z0-9-]*$/u;
36732
- DEFAULT_SECTION_ROLE_CONVENTION = {
36733
- baseClassName: "section",
36734
- requireUniqueFullPatternRoles: false,
36735
- roleAttributePaths: ["metadata.sectionRole"],
36736
- roleClassNamePattern: "section--{role}",
36737
- wrapperBlockName: "core/group"
36738
- };
36739
36748
  });
36740
36749
 
36741
36750
  // ../wp-typia-project-tools/src/runtime/cli-add-types.ts
@@ -37558,7 +37567,7 @@ function formatAddHelpText() {
37558
37567
  wp-typia add variation <name> --block <block-slug> [--dry-run]
37559
37568
  wp-typia add style <name> --block <block-slug> [--dry-run]
37560
37569
  wp-typia add transform <name> --from <namespace/block> --to <block-slug|namespace/block-slug> [--dry-run]
37561
- wp-typia add pattern <name> [--scope <full|section>] [--section-role <role>] [--tags <tag,...>] [--thumbnail-url <url>] [--dry-run]
37570
+ wp-typia add pattern <name> [--scope <full|section>] [--section-role <role>] [--catalog-title <title>] [--tags <tag,...>|--tag <tag>...] [--thumbnail-url <url>] [--dry-run]
37562
37571
  wp-typia add binding-source <name> [--block <block-slug|namespace/block-slug> --attribute <attribute>] [--from-post-meta|--post-meta <post-meta> [--meta-path <field>]] [--dry-run]
37563
37572
  wp-typia add contract <name> [--type <ExportedTypeName>] [--dry-run]
37564
37573
  wp-typia add rest-resource <name> [--namespace <vendor/v1>] [--methods <${REST_RESOURCE_METHOD_IDS.join(",")}>] [--route-pattern <route-pattern>] [--permission-callback <callback>] [--controller-class <ClassName>] [--controller-extends <BaseClass>] [--dry-run]
@@ -37574,6 +37583,7 @@ Notes:
37574
37583
  Pass \`--dry-run\` to preview the workspace files that would change without writing them.
37575
37584
  Interactive add flows let you choose a template when \`--template\` is omitted; non-interactive runs default to \`basic\`.
37576
37585
  \`add core-variation\` registers editor-side variations for existing core or external blocks without generating block.json or Typia manifests.
37586
+ Unknown \`core/*\` core-variation targets warn instead of failing so newer WordPress core blocks remain scaffoldable; third-party namespaces are allowed without local discovery.
37577
37587
  \`add admin-view\` scaffolds an opt-in DataViews-powered WordPress admin screen under \`src/admin-views/\`.
37578
37588
  Pass \`--source rest-resource:<slug>\` to reuse a list-capable REST resource.
37579
37589
  Pass \`--source core-data:postType/post\` or \`--source core-data:taxonomy/category\` to bind a WordPress-owned entity collection.
@@ -37585,7 +37595,7 @@ Notes:
37585
37595
  \`add variation\` targets an existing block slug from \`scripts/block-config.ts\`.
37586
37596
  \`add style\` registers a Block Styles option for an existing generated block.
37587
37597
  \`add transform\` adds a block-to-block transform into an existing generated block.
37588
- \`add pattern\` scaffolds a namespaced PHP pattern shell under \`src/patterns/full/\` or \`src/patterns/sections/\` and records typed catalog metadata in \`PATTERNS\`.
37598
+ \`add pattern\` scaffolds a namespaced PHP pattern shell under \`src/patterns/full/\` or \`src/patterns/sections/\` and records typed catalog metadata in \`PATTERNS\`; pass \`--catalog-title "Hero Photo"\` to override the generated catalog title, and pass \`--tags hero,landing\` or repeat \`--tag hero --tag landing\` to set catalog tags.
37589
37599
  \`add binding-source\` scaffolds shared PHP and editor registration under \`src/bindings/\`; pass \`--block\` and \`--attribute\` together to declare an end-to-end bindable attribute on an existing generated block. Pass \`--from-post-meta\` or \`--post-meta\` to generate a source backed by a typed post-meta contract; \`--meta-path\` selects one top-level field as the default binding arg.
37590
37600
  \`add contract\` registers a standalone TypeScript wire contract under \`src/contracts/\` and generates a stable JSON Schema artifact without creating PHP route glue.
37591
37601
  \`add rest-resource\` scaffolds plugin-level TypeScript REST contracts under \`src/rest/\` and PHP route glue under \`inc/rest/\`. Use \`--route-pattern\`, \`--permission-callback\`, \`--controller-class\`, and \`--controller-extends\` when an existing WordPress controller or permission model needs to own part of the generated route surface.
@@ -214439,11 +214449,10 @@ function readPackageManifest(location) {
214439
214449
  if (!location.packageJsonPath || location.source === null) {
214440
214450
  return null;
214441
214451
  }
214442
- try {
214443
- return JSON.parse(location.source);
214444
- } catch (error48) {
214445
- throw new Error(`Failed to parse package version manifest at ${location.packageJsonPath}: ${error48 instanceof Error ? error48.message : String(error48)}`);
214446
- }
214452
+ return safeJsonParse(location.source, {
214453
+ context: "package version manifest",
214454
+ filePath: location.packageJsonPath
214455
+ });
214447
214456
  }
214448
214457
  function tryReadPackageManifest(location) {
214449
214458
  if (!location) {
@@ -214544,6 +214553,7 @@ function getPackageVersions() {
214544
214553
  var require2, DEFAULT_VERSION_RANGE = "^0.0.0", DEFAULT_EXACT_VERSION = "0.0.0", DEFAULT_TSX_PACKAGE_VERSION = "^4.20.5", DEFAULT_TYPIA_UNPLUGIN_PACKAGE_VERSION = "^12.0.1", DEFAULT_WORDPRESS_ABILITIES_VERSION = "^0.10.0", DEFAULT_WORDPRESS_CORE_ABILITIES_VERSION = "^0.9.0", DEFAULT_WORDPRESS_CORE_DATA_VERSION = "^7.44.0", DEFAULT_WORDPRESS_DATA_VERSION = "^9.28.0", DEFAULT_WORDPRESS_DATAVIEWS_VERSION = "^14.1.0", DEFAULT_WORDPRESS_ENV_VERSION = "^11.2.0", DEFAULT_WP_TYPIA_DATAVIEWS_VERSION = "^0.1.1", cachedPackageVersions = null;
214545
214554
  var init_package_versions = __esm(() => {
214546
214555
  init_fs_async();
214556
+ init_json_utils();
214547
214557
  init_template_registry();
214548
214558
  require2 = createRequire(import.meta.url);
214549
214559
  });
@@ -225957,7 +225967,9 @@ function sanitizeExternalTemplateCacheMetadata(metadata2) {
225957
225967
  function parseExternalTemplateCacheEntryMarker(markerText) {
225958
225968
  let marker;
225959
225969
  try {
225960
- marker = JSON.parse(markerText);
225970
+ marker = safeJsonParse(markerText, {
225971
+ context: "external template cache entry marker"
225972
+ });
225961
225973
  } catch {
225962
225974
  return null;
225963
225975
  }
@@ -225991,7 +226003,9 @@ function isExternalTemplateCacheEntryFreshForTtl(createdAtMs, nowMs, ttlMs) {
225991
226003
  function parseExternalTemplateCachePruneMarker(markerText) {
225992
226004
  let marker;
225993
226005
  try {
225994
- marker = JSON.parse(markerText);
226006
+ marker = safeJsonParse(markerText, {
226007
+ context: "external template cache prune marker"
226008
+ });
225995
226009
  } catch {
225996
226010
  return null;
225997
226011
  }
@@ -226045,6 +226059,7 @@ function formatExternalTemplateCachePruneMarker({
226045
226059
  }
226046
226060
  var CACHE_MARKER_FILE = "wp-typia-template-cache.json", CACHE_PRUNE_MARKER_FILE = "wp-typia-template-cache-prune.json", REDACTED_CACHE_METADATA_VALUE = "[redacted]", URL_LIKE_METADATA_KEY;
226047
226061
  var init_template_source_cache_markers = __esm(() => {
226062
+ init_json_utils();
226048
226063
  URL_LIKE_METADATA_KEY = /(url|uri|registry|tarball)/iu;
226049
226064
  });
226050
226065
 
@@ -237341,11 +237356,6 @@ main().catch( ( error ) => {
237341
237356
  }
237342
237357
 
237343
237358
  // ../wp-typia-project-tools/src/runtime/cli-add-workspace-ai-source-emitters.ts
237344
- function indentMultiline2(source, prefix) {
237345
- return source.split(`
237346
- `).map((line) => `${prefix}${line}`).join(`
237347
- `);
237348
- }
237349
237359
  function buildAiFeatureConfigEntry(aiFeatureSlug, namespace) {
237350
237360
  const pascalCase = toPascalCase(aiFeatureSlug);
237351
237361
  const title = toTitleCase(aiFeatureSlug);
@@ -237367,7 +237377,7 @@ function buildAiFeatureConfigEntry(aiFeatureSlug, namespace) {
237367
237377
  ` openApiFile: ${quoteTsString(`src/ai-features/${aiFeatureSlug}/api.openapi.json`)},`,
237368
237378
  ` phpFile: ${quoteTsString(`inc/ai-features/${aiFeatureSlug}.php`)},`,
237369
237379
  "\t\trestManifest: defineEndpointManifest(",
237370
- indentMultiline2(JSON.stringify(manifest, null, "\t"), "\t\t\t"),
237380
+ indentMultiline(JSON.stringify(manifest, null, "\t"), "\t\t\t"),
237371
237381
  "\t\t),",
237372
237382
  ` slug: ${quoteTsString(aiFeatureSlug)},`,
237373
237383
  ` typesFile: ${quoteTsString(`src/ai-features/${aiFeatureSlug}/api-types.ts`)},`,
@@ -237501,26 +237511,7 @@ import {
237501
237511
  run${pascalCase}AiFeatureEndpoint,
237502
237512
  } from './api-client';
237503
237513
 
237504
- function resolveRestNonce( fallback?: string ): string | undefined {
237505
- if ( typeof fallback === 'string' && fallback.length > 0 ) {
237506
- return fallback;
237507
- }
237508
-
237509
- if ( typeof window === 'undefined' ) {
237510
- return undefined;
237511
- }
237512
-
237513
- const wpApiSettings = (
237514
- window as typeof window & {
237515
- wpApiSettings?: { nonce?: string };
237516
- }
237517
- ).wpApiSettings;
237518
-
237519
- return typeof wpApiSettings?.nonce === 'string' &&
237520
- wpApiSettings.nonce.length > 0
237521
- ? wpApiSettings.nonce
237522
- : undefined;
237523
- }
237514
+ ${formatResolveRestNonceSource("spaced")}
237524
237515
 
237525
237516
  function isPlainObject( value: unknown ): value is Record< string, unknown > {
237526
237517
  return (
@@ -240197,7 +240188,7 @@ function normalizeOptionalSlug(label, value2, usage) {
240197
240188
  return assertValidGeneratedSlug(label, normalizeBlockSlug(value2), usage);
240198
240189
  }
240199
240190
  function normalizePatternTags(tags) {
240200
- const rawTags = typeof tags === "string" ? tags.split(",") : Array.isArray(tags) ? [...tags] : [];
240191
+ const rawTags = typeof tags === "string" ? tags.split(",") : Array.isArray(tags) ? tags.flatMap((tag) => tag.split(",")) : [];
240201
240192
  const normalizedTags = rawTags.map((tag) => normalizeBlockSlug(tag)).filter((tag) => tag.length > 0);
240202
240193
  for (const tag of normalizedTags) {
240203
240194
  if (!PATTERN_TAG_PATTERN2.test(tag)) {
@@ -241321,6 +241312,12 @@ function buildCoreVariationImportPath(ref) {
241321
241312
  function formatCoreVariationTitle(variationSlug) {
241322
241313
  return toTitleCase(variationSlug);
241323
241314
  }
241315
+ function getUnknownCoreVariationTargetWarning(targetBlockName) {
241316
+ if (!targetBlockName.startsWith("core/") || KNOWN_CORE_VARIATION_TARGETS.has(targetBlockName)) {
241317
+ return;
241318
+ }
241319
+ return `Target block "${targetBlockName}" uses the WordPress core namespace but is not in wp-typia's known core block list. The variation was generated for forward compatibility; verify the block name or update wp-typia if this is a newer core block.`;
241320
+ }
241324
241321
  function assertCoreVariationDoesNotExist(projectDir, targetBlockName, variationSlug) {
241325
241322
  const variationFilePath = getCoreVariationFilePath(projectDir, targetBlockName, variationSlug);
241326
241323
  if (fs31.existsSync(variationFilePath)) {
@@ -241528,6 +241525,7 @@ async function runAddCoreVariationCommand({
241528
241525
  const workspace = resolveWorkspaceProject(cwd);
241529
241526
  const resolvedTargetBlockName = assertFullBlockName(targetBlockName, "core-variation target");
241530
241527
  const variationSlug = assertValidGeneratedSlug("Core variation name", normalizeBlockSlug(variationName), CORE_VARIATION_USAGE);
241528
+ const unknownCoreTargetWarning = getUnknownCoreVariationTargetWarning(resolvedTargetBlockName);
241531
241529
  assertCoreVariationSlugIsNotRegistryIndex(variationSlug);
241532
241530
  assertCoreVariationDoesNotExist(workspace.projectDir, resolvedTargetBlockName, variationSlug);
241533
241531
  const bootstrapPath = path82.join(workspace.projectDir, `${workspace.packageName.split("/").pop() ?? workspace.packageName}.php`);
@@ -241568,14 +241566,15 @@ async function runAddCoreVariationCommand({
241568
241566
  projectDir: workspace.projectDir,
241569
241567
  targetBlockName: resolvedTargetBlockName,
241570
241568
  variationFile: path82.relative(workspace.projectDir, variationFilePath),
241571
- variationSlug
241569
+ variationSlug,
241570
+ ...unknownCoreTargetWarning ? { warnings: [unknownCoreTargetWarning] } : {}
241572
241571
  };
241573
241572
  } catch (error48) {
241574
241573
  await rollbackWorkspaceMutation(mutationSnapshot);
241575
241574
  throw error48;
241576
241575
  }
241577
241576
  }
241578
- var CORE_VARIATIONS_EDITOR_PLUGIN_SLUG = "core-variations", CORE_VARIATION_USAGE = "wp-typia add core-variation <block-name> <name> or wp-typia add core-variation <name> --block <namespace/block>", CORE_VARIATION_SIMPLE_CONTAINER_BLOCKS;
241577
+ var CORE_VARIATIONS_EDITOR_PLUGIN_SLUG = "core-variations", CORE_VARIATION_USAGE = "wp-typia add core-variation <block-name> <name> or wp-typia add core-variation <name> --block <namespace/block>", KNOWN_CORE_VARIATION_TARGETS, CORE_VARIATION_SIMPLE_CONTAINER_BLOCKS;
241579
241578
  var init_cli_add_workspace_core_variation = __esm(() => {
241580
241579
  init_block_targets();
241581
241580
  init_cli_add_shared();
@@ -241583,6 +241582,101 @@ var init_cli_add_workspace_core_variation = __esm(() => {
241583
241582
  init_fs_async();
241584
241583
  init_string_case();
241585
241584
  init_workspace_project();
241585
+ KNOWN_CORE_VARIATION_TARGETS = new Set([
241586
+ "core/archives",
241587
+ "core/audio",
241588
+ "core/avatar",
241589
+ "core/block",
241590
+ "core/button",
241591
+ "core/buttons",
241592
+ "core/calendar",
241593
+ "core/categories",
241594
+ "core/code",
241595
+ "core/column",
241596
+ "core/columns",
241597
+ "core/comment-author-name",
241598
+ "core/comment-content",
241599
+ "core/comment-date",
241600
+ "core/comment-edit-link",
241601
+ "core/comment-reply-link",
241602
+ "core/comment-template",
241603
+ "core/comments",
241604
+ "core/comments-pagination",
241605
+ "core/comments-pagination-next",
241606
+ "core/comments-pagination-numbers",
241607
+ "core/comments-pagination-previous",
241608
+ "core/comments-title",
241609
+ "core/cover",
241610
+ "core/details",
241611
+ "core/embed",
241612
+ "core/file",
241613
+ "core/footnotes",
241614
+ "core/freeform",
241615
+ "core/gallery",
241616
+ "core/group",
241617
+ "core/heading",
241618
+ "core/home-link",
241619
+ "core/html",
241620
+ "core/image",
241621
+ "core/latest-comments",
241622
+ "core/latest-posts",
241623
+ "core/legacy-widget",
241624
+ "core/list",
241625
+ "core/list-item",
241626
+ "core/loginout",
241627
+ "core/media-text",
241628
+ "core/missing",
241629
+ "core/more",
241630
+ "core/navigation",
241631
+ "core/navigation-link",
241632
+ "core/navigation-submenu",
241633
+ "core/nextpage",
241634
+ "core/page-list",
241635
+ "core/paragraph",
241636
+ "core/pattern",
241637
+ "core/post-author",
241638
+ "core/post-author-biography",
241639
+ "core/post-author-name",
241640
+ "core/post-comments",
241641
+ "core/post-comments-form",
241642
+ "core/post-content",
241643
+ "core/post-date",
241644
+ "core/post-excerpt",
241645
+ "core/post-featured-image",
241646
+ "core/post-navigation-link",
241647
+ "core/post-terms",
241648
+ "core/post-template",
241649
+ "core/post-title",
241650
+ "core/preformatted",
241651
+ "core/pullquote",
241652
+ "core/query",
241653
+ "core/query-no-results",
241654
+ "core/query-pagination",
241655
+ "core/query-pagination-next",
241656
+ "core/query-pagination-numbers",
241657
+ "core/query-pagination-previous",
241658
+ "core/query-title",
241659
+ "core/quote",
241660
+ "core/read-more",
241661
+ "core/rss",
241662
+ "core/search",
241663
+ "core/separator",
241664
+ "core/shortcode",
241665
+ "core/site-logo",
241666
+ "core/site-tagline",
241667
+ "core/site-title",
241668
+ "core/social-link",
241669
+ "core/social-links",
241670
+ "core/spacer",
241671
+ "core/table",
241672
+ "core/table-of-contents",
241673
+ "core/tag-cloud",
241674
+ "core/template-part",
241675
+ "core/term-description",
241676
+ "core/text-columns",
241677
+ "core/verse",
241678
+ "core/video"
241679
+ ]);
241586
241680
  CORE_VARIATION_SIMPLE_CONTAINER_BLOCKS = new Set([
241587
241681
  "core/column",
241588
241682
  "core/cover",
@@ -299601,6 +299695,10 @@ var ADD_OPTION_METADATA = {
299601
299695
  description: "Target block slug/name for variation, core-variation, style, and end-to-end binding-source workflows.",
299602
299696
  type: "string"
299603
299697
  },
299698
+ "catalog-title": {
299699
+ description: "Human-readable title for typed pattern catalog entries; defaults to the pattern slug title.",
299700
+ type: "string"
299701
+ },
299604
299702
  "controller-class": {
299605
299703
  description: "REST resource controller class used for generated route callbacks or declared manual/provider route ownership.",
299606
299704
  type: "string"
@@ -299758,7 +299856,13 @@ var ADD_OPTION_METADATA = {
299758
299856
  type: "string"
299759
299857
  },
299760
299858
  tags: {
299761
- description: "Comma-separated tags for typed pattern catalog entries.",
299859
+ description: "Comma-separated tags for typed pattern catalog entries; may be repeated.",
299860
+ repeatable: true,
299861
+ type: "string"
299862
+ },
299863
+ tag: {
299864
+ description: "Repeatable singular tag for typed pattern catalog entries.",
299865
+ repeatable: true,
299762
299866
  type: "string"
299763
299867
  },
299764
299868
  type: {
@@ -300008,7 +300112,8 @@ function buildCommandOptions(metadata2) {
300008
300112
  {
300009
300113
  ...option3.argumentKind ? { argumentKind: option3.argumentKind } : {},
300010
300114
  description: option3.description,
300011
- schema: option3.type === "boolean" ? exports_external.boolean().default(false) : exports_external.string().optional(),
300115
+ ...option3.repeatable ? { repeatable: true } : {},
300116
+ schema: option3.type === "boolean" ? exports_external.boolean().default(false) : option3.repeatable ? exports_external.union([exports_external.string(), exports_external.array(exports_external.string())]).optional() : exports_external.string().optional(),
300012
300117
  ...option3.short ? { short: option3.short } : {}
300013
300118
  }
300014
300119
  ]));
@@ -300028,6 +300133,7 @@ function buildCommandOptionParser(...metadataMaps) {
300028
300133
  }
300029
300134
  return {
300030
300135
  booleanOptionNames: new Set(collectOptionNamesByType(metadata2, "boolean")),
300136
+ repeatableOptionNames: new Set(Object.entries(metadata2).filter(([, option3]) => option3.repeatable).map(([name2]) => name2)),
300031
300137
  shortFlagMap: new Map(Object.entries(metadata2).flatMap(([name2, option3]) => option3.short ? [[option3.short, { name: name2, type: option3.type }]] : [])),
300032
300138
  stringOptionNames: new Set(collectOptionNamesByType(metadata2, "string"))
300033
300139
  };
@@ -300054,6 +300160,10 @@ function resolveCommandOptionValues(metadata2, options) {
300054
300160
  resolved[name2] = Boolean(value2 ?? false);
300055
300161
  continue;
300056
300162
  }
300163
+ if (descriptor.repeatable && Array.isArray(value2)) {
300164
+ resolved[name2] = value2.every((item) => typeof item === "string") ? value2.join(",") : undefined;
300165
+ continue;
300166
+ }
300057
300167
  resolved[name2] = typeof value2 === "string" ? value2 : undefined;
300058
300168
  }
300059
300169
  return resolved;
@@ -300763,6 +300873,7 @@ var coreVariationAddKindEntry = defineAddKindRegistryEntry({
300763
300873
  variationFile: result.variationFile,
300764
300874
  variationSlug: result.variationSlug
300765
300875
  }),
300876
+ getWarnings: (result) => result.warnings,
300766
300877
  missingNameMessage: CORE_VARIATION_MISSING_NAME_MESSAGE,
300767
300878
  name: variationName,
300768
300879
  warnLine: context.warnLine
@@ -300929,8 +301040,10 @@ var patternAddKindEntry = defineAddKindRegistryEntry({
300929
301040
  },
300930
301041
  description: "Add a PHP block pattern shell",
300931
301042
  hiddenStringSubmitFields: [
301043
+ "catalog-title",
300932
301044
  "scope",
300933
301045
  "section-role",
301046
+ "tag",
300934
301047
  "tags",
300935
301048
  "thumbnail-url"
300936
301049
  ],
@@ -300939,10 +301052,12 @@ var patternAddKindEntry = defineAddKindRegistryEntry({
300939
301052
  const name2 = requireAddKindName(context, PATTERN_MISSING_NAME_MESSAGE);
300940
301053
  const scope = typeof context.flags.scope === "string" ? context.flags.scope : undefined;
300941
301054
  const sectionRole = typeof context.flags["section-role"] === "string" ? context.flags["section-role"] : undefined;
300942
- const tags = typeof context.flags.tags === "string" ? context.flags.tags : undefined;
301055
+ const catalogTitle = typeof context.flags["catalog-title"] === "string" ? context.flags["catalog-title"] : undefined;
301056
+ const tags = normalizePatternTagFlags(context.flags.tags, context.flags.tag);
300943
301057
  const thumbnailUrl = typeof context.flags["thumbnail-url"] === "string" ? context.flags["thumbnail-url"] : undefined;
300944
301058
  return {
300945
301059
  execute: (cwd) => context.addRuntime.runAddPatternCommand({
301060
+ catalogTitle,
300946
301061
  cwd,
300947
301062
  patternScope: scope,
300948
301063
  patternName: name2,
@@ -300961,9 +301076,31 @@ var patternAddKindEntry = defineAddKindRegistryEntry({
300961
301076
  },
300962
301077
  sortOrder: 60,
300963
301078
  supportsDryRun: true,
300964
- usage: "wp-typia add pattern <name> [--scope <full|section>] [--section-role <role>] [--tags <tag,...>] [--thumbnail-url <url>] [--dry-run]",
301079
+ usage: "wp-typia add pattern <name> [--scope <full|section>] [--section-role <role>] [--catalog-title <title>] [--tags <tag,...>|--tag <tag>...] [--thumbnail-url <url>] [--dry-run]",
300965
301080
  visibleFieldNames: () => NAME_ONLY_VISIBLE_FIELDS
300966
301081
  });
301082
+ function collectStringFlagValues(value2) {
301083
+ if (typeof value2 === "string") {
301084
+ return [value2];
301085
+ }
301086
+ if (Array.isArray(value2)) {
301087
+ return value2.filter((item) => typeof item === "string");
301088
+ }
301089
+ return [];
301090
+ }
301091
+ function normalizePatternTagFlags(tagsFlag, tagFlag) {
301092
+ const tags = [
301093
+ ...collectStringFlagValues(tagsFlag),
301094
+ ...collectStringFlagValues(tagFlag)
301095
+ ];
301096
+ if (tags.length === 0) {
301097
+ return;
301098
+ }
301099
+ if (tags.length === 1) {
301100
+ return tags[0];
301101
+ }
301102
+ return tags;
301103
+ }
300967
301104
 
300968
301105
  // src/add-kinds/post-meta.ts
300969
301106
  var POST_META_MISSING_NAME_MESSAGE = "`wp-typia add post-meta` requires <name>. Usage: wp-typia add post-meta <name> --post-type <post-type> [--type <ExportedTypeName>] [--meta-key <meta-key>].";
@@ -301712,7 +301849,7 @@ function buildStructuredInitSuccessPayload(plan) {
301712
301849
  // package.json
301713
301850
  var package_default2 = {
301714
301851
  name: "wp-typia",
301715
- version: "0.24.0",
301852
+ version: "0.24.1",
301716
301853
  description: "Canonical CLI package for wp-typia scaffolding and project workflows",
301717
301854
  packageManager: "bun@1.3.11",
301718
301855
  type: "module",
@@ -301782,7 +301919,7 @@ var package_default2 = {
301782
301919
  "@bunli/tui": "0.6.0",
301783
301920
  "@bunli/utils": "0.6.0",
301784
301921
  "@wp-typia/api-client": "^0.4.5",
301785
- "@wp-typia/project-tools": "0.24.0",
301922
+ "@wp-typia/project-tools": "0.24.1",
301786
301923
  "better-result": "^2.7.0",
301787
301924
  react: "^19.2.5",
301788
301925
  "react-dom": "^19.2.5",
@@ -304170,4 +304307,4 @@ export {
304170
304307
  cli
304171
304308
  };
304172
304309
 
304173
- //# debugId=9B4E6E13B5DCD93064756E2164756E21
304310
+ //# debugId=2782AF044AA7C53F64756E2164756E21