wp-typia 0.24.0 → 0.24.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.
@@ -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, pass \`--tags hero,landing\` for a comma-separated tag list, and repeat \`--tag hero --tag landing\` for single tag values.
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 (
@@ -240190,17 +240181,21 @@ function resolvePatternScope(scope) {
240190
240181
  }
240191
240182
  throw new Error(`Pattern scope must be one of: ${PATTERN_CATALOG_SCOPE_IDS.join(", ")}.`);
240192
240183
  }
240193
- function normalizeOptionalSlug(label, value2, usage) {
240184
+ function normalizePatternSectionRole(value2) {
240194
240185
  if (value2 === undefined || value2.trim() === "") {
240195
240186
  return;
240196
240187
  }
240197
- return assertValidGeneratedSlug(label, normalizeBlockSlug(value2), usage);
240188
+ const sectionRole = normalizeBlockSlug(value2);
240189
+ if (!PATTERN_SECTION_ROLE_PATTERN.test(sectionRole)) {
240190
+ throw new Error("Pattern section role must start with a lowercase letter and contain only lowercase letters, numbers, and hyphens. Section roles apply only with `--scope section`.");
240191
+ }
240192
+ return sectionRole;
240198
240193
  }
240199
240194
  function normalizePatternTags(tags) {
240200
- const rawTags = typeof tags === "string" ? tags.split(",") : Array.isArray(tags) ? [...tags] : [];
240195
+ const rawTags = typeof tags === "string" ? tags.split(",") : Array.isArray(tags) ? tags.flatMap((tag) => tag.split(",")) : [];
240201
240196
  const normalizedTags = rawTags.map((tag) => normalizeBlockSlug(tag)).filter((tag) => tag.length > 0);
240202
240197
  for (const tag of normalizedTags) {
240203
- if (!PATTERN_TAG_PATTERN2.test(tag)) {
240198
+ if (!PATTERN_TAG_PATTERN.test(tag)) {
240204
240199
  throw new Error(`Pattern tag "${tag}" must contain only lowercase letters, numbers, and hyphens.`);
240205
240200
  }
240206
240201
  }
@@ -240225,12 +240220,12 @@ function resolvePatternContentFile(patternSlug, patternScope, contentFile) {
240225
240220
  }
240226
240221
  function resolvePatternCatalogOptions(patternSlug, options) {
240227
240222
  const patternScope = resolvePatternScope(options.patternScope);
240228
- const sectionRole = normalizeOptionalSlug("Pattern section role", options.sectionRole, "wp-typia add pattern <name> --scope section --section-role <role>");
240223
+ const sectionRole = normalizePatternSectionRole(options.sectionRole);
240229
240224
  if (patternScope === "section" && !sectionRole) {
240230
- throw new Error("`wp-typia add pattern --scope section` requires --section-role <role>.");
240225
+ throw new Error("`wp-typia add pattern --scope section` requires --section-role <role> because section-scoped patterns need a typed catalog section role.");
240231
240226
  }
240232
240227
  if (patternScope !== "section" && sectionRole) {
240233
- throw new Error("`--section-role` requires `--scope section`.");
240228
+ throw new Error("`--section-role` only applies with `--scope section`. Use `--scope section --section-role <role>` or omit `--section-role` for full patterns.");
240234
240229
  }
240235
240230
  const title = options.catalogTitle && options.catalogTitle.trim() !== "" ? options.catalogTitle.trim() : toTitleCase(patternSlug);
240236
240231
  const thumbnailUrl = normalizePatternThumbnailUrl(options.thumbnailUrl);
@@ -240243,12 +240238,11 @@ function resolvePatternCatalogOptions(patternSlug, options) {
240243
240238
  title
240244
240239
  };
240245
240240
  }
240246
- var PATTERN_CONTENT_FILE_ROOT2 = "src/patterns/", PATTERN_TAG_PATTERN2;
240241
+ var PATTERN_CONTENT_FILE_ROOT2 = "src/patterns/";
240247
240242
  var init_cli_add_workspace_pattern_options = __esm(() => {
240248
240243
  init_cli_add_shared();
240249
240244
  init_pattern_catalog();
240250
240245
  init_string_case();
240251
- PATTERN_TAG_PATTERN2 = /^[a-z0-9][a-z0-9-]*$/u;
240252
240246
  });
240253
240247
 
240254
240248
  // ../wp-typia-project-tools/src/runtime/cli-add-workspace-pattern-source-emitters.ts
@@ -241321,6 +241315,12 @@ function buildCoreVariationImportPath(ref) {
241321
241315
  function formatCoreVariationTitle(variationSlug) {
241322
241316
  return toTitleCase(variationSlug);
241323
241317
  }
241318
+ function getUnknownCoreVariationTargetWarning(targetBlockName) {
241319
+ if (!targetBlockName.startsWith("core/") || KNOWN_CORE_VARIATION_TARGETS.has(targetBlockName)) {
241320
+ return;
241321
+ }
241322
+ 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.`;
241323
+ }
241324
241324
  function assertCoreVariationDoesNotExist(projectDir, targetBlockName, variationSlug) {
241325
241325
  const variationFilePath = getCoreVariationFilePath(projectDir, targetBlockName, variationSlug);
241326
241326
  if (fs31.existsSync(variationFilePath)) {
@@ -241528,6 +241528,7 @@ async function runAddCoreVariationCommand({
241528
241528
  const workspace = resolveWorkspaceProject(cwd);
241529
241529
  const resolvedTargetBlockName = assertFullBlockName(targetBlockName, "core-variation target");
241530
241530
  const variationSlug = assertValidGeneratedSlug("Core variation name", normalizeBlockSlug(variationName), CORE_VARIATION_USAGE);
241531
+ const unknownCoreTargetWarning = getUnknownCoreVariationTargetWarning(resolvedTargetBlockName);
241531
241532
  assertCoreVariationSlugIsNotRegistryIndex(variationSlug);
241532
241533
  assertCoreVariationDoesNotExist(workspace.projectDir, resolvedTargetBlockName, variationSlug);
241533
241534
  const bootstrapPath = path82.join(workspace.projectDir, `${workspace.packageName.split("/").pop() ?? workspace.packageName}.php`);
@@ -241568,14 +241569,15 @@ async function runAddCoreVariationCommand({
241568
241569
  projectDir: workspace.projectDir,
241569
241570
  targetBlockName: resolvedTargetBlockName,
241570
241571
  variationFile: path82.relative(workspace.projectDir, variationFilePath),
241571
- variationSlug
241572
+ variationSlug,
241573
+ ...unknownCoreTargetWarning ? { warnings: [unknownCoreTargetWarning] } : {}
241572
241574
  };
241573
241575
  } catch (error48) {
241574
241576
  await rollbackWorkspaceMutation(mutationSnapshot);
241575
241577
  throw error48;
241576
241578
  }
241577
241579
  }
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;
241580
+ 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
241581
  var init_cli_add_workspace_core_variation = __esm(() => {
241580
241582
  init_block_targets();
241581
241583
  init_cli_add_shared();
@@ -241583,6 +241585,101 @@ var init_cli_add_workspace_core_variation = __esm(() => {
241583
241585
  init_fs_async();
241584
241586
  init_string_case();
241585
241587
  init_workspace_project();
241588
+ KNOWN_CORE_VARIATION_TARGETS = new Set([
241589
+ "core/archives",
241590
+ "core/audio",
241591
+ "core/avatar",
241592
+ "core/block",
241593
+ "core/button",
241594
+ "core/buttons",
241595
+ "core/calendar",
241596
+ "core/categories",
241597
+ "core/code",
241598
+ "core/column",
241599
+ "core/columns",
241600
+ "core/comment-author-name",
241601
+ "core/comment-content",
241602
+ "core/comment-date",
241603
+ "core/comment-edit-link",
241604
+ "core/comment-reply-link",
241605
+ "core/comment-template",
241606
+ "core/comments",
241607
+ "core/comments-pagination",
241608
+ "core/comments-pagination-next",
241609
+ "core/comments-pagination-numbers",
241610
+ "core/comments-pagination-previous",
241611
+ "core/comments-title",
241612
+ "core/cover",
241613
+ "core/details",
241614
+ "core/embed",
241615
+ "core/file",
241616
+ "core/footnotes",
241617
+ "core/freeform",
241618
+ "core/gallery",
241619
+ "core/group",
241620
+ "core/heading",
241621
+ "core/home-link",
241622
+ "core/html",
241623
+ "core/image",
241624
+ "core/latest-comments",
241625
+ "core/latest-posts",
241626
+ "core/legacy-widget",
241627
+ "core/list",
241628
+ "core/list-item",
241629
+ "core/loginout",
241630
+ "core/media-text",
241631
+ "core/missing",
241632
+ "core/more",
241633
+ "core/navigation",
241634
+ "core/navigation-link",
241635
+ "core/navigation-submenu",
241636
+ "core/nextpage",
241637
+ "core/page-list",
241638
+ "core/paragraph",
241639
+ "core/pattern",
241640
+ "core/post-author",
241641
+ "core/post-author-biography",
241642
+ "core/post-author-name",
241643
+ "core/post-comments",
241644
+ "core/post-comments-form",
241645
+ "core/post-content",
241646
+ "core/post-date",
241647
+ "core/post-excerpt",
241648
+ "core/post-featured-image",
241649
+ "core/post-navigation-link",
241650
+ "core/post-terms",
241651
+ "core/post-template",
241652
+ "core/post-title",
241653
+ "core/preformatted",
241654
+ "core/pullquote",
241655
+ "core/query",
241656
+ "core/query-no-results",
241657
+ "core/query-pagination",
241658
+ "core/query-pagination-next",
241659
+ "core/query-pagination-numbers",
241660
+ "core/query-pagination-previous",
241661
+ "core/query-title",
241662
+ "core/quote",
241663
+ "core/read-more",
241664
+ "core/rss",
241665
+ "core/search",
241666
+ "core/separator",
241667
+ "core/shortcode",
241668
+ "core/site-logo",
241669
+ "core/site-tagline",
241670
+ "core/site-title",
241671
+ "core/social-link",
241672
+ "core/social-links",
241673
+ "core/spacer",
241674
+ "core/table",
241675
+ "core/table-of-contents",
241676
+ "core/tag-cloud",
241677
+ "core/template-part",
241678
+ "core/term-description",
241679
+ "core/text-columns",
241680
+ "core/verse",
241681
+ "core/video"
241682
+ ]);
241586
241683
  CORE_VARIATION_SIMPLE_CONTAINER_BLOCKS = new Set([
241587
241684
  "core/column",
241588
241685
  "core/cover",
@@ -244047,10 +244144,13 @@ __export(exports_cli_add, {
244047
244144
  runAddAiFeatureCommand: () => runAddAiFeatureCommand,
244048
244145
  runAddAdminViewCommand: () => runAddAdminViewCommand,
244049
244146
  runAddAbilityCommand: () => runAddAbilityCommand,
244147
+ normalizeBlockSlug: () => normalizeBlockSlug,
244050
244148
  isAddBlockTemplateId: () => isAddBlockTemplateId,
244051
244149
  getWorkspaceBlockSelectOptionsAsync: () => getWorkspaceBlockSelectOptionsAsync,
244052
244150
  getWorkspaceBlockSelectOptions: () => getWorkspaceBlockSelectOptions,
244053
244151
  formatAddHelpText: () => formatAddHelpText,
244152
+ PATTERN_TAG_PATTERN: () => PATTERN_TAG_PATTERN,
244153
+ PATTERN_SECTION_ROLE_PATTERN: () => PATTERN_SECTION_ROLE_PATTERN,
244054
244154
  PATTERN_CATALOG_SCOPE_IDS: () => PATTERN_CATALOG_SCOPE_IDS,
244055
244155
  EDITOR_PLUGIN_SLOT_IDS: () => EDITOR_PLUGIN_SLOT_IDS,
244056
244156
  ADD_KIND_IDS: () => ADD_KIND_IDS,
@@ -299601,6 +299701,10 @@ var ADD_OPTION_METADATA = {
299601
299701
  description: "Target block slug/name for variation, core-variation, style, and end-to-end binding-source workflows.",
299602
299702
  type: "string"
299603
299703
  },
299704
+ "catalog-title": {
299705
+ description: "Human-readable title for typed pattern catalog entries; defaults to the pattern slug title.",
299706
+ type: "string"
299707
+ },
299604
299708
  "controller-class": {
299605
299709
  description: "REST resource controller class used for generated route callbacks or declared manual/provider route ownership.",
299606
299710
  type: "string"
@@ -299710,11 +299814,11 @@ var ADD_OPTION_METADATA = {
299710
299814
  type: "string"
299711
299815
  },
299712
299816
  scope: {
299713
- description: "Pattern catalog scope for pattern workflows (full or section).",
299817
+ description: "Pattern catalog scope for pattern workflows; one of full or section.",
299714
299818
  type: "string"
299715
299819
  },
299716
299820
  "section-role": {
299717
- description: "Typed section role for section-scoped pattern catalog entries.",
299821
+ description: "Typed section role for section-scoped pattern catalog entries; requires --scope section.",
299718
299822
  type: "string"
299719
299823
  },
299720
299824
  "secret-field": {
@@ -299758,7 +299862,13 @@ var ADD_OPTION_METADATA = {
299758
299862
  type: "string"
299759
299863
  },
299760
299864
  tags: {
299761
- description: "Comma-separated tags for typed pattern catalog entries.",
299865
+ description: "Comma-separated tags for typed pattern catalog entries; combine with repeatable --tag for single tags.",
299866
+ repeatable: true,
299867
+ type: "string"
299868
+ },
299869
+ tag: {
299870
+ description: "Repeatable single tag for typed pattern catalog entries; use --tags for comma-separated lists.",
299871
+ repeatable: true,
299762
299872
  type: "string"
299763
299873
  },
299764
299874
  type: {
@@ -300008,7 +300118,8 @@ function buildCommandOptions(metadata2) {
300008
300118
  {
300009
300119
  ...option3.argumentKind ? { argumentKind: option3.argumentKind } : {},
300010
300120
  description: option3.description,
300011
- schema: option3.type === "boolean" ? exports_external.boolean().default(false) : exports_external.string().optional(),
300121
+ ...option3.repeatable ? { repeatable: true } : {},
300122
+ 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
300123
  ...option3.short ? { short: option3.short } : {}
300013
300124
  }
300014
300125
  ]));
@@ -300028,6 +300139,7 @@ function buildCommandOptionParser(...metadataMaps) {
300028
300139
  }
300029
300140
  return {
300030
300141
  booleanOptionNames: new Set(collectOptionNamesByType(metadata2, "boolean")),
300142
+ repeatableOptionNames: new Set(Object.entries(metadata2).filter(([, option3]) => option3.repeatable).map(([name2]) => name2)),
300031
300143
  shortFlagMap: new Map(Object.entries(metadata2).flatMap(([name2, option3]) => option3.short ? [[option3.short, { name: name2, type: option3.type }]] : [])),
300032
300144
  stringOptionNames: new Set(collectOptionNamesByType(metadata2, "string"))
300033
300145
  };
@@ -300054,6 +300166,10 @@ function resolveCommandOptionValues(metadata2, options) {
300054
300166
  resolved[name2] = Boolean(value2 ?? false);
300055
300167
  continue;
300056
300168
  }
300169
+ if (descriptor.repeatable && Array.isArray(value2)) {
300170
+ resolved[name2] = value2.every((item) => typeof item === "string") ? value2.join(",") : undefined;
300171
+ continue;
300172
+ }
300057
300173
  resolved[name2] = typeof value2 === "string" ? value2 : undefined;
300058
300174
  }
300059
300175
  return resolved;
@@ -300240,6 +300356,13 @@ var NAME_ONLY_VISIBLE_FIELDS = [
300240
300356
  "kind",
300241
300357
  "name"
300242
300358
  ];
300359
+ var PATTERN_CATALOG_VISIBLE_FIELDS = [
300360
+ "kind",
300361
+ "name",
300362
+ "scope",
300363
+ "section-role",
300364
+ "catalog-title"
300365
+ ];
300243
300366
  var NAME_SOURCE_VISIBLE_FIELDS = [
300244
300367
  "kind",
300245
300368
  "name",
@@ -300710,6 +300833,15 @@ var contractAddKindEntry = defineAddKindRegistryEntry({
300710
300833
  init_cli_diagnostics();
300711
300834
  var CORE_VARIATION_MISSING_NAME_MESSAGE = "`wp-typia add core-variation` requires <name>. Usage: wp-typia add core-variation <block-name> <name> or wp-typia add core-variation <name> --block <namespace/block>.";
300712
300835
  var CORE_VARIATION_MISSING_BLOCK_MESSAGE = "`wp-typia add core-variation` requires <block-name>. Usage: wp-typia add core-variation <block-name> <name> or wp-typia add core-variation <name> --block <namespace/block>.";
300836
+ var CORE_VARIATION_BLOCK_NAME_PATTERN = /^[^/\s]+\/[^/\s]+$/u;
300837
+ function formatCoreVariationMissingPositionalNameMessage(blockName) {
300838
+ return [
300839
+ `\`wp-typia add core-variation ${blockName}\` is missing <name>.`,
300840
+ "Usage: wp-typia add core-variation <block-name> <name>",
300841
+ "Alternative: wp-typia add core-variation <name> --block <namespace/block>"
300842
+ ].join(`
300843
+ `);
300844
+ }
300713
300845
  function resolveCoreVariationInputs(context) {
300714
300846
  const positionalTargetBlockName = context.positionalArgs?.[1];
300715
300847
  const positionalVariationName = context.positionalArgs?.[2];
@@ -300722,16 +300854,17 @@ function resolveCoreVariationInputs(context) {
300722
300854
  variationName: positionalVariationName
300723
300855
  };
300724
300856
  }
300725
- if (context.name?.includes("/") && !readOptionalStrictStringFlag(context.flags, "block")) {
300726
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, CORE_VARIATION_MISSING_NAME_MESSAGE);
300857
+ const targetBlockFlag = readOptionalStrictStringFlag(context.flags, "block");
300858
+ const missingPositionalNameTarget = context.name !== undefined && positionalTargetBlockName === context.name && CORE_VARIATION_BLOCK_NAME_PATTERN.test(context.name) ? context.name : undefined;
300859
+ if (missingPositionalNameTarget && !targetBlockFlag) {
300860
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, formatCoreVariationMissingPositionalNameMessage(missingPositionalNameTarget));
300727
300861
  }
300728
300862
  const variationName = requireAddKindName(context, CORE_VARIATION_MISSING_NAME_MESSAGE);
300729
- const targetBlockName = readOptionalStrictStringFlag(context.flags, "block");
300730
- if (!targetBlockName) {
300863
+ if (!targetBlockFlag) {
300731
300864
  throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, CORE_VARIATION_MISSING_BLOCK_MESSAGE);
300732
300865
  }
300733
300866
  return {
300734
- targetBlockName,
300867
+ targetBlockName: targetBlockFlag,
300735
300868
  variationName
300736
300869
  };
300737
300870
  }
@@ -300763,6 +300896,7 @@ var coreVariationAddKindEntry = defineAddKindRegistryEntry({
300763
300896
  variationFile: result.variationFile,
300764
300897
  variationSlug: result.variationSlug
300765
300898
  }),
300899
+ getWarnings: (result) => result.warnings,
300766
300900
  missingNameMessage: CORE_VARIATION_MISSING_NAME_MESSAGE,
300767
300901
  name: variationName,
300768
300902
  warnLine: context.warnLine
@@ -300909,10 +301043,12 @@ var integrationEnvAddKindEntry = defineAddKindRegistryEntry({
300909
301043
  supportsDryRun: true,
300910
301044
  usage: "wp-typia add integration-env <name> [--wp-env] [--release-zip] [--service <none|docker-compose>] [--dry-run]",
300911
301045
  visibleFieldNames: () => NAME_ONLY_VISIBLE_FIELDS,
300912
- hiddenBooleanSubmitFields: ["wp-env", "release-zip"]
301046
+ hiddenBooleanSubmitFields: ["wp-env", "release-zip"],
301047
+ hiddenStringSubmitFields: ["service"]
300913
301048
  });
300914
301049
 
300915
301050
  // src/add-kinds/pattern.ts
301051
+ init_cli_diagnostics();
300916
301052
  var PATTERN_MISSING_NAME_MESSAGE = "`wp-typia add pattern` requires <name>. Usage: wp-typia add pattern <name>.";
300917
301053
  var patternAddKindEntry = defineAddKindRegistryEntry({
300918
301054
  completion: {
@@ -300928,21 +301064,18 @@ var patternAddKindEntry = defineAddKindRegistryEntry({
300928
301064
  title: "Added workspace pattern"
300929
301065
  },
300930
301066
  description: "Add a PHP block pattern shell",
300931
- hiddenStringSubmitFields: [
300932
- "scope",
300933
- "section-role",
300934
- "tags",
300935
- "thumbnail-url"
300936
- ],
301067
+ hiddenStringSubmitFields: ["tag", "tags", "thumbnail-url"],
300937
301068
  nameLabel: "Pattern name",
300938
301069
  async prepareExecution(context) {
300939
301070
  const name2 = requireAddKindName(context, PATTERN_MISSING_NAME_MESSAGE);
300940
- const scope = typeof context.flags.scope === "string" ? context.flags.scope : undefined;
300941
- 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;
301071
+ const scope = resolvePatternScopeFlag(context);
301072
+ const sectionRole = resolvePatternSectionRoleFlag(context, scope);
301073
+ const catalogTitle = typeof context.flags["catalog-title"] === "string" ? context.flags["catalog-title"] : undefined;
301074
+ const tags = normalizePatternTagFlags(context.flags.tags, context.flags.tag);
300943
301075
  const thumbnailUrl = typeof context.flags["thumbnail-url"] === "string" ? context.flags["thumbnail-url"] : undefined;
300944
301076
  return {
300945
301077
  execute: (cwd) => context.addRuntime.runAddPatternCommand({
301078
+ catalogTitle,
300946
301079
  cwd,
300947
301080
  patternScope: scope,
300948
301081
  patternName: name2,
@@ -300961,9 +301094,58 @@ var patternAddKindEntry = defineAddKindRegistryEntry({
300961
301094
  },
300962
301095
  sortOrder: 60,
300963
301096
  supportsDryRun: true,
300964
- usage: "wp-typia add pattern <name> [--scope <full|section>] [--section-role <role>] [--tags <tag,...>] [--thumbnail-url <url>] [--dry-run]",
300965
- visibleFieldNames: () => NAME_ONLY_VISIBLE_FIELDS
301097
+ usage: "wp-typia add pattern <name> [--scope <full|section>] [--section-role <role>] [--catalog-title <title>] [--tags <tag,...>] [--tag <tag>...] [--thumbnail-url <url>] [--dry-run]",
301098
+ visibleFieldNames: () => PATTERN_CATALOG_VISIBLE_FIELDS
300966
301099
  });
301100
+ function createInvalidPatternArgumentError(message) {
301101
+ return createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, message);
301102
+ }
301103
+ function createMissingPatternArgumentError(message) {
301104
+ return createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, message);
301105
+ }
301106
+ function resolvePatternScopeFlag(context) {
301107
+ const scope = readOptionalLooseStringFlag(context.flags, "scope");
301108
+ if (!scope) {
301109
+ return;
301110
+ }
301111
+ if (context.addRuntime.PATTERN_CATALOG_SCOPE_IDS.includes(scope)) {
301112
+ return scope;
301113
+ }
301114
+ throw createInvalidPatternArgumentError(`\`--scope\` must be one of: ${context.addRuntime.PATTERN_CATALOG_SCOPE_IDS.join(", ")}. Usage: wp-typia add pattern <name> --scope <full|section>.`);
301115
+ }
301116
+ function resolvePatternSectionRoleFlag(context, scope) {
301117
+ const sectionRole = readOptionalLooseStringFlag(context.flags, "section-role");
301118
+ if (scope === "section" && sectionRole === undefined) {
301119
+ throw createMissingPatternArgumentError("`wp-typia add pattern --scope section` requires --section-role <role> because section-scoped patterns need a typed catalog section role.");
301120
+ }
301121
+ if (scope !== "section" && sectionRole !== undefined) {
301122
+ throw createInvalidPatternArgumentError("`--section-role` only applies with `--scope section`. Use `--scope section --section-role <role>` or omit `--section-role` for full patterns.");
301123
+ }
301124
+ const normalizedSectionRole = sectionRole === undefined ? undefined : context.addRuntime.normalizeBlockSlug(sectionRole);
301125
+ if (normalizedSectionRole && !context.addRuntime.PATTERN_SECTION_ROLE_PATTERN.test(normalizedSectionRole)) {
301126
+ throw createInvalidPatternArgumentError("`--section-role` must start with a lowercase letter and contain only lowercase letters, numbers, and hyphens. Section roles apply only with `--scope section`.");
301127
+ }
301128
+ if (sectionRole !== undefined && !normalizedSectionRole) {
301129
+ throw createInvalidPatternArgumentError("`--section-role` must start with a lowercase letter and contain only lowercase letters, numbers, and hyphens. Section roles apply only with `--scope section`.");
301130
+ }
301131
+ return normalizedSectionRole;
301132
+ }
301133
+ function collectStringFlagValues(value2) {
301134
+ if (typeof value2 === "string") {
301135
+ return [value2];
301136
+ }
301137
+ if (Array.isArray(value2)) {
301138
+ return value2.filter((item) => typeof item === "string");
301139
+ }
301140
+ return [];
301141
+ }
301142
+ function normalizePatternTagFlags(tagsFlag, tagFlag) {
301143
+ const tags = [
301144
+ ...collectStringFlagValues(tagsFlag),
301145
+ ...collectStringFlagValues(tagFlag)
301146
+ ];
301147
+ return tags.length > 0 ? tags : undefined;
301148
+ }
300967
301149
 
300968
301150
  // src/add-kinds/post-meta.ts
300969
301151
  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 +301894,7 @@ function buildStructuredInitSuccessPayload(plan) {
301712
301894
  // package.json
301713
301895
  var package_default2 = {
301714
301896
  name: "wp-typia",
301715
- version: "0.24.0",
301897
+ version: "0.24.2",
301716
301898
  description: "Canonical CLI package for wp-typia scaffolding and project workflows",
301717
301899
  packageManager: "bun@1.3.11",
301718
301900
  type: "module",
@@ -301782,7 +301964,7 @@ var package_default2 = {
301782
301964
  "@bunli/tui": "0.6.0",
301783
301965
  "@bunli/utils": "0.6.0",
301784
301966
  "@wp-typia/api-client": "^0.4.5",
301785
- "@wp-typia/project-tools": "0.24.0",
301967
+ "@wp-typia/project-tools": "0.24.2",
301786
301968
  "better-result": "^2.7.0",
301787
301969
  react: "^19.2.5",
301788
301970
  "react-dom": "^19.2.5",
@@ -304170,4 +304352,4 @@ export {
304170
304352
  cli
304171
304353
  };
304172
304354
 
304173
- //# debugId=9B4E6E13B5DCD93064756E2164756E21
304355
+ //# debugId=EDC8802048054A1E64756E2164756E21