@neopress/cli 4.8.1 → 4.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin.cjs CHANGED
@@ -26407,6 +26407,7 @@ function serializeTemplate(t) {
26407
26407
  referenceUrl: t.reference_url,
26408
26408
  previewImgUrls: t.preview_img_urls,
26409
26409
  previewVideoUrl: t.preview_video_url ?? null,
26410
+ language: t.language ?? null,
26410
26411
  createdAt: t.created_at
26411
26412
  };
26412
26413
  }
@@ -30438,7 +30439,7 @@ var TemplatesEndpoint = class {
30438
30439
  if (siteIds.length === 0) return [];
30439
30440
  const namePrefix = params?.namePrefix?.trim();
30440
30441
  const limit = Math.min(Math.max(params?.limit ?? 100, 1), 500);
30441
- let query = this.client.db.from("templates").select("id, name, reference_url, preview_img_urls, description, created_at").in("id", siteIds);
30442
+ let query = this.client.db.from("templates").select("id, name, reference_url, preview_img_urls, description, language, created_at").in("id", siteIds);
30442
30443
  if (namePrefix) query = query.ilike("name", `${namePrefix}%`);
30443
30444
  if (params?.order) query = query.order("created_at", { ascending: params.order === "asc" });
30444
30445
  query = query.limit(limit);
@@ -30454,6 +30455,7 @@ var TemplatesEndpoint = class {
30454
30455
  referenceUrl: t.reference_url,
30455
30456
  previewImgUrls: t.preview_img_urls ?? null,
30456
30457
  description: t.description ?? null,
30458
+ language: t.language ?? null,
30457
30459
  createdAt: t.created_at
30458
30460
  };
30459
30461
  });
@@ -31019,7 +31021,7 @@ Draft content fields (--tsx/--i18n/--draft-meta) need \`neopress publish\` to go
31019
31021
  pages.command("get <pageId>").description("Get page details").action(async (pageId) => {
31020
31022
  output(await (await getClientAsync()).pages.get(parseInt(pageId, 10)));
31021
31023
  });
31022
- pages.command("create").description("Create a new page").requiredOption("--path <path>", "Page path (e.g., /about)").option("--title <title>", "Page title").option("--tsx <file>", "TSX file path").option("--i18n <json>", "Page i18n JSON string or @file path").option("--public-locales <locales>", "Comma-separated locale list or JSON string array").option("--metadata <json>", "Page metadata JSON string or @file path").option("--draft-meta <json>", "Draft runtime metadata JSON string or @file path").option("--query-config <json>", "Query config JSON string or @file path; stored as draftMeta.queryConfig").option("--collection <id>", "Collection ID for dynamic pages").option("--type <type>", "Page type (static/dynamic)", "static").addHelpText("after", `
31024
+ pages.command("create").description("Create a new page").requiredOption("--path <path>", "Page path (e.g., /about)").option("--title <title>", "Page title").option("--tsx <file>", "TSX file path").option("--i18n <json>", "Page i18n JSON string or @file path").option("--public-locales <locales>", "Comma-separated locale list or JSON string array").option("--metadata <json>", "Page metadata JSON string or @file path").option("--draft-meta <json>", "Draft runtime metadata JSON string or @file path").option("--query-config <json>", "Query config JSON string or @file path (including collectionWindow bindings); stored as draftMeta.queryConfig").option("--collection <id>", "Collection ID for dynamic pages").option("--type <type>", "Page type (static/dynamic)", "static").addHelpText("after", `
31023
31025
  Examples:
31024
31026
  $ neopress pages create --path /about --title About --tsx ./about.tsx
31025
31027
  $ neopress pages create --path /blog --type dynamic --collection 12 --tsx ./blog.tsx
@@ -31052,7 +31054,7 @@ Examples:
31052
31054
  $ neopress pages update 12 --title About --path /about-us
31053
31055
  $ neopress pages update 12 --collection 12 --query-config @query.json
31054
31056
 
31055
- Pass at least one field flag. --tsx reads the component from a file; JSON options take inline JSON or @file. Draft content (--tsx/--i18n/--draft-meta/--query-config) needs \`neopress publish\` to go live; --title/--path/--collection apply immediately.`).option("--path <path>", "New page path").option("--title <title>", "New title").option("--tsx <file>", "TSX file path").option("--i18n <json>", "Page i18n JSON string or @file path").option("--public-locales <locales>", "Comma-separated locale list or JSON string array").option("--metadata <json>", "Page metadata JSON string or @file path").option("--draft-meta <json>", "Draft runtime metadata JSON string or @file path").option("--query-config <json>", "Query config JSON string or @file path; stored as draftMeta.queryConfig").option("--collection <id>", "Collection ID for dynamic pages").action(async (pageId, options) => {
31057
+ Pass at least one field flag. --tsx reads the component from a file; JSON options take inline JSON or @file. Draft content (--tsx/--i18n/--draft-meta/--query-config) needs \`neopress publish\` to go live; --title/--path/--collection apply immediately.`).option("--path <path>", "New page path").option("--title <title>", "New title").option("--tsx <file>", "TSX file path").option("--i18n <json>", "Page i18n JSON string or @file path").option("--public-locales <locales>", "Comma-separated locale list or JSON string array").option("--metadata <json>", "Page metadata JSON string or @file path").option("--draft-meta <json>", "Draft runtime metadata JSON string or @file path").option("--query-config <json>", "Query config JSON string or @file path (including collectionWindow bindings); stored as draftMeta.queryConfig").option("--collection <id>", "Collection ID for dynamic pages").action(async (pageId, options) => {
31056
31058
  const client = await getClientAsync();
31057
31059
  const data = {};
31058
31060
  if (options.path) data.path = options.path;
@@ -31527,13 +31529,21 @@ Examples:
31527
31529
  }
31528
31530
  //#endregion
31529
31531
  //#region src/commands/templates.ts
31532
+ /**
31533
+ * Template commands
31534
+ */
31530
31535
  function collectPreviewImgUrl(value, previous = []) {
31531
31536
  return previous.concat(value);
31532
31537
  }
31538
+ function parseLanguage(value) {
31539
+ const language = value.trim().toLowerCase();
31540
+ if (!/^[a-z]{2}$/.test(language)) throw new InvalidArgumentError("must be a two-letter ISO 639-1 language code (e.g. ko, en, es)");
31541
+ return language;
31542
+ }
31533
31543
  function registerTemplateCommands(program) {
31534
31544
  const templates = program.command("templates").description("Manage template metadata for the active site").addHelpText("after", `
31535
31545
  Examples:
31536
- $ neopress templates mark --name "SaaS Landing" --reference-url https://example.com --preview-img-url https://cdn.example.com/1.png
31546
+ $ neopress templates mark --name "SaaS Landing" --reference-url https://example.com --language en --preview-img-url https://cdn.example.com/1.png
31537
31547
  $ neopress templates list --limit 50
31538
31548
  $ neopress templates delete
31539
31549
  \`templates mark\` operates on the active site. \`templates delete\` permanently removes the template metadata AND the connected site — it is destructive and not recoverable.`);
@@ -31549,14 +31559,15 @@ Examples:
31549
31559
  });
31550
31560
  templates.command("mark").description("Mark or update the active site as a template").addHelpText("after", `
31551
31561
  Examples:
31552
- $ neopress templates mark --name "SaaS Landing" --reference-url https://example.com --preview-img-url https://cdn.example.com/1.png
31553
- $ neopress templates mark --name Portfolio --reference-url https://example.com --preview-img-url https://cdn.example.com/a.png --preview-img-url https://cdn.example.com/b.png --description "Minimal portfolio"
31554
- $ neopress templates mark --name "SaaS Landing" --reference-url https://example.com --preview-img-url https://cdn.example.com/poster.webp --preview-video-url https://cdn.example.com/preview.webm
31555
- --name and --reference-url are required, and at least one --preview-img-url must be given (repeat the flag for multiple images). --preview-video-url is the gallery hover video; pair it with the poster (its first frame) as the first --preview-img-url. Upserts the template metadata for the active site and sets the site status to active; running it again updates the existing template.`).requiredOption("--name <name>", "Template display name").option("--description <description>", "Template description, up to 150 characters").requiredOption("--reference-url <url>", "Reference URL for template provenance").option("--preview-img-url <url>", "Preview image URL (required — at least one). Repeat for multiple images.", collectPreviewImgUrl, []).option("--preview-video-url <url>", "Preview video URL played on gallery hover. The first --preview-img-url should be this video's first frame.").action(async (options) => {
31562
+ $ neopress templates mark --name "SaaS Landing" --reference-url https://example.com --language en --preview-img-url https://cdn.example.com/1.png
31563
+ $ neopress templates mark --name Portfolio --reference-url https://example.com --language ko --preview-img-url https://cdn.example.com/a.png --preview-img-url https://cdn.example.com/b.png --description "Minimal portfolio"
31564
+ $ neopress templates mark --name "SaaS Landing" --reference-url https://example.com --language es --preview-img-url https://cdn.example.com/poster.webp --preview-video-url https://cdn.example.com/preview.webm
31565
+ --name, --reference-url, and --language are required, and at least one --preview-img-url must be given (repeat the flag for multiple images). --language is the language the template's own content is written in, as a two-letter ISO 639-1 code (ko, en, es) — not a region locale like en-US. --preview-video-url is the gallery hover video; pair it with the poster (its first frame) as the first --preview-img-url. Upserts the template metadata for the active site and sets the site status to active; running it again updates the existing template.`).requiredOption("--name <name>", "Template display name").option("--description <description>", "Template description, up to 150 characters").requiredOption("--reference-url <url>", "Reference URL for template provenance").requiredOption("--language <code>", "Primary language of the template content, as a two-letter ISO 639-1 code (e.g. ko, en, es)", parseLanguage).option("--preview-img-url <url>", "Preview image URL (required — at least one). Repeat for multiple images.", collectPreviewImgUrl, []).option("--preview-video-url <url>", "Preview video URL played on gallery hover. The first --preview-img-url should be this video's first frame.").action(async (options) => {
31556
31566
  output(await (await getClientAsync()).templates.mark({
31557
31567
  name: options.name,
31558
31568
  description: options.description,
31559
31569
  referenceUrl: options.referenceUrl,
31570
+ language: options.language,
31560
31571
  previewImgUrls: options.previewImgUrl.length > 0 ? options.previewImgUrl : void 0,
31561
31572
  previewVideoUrl: options.previewVideoUrl
31562
31573
  }));
@@ -31913,7 +31924,7 @@ function registerGuideCommands(program) {
31913
31924
  * Designed for use with Claude Code and other AI tools via --json mode.
31914
31925
  */
31915
31926
  const program = new Command();
31916
- program.name("neopress").description("Neopress CLI — manage your site from the terminal").version("4.8.1").option("--json", "Output in JSON format (for AI tools and pipes)").option("--site <idOrHandle>", "Target a specific site (overrides active site; not persisted)").option("--no-input", "Non-interactive mode").hook("preAction", (thisCommand) => {
31927
+ program.name("neopress").description("Neopress CLI — manage your site from the terminal").version("4.9.0").option("--json", "Output in JSON format (for AI tools and pipes)").option("--site <idOrHandle>", "Target a specific site (overrides active site; not persisted)").option("--no-input", "Non-interactive mode").hook("preAction", (thisCommand) => {
31917
31928
  const opts = thisCommand.optsWithGlobals();
31918
31929
  if (opts.site) setSiteOverride(String(opts.site));
31919
31930
  if (opts.json || !process.stdout.isTTY) setJsonMode(true);
package/dist/index.d.ts CHANGED
@@ -44,6 +44,8 @@ interface Template {
44
44
  referenceUrl: string;
45
45
  previewImgUrls: string[] | null;
46
46
  previewVideoUrl: string | null;
47
+ /** Primary language of the template's content, as an ISO 639-1 code (ko/en/es). */
48
+ language: string | null;
47
49
  createdAt: string | null;
48
50
  }
49
51
  interface TemplateListItem {
@@ -54,6 +56,7 @@ interface TemplateListItem {
54
56
  referenceUrl: string;
55
57
  previewImgUrls: string[] | null;
56
58
  description: string | null;
59
+ language: string | null;
57
60
  createdAt: string;
58
61
  }
59
62
  interface Page {
@@ -600,6 +603,11 @@ interface TemplateMarkParams {
600
603
  * card cross-fades from poster to video, so the poster must be the video's
601
604
  * first frame. Omit to leave an existing value untouched; `null` clears it. */
602
605
  previewVideoUrl?: string | null;
606
+ /** Primary language of the template's content — required, ISO 639-1 lowercase
607
+ * two-letter code (`ko`, `en`, `es`). Region-qualified locales (`en-US`) are
608
+ * rejected: the gallery filters on this key and must not see one language
609
+ * under two spellings. */
610
+ language: string;
603
611
  }
604
612
  interface TemplateDeleteResult {
605
613
  siteId: number;
package/dist/index.js CHANGED
@@ -22982,6 +22982,7 @@ function serializeTemplate(t) {
22982
22982
  referenceUrl: t.reference_url,
22983
22983
  previewImgUrls: t.preview_img_urls,
22984
22984
  previewVideoUrl: t.preview_video_url ?? null,
22985
+ language: t.language ?? null,
22985
22986
  createdAt: t.created_at
22986
22987
  };
22987
22988
  }
@@ -27013,7 +27014,7 @@ var TemplatesEndpoint = class {
27013
27014
  if (siteIds.length === 0) return [];
27014
27015
  const namePrefix = params?.namePrefix?.trim();
27015
27016
  const limit = Math.min(Math.max(params?.limit ?? 100, 1), 500);
27016
- let query = this.client.db.from("templates").select("id, name, reference_url, preview_img_urls, description, created_at").in("id", siteIds);
27017
+ let query = this.client.db.from("templates").select("id, name, reference_url, preview_img_urls, description, language, created_at").in("id", siteIds);
27017
27018
  if (namePrefix) query = query.ilike("name", `${namePrefix}%`);
27018
27019
  if (params?.order) query = query.order("created_at", { ascending: params.order === "asc" });
27019
27020
  query = query.limit(limit);
@@ -27029,6 +27030,7 @@ var TemplatesEndpoint = class {
27029
27030
  referenceUrl: t.reference_url,
27030
27031
  previewImgUrls: t.preview_img_urls ?? null,
27031
27032
  description: t.description ?? null,
27033
+ language: t.language ?? null,
27032
27034
  createdAt: t.created_at
27033
27035
  };
27034
27036
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neopress/cli",
3
- "version": "4.8.1",
3
+ "version": "4.9.0",
4
4
  "description": "Neopress CLI — manage your Neopress site from the terminal",
5
5
  "type": "module",
6
6
  "keywords": [