@avocadostudio-ai/cli 0.3.2 → 0.4.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/README.md CHANGED
@@ -1,8 +1,31 @@
1
1
  # @avocadostudio-ai/cli
2
2
 
3
- Self-host launcher for the Avocado Studio editor UI. Serves a prebuilt editor bundle and points it at any [Avocado Studio orchestrator](https://github.com/avocadostudio-ai/avocado) you control.
3
+ Self-host launcher for the Avocado Studio editor UI. Serves a prebuilt editor bundle and points it at any Avocado Studio orchestrator you control.
4
4
 
5
- ## Quick Start
5
+ **This package is the editor UI and nothing else.** There is no third service to
6
+ deploy, and for most sites there is no separate orchestrator to deploy either —
7
+ see [Library mode](#library-mode-the-common-case) before following the Quick
8
+ Start, which describes the standalone deployment.
9
+
10
+ ## Library mode: the common case
11
+
12
+ If your site mounts `createOrchestrator` from `@avocadostudio-ai/site-sdk` — the
13
+ path the [integration docs](https://docs.avocadostudio.dev/integration/nextjs-integration)
14
+ describe — the orchestrator is already running *inside your site*, at
15
+ `/api/avocado`. Point the CLI at it:
16
+
17
+ ```bash
18
+ npx @avocadostudio-ai/cli start \
19
+ --orchestrator http://localhost:3000/api/avocado \
20
+ --preview http://localhost:3000
21
+ ```
22
+
23
+ Two commands total, in two terminals: your `dev` script, and this. Substitute
24
+ your own port — `3000` is the Next.js default, not a requirement. The default
25
+ `--orchestrator` value below (`http://localhost:4200`) is for the standalone
26
+ server and is **wrong for library mode**; pass the flag.
27
+
28
+ ## Quick Start (standalone orchestrator)
6
29
 
7
30
  ```bash
8
31
  npx @avocadostudio-ai/cli start --orchestrator https://your-orchestrator.example.com
@@ -20,8 +43,8 @@ npx @avocadostudio-ai/cli start \
20
43
 
21
44
  ## What You Need
22
45
 
23
- - An Avocado Studio orchestrator running and reachable from your browser. See the [orchestrator setup docs](https://github.com/avocadostudio-ai/avocado/tree/main/apps/orchestrator).
24
- - A site that integrates the [`@avocadostudio-ai/site-sdk`](https://github.com/avocadostudio-ai/avocado/tree/main/packages/site-sdk) so the editor can load, edit, and publish to it.
46
+ - An orchestrator the editor can reach — either mounted in your site (library mode, above) or deployed separately.
47
+ - A site that integrates [`@avocadostudio-ai/site-sdk`](https://www.npmjs.com/package/@avocadostudio-ai/site-sdk) so the editor can load, edit, and publish to it. Its README is the fullest reference for both modes.
25
48
  - Node.js 22+.
26
49
 
27
50
  ## Flags
@@ -46,13 +69,13 @@ This means the same prebuilt bundle works against any orchestrator — no rebuil
46
69
 
47
70
  The CLI ships a frozen editor build that speaks postMessage protocol `site-editor/v1`. On startup it probes the orchestrator's `/health` endpoint and warns if the reported `protocolVersion` does not match. The warning does not block startup — the editor may still work if the protocol changes were backwards-compatible.
48
71
 
49
- Pin the CLI version to your orchestrator deployment if you want strict compatibility. Use `npx @avocadostudio-ai/cli@0.1.0 start ...` to lock to a specific version.
72
+ Pin the CLI version to your orchestrator deployment if you want strict compatibility — `npx @avocadostudio-ai/cli@<version> start ...`, using the version your site's `@avocadostudio-ai/*` packages are on. Keep the two in step: the CLI ships a frozen editor build, so a CLI several releases behind your site is the usual cause of an editor that loads and then behaves oddly.
50
73
 
51
74
  ## What This Is Not
52
75
 
53
76
  - **Not an auth layer.** The orchestrator handles auth via its `/auth/status` and `/auth/verify` routes; set `ACCESS_PASSWORD_HASH` on the orchestrator side. The CLI doesn't proxy or gate requests.
54
77
  - **Not a managed service.** No telemetry is sent anywhere. If you want the hosted Avocado Studio with managed orchestrator + eval pipeline, see the project homepage.
55
- - **Not bundled with an orchestrator.** You run the orchestrator separately (Render, Fly, Docker, your own box). This CLI is just the editor UI.
78
+ - **Not an orchestrator.** This CLI is the editor UI. The orchestrator runs either inside your site (`createOrchestrator`, the common case) or separately (Render, Fly, Docker, your own box). Either way it is not in this package — but "separately" is not the only option, and reading this line as "you must deploy a third service" is the misreading it used to invite.
56
79
 
57
80
  ## License
58
81
 
package/dist/index.js CHANGED
@@ -15,70 +15,6 @@ import { fileURLToPath } from "node:url";
15
15
  // ../shared/src/protocol.ts
16
16
  var EDITOR_PROTOCOL_VERSION = "site-editor/v1";
17
17
 
18
- // ../richtext/src/parse.ts
19
- var INLINE_PATTERN = new RegExp(
20
- [
21
- // Code spans bind tightest, so they come first: nothing inside them is markup.
22
- "(?<!\\\\)`(?<code>[^`]+?)`",
23
- // Before the link alternative, so the `!` is consumed rather than left behind.
24
- "!\\[(?<imageAlt>.*?)(?<!\\\\)\\]\\((?<imageSrc>.+?)(?<!\\\\)\\)",
25
- "(?<!\\\\)\\*\\*(?<strong>.+?)(?<!\\\\)\\*\\*",
26
- "(?<!\\\\)~~(?<strike>.+?)(?<!\\\\)~~",
27
- "(?<!\\\\)\\*(?<em>.+?)(?<!\\\\)\\*",
28
- "(?<!\\\\)\\[(?<linkText>.+?)(?<!\\\\)\\]\\((?<linkHref>.+?)(?<!\\\\)\\)"
29
- ].join("|"),
30
- "g"
31
- );
32
-
33
- // ../richtext/src/doc.ts
34
- var MARK = {
35
- bold: "bold",
36
- italic: "italic",
37
- strike: "strike",
38
- code: "code",
39
- underline: "underline",
40
- link: "link"
41
- };
42
-
43
- // ../richtext/src/merge.ts
44
- var MARKDOWN_MARKS = [MARK.bold, MARK.italic, MARK.strike, MARK.code, MARK.link];
45
-
46
- // ../richtext/src/portable-text.ts
47
- var DECORATOR_TO_MARK = {
48
- strong: MARK.bold,
49
- em: MARK.italic,
50
- underline: MARK.underline,
51
- "strike-through": MARK.strike,
52
- code: MARK.code
53
- };
54
- var MARK_TO_DECORATOR = Object.fromEntries(
55
- Object.entries(DECORATOR_TO_MARK).map(([decorator, mark]) => [mark, decorator])
56
- );
57
-
58
- // ../richtext/src/contentful.ts
59
- var CONTENTFUL_TO_MARK = {
60
- bold: MARK.bold,
61
- italic: MARK.italic,
62
- underline: MARK.underline,
63
- code: MARK.code,
64
- strikethrough: MARK.strike
65
- };
66
- var MARK_TO_CONTENTFUL = Object.fromEntries(
67
- Object.entries(CONTENTFUL_TO_MARK).map(([contentful, mark]) => [mark, contentful])
68
- );
69
-
70
- // ../richtext/src/strapi.ts
71
- var FLAG_TO_MARK = {
72
- bold: MARK.bold,
73
- italic: MARK.italic,
74
- underline: MARK.underline,
75
- strikethrough: MARK.strike,
76
- code: MARK.code
77
- };
78
- var MARK_TO_FLAG = Object.fromEntries(
79
- Object.entries(FLAG_TO_MARK).map(([flag, mark]) => [mark, flag])
80
- );
81
-
82
18
  // ../../node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/classic/external.js
83
19
  var external_exports = {};
84
20
  __export(external_exports, {
@@ -13922,8 +13858,29 @@ var f = {
13922
13858
  text: (label) => ({ kind: "text", label }),
13923
13859
  longtext: (label) => ({ kind: "text", label, multiline: true }),
13924
13860
  richtext: (label) => ({ kind: "richtext", label }),
13861
+ /** A resource address — an iframe src, a video file. Never an internal page. */
13925
13862
  url: (label) => ({ kind: "url", label, inlineEditable: false }),
13863
+ /** A navigation target: an internal page, or an external URL / mailto / tel / anchor. */
13864
+ link: (label) => ({ kind: "link", label, inlineEditable: false }),
13865
+ /**
13866
+ * The "open in new tab" companion for a link prop. Named by convention
13867
+ * (`newTabKeyFor`) so the property panel renders it inside the link control
13868
+ * rather than as a row of its own — the same pairing as `image`/`imageAlt`.
13869
+ */
13870
+ newTab: (label = "Open in new tab") => ({ kind: "boolean", label, inlineEditable: false }),
13926
13871
  image: (label, imageSpec) => ({ kind: "image", label, inlineEditable: false, ...imageSpec ? { imageSpec } : {} }),
13872
+ /**
13873
+ * A single emoji or symbol glyph, or the URL of a small image.
13874
+ *
13875
+ * Text in the panel, and deliberately *not* editable on the page. Whatever a
13876
+ * person types into an icon goes through `renderBlockIcon`, which draws only a
13877
+ * glyph or an image and renders **nothing** for anything else — so an inline
13878
+ * edit that typed a word ("rocket", the name the planner reaches for) would
13879
+ * make the icon silently disappear with the value stored and invisible. The
13880
+ * panel's labelled box is the affordance that fits a value from a constrained
13881
+ * vocabulary; a cursor blinking inside the emoji is not.
13882
+ */
13883
+ icon: (label = "Icon (single emoji)") => ({ kind: "text", label, inlineEditable: false }),
13927
13884
  imageAlt: (label) => ({ kind: "imageAlt", label }),
13928
13885
  headingLevel: () => ({ kind: "headingLevel", label: "Heading type", inlineEditable: false })
13929
13886
  };
@@ -13935,13 +13892,15 @@ registerBlock("Hero", {
13935
13892
  subheading: external_exports.string().min(1),
13936
13893
  ctaText: external_exports.string().min(1),
13937
13894
  ctaHref: external_exports.string().min(1),
13895
+ ctaNewTab: external_exports.boolean().optional(),
13938
13896
  imageUrl: external_exports.string().min(1),
13939
13897
  imageAlt: external_exports.string().min(1),
13940
13898
  imagePosition: external_exports.enum(["left", "right", "full"]).default("right").catch("right"),
13941
13899
  textAlign: external_exports.enum(["left", "center"]).default("left").catch("left"),
13942
13900
  eyebrow: external_exports.string().optional(),
13943
13901
  secondaryCtaText: external_exports.string().optional(),
13944
- secondaryCtaHref: external_exports.string().optional()
13902
+ secondaryCtaHref: external_exports.string().optional(),
13903
+ secondaryCtaNewTab: external_exports.boolean().optional()
13945
13904
  }),
13946
13905
  meta: {
13947
13906
  displayName: "Hero",
@@ -13951,14 +13910,16 @@ registerBlock("Hero", {
13951
13910
  heading: f.text("Heading"),
13952
13911
  subheading: f.text("Subheading"),
13953
13912
  ctaText: f.text("CTA button text"),
13954
- ctaHref: f.url("CTA link"),
13913
+ ctaHref: f.link("CTA link"),
13914
+ ctaNewTab: f.newTab(),
13955
13915
  imageUrl: f.image("Hero image", { aspectRatio: "landscape", width: 1536, height: 1024 }),
13956
13916
  imageAlt: f.imageAlt("Hero image alt text"),
13957
13917
  imagePosition: { kind: "enum", label: "Image position", options: ["left", "right", "full"], inlineEditable: false },
13958
13918
  textAlign: { kind: "enum", label: "Text alignment", options: ["left", "center"], inlineEditable: false },
13959
13919
  eyebrow: f.text("Eyebrow text"),
13960
13920
  secondaryCtaText: f.text("Secondary CTA text"),
13961
- secondaryCtaHref: f.url("Secondary CTA link"),
13921
+ secondaryCtaHref: f.link("Secondary CTA link"),
13922
+ secondaryCtaNewTab: f.newTab(),
13962
13923
  headingLevel: f.headingLevel()
13963
13924
  }
13964
13925
  }
@@ -13989,7 +13950,7 @@ registerBlock("FeatureGrid", {
13989
13950
  features: {
13990
13951
  label: "Features",
13991
13952
  itemFields: {
13992
- icon: f.text("Icon (single emoji)"),
13953
+ icon: f.icon(),
13993
13954
  title: f.text("Feature title"),
13994
13955
  description: f.longtext("Feature description")
13995
13956
  }
@@ -14021,7 +13982,7 @@ registerBlock("Testimonials", {
14021
13982
  items: {
14022
13983
  label: "Testimonials",
14023
13984
  itemFields: {
14024
- icon: f.text("Icon (single emoji)"),
13985
+ icon: f.icon(),
14025
13986
  quote: f.longtext("Quote"),
14026
13987
  author: f.text("Author"),
14027
13988
  role: f.text("Role / Company"),
@@ -14060,8 +14021,10 @@ registerBlock("CTA", {
14060
14021
  description: external_exports.string().min(1),
14061
14022
  ctaText: external_exports.string().min(1),
14062
14023
  ctaHref: external_exports.string().min(1),
14024
+ ctaNewTab: external_exports.boolean().optional(),
14063
14025
  secondaryCtaText: external_exports.string().optional(),
14064
- secondaryCtaHref: external_exports.string().optional()
14026
+ secondaryCtaHref: external_exports.string().optional(),
14027
+ secondaryCtaNewTab: external_exports.boolean().optional()
14065
14028
  }),
14066
14029
  meta: {
14067
14030
  displayName: "Call to Action",
@@ -14071,9 +14034,11 @@ registerBlock("CTA", {
14071
14034
  title: f.text("Headline"),
14072
14035
  description: f.longtext("Description"),
14073
14036
  ctaText: f.text("Button text"),
14074
- ctaHref: f.url("Button link"),
14037
+ ctaHref: f.link("Button link"),
14038
+ ctaNewTab: f.newTab(),
14075
14039
  secondaryCtaText: f.text("Secondary button text"),
14076
- secondaryCtaHref: f.url("Secondary button link"),
14040
+ secondaryCtaHref: f.link("Secondary button link"),
14041
+ secondaryCtaNewTab: f.newTab(),
14077
14042
  headingLevel: f.headingLevel()
14078
14043
  }
14079
14044
  }
@@ -14086,6 +14051,7 @@ registerBlock("Card", {
14086
14051
  description: external_exports.string().min(1),
14087
14052
  ctaText: external_exports.string().min(1),
14088
14053
  ctaHref: external_exports.string().min(1),
14054
+ ctaNewTab: external_exports.boolean().optional(),
14089
14055
  imageUrl: external_exports.string().min(1).optional(),
14090
14056
  imageAlt: external_exports.string().min(1).optional(),
14091
14057
  variant: external_exports.enum(["default", "full-bleed"]).default("default").catch("default")
@@ -14098,7 +14064,8 @@ registerBlock("Card", {
14098
14064
  title: f.text("Card title"),
14099
14065
  description: f.longtext("Card description"),
14100
14066
  ctaText: f.text("Button text"),
14101
- ctaHref: f.url("Button link"),
14067
+ ctaHref: f.link("Button link"),
14068
+ ctaNewTab: f.newTab(),
14102
14069
  imageUrl: f.image("Card image", { aspectRatio: "landscape", width: 768, height: 512 }),
14103
14070
  imageAlt: f.imageAlt("Card image alt text"),
14104
14071
  variant: { kind: "enum", label: "Variant", options: ["default", "full-bleed"], inlineEditable: false },
@@ -14121,6 +14088,7 @@ registerBlock("CardGrid", {
14121
14088
  description: external_exports.string().min(1),
14122
14089
  ctaText: external_exports.string().min(1),
14123
14090
  ctaHref: external_exports.string().min(1),
14091
+ ctaNewTab: external_exports.boolean().optional(),
14124
14092
  imageUrl: external_exports.string().min(1).optional(),
14125
14093
  imageAlt: external_exports.string().min(1).optional()
14126
14094
  })
@@ -14144,7 +14112,8 @@ registerBlock("CardGrid", {
14144
14112
  title: f.text("Card title"),
14145
14113
  description: f.longtext("Card description"),
14146
14114
  ctaText: f.text("Button text"),
14147
- ctaHref: f.url("Button link"),
14115
+ ctaHref: f.link("Button link"),
14116
+ ctaNewTab: f.newTab(),
14148
14117
  imageUrl: f.image("Card image", { aspectRatio: "landscape", width: 768, height: 512 }),
14149
14118
  imageAlt: f.imageAlt("Card image alt text")
14150
14119
  }
@@ -14192,7 +14161,7 @@ registerBlock("Stats", {
14192
14161
  stats: {
14193
14162
  label: "Stats",
14194
14163
  itemFields: {
14195
- icon: f.text("Icon (single emoji)"),
14164
+ icon: f.icon(),
14196
14165
  value: f.text("Value"),
14197
14166
  label: f.text("Label"),
14198
14167
  description: f.text("Description")
@@ -14212,6 +14181,7 @@ var twoColumnChild = external_exports.object({
14212
14181
  text: external_exports.string().optional(),
14213
14182
  label: external_exports.string().optional(),
14214
14183
  href: external_exports.string().optional(),
14184
+ newTab: external_exports.boolean().optional(),
14215
14185
  src: external_exports.string().optional(),
14216
14186
  alt: external_exports.string().optional(),
14217
14187
  poster: external_exports.string().optional(),
@@ -14223,11 +14193,28 @@ var twoColumnItemFields = {
14223
14193
  type: { kind: "enum", label: "Component type", options: ["heading", "subheading", "paragraph", "list", "cta", "ctas", "image", "video"] },
14224
14194
  text: f.longtext("Text content"),
14225
14195
  label: f.text("Button label"),
14226
- href: f.url("Link URL"),
14196
+ href: f.link("Link URL"),
14197
+ newTab: f.newTab(),
14227
14198
  src: f.image("Media source", { aspectRatio: "portrait", width: 768, height: 1024 }),
14228
14199
  alt: f.imageAlt("Alt text"),
14229
14200
  poster: f.image("Video poster image", { aspectRatio: "landscape", width: 768, height: 512 })
14230
14201
  };
14202
+ var twoColumnItemFieldsByType = {
14203
+ heading: { text: f.longtext("Heading text") },
14204
+ subheading: { text: f.longtext("Subheading text") },
14205
+ paragraph: { text: f.richtext("Body text") },
14206
+ list: { text: f.longtext("Text content") },
14207
+ cta: { label: f.text("Button label"), href: f.link("Link URL"), newTab: f.newTab() },
14208
+ ctas: { label: f.text("Button label"), href: f.link("Link URL"), newTab: f.newTab() },
14209
+ image: {
14210
+ src: f.image("Image", { aspectRatio: "portrait", width: 768, height: 1024 }),
14211
+ alt: f.imageAlt("Alt text")
14212
+ },
14213
+ video: {
14214
+ src: f.url("Video file URL"),
14215
+ poster: f.image("Video poster image", { aspectRatio: "landscape", width: 768, height: 512 })
14216
+ }
14217
+ };
14231
14218
  registerBlock("TwoColumn", {
14232
14219
  schema: external_exports.object({
14233
14220
  variant: external_exports.enum(["default", "accent"]).default("default").catch("default"),
@@ -14243,8 +14230,18 @@ registerBlock("TwoColumn", {
14243
14230
  headingLevel: f.headingLevel()
14244
14231
  },
14245
14232
  listFields: {
14246
- left: { label: "Left column items", itemFields: twoColumnItemFields },
14247
- right: { label: "Right column items", itemFields: twoColumnItemFields }
14233
+ left: {
14234
+ label: "Left column items",
14235
+ itemFields: twoColumnItemFields,
14236
+ discriminator: "type",
14237
+ itemFieldsByType: twoColumnItemFieldsByType
14238
+ },
14239
+ right: {
14240
+ label: "Right column items",
14241
+ itemFields: twoColumnItemFields,
14242
+ discriminator: "type",
14243
+ itemFieldsByType: twoColumnItemFieldsByType
14244
+ }
14248
14245
  }
14249
14246
  }
14250
14247
  });
@@ -14293,7 +14290,8 @@ registerBlock("Footer", {
14293
14290
  var navLinkLeaf = external_exports.object({
14294
14291
  id: external_exports.string().optional(),
14295
14292
  label: external_exports.string().min(1),
14296
- href: external_exports.string().min(1)
14293
+ href: external_exports.string().min(1),
14294
+ newTab: external_exports.boolean().optional()
14297
14295
  });
14298
14296
  registerBlock("SiteHeader", {
14299
14297
  schema: external_exports.object({
@@ -14320,7 +14318,8 @@ registerBlock("SiteHeader", {
14320
14318
  label: "Nav links",
14321
14319
  itemFields: {
14322
14320
  label: f.text("Link label"),
14323
- href: f.url("Link URL")
14321
+ href: f.link("Link URL"),
14322
+ newTab: f.newTab()
14324
14323
  }
14325
14324
  }
14326
14325
  }
@@ -14355,6 +14354,7 @@ registerBlock("Banner", {
14355
14354
  variant: external_exports.enum(["info", "success", "warning"]).default("info").catch("info"),
14356
14355
  ctaText: external_exports.string().optional(),
14357
14356
  ctaHref: external_exports.string().optional(),
14357
+ ctaNewTab: external_exports.boolean().optional(),
14358
14358
  backgroundColor: external_exports.string().optional(),
14359
14359
  textColor: external_exports.string().optional()
14360
14360
  }),
@@ -14366,7 +14366,8 @@ registerBlock("Banner", {
14366
14366
  text: f.text("Banner text"),
14367
14367
  variant: { kind: "enum", label: "Variant", options: ["info", "success", "warning"], inlineEditable: false },
14368
14368
  ctaText: f.text("Button label"),
14369
- ctaHref: f.url("Button link"),
14369
+ ctaHref: f.link("Button link"),
14370
+ ctaNewTab: f.newTab(),
14370
14371
  backgroundColor: { kind: "color", label: "Background color", inlineEditable: false },
14371
14372
  textColor: { kind: "color", label: "Text color", inlineEditable: false }
14372
14373
  }
@@ -14383,7 +14384,8 @@ registerBlock("Carousel", {
14383
14384
  heading: external_exports.string().optional(),
14384
14385
  description: external_exports.string().optional(),
14385
14386
  ctaText: external_exports.string().optional(),
14386
- ctaHref: external_exports.string().optional()
14387
+ ctaHref: external_exports.string().optional(),
14388
+ ctaNewTab: external_exports.boolean().optional()
14387
14389
  })).min(1),
14388
14390
  autoplay: external_exports.enum(["true", "false"]).default("false").catch("false"),
14389
14391
  interval: external_exports.number().optional()
@@ -14405,7 +14407,8 @@ registerBlock("Carousel", {
14405
14407
  heading: f.text("Heading"),
14406
14408
  description: f.longtext("Description"),
14407
14409
  ctaText: f.text("Button label"),
14408
- ctaHref: f.url("Button link")
14410
+ ctaHref: f.link("Button link"),
14411
+ ctaNewTab: f.newTab()
14409
14412
  }
14410
14413
  }
14411
14414
  }
@@ -14490,8 +14493,11 @@ registerBlock("Table", {
14490
14493
  fields: {
14491
14494
  title: f.text("Section title"),
14492
14495
  headingLevel: f.headingLevel(),
14493
- headers: f.text("Column headers"),
14494
- rows: f.text("Table rows"),
14496
+ // Both are lists of scalars, which `FieldKind` cannot name — the panel
14497
+ // recognises the value's shape instead: `headers` edits one per line,
14498
+ // `rows` (string[][]) is shown there and edited cell-by-cell in the page.
14499
+ headers: f.text("Column headers (one per line)"),
14500
+ rows: f.text("Table rows (edit cells in the page)"),
14495
14501
  striped: { kind: "enum", label: "Striped rows", options: ["true", "false"], inlineEditable: false }
14496
14502
  }
14497
14503
  }
@@ -14558,8 +14564,22 @@ var jsonSchemaLikeSchema = external_exports.lazy(
14558
14564
  description: external_exports.string().optional()
14559
14565
  }).catchall(external_exports.unknown())
14560
14566
  );
14567
+ var FIELD_KINDS = [
14568
+ "text",
14569
+ "richtext",
14570
+ "url",
14571
+ "link",
14572
+ "file",
14573
+ "image",
14574
+ "imageAlt",
14575
+ "enum",
14576
+ "color",
14577
+ "number",
14578
+ "boolean",
14579
+ "headingLevel"
14580
+ ];
14561
14581
  var fieldMetaSchema = external_exports.object({
14562
- kind: external_exports.enum(["text", "richtext", "url", "image", "imageAlt", "enum", "color", "number", "boolean", "headingLevel"]),
14582
+ kind: external_exports.enum(FIELD_KINDS),
14563
14583
  label: external_exports.string().optional(),
14564
14584
  inlineEditable: external_exports.boolean().optional(),
14565
14585
  options: external_exports.array(external_exports.string()).optional(),
@@ -14612,6 +14632,70 @@ var blockManifestSchema = external_exports.object({
14612
14632
  blocks: external_exports.array(blockDefinitionSchema)
14613
14633
  });
14614
14634
 
14635
+ // ../richtext/src/parse.ts
14636
+ var INLINE_PATTERN = new RegExp(
14637
+ [
14638
+ // Code spans bind tightest, so they come first: nothing inside them is markup.
14639
+ "(?<!\\\\)`(?<code>[^`]+?)`",
14640
+ // Before the link alternative, so the `!` is consumed rather than left behind.
14641
+ "!\\[(?<imageAlt>.*?)(?<!\\\\)\\]\\((?<imageSrc>.+?)(?<!\\\\)\\)",
14642
+ "(?<!\\\\)\\*\\*(?<strong>.+?)(?<!\\\\)\\*\\*",
14643
+ "(?<!\\\\)~~(?<strike>.+?)(?<!\\\\)~~",
14644
+ "(?<!\\\\)\\*(?<em>.+?)(?<!\\\\)\\*",
14645
+ "(?<!\\\\)\\[(?<linkText>.+?)(?<!\\\\)\\]\\((?<linkHref>.+?)(?<!\\\\)\\)"
14646
+ ].join("|"),
14647
+ "g"
14648
+ );
14649
+
14650
+ // ../richtext/src/doc.ts
14651
+ var MARK = {
14652
+ bold: "bold",
14653
+ italic: "italic",
14654
+ strike: "strike",
14655
+ code: "code",
14656
+ underline: "underline",
14657
+ link: "link"
14658
+ };
14659
+
14660
+ // ../richtext/src/merge.ts
14661
+ var MARKDOWN_MARKS = [MARK.bold, MARK.italic, MARK.strike, MARK.code, MARK.link];
14662
+
14663
+ // ../richtext/src/portable-text.ts
14664
+ var DECORATOR_TO_MARK = {
14665
+ strong: MARK.bold,
14666
+ em: MARK.italic,
14667
+ underline: MARK.underline,
14668
+ "strike-through": MARK.strike,
14669
+ code: MARK.code
14670
+ };
14671
+ var MARK_TO_DECORATOR = Object.fromEntries(
14672
+ Object.entries(DECORATOR_TO_MARK).map(([decorator, mark]) => [mark, decorator])
14673
+ );
14674
+
14675
+ // ../richtext/src/contentful.ts
14676
+ var CONTENTFUL_TO_MARK = {
14677
+ bold: MARK.bold,
14678
+ italic: MARK.italic,
14679
+ underline: MARK.underline,
14680
+ code: MARK.code,
14681
+ strikethrough: MARK.strike
14682
+ };
14683
+ var MARK_TO_CONTENTFUL = Object.fromEntries(
14684
+ Object.entries(CONTENTFUL_TO_MARK).map(([contentful, mark]) => [mark, contentful])
14685
+ );
14686
+
14687
+ // ../richtext/src/strapi.ts
14688
+ var FLAG_TO_MARK = {
14689
+ bold: MARK.bold,
14690
+ italic: MARK.italic,
14691
+ underline: MARK.underline,
14692
+ strikethrough: MARK.strike,
14693
+ code: MARK.code
14694
+ };
14695
+ var MARK_TO_FLAG = Object.fromEntries(
14696
+ Object.entries(FLAG_TO_MARK).map(([flag, mark]) => [mark, flag])
14697
+ );
14698
+
14615
14699
  // ../shared/src/ops/theme-tokens.ts
14616
14700
  var THEME_TOKEN_TO_CSS_VARS = {
14617
14701
  brandColor: ["--brand", "--brand-hover", "--link"],
@@ -15041,7 +15125,19 @@ var chatStartResponseSchema = external_exports.object({
15041
15125
  error: external_exports.string().optional()
15042
15126
  }).passthrough();
15043
15127
  var slugsResponseSchema = external_exports.object({
15044
- slugs: external_exports.array(external_exports.string()).optional()
15128
+ slugs: external_exports.array(external_exports.string()).optional(),
15129
+ /*
15130
+ * The same pages the `slugs` array names, with the title and the URL that
15131
+ * `/draft/slugs` has always returned beside them. The editor parsed this
15132
+ * response and kept only the bare slugs, so the link picker had nothing to
15133
+ * label a page with; `path` is what a locale-prefixed site navigates to when
15134
+ * it differs from the slug (see docs/ideas/page-identity-punch-list.md).
15135
+ */
15136
+ pages: external_exports.array(external_exports.object({
15137
+ slug: external_exports.string(),
15138
+ path: external_exports.string().optional(),
15139
+ title: external_exports.string().optional()
15140
+ }).passthrough()).optional()
15045
15141
  }).passthrough();
15046
15142
  var bootstrapResponseSchema = external_exports.object({
15047
15143
  slugs: external_exports.array(external_exports.string()).optional()
@@ -1 +1 @@
1
- import{P as b}from"./chunk-2CNEFIQP-D3Yc-Xrd.js";import{u as y,a as j,E as L,_ as m,L as M,b as p,o as P,i as A}from"./PuckPrototypeRoute-dMA7e2BV.js";import{r as s,j as g}from"./index-bSQ3lNnY.js";import{E as N,u as U}from"./index-Zan79wWH.js";import"./index-QORB5JJO.js";A();A();function C({content:a,onChange:x,extensions:v,editable:d=!0,onFocusChange:o,name:c}){const[i,E]=P(null,50,{leading:!0,maxWait:200}),l=s.useRef(!1),S=s.useRef(""),f=s.useRef(null),R=!!f.current,_=j(t=>t.state.ui.field.focus===c),T=t=>{f.current&&clearTimeout(f.current),f.current=setTimeout(()=>{S.current===t&&(f.current=null)},200)},u=y(),e=U({extensions:v,content:a,editable:d,immediatelyRender:!1,parseOptions:{preserveWhitespace:"full"},onUpdate:({editor:t})=>{if(l.current||!_){u.getState().setUi({field:{focus:c}});return}const r=t.getHTML(),{from:n,to:h}=t.state.selection;E({from:n,to:h,html:r}),T(r),S.current=r}});return s.useEffect(()=>{if(!e)return;const t=()=>{o==null||o(e)};return e.on("focus",t),()=>{e.off("focus",t)}},[e,o]),s.useEffect(()=>{if(i){const{ui:t}=u.getState().state;x(i.html,{field:m(p({},t.field),{metadata:{from:i.from,to:i.to}})})}},[e,i,x,u,c]),s.useEffect(()=>{e==null||e.setEditable(d)},[e,d]),s.useEffect(()=>{var t;if(!e||R||e.getHTML()===a)return;l.current=!0,e.commands.setContent(a,{emitUpdate:!1});const{ui:n}=u.getState().state;typeof((t=n.field.metadata)==null?void 0:t.from)<"u"&&e.commands.setTextSelection({from:n.field.metadata.from,to:n.field.metadata.to}),l.current=!1},[a,e,u]),e}var F=s.memo(a=>{const{onChange:x,content:v,readOnly:d=!1,field:o,inline:c=!1,onFocus:i,id:E,name:l}=a,{tiptap:S={},options:f}=o,{extensions:R=[]}=S,_=s.useMemo(()=>[b.configure(f),...R],[o,R]),T=y(),u=`${l}${c?"::inline":""}`,e=C({content:v,onChange:x,extensions:_,editable:!d,name:u,onFocusChange:r=>{if(r){const n=T.getState();T.setState({currentRichText:{field:o,editor:r,id:E,inline:c},state:m(p({},n.state),{ui:m(p({},n.state.ui),{field:m(p({},n.state.ui.field),{focus:u})})})}),i==null||i(r)}}}),t=j(r=>{var n,h;return!c&&((n=r.currentRichText)==null?void 0:n.id)===E&&((h=r.currentRichText)!=null&&h.inlineComponentId)?r.currentRichText.editor:e});return e?g.jsx(L,m(p({},a),{editor:e,menu:g.jsx(M,{field:o,editor:t,readOnly:d}),children:g.jsx(N,{editor:e,className:"rich-text"})})):null});F.displayName="Editor";export{F as Editor};
1
+ import{P as b}from"./chunk-2CNEFIQP-1U6REFbg.js";import{u as y,a as j,E as L,_ as m,L as M,b as p,o as P,i as A}from"./PuckPrototypeRoute-CNaUpPOV.js";import{r as s,j as g}from"./index-Bjgitaku.js";import{E as N,u as U}from"./index-BmcA7Icg.js";import"./index-DtBBabz0.js";A();A();function C({content:a,onChange:x,extensions:v,editable:d=!0,onFocusChange:o,name:c}){const[i,E]=P(null,50,{leading:!0,maxWait:200}),l=s.useRef(!1),S=s.useRef(""),f=s.useRef(null),R=!!f.current,_=j(t=>t.state.ui.field.focus===c),T=t=>{f.current&&clearTimeout(f.current),f.current=setTimeout(()=>{S.current===t&&(f.current=null)},200)},u=y(),e=U({extensions:v,content:a,editable:d,immediatelyRender:!1,parseOptions:{preserveWhitespace:"full"},onUpdate:({editor:t})=>{if(l.current||!_){u.getState().setUi({field:{focus:c}});return}const r=t.getHTML(),{from:n,to:h}=t.state.selection;E({from:n,to:h,html:r}),T(r),S.current=r}});return s.useEffect(()=>{if(!e)return;const t=()=>{o==null||o(e)};return e.on("focus",t),()=>{e.off("focus",t)}},[e,o]),s.useEffect(()=>{if(i){const{ui:t}=u.getState().state;x(i.html,{field:m(p({},t.field),{metadata:{from:i.from,to:i.to}})})}},[e,i,x,u,c]),s.useEffect(()=>{e==null||e.setEditable(d)},[e,d]),s.useEffect(()=>{var t;if(!e||R||e.getHTML()===a)return;l.current=!0,e.commands.setContent(a,{emitUpdate:!1});const{ui:n}=u.getState().state;typeof((t=n.field.metadata)==null?void 0:t.from)<"u"&&e.commands.setTextSelection({from:n.field.metadata.from,to:n.field.metadata.to}),l.current=!1},[a,e,u]),e}var F=s.memo(a=>{const{onChange:x,content:v,readOnly:d=!1,field:o,inline:c=!1,onFocus:i,id:E,name:l}=a,{tiptap:S={},options:f}=o,{extensions:R=[]}=S,_=s.useMemo(()=>[b.configure(f),...R],[o,R]),T=y(),u=`${l}${c?"::inline":""}`,e=C({content:v,onChange:x,extensions:_,editable:!d,name:u,onFocusChange:r=>{if(r){const n=T.getState();T.setState({currentRichText:{field:o,editor:r,id:E,inline:c},state:m(p({},n.state),{ui:m(p({},n.state.ui),{field:m(p({},n.state.ui.field),{focus:u})})})}),i==null||i(r)}}}),t=j(r=>{var n,h;return!c&&((n=r.currentRichText)==null?void 0:n.id)===E&&((h=r.currentRichText)!=null&&h.inlineComponentId)?r.currentRichText.editor:e});return e?g.jsx(L,m(p({},a),{editor:e,menu:g.jsx(M,{field:o,editor:t,readOnly:d}),children:g.jsx(N,{editor:e,className:"rich-text"})})):null});F.displayName="Editor";export{F as Editor};