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.
@@ -170921,17 +170921,168 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
170921
170921
  } });
170922
170922
  });
170923
170923
 
170924
- // ../wp-typia-project-tools/src/runtime/pattern-catalog.ts
170925
- import fs from "fs";
170926
- import path from "path";
170924
+ // ../wp-typia-project-tools/src/runtime/string-case.ts
170925
+ var COMMON_ACRONYM_PREFIXES = [
170926
+ "HTML",
170927
+ "HTTP",
170928
+ "JSON",
170929
+ "REST",
170930
+ "UUID",
170931
+ "AJAX",
170932
+ "API",
170933
+ "CPT",
170934
+ "CSS",
170935
+ "CTA",
170936
+ "DOM",
170937
+ "PHP",
170938
+ "SQL",
170939
+ "SVG",
170940
+ "URL",
170941
+ "XML",
170942
+ "ID",
170943
+ "JS",
170944
+ "UI",
170945
+ "WP"
170946
+ ];
170947
+ var COMMON_ACRONYM_LOWERCASE_SUFFIXES = ["slug"];
170948
+ function capitalizeSegment(segment) {
170949
+ return segment.charAt(0).toUpperCase() + segment.slice(1);
170950
+ }
170951
+ function findCommonAcronymPrefix(segment) {
170952
+ return COMMON_ACRONYM_PREFIXES.find((prefix) => segment.startsWith(prefix));
170953
+ }
170954
+ function isCommonAcronymLowercaseSuffix(suffix) {
170955
+ return COMMON_ACRONYM_LOWERCASE_SUFFIXES.includes(suffix);
170956
+ }
170957
+ function splitKnownAcronymSegment(segment) {
170958
+ const prefixes = [];
170959
+ let remaining = segment;
170960
+ while (remaining.length > 0) {
170961
+ const prefix = findCommonAcronymPrefix(remaining);
170962
+ if (!prefix) {
170963
+ break;
170964
+ }
170965
+ const suffix = remaining.slice(prefix.length);
170966
+ if (/^[A-Z][a-z]/.test(suffix)) {
170967
+ return [...prefixes, prefix, suffix].join("-");
170968
+ }
170969
+ if (/^[a-z]+$/.test(suffix) && isCommonAcronymLowercaseSuffix(suffix)) {
170970
+ return [...prefixes, prefix, suffix].join("-");
170971
+ }
170972
+ if (!findCommonAcronymPrefix(suffix)) {
170973
+ break;
170974
+ }
170975
+ prefixes.push(prefix);
170976
+ remaining = suffix;
170977
+ }
170978
+ return segment;
170979
+ }
170980
+ function splitAcronymBoundary(value) {
170981
+ return value.replace(/[A-Z]{2,}[a-z]+/g, splitKnownAcronymSegment);
170982
+ }
170983
+ function toKebabCase(input) {
170984
+ return splitAcronymBoundary(input.trim()).replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/[^A-Za-z0-9]+/g, "-").replace(/^-+|-+$/g, "").replace(/-{2,}/g, "-").toLowerCase();
170985
+ }
170986
+ function toSnakeCase(input) {
170987
+ return toKebabCase(input).replace(/-/g, "_");
170988
+ }
170989
+ function toPascalCase(input) {
170990
+ return toKebabCase(input).split("-").filter(Boolean).map(capitalizeSegment).join("");
170991
+ }
170992
+ function toCamelCase(input) {
170993
+ const pascalCase = toPascalCase(input);
170994
+ return `${pascalCase.charAt(0).toLowerCase()}${pascalCase.slice(1)}`;
170995
+ }
170996
+ function toSegmentPascalCase(input) {
170997
+ return input.replace(/[^A-Za-z0-9]+/g, " ").trim().split(/\s+/).filter(Boolean).map(capitalizeSegment).join("");
170998
+ }
170999
+ function toTitleCase(input) {
171000
+ return toKebabCase(input).split("-").filter(Boolean).map(capitalizeSegment).join(" ");
171001
+ }
171002
+
171003
+ // ../wp-typia-project-tools/src/runtime/scaffold-identifiers.ts
171004
+ var BLOCK_SLUG_PATTERN = /^[a-z][a-z0-9-]*$/;
171005
+ var PHP_PREFIX_PATTERN = /^[a-z_][a-z0-9_]*$/;
171006
+ var PHP_PREFIX_MAX_LENGTH = 50;
171007
+ function validateBlockSlug(input) {
171008
+ return BLOCK_SLUG_PATTERN.test(input) || "Use lowercase letters, numbers, and hyphens only";
171009
+ }
171010
+ function validateNamespace(input) {
171011
+ return BLOCK_SLUG_PATTERN.test(toKebabCase(input)) ? true : "Use lowercase letters, numbers, and hyphens only";
171012
+ }
171013
+ function validateTextDomain(input) {
171014
+ return BLOCK_SLUG_PATTERN.test(toKebabCase(input)) ? true : "Use lowercase letters, numbers, and hyphens only";
171015
+ }
171016
+ function validatePhpPrefix(input) {
171017
+ const normalizedPrefix = toSnakeCase(input);
171018
+ if (normalizedPrefix.length > PHP_PREFIX_MAX_LENGTH) {
171019
+ return `Use ${PHP_PREFIX_MAX_LENGTH} characters or fewer to keep generated database identifiers within MySQL limits`;
171020
+ }
171021
+ return PHP_PREFIX_PATTERN.test(normalizedPrefix) ? true : "Use letters, numbers, and underscores only, starting with a letter";
171022
+ }
171023
+ function assertValidIdentifier(label, value, validate) {
171024
+ const result = validate(value);
171025
+ if (result !== true) {
171026
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, typeof result === "string" ? `${label}: ${result}` : `${label} is invalid`);
171027
+ }
171028
+ return value;
171029
+ }
171030
+ function normalizeBlockSlug(input) {
171031
+ return toKebabCase(input);
171032
+ }
171033
+ function resolveNonEmptyNormalizedBlockSlug(options) {
171034
+ const normalizedSlug = normalizeBlockSlug(options.input);
171035
+ if (normalizedSlug.length > 0) {
171036
+ return normalizedSlug;
171037
+ }
171038
+ if (options.input.trim().length === 0) {
171039
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, `${options.label} is required. Use \`${options.usage}\`.`);
171040
+ }
171041
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, `${options.label} "${options.input.trim()}" normalizes to an empty slug. Use letters or numbers so wp-typia can generate a block slug.`);
171042
+ }
171043
+ function resolveValidatedBlockSlug(value) {
171044
+ return assertValidIdentifier("Block slug", normalizeBlockSlug(value), validateBlockSlug);
171045
+ }
171046
+ function resolveValidatedNamespace(value) {
171047
+ return assertValidIdentifier("Namespace", toKebabCase(value), validateNamespace);
171048
+ }
171049
+ function resolveValidatedTextDomain(value) {
171050
+ return assertValidIdentifier("Text domain", toKebabCase(value), validateTextDomain);
171051
+ }
171052
+ function resolveValidatedPhpPrefix(value) {
171053
+ return assertValidIdentifier("PHP prefix", toSnakeCase(value), validatePhpPrefix);
171054
+ }
171055
+ function buildBlockCssClassName(namespace, slug) {
171056
+ const normalizedSlug = resolveValidatedBlockSlug(slug);
171057
+ const normalizedNamespace = typeof namespace === "string" && namespace.trim().length > 0 ? resolveValidatedNamespace(namespace) : "";
171058
+ if (normalizedNamespace === normalizedSlug) {
171059
+ return `wp-block-${normalizedSlug}-block`;
171060
+ }
171061
+ return normalizedNamespace.length > 0 ? `wp-block-${normalizedNamespace}-${normalizedSlug}` : `wp-block-${normalizedSlug}`;
171062
+ }
171063
+ function buildFrontendCssClassName(blockCssClassName) {
171064
+ return `${blockCssClassName}-frontend`;
171065
+ }
171066
+ function resolveScaffoldIdentifiers({
171067
+ namespace,
171068
+ phpPrefix,
171069
+ slug,
171070
+ textDomain
171071
+ }) {
171072
+ const normalizedSlug = resolveValidatedBlockSlug(slug);
171073
+ return {
171074
+ namespace: resolveValidatedNamespace(namespace),
171075
+ phpPrefix: resolveValidatedPhpPrefix(phpPrefix ?? normalizedSlug),
171076
+ slug: normalizedSlug,
171077
+ textDomain: resolveValidatedTextDomain(textDomain ?? normalizedSlug)
171078
+ };
171079
+ }
171080
+
171081
+ // ../wp-typia-project-tools/src/runtime/pattern-catalog-section-roles.ts
170927
171082
  import {
170928
171083
  validateBlockPatternContentNesting
170929
171084
  } from "@wp-typia/block-runtime/metadata-core";
170930
- var PATTERN_CATALOG_SCOPE_IDS = ["full", "section"];
170931
- var PATTERN_SLUG_PATTERN = /^[a-z][a-z0-9-]*$/u;
170932
- var PATTERN_SECTION_ROLE_PATTERN = PATTERN_SLUG_PATTERN;
170933
- var PATTERN_TAG_PATTERN = /^[a-z0-9][a-z0-9-]*$/u;
170934
- var PATTERN_CONTENT_FILE_ROOT = "src/patterns/";
171085
+ var PATTERN_SECTION_ROLE_PATTERN = /^[a-z][a-z0-9-]*$/u;
170935
171086
  var DEFAULT_SECTION_ROLE_CONVENTION = {
170936
171087
  baseClassName: "section",
170937
171088
  requireUniqueFullPatternRoles: false,
@@ -170942,20 +171093,6 @@ var DEFAULT_SECTION_ROLE_CONVENTION = {
170942
171093
  function createPatternCatalogDiagnostic(diagnostic) {
170943
171094
  return diagnostic;
170944
171095
  }
170945
- function isPatternCatalogScope(value) {
170946
- return PATTERN_CATALOG_SCOPE_IDS.includes(value);
170947
- }
170948
- function isSafeRelativePath(value) {
170949
- return value.length > 0 && !path.isAbsolute(value) && !value.includes("\\") && !value.split(/[\\/]+/u).includes("..") && !/[<>:"|?*\u0000-\u001F]/u.test(value);
170950
- }
170951
- function isPatternContentFilePath(value) {
170952
- if (!isSafeRelativePath(value) || !value.startsWith(PATTERN_CONTENT_FILE_ROOT) || !value.endsWith(".php")) {
170953
- return false;
170954
- }
170955
- const patternRelativePath = value.slice(PATTERN_CONTENT_FILE_ROOT.length);
170956
- const segments = patternRelativePath.split("/");
170957
- return (segments.length === 1 || segments.length === 2) && segments.every((segment) => segment.length > 0);
170958
- }
170959
171096
  function normalizeSectionRoleConventionInput(convention = {}) {
170960
171097
  return {
170961
171098
  baseClassName: convention.baseClassName ?? DEFAULT_SECTION_ROLE_CONVENTION.baseClassName,
@@ -170975,7 +171112,7 @@ function createRoleClassNamePattern(pattern) {
170975
171112
  }
170976
171113
  return new RegExp(`^${escapeRegExp(parts[0] ?? "")}(?<role>\\S*)${escapeRegExp(parts[1] ?? "")}$`, "u");
170977
171114
  }
170978
- function normalizeSectionRoleConvention(convention = {}) {
171115
+ function normalizePatternCatalogSectionRoleConvention(convention = {}) {
170979
171116
  const normalized = normalizeSectionRoleConventionInput(convention);
170980
171117
  return {
170981
171118
  ...normalized,
@@ -171037,7 +171174,7 @@ function collectSectionRoleMatches(blocks, convention, pathSegments = []) {
171037
171174
  `${block.blockName}[${index}]`
171038
171175
  ];
171039
171176
  const blockPath = blockPathSegments.join(" > ");
171040
- const roles = extractPatternSectionRolesFromAttributes(block.attributes, convention);
171177
+ const roles = extractPatternSectionRolesFromNormalizedAttributes(block.attributes, convention);
171041
171178
  const matches = isSectionWrapperCandidate(block, roles, convention) ? [
171042
171179
  {
171043
171180
  blockName: block.blockName,
@@ -171060,27 +171197,12 @@ function unescapeSerializedBlockCommentJsonQuotes(content) {
171060
171197
  return `<!--${body.replace(/\\"/gu, '"')}-->`;
171061
171198
  });
171062
171199
  }
171063
- function extractPatternSectionRolesFromAttributes(attributes, convention = {}) {
171064
- const normalized = normalizeSectionRoleConvention(convention);
171200
+ function extractPatternSectionRolesFromNormalizedAttributes(attributes, normalized) {
171065
171201
  const classRoles = getClassNameTokens(attributes).map((token) => normalized.roleClassNamePatternRegExp.exec(token)?.groups?.role).filter((role) => typeof role === "string");
171066
171202
  const attributeRoles = normalized.roleAttributePaths.flatMap((pathName) => collectStringValues(getAttributePathValue(attributes, pathName)));
171067
171203
  return uniqueValues([...classRoles, ...attributeRoles]);
171068
171204
  }
171069
- function isValidPatternThumbnailUrl(value) {
171070
- if (value.length === 0) {
171071
- return false;
171072
- }
171073
- try {
171074
- const url = new URL(value);
171075
- return url.protocol === "http:" || url.protocol === "https:";
171076
- } catch {
171077
- return isSafeRelativePath(value);
171078
- }
171079
- }
171080
- function resolvePatternCatalogContentFile(pattern) {
171081
- return pattern.contentFile ?? pattern.file;
171082
- }
171083
- function createKnownSectionRoleSet(patterns) {
171205
+ function collectKnownPatternSectionRoles(patterns) {
171084
171206
  return new Set(patterns.map((pattern) => pattern.sectionRole).filter((sectionRole) => typeof sectionRole === "string" && PATTERN_SECTION_ROLE_PATTERN.test(sectionRole)));
171085
171207
  }
171086
171208
  function validatePatternContentSectionRoles({
@@ -171172,26 +171294,65 @@ function validatePatternContentSectionRoles({
171172
171294
  }
171173
171295
  return diagnostics;
171174
171296
  }
171297
+
171298
+ // ../wp-typia-project-tools/src/runtime/pattern-catalog.ts
171299
+ import fs from "fs";
171300
+ import path from "path";
171301
+ var PATTERN_CATALOG_SCOPE_IDS = ["full", "section"];
171302
+ var PATTERN_SLUG_PATTERN = /^[a-z][a-z0-9-]*$/u;
171303
+ var PATTERN_TAG_PATTERN = /^[a-z0-9][a-z0-9-]*$/u;
171304
+ var PATTERN_CONTENT_FILE_ROOT = "src/patterns/";
171305
+ function createPatternCatalogDiagnostic2(diagnostic) {
171306
+ return diagnostic;
171307
+ }
171308
+ function isPatternCatalogScope(value) {
171309
+ return PATTERN_CATALOG_SCOPE_IDS.includes(value);
171310
+ }
171311
+ function isSafeRelativePath(value) {
171312
+ return value.length > 0 && !path.isAbsolute(value) && !value.includes("\\") && !value.split(/[\\/]+/u).includes("..") && !/[<>:"|?*\u0000-\u001F]/u.test(value);
171313
+ }
171314
+ function isPatternContentFilePath(value) {
171315
+ if (!isSafeRelativePath(value) || !value.startsWith(PATTERN_CONTENT_FILE_ROOT) || !value.endsWith(".php")) {
171316
+ return false;
171317
+ }
171318
+ const patternRelativePath = value.slice(PATTERN_CONTENT_FILE_ROOT.length);
171319
+ const segments = patternRelativePath.split("/");
171320
+ return (segments.length === 1 || segments.length === 2) && segments.every((segment) => segment.length > 0);
171321
+ }
171322
+ function isValidPatternThumbnailUrl(value) {
171323
+ if (value.length === 0) {
171324
+ return false;
171325
+ }
171326
+ try {
171327
+ const url = new URL(value);
171328
+ return url.protocol === "http:" || url.protocol === "https:";
171329
+ } catch {
171330
+ return isSafeRelativePath(value);
171331
+ }
171332
+ }
171333
+ function resolvePatternCatalogContentFile(pattern) {
171334
+ return pattern.contentFile ?? pattern.file;
171335
+ }
171175
171336
  function validatePatternCatalog(patterns, options = {}) {
171176
171337
  const diagnostics = [];
171177
171338
  const seenSlugs = new Map;
171178
171339
  let sectionRoleConvention = null;
171179
171340
  if (options.sectionRoleConvention !== false) {
171180
171341
  try {
171181
- sectionRoleConvention = normalizeSectionRoleConvention(options.sectionRoleConvention);
171342
+ sectionRoleConvention = normalizePatternCatalogSectionRoleConvention(options.sectionRoleConvention);
171182
171343
  } catch (error) {
171183
- diagnostics.push(createPatternCatalogDiagnostic({
171344
+ diagnostics.push(createPatternCatalogDiagnostic2({
171184
171345
  code: "invalid-pattern-section-role-convention",
171185
171346
  message: `sectionRoleConvention.roleClassNamePattern is invalid: ${error instanceof Error ? error.message : String(error)}`,
171186
171347
  severity: "error"
171187
171348
  }));
171188
171349
  }
171189
171350
  }
171190
- const knownSectionRoles = createKnownSectionRoleSet(patterns);
171351
+ const knownSectionRoles = collectKnownPatternSectionRoles(patterns);
171191
171352
  for (const [index, pattern] of patterns.entries()) {
171192
171353
  const label = pattern.slug || `PATTERNS[${index}]`;
171193
171354
  if (!PATTERN_SLUG_PATTERN.test(pattern.slug)) {
171194
- diagnostics.push(createPatternCatalogDiagnostic({
171355
+ diagnostics.push(createPatternCatalogDiagnostic2({
171195
171356
  code: "invalid-pattern-slug",
171196
171357
  message: `${label}: slug must start with a lowercase letter and contain only lowercase letters, numbers, and hyphens.`,
171197
171358
  patternSlug: pattern.slug,
@@ -171200,7 +171361,7 @@ function validatePatternCatalog(patterns, options = {}) {
171200
171361
  }
171201
171362
  const previousIndex = seenSlugs.get(pattern.slug);
171202
171363
  if (previousIndex !== undefined) {
171203
- diagnostics.push(createPatternCatalogDiagnostic({
171364
+ diagnostics.push(createPatternCatalogDiagnostic2({
171204
171365
  code: "duplicate-pattern-slug",
171205
171366
  message: `${label}: duplicate slug already declared at PATTERNS[${previousIndex}].`,
171206
171367
  patternSlug: pattern.slug,
@@ -171211,7 +171372,7 @@ function validatePatternCatalog(patterns, options = {}) {
171211
171372
  }
171212
171373
  const scope = pattern.scope ?? "full";
171213
171374
  if (!isPatternCatalogScope(scope)) {
171214
- diagnostics.push(createPatternCatalogDiagnostic({
171375
+ diagnostics.push(createPatternCatalogDiagnostic2({
171215
171376
  code: "invalid-pattern-scope",
171216
171377
  message: `${label}: scope must be one of ${PATTERN_CATALOG_SCOPE_IDS.join(", ")}.`,
171217
171378
  patternSlug: pattern.slug,
@@ -171219,7 +171380,7 @@ function validatePatternCatalog(patterns, options = {}) {
171219
171380
  }));
171220
171381
  }
171221
171382
  if (scope === "section" && !pattern.sectionRole) {
171222
- diagnostics.push(createPatternCatalogDiagnostic({
171383
+ diagnostics.push(createPatternCatalogDiagnostic2({
171223
171384
  code: "missing-pattern-section-role",
171224
171385
  message: `${label}: section-scoped patterns must declare sectionRole.`,
171225
171386
  patternSlug: pattern.slug,
@@ -171227,7 +171388,7 @@ function validatePatternCatalog(patterns, options = {}) {
171227
171388
  }));
171228
171389
  }
171229
171390
  if (pattern.sectionRole !== undefined && !PATTERN_SECTION_ROLE_PATTERN.test(pattern.sectionRole)) {
171230
- diagnostics.push(createPatternCatalogDiagnostic({
171391
+ diagnostics.push(createPatternCatalogDiagnostic2({
171231
171392
  code: "invalid-pattern-section-role",
171232
171393
  message: `${label}: sectionRole must start with a lowercase letter and contain only lowercase letters, numbers, and hyphens.`,
171233
171394
  patternSlug: pattern.slug,
@@ -171236,7 +171397,7 @@ function validatePatternCatalog(patterns, options = {}) {
171236
171397
  }
171237
171398
  for (const [tagIndex, tag] of (pattern.tags ?? []).entries()) {
171238
171399
  if (!PATTERN_TAG_PATTERN.test(tag)) {
171239
- diagnostics.push(createPatternCatalogDiagnostic({
171400
+ diagnostics.push(createPatternCatalogDiagnostic2({
171240
171401
  code: "invalid-pattern-tag",
171241
171402
  message: `${label}: tags[${tagIndex}] must contain only lowercase letters, numbers, and hyphens.`,
171242
171403
  patternSlug: pattern.slug,
@@ -171245,7 +171406,7 @@ function validatePatternCatalog(patterns, options = {}) {
171245
171406
  }
171246
171407
  }
171247
171408
  if (pattern.thumbnailUrl !== undefined && !isValidPatternThumbnailUrl(pattern.thumbnailUrl)) {
171248
- diagnostics.push(createPatternCatalogDiagnostic({
171409
+ diagnostics.push(createPatternCatalogDiagnostic2({
171249
171410
  code: "invalid-pattern-thumbnail-url",
171250
171411
  message: `${label}: thumbnailUrl must be an http(s) URL or safe relative project path.`,
171251
171412
  patternSlug: pattern.slug,
@@ -171254,7 +171415,7 @@ function validatePatternCatalog(patterns, options = {}) {
171254
171415
  }
171255
171416
  const contentFile = resolvePatternCatalogContentFile(pattern);
171256
171417
  if (!contentFile) {
171257
- diagnostics.push(createPatternCatalogDiagnostic({
171418
+ diagnostics.push(createPatternCatalogDiagnostic2({
171258
171419
  code: "missing-pattern-content-file",
171259
171420
  message: `${label}: contentFile or legacy file must point at the pattern PHP file.`,
171260
171421
  patternSlug: pattern.slug,
@@ -171263,7 +171424,7 @@ function validatePatternCatalog(patterns, options = {}) {
171263
171424
  continue;
171264
171425
  }
171265
171426
  if (!isPatternContentFilePath(contentFile)) {
171266
- diagnostics.push(createPatternCatalogDiagnostic({
171427
+ diagnostics.push(createPatternCatalogDiagnostic2({
171267
171428
  code: "invalid-pattern-content-file",
171268
171429
  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.`,
171269
171430
  patternSlug: pattern.slug,
@@ -171276,7 +171437,7 @@ function validatePatternCatalog(patterns, options = {}) {
171276
171437
  }
171277
171438
  const absoluteContentFile = path.join(options.projectDir, contentFile);
171278
171439
  if (!fs.existsSync(absoluteContentFile)) {
171279
- diagnostics.push(createPatternCatalogDiagnostic({
171440
+ diagnostics.push(createPatternCatalogDiagnostic2({
171280
171441
  code: "missing-pattern-content-file",
171281
171442
  message: `${label}: missing pattern content file ${contentFile}.`,
171282
171443
  patternSlug: pattern.slug,
@@ -171289,7 +171450,7 @@ function validatePatternCatalog(patterns, options = {}) {
171289
171450
  try {
171290
171451
  content = fs.readFileSync(absoluteContentFile, "utf8");
171291
171452
  } catch (error) {
171292
- diagnostics.push(createPatternCatalogDiagnostic({
171453
+ diagnostics.push(createPatternCatalogDiagnostic2({
171293
171454
  code: "invalid-pattern-content-file",
171294
171455
  message: `${label}: failed to read pattern content file ${contentFile}: ${error instanceof Error ? error.message : String(error)}.`,
171295
171456
  patternSlug: pattern.slug,
@@ -171374,85 +171535,6 @@ var HOOKED_BLOCK_POSITION_IDS = ["before", "after", "firstChild", "lastChild"];
171374
171535
  var HOOKED_BLOCK_POSITION_SET = new Set(HOOKED_BLOCK_POSITION_IDS);
171375
171536
  var HOOKED_BLOCK_ANCHOR_PATTERN = /^[a-z0-9-]+\/[a-z0-9-]+$/;
171376
171537
 
171377
- // ../wp-typia-project-tools/src/runtime/string-case.ts
171378
- var COMMON_ACRONYM_PREFIXES = [
171379
- "HTML",
171380
- "HTTP",
171381
- "JSON",
171382
- "REST",
171383
- "UUID",
171384
- "AJAX",
171385
- "API",
171386
- "CPT",
171387
- "CSS",
171388
- "CTA",
171389
- "DOM",
171390
- "PHP",
171391
- "SQL",
171392
- "SVG",
171393
- "URL",
171394
- "XML",
171395
- "ID",
171396
- "JS",
171397
- "UI",
171398
- "WP"
171399
- ];
171400
- var COMMON_ACRONYM_LOWERCASE_SUFFIXES = ["slug"];
171401
- function capitalizeSegment(segment) {
171402
- return segment.charAt(0).toUpperCase() + segment.slice(1);
171403
- }
171404
- function findCommonAcronymPrefix(segment) {
171405
- return COMMON_ACRONYM_PREFIXES.find((prefix) => segment.startsWith(prefix));
171406
- }
171407
- function isCommonAcronymLowercaseSuffix(suffix) {
171408
- return COMMON_ACRONYM_LOWERCASE_SUFFIXES.includes(suffix);
171409
- }
171410
- function splitKnownAcronymSegment(segment) {
171411
- const prefixes = [];
171412
- let remaining = segment;
171413
- while (remaining.length > 0) {
171414
- const prefix = findCommonAcronymPrefix(remaining);
171415
- if (!prefix) {
171416
- break;
171417
- }
171418
- const suffix = remaining.slice(prefix.length);
171419
- if (/^[A-Z][a-z]/.test(suffix)) {
171420
- return [...prefixes, prefix, suffix].join("-");
171421
- }
171422
- if (/^[a-z]+$/.test(suffix) && isCommonAcronymLowercaseSuffix(suffix)) {
171423
- return [...prefixes, prefix, suffix].join("-");
171424
- }
171425
- if (!findCommonAcronymPrefix(suffix)) {
171426
- break;
171427
- }
171428
- prefixes.push(prefix);
171429
- remaining = suffix;
171430
- }
171431
- return segment;
171432
- }
171433
- function splitAcronymBoundary(value) {
171434
- return value.replace(/[A-Z]{2,}[a-z]+/g, splitKnownAcronymSegment);
171435
- }
171436
- function toKebabCase(input) {
171437
- return splitAcronymBoundary(input.trim()).replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/[^A-Za-z0-9]+/g, "-").replace(/^-+|-+$/g, "").replace(/-{2,}/g, "-").toLowerCase();
171438
- }
171439
- function toSnakeCase(input) {
171440
- return toKebabCase(input).replace(/-/g, "_");
171441
- }
171442
- function toPascalCase(input) {
171443
- return toKebabCase(input).split("-").filter(Boolean).map(capitalizeSegment).join("");
171444
- }
171445
- function toCamelCase(input) {
171446
- const pascalCase = toPascalCase(input);
171447
- return `${pascalCase.charAt(0).toLowerCase()}${pascalCase.slice(1)}`;
171448
- }
171449
- function toSegmentPascalCase(input) {
171450
- return input.replace(/[^A-Za-z0-9]+/g, " ").trim().split(/\s+/).filter(Boolean).map(capitalizeSegment).join("");
171451
- }
171452
- function toTitleCase(input) {
171453
- return toKebabCase(input).split("-").filter(Boolean).map(capitalizeSegment).join(" ");
171454
- }
171455
-
171456
171538
  // ../wp-typia-project-tools/src/runtime/cli-add-validation.ts
171457
171539
  var WORKSPACE_GENERATED_SLUG_PATTERN = /^[a-z][a-z0-9-]*$/;
171458
171540
  var WORDPRESS_POST_TYPE_PATTERN = /^[a-z0-9_][a-z0-9_-]*$/u;
@@ -171790,7 +171872,7 @@ function formatAddHelpText() {
171790
171872
  wp-typia add variation <name> --block <block-slug> [--dry-run]
171791
171873
  wp-typia add style <name> --block <block-slug> [--dry-run]
171792
171874
  wp-typia add transform <name> --from <namespace/block> --to <block-slug|namespace/block-slug> [--dry-run]
171793
- wp-typia add pattern <name> [--scope <full|section>] [--section-role <role>] [--tags <tag,...>] [--thumbnail-url <url>] [--dry-run]
171875
+ wp-typia add pattern <name> [--scope <full|section>] [--section-role <role>] [--catalog-title <title>] [--tags <tag,...>] [--tag <tag>...] [--thumbnail-url <url>] [--dry-run]
171794
171876
  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]
171795
171877
  wp-typia add contract <name> [--type <ExportedTypeName>] [--dry-run]
171796
171878
  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]
@@ -171806,6 +171888,7 @@ Notes:
171806
171888
  Pass \`--dry-run\` to preview the workspace files that would change without writing them.
171807
171889
  Interactive add flows let you choose a template when \`--template\` is omitted; non-interactive runs default to \`basic\`.
171808
171890
  \`add core-variation\` registers editor-side variations for existing core or external blocks without generating block.json or Typia manifests.
171891
+ Unknown \`core/*\` core-variation targets warn instead of failing so newer WordPress core blocks remain scaffoldable; third-party namespaces are allowed without local discovery.
171809
171892
  \`add admin-view\` scaffolds an opt-in DataViews-powered WordPress admin screen under \`src/admin-views/\`.
171810
171893
  Pass \`--source rest-resource:<slug>\` to reuse a list-capable REST resource.
171811
171894
  Pass \`--source core-data:postType/post\` or \`--source core-data:taxonomy/category\` to bind a WordPress-owned entity collection.
@@ -171817,7 +171900,7 @@ Notes:
171817
171900
  \`add variation\` targets an existing block slug from \`scripts/block-config.ts\`.
171818
171901
  \`add style\` registers a Block Styles option for an existing generated block.
171819
171902
  \`add transform\` adds a block-to-block transform into an existing generated block.
171820
- \`add pattern\` scaffolds a namespaced PHP pattern shell under \`src/patterns/full/\` or \`src/patterns/sections/\` and records typed catalog metadata in \`PATTERNS\`.
171903
+ \`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.
171821
171904
  \`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.
171822
171905
  \`add contract\` registers a standalone TypeScript wire contract under \`src/contracts/\` and generates a stable JSON Schema artifact without creating PHP route glue.
171823
171906
  \`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.
@@ -171828,84 +171911,6 @@ Notes:
171828
171911
  \`add hooked-block\` patches an existing workspace block's \`block.json\` \`blockHooks\` metadata.
171829
171912
  \`add editor-plugin\` scaffolds a document-level editor extension under \`src/editor-plugins/\`; legacy aliases \`PluginSidebar\` and \`PluginDocumentSettingPanel\` resolve to \`sidebar\` and \`document-setting-panel\`.`;
171830
171913
  }
171831
-
171832
- // ../wp-typia-project-tools/src/runtime/scaffold-identifiers.ts
171833
- var BLOCK_SLUG_PATTERN = /^[a-z][a-z0-9-]*$/;
171834
- var PHP_PREFIX_PATTERN = /^[a-z_][a-z0-9_]*$/;
171835
- var PHP_PREFIX_MAX_LENGTH = 50;
171836
- function validateBlockSlug(input) {
171837
- return BLOCK_SLUG_PATTERN.test(input) || "Use lowercase letters, numbers, and hyphens only";
171838
- }
171839
- function validateNamespace(input) {
171840
- return BLOCK_SLUG_PATTERN.test(toKebabCase(input)) ? true : "Use lowercase letters, numbers, and hyphens only";
171841
- }
171842
- function validateTextDomain(input) {
171843
- return BLOCK_SLUG_PATTERN.test(toKebabCase(input)) ? true : "Use lowercase letters, numbers, and hyphens only";
171844
- }
171845
- function validatePhpPrefix(input) {
171846
- const normalizedPrefix = toSnakeCase(input);
171847
- if (normalizedPrefix.length > PHP_PREFIX_MAX_LENGTH) {
171848
- return `Use ${PHP_PREFIX_MAX_LENGTH} characters or fewer to keep generated database identifiers within MySQL limits`;
171849
- }
171850
- return PHP_PREFIX_PATTERN.test(normalizedPrefix) ? true : "Use letters, numbers, and underscores only, starting with a letter";
171851
- }
171852
- function assertValidIdentifier(label, value, validate) {
171853
- const result = validate(value);
171854
- if (result !== true) {
171855
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, typeof result === "string" ? `${label}: ${result}` : `${label} is invalid`);
171856
- }
171857
- return value;
171858
- }
171859
- function normalizeBlockSlug(input) {
171860
- return toKebabCase(input);
171861
- }
171862
- function resolveNonEmptyNormalizedBlockSlug(options) {
171863
- const normalizedSlug = normalizeBlockSlug(options.input);
171864
- if (normalizedSlug.length > 0) {
171865
- return normalizedSlug;
171866
- }
171867
- if (options.input.trim().length === 0) {
171868
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, `${options.label} is required. Use \`${options.usage}\`.`);
171869
- }
171870
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, `${options.label} "${options.input.trim()}" normalizes to an empty slug. Use letters or numbers so wp-typia can generate a block slug.`);
171871
- }
171872
- function resolveValidatedBlockSlug(value) {
171873
- return assertValidIdentifier("Block slug", normalizeBlockSlug(value), validateBlockSlug);
171874
- }
171875
- function resolveValidatedNamespace(value) {
171876
- return assertValidIdentifier("Namespace", toKebabCase(value), validateNamespace);
171877
- }
171878
- function resolveValidatedTextDomain(value) {
171879
- return assertValidIdentifier("Text domain", toKebabCase(value), validateTextDomain);
171880
- }
171881
- function resolveValidatedPhpPrefix(value) {
171882
- return assertValidIdentifier("PHP prefix", toSnakeCase(value), validatePhpPrefix);
171883
- }
171884
- function buildBlockCssClassName(namespace, slug) {
171885
- const normalizedSlug = resolveValidatedBlockSlug(slug);
171886
- const normalizedNamespace = typeof namespace === "string" && namespace.trim().length > 0 ? resolveValidatedNamespace(namespace) : "";
171887
- if (normalizedNamespace === normalizedSlug) {
171888
- return `wp-block-${normalizedSlug}-block`;
171889
- }
171890
- return normalizedNamespace.length > 0 ? `wp-block-${normalizedNamespace}-${normalizedSlug}` : `wp-block-${normalizedSlug}`;
171891
- }
171892
- function buildFrontendCssClassName(blockCssClassName) {
171893
- return `${blockCssClassName}-frontend`;
171894
- }
171895
- function resolveScaffoldIdentifiers({
171896
- namespace,
171897
- phpPrefix,
171898
- slug,
171899
- textDomain
171900
- }) {
171901
- const normalizedSlug = resolveValidatedBlockSlug(slug);
171902
- return {
171903
- namespace: resolveValidatedNamespace(namespace),
171904
- phpPrefix: resolveValidatedPhpPrefix(phpPrefix ?? normalizedSlug),
171905
- slug: normalizedSlug,
171906
- textDomain: resolveValidatedTextDomain(textDomain ?? normalizedSlug)
171907
- };
171908
- }
171909
171914
  // ../wp-typia-project-tools/src/runtime/cli-add-filesystem.ts
171910
171915
  import { promises as fsp2 } from "fs";
171911
171916
  import path2 from "path";
@@ -173811,6 +173816,6 @@ async function appendWorkspaceInventoryEntries(projectDir, options) {
173811
173816
  await writeFile(blockConfigPath, nextSource, "utf8");
173812
173817
  }
173813
173818
  }
173814
- export { toKebabCase, toSnakeCase, toPascalCase, toCamelCase, toSegmentPascalCase, toTitleCase, validateBlockSlug, validateNamespace, normalizeBlockSlug, resolveNonEmptyNormalizedBlockSlug, buildBlockCssClassName, buildFrontendCssClassName, resolveScaffoldIdentifiers, PATTERN_CATALOG_SCOPE_IDS, isValidPatternThumbnailUrl, resolvePatternCatalogContentFile, validatePatternCatalog, formatPatternCatalogDiagnostics, REST_RESOURCE_METHOD_IDS, MANUAL_REST_CONTRACT_HTTP_METHOD_IDS, MANUAL_REST_CONTRACT_AUTH_IDS, EDITOR_PLUGIN_SLOT_IDS, resolveEditorPluginSlotAlias, ADD_BLOCK_TEMPLATE_IDS, suggestAddBlockTemplateId, HOOKED_BLOCK_POSITION_SET, HOOKED_BLOCK_ANCHOR_PATTERN, REST_RESOURCE_NAMESPACE_PATTERN, assertValidGeneratedSlug, assertValidTypeScriptIdentifier, resolveRestResourceNamespace, assertValidPostMetaPostType, resolvePostMetaKey, assertValidRestResourceMethods, resolveOptionalPhpCallbackReference, resolveOptionalPhpClassReference, assertValidManualRestContractHttpMethod, assertValidManualRestContractAuth, isGeneratedRestResourceRoutePatternCompatible, collectRestRouteNamedCaptureNames, resolveManualRestContractPathPattern, resolveGeneratedRestResourceRoutePattern, assertValidHookedBlockPosition, buildWorkspacePhpPrefix, isAddBlockTemplateId, quoteTsString, assertValidHookAnchor, assertValidEditorPluginSlot, assertValidIntegrationEnvService, pathExists, readOptionalUtf8File, getNodeErrorCode, getOptionalNodeErrorCode, isFileNotFoundError, getWorkspaceBootstrapPath, patchFile, readOptionalFile, snapshotWorkspaceFiles, rollbackWorkspaceMutation, resolveWorkspaceBlock, readWorkspaceBlockJson, getMutableBlockHooks, assertVariationDoesNotExist, assertBlockStyleDoesNotExist, assertBlockTransformDoesNotExist, assertPatternDoesNotExist, assertBindingSourceDoesNotExist, assertRestResourceDoesNotExist, assertPostMetaDoesNotExist, assertContractDoesNotExist, assertAdminViewDoesNotExist, assertAbilityDoesNotExist, assertAiFeatureDoesNotExist, assertEditorPluginDoesNotExist, formatAddHelpText, require_typescript, getPropertyNameText, readWorkspaceInventory, readWorkspaceInventoryAsync, getWorkspaceBlockSelectOptions, getWorkspaceBlockSelectOptionsAsync, escapeRegex, quotePhpString, hasPhpFunctionDefinition, hasPhpFunctionCall, findPhpFunctionRange, replacePhpFunctionDefinition, updateWorkspaceInventorySource, appendWorkspaceInventoryEntries };
173819
+ export { toKebabCase, toSnakeCase, toPascalCase, toCamelCase, toSegmentPascalCase, toTitleCase, validateBlockSlug, validateNamespace, normalizeBlockSlug, resolveNonEmptyNormalizedBlockSlug, buildBlockCssClassName, buildFrontendCssClassName, resolveScaffoldIdentifiers, PATTERN_SECTION_ROLE_PATTERN, PATTERN_CATALOG_SCOPE_IDS, PATTERN_TAG_PATTERN, isValidPatternThumbnailUrl, resolvePatternCatalogContentFile, validatePatternCatalog, formatPatternCatalogDiagnostics, REST_RESOURCE_METHOD_IDS, MANUAL_REST_CONTRACT_HTTP_METHOD_IDS, MANUAL_REST_CONTRACT_AUTH_IDS, EDITOR_PLUGIN_SLOT_IDS, resolveEditorPluginSlotAlias, ADD_BLOCK_TEMPLATE_IDS, suggestAddBlockTemplateId, HOOKED_BLOCK_POSITION_SET, HOOKED_BLOCK_ANCHOR_PATTERN, REST_RESOURCE_NAMESPACE_PATTERN, assertValidGeneratedSlug, assertValidTypeScriptIdentifier, resolveRestResourceNamespace, assertValidPostMetaPostType, resolvePostMetaKey, assertValidRestResourceMethods, resolveOptionalPhpCallbackReference, resolveOptionalPhpClassReference, assertValidManualRestContractHttpMethod, assertValidManualRestContractAuth, isGeneratedRestResourceRoutePatternCompatible, collectRestRouteNamedCaptureNames, resolveManualRestContractPathPattern, resolveGeneratedRestResourceRoutePattern, assertValidHookedBlockPosition, buildWorkspacePhpPrefix, isAddBlockTemplateId, quoteTsString, assertValidHookAnchor, assertValidEditorPluginSlot, assertValidIntegrationEnvService, pathExists, readOptionalUtf8File, getNodeErrorCode, getOptionalNodeErrorCode, isFileNotFoundError, getWorkspaceBootstrapPath, patchFile, readOptionalFile, snapshotWorkspaceFiles, rollbackWorkspaceMutation, resolveWorkspaceBlock, readWorkspaceBlockJson, getMutableBlockHooks, assertVariationDoesNotExist, assertBlockStyleDoesNotExist, assertBlockTransformDoesNotExist, assertPatternDoesNotExist, assertBindingSourceDoesNotExist, assertRestResourceDoesNotExist, assertPostMetaDoesNotExist, assertContractDoesNotExist, assertAdminViewDoesNotExist, assertAbilityDoesNotExist, assertAiFeatureDoesNotExist, assertEditorPluginDoesNotExist, formatAddHelpText, require_typescript, getPropertyNameText, readWorkspaceInventory, readWorkspaceInventoryAsync, getWorkspaceBlockSelectOptions, getWorkspaceBlockSelectOptionsAsync, escapeRegex, quotePhpString, hasPhpFunctionDefinition, hasPhpFunctionCall, findPhpFunctionRange, replacePhpFunctionDefinition, updateWorkspaceInventorySource, appendWorkspaceInventoryEntries };
173815
173820
 
173816
- //# debugId=7B77B39B1AF35AE264756E2164756E21
173821
+ //# debugId=9E60A37E69B52ED864756E2164756E21
@@ -21,19 +21,19 @@ import {
21
21
  resolvePackageManagerId,
22
22
  resolveTemplateId,
23
23
  scaffoldProject
24
- } from "./cli-74y6z3yx.js";
24
+ } from "./cli-4eqznv15.js";
25
25
  import"./cli-9fx0qgb7.js";
26
- import"./cli-sw06c521.js";
27
- import"./cli-y0a8nztv.js";
26
+ import"./cli-vxd8eyax.js";
27
+ import"./cli-wfvf3tv1.js";
28
28
  import {
29
29
  OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE,
30
30
  isBuiltInTemplateId
31
31
  } from "./cli-8hxf9qw6.js";
32
- import"./cli-0v407aag.js";
32
+ import"./cli-6ys6d16y.js";
33
33
  import"./cli-e4bwd81c.js";
34
34
  import {
35
35
  pathExists
36
- } from "./cli-v0nnagb3.js";
36
+ } from "./cli-kbqztfkt.js";
37
37
  import"./cli-cvxvcw7c.js";
38
38
  import {
39
39
  createManagedTempRoot
@@ -11,7 +11,7 @@ import {
11
11
  } from "./cli-8hxf9qw6.js";
12
12
  import {
13
13
  pathExists
14
- } from "./cli-v0nnagb3.js";
14
+ } from "./cli-kbqztfkt.js";
15
15
  import {
16
16
  createManagedTempRoot
17
17
  } from "./cli-t73q5aqz.js";