@obelism/content 0.21.0 → 0.23.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 +54 -9
- package/dist/bin/content.js +15 -2
- package/dist/bridge.d.mts +1 -0
- package/dist/bridge.d.mts.map +1 -1
- package/dist/bridge.d.ts +1 -0
- package/dist/bridge.d.ts.map +1 -1
- package/dist/bridge.global.js +1 -1
- package/dist/bridge.js +18 -6
- package/dist/bridge.mjs +18 -6
- package/dist/index.d.mts +7 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -6
- package/dist/index.mjs +25 -6
- package/dist/oidc.d.mts +13 -0
- package/dist/oidc.d.mts.map +1 -0
- package/dist/oidc.d.ts +13 -0
- package/dist/oidc.d.ts.map +1 -0
- package/dist/oidc.js +71 -0
- package/dist/oidc.mjs +67 -0
- package/dist/{preview-ooq8w3jv.js → preview-c4giufnr.js} +5 -3
- package/dist/{preview-fu3qtgfx.mjs → preview-el7sfk3h.mjs} +5 -3
- package/dist/prompt.js +1 -1
- package/dist/prompt.mjs +1 -1
- package/dist/site.js +8 -2
- package/dist/site.mjs +8 -2
- package/dist/{standardWebhooks-kh5dc0ff.js → standardWebhooks-leiz4jdn.js} +10 -2
- package/dist/{standardWebhooks-ew5mhpac.mjs → standardWebhooks-ow7vu8g1.mjs} +10 -2
- package/dist/tokenSource-my2ymemb.d.ts +4 -0
- package/dist/tokenSource-my2ymemb.d.ts.map +1 -0
- package/dist/webhooks.js +1 -1
- package/dist/webhooks.mjs +1 -1
- package/package.json +26 -7
package/README.md
CHANGED
|
@@ -43,9 +43,37 @@ await content.getEntries({
|
|
|
43
43
|
await content.getContentModel() // the model file
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
Each method takes `{ locale, depth, richText, init }` to override the
|
|
46
|
+
Each method takes `{ locale, depth, richText, drafts, init }` to override the
|
|
47
47
|
defaults.
|
|
48
48
|
|
|
49
|
+
### Without a stored token
|
|
50
|
+
|
|
51
|
+
On Vercel, or in GitHub Actions, the client can send the identity token its
|
|
52
|
+
host gives it instead of a delivery or preview token. Connect the deployment
|
|
53
|
+
first, under **Connected deployments** on the space's page on
|
|
54
|
+
www.obelism.studio: each of its environments (Vercel's production, preview,
|
|
55
|
+
development) maps to one environment of the space, with published content,
|
|
56
|
+
drafts too, or management. Then pass a token source:
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
import { ContentClient } from '@obelism/content'
|
|
60
|
+
import { vercelOidc } from '@obelism/content/oidc' // needs @vercel/oidc installed
|
|
61
|
+
|
|
62
|
+
const content = new ContentClient({
|
|
63
|
+
token: vercelOidc(), // or githubOidc() in a workflow
|
|
64
|
+
space: process.env.CONTENT_SPACE_ID, // picks one when the deployment is connected to several
|
|
65
|
+
environment: process.env.CONTENT_ENVIRONMENT, // refused if the rule maps it elsewhere
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
// A preview route: drafts, when the connection's rule has them
|
|
69
|
+
const draft = await content.getPage(path, { drafts: true })
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
A host token reads published content unless the client or the request sets
|
|
73
|
+
`drafts: true`, so a site's pages and its preview can share one deployment.
|
|
74
|
+
`token` takes any function that gives a token per request. Requests with a
|
|
75
|
+
host token skip the edge cache, since the token changes every hour or two.
|
|
76
|
+
|
|
49
77
|
Pages and folders can have a slug per locale. `getPage` looks the path up
|
|
50
78
|
in the requested locale's paths, `entry.path` is the path in that locale and
|
|
51
79
|
`entry.paths` the path in every locale (`{ en: 'about-us', nl: 'over-ons' }`),
|
|
@@ -63,8 +91,10 @@ with generics: `content.getPage<Entry<{ title: string }>>('home')`.
|
|
|
63
91
|
The visual editor loads your site with
|
|
64
92
|
`?cms_preview=1&cms_entry=…&cms_environment=…&cms_token=…`. `cms_token` is
|
|
65
93
|
made for the person editing and reads drafts for 8 hours; read the page with
|
|
66
|
-
it, server-side
|
|
67
|
-
|
|
94
|
+
it, server-side, naming your space and environment: anyone with a space of
|
|
95
|
+
their own can make a `cms_token` for it, and only a request that names yours
|
|
96
|
+
refuses one for another. Never show drafts because `cms_preview` is there:
|
|
97
|
+
anyone can add it to a URL.
|
|
68
98
|
|
|
69
99
|
```ts
|
|
70
100
|
import {
|
|
@@ -75,11 +105,16 @@ import {
|
|
|
75
105
|
|
|
76
106
|
const preview = readPreviewParams(request.url)
|
|
77
107
|
const content = preview?.token
|
|
78
|
-
? new ContentClient({
|
|
108
|
+
? new ContentClient({
|
|
109
|
+
token: preview.token,
|
|
110
|
+
space: process.env.CONTENT_SPACE_ID,
|
|
111
|
+
environment: process.env.CONTENT_ENVIRONMENT,
|
|
112
|
+
init: { cache: 'no-store' },
|
|
113
|
+
})
|
|
79
114
|
: deliveryClient
|
|
80
115
|
|
|
81
116
|
const page = await content.getPage(path).catch((error) => {
|
|
82
|
-
// A made-up or
|
|
117
|
+
// A made-up, expired or other space's token: show what's published.
|
|
83
118
|
if (error instanceof ContentApiError && error.status === 401) {
|
|
84
119
|
return deliveryClient.getPage(path)
|
|
85
120
|
}
|
|
@@ -129,12 +164,19 @@ const unmount = mountPromptBox(document, bridge, { labels: { open: 'Ask' } })
|
|
|
129
164
|
|
|
130
165
|
`actions` puts controls of your own in the box: an element of your page,
|
|
131
166
|
shown next to the closed box and in the open box's footer (by a `<slot>`, so
|
|
132
|
-
your CSS styles it). `signOut: false` leaves Sign out out.
|
|
133
|
-
|
|
167
|
+
your CSS styles it). `signOut: false` leaves Sign out out. A bridge with no
|
|
168
|
+
page (`entryId` null) normally offers only **New page**; `promptWithoutPage:
|
|
169
|
+
true` keeps the prompt there too, for a bridge whose `prompt` acts on
|
|
170
|
+
something else (Content's canvas: the whole site), with New page beside it.
|
|
171
|
+
Content's canvas uses all three, with Save all in `actions`.
|
|
134
172
|
|
|
135
173
|
```ts
|
|
136
174
|
const controls = document.createElement('div')
|
|
137
|
-
mountPromptBox(document, bridge, {
|
|
175
|
+
mountPromptBox(document, bridge, {
|
|
176
|
+
actions: controls,
|
|
177
|
+
signOut: false,
|
|
178
|
+
promptWithoutPage: true,
|
|
179
|
+
})
|
|
138
180
|
```
|
|
139
181
|
|
|
140
182
|
Inside the visual editor, people who may edit get a prompt box at the bottom
|
|
@@ -474,7 +516,10 @@ npx @obelism/content model apply # apply it, all or nothing
|
|
|
474
516
|
Options: `--file`, `--url` (or `$CONTENT_URL`), `--prune`, and for `apply`
|
|
475
517
|
`--lock` (the environment's model becomes managed in code: read-only in the
|
|
476
518
|
dashboard, the agent API and MCP) or `--unlock`. In GitHub Actions
|
|
477
|
-
the plan is also written to the job summary
|
|
519
|
+
the plan is also written to the job summary, and without
|
|
520
|
+
`CONTENT_MANAGEMENT_TOKEN` the job's own token is used, when the job has
|
|
521
|
+
`permissions: id-token: write` and the repository is connected to the space
|
|
522
|
+
with management for its environment.
|
|
478
523
|
|
|
479
524
|
### Types
|
|
480
525
|
|
package/dist/bin/content.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
var node_util = require('node:util');
|
|
3
3
|
var config = require('../config-ci2hxmas.js');
|
|
4
|
+
var oidc = require('../oidc.js');
|
|
4
5
|
var node_child_process = require('node:child_process');
|
|
5
6
|
var promises = require('node:fs/promises');
|
|
6
7
|
var node_path = require('node:path');
|
|
@@ -407,6 +408,14 @@ const ENV_VARIABLES = [
|
|
|
407
408
|
'CONTENT_PREVIEW_TOKEN',
|
|
408
409
|
'also reads drafts, server-side only (cms_p_…)'
|
|
409
410
|
],
|
|
411
|
+
[
|
|
412
|
+
'CONTENT_SPACE_ID',
|
|
413
|
+
"the space the tokens are for (space_…): the editor's cms_token for any other reads nothing"
|
|
414
|
+
],
|
|
415
|
+
[
|
|
416
|
+
'CONTENT_ENVIRONMENT',
|
|
417
|
+
'the environment the tokens are for'
|
|
418
|
+
],
|
|
410
419
|
[
|
|
411
420
|
'CONTENT_MANAGEMENT_TOKEN',
|
|
412
421
|
'changes the content model: content model pull|plan|apply (cms_m_…)'
|
|
@@ -536,6 +545,7 @@ const runInitCommand = async ({ url, token, dir, install: shouldInstall, cwd = p
|
|
|
536
545
|
'',
|
|
537
546
|
'Next:',
|
|
538
547
|
'- Create a delivery token in Space settings and set CONTENT_DELIVERY_TOKEN (a preview token only if the site builds from drafts; the visual editor brings its own, as cms_token).',
|
|
548
|
+
'- Set CONTENT_SPACE_ID and CONTENT_ENVIRONMENT, and pass them as space and environment to the ContentClient you read cms_token with, so a cms_token for another space reads nothing.',
|
|
539
549
|
'- Fetch content with ContentClient from @obelism/content; the examples show what each type looks like.',
|
|
540
550
|
...improve.enabled ? [
|
|
541
551
|
"- Render _improve blocks: ask improve's SDK for the visitor's option (getTestValue / getFlagValue with the block's slug) and render pickImproveVariant(block, option)."
|
|
@@ -742,7 +752,10 @@ const USAGE = `Usage: content init [--dir content] [--url origin] [--skip-instal
|
|
|
742
752
|
--unlock apply also gives the model back to the dashboard
|
|
743
753
|
|
|
744
754
|
Needs CONTENT_MANAGEMENT_TOKEN: a management token from Space settings
|
|
745
|
-
(not for types --file)
|
|
755
|
+
(not for types --file). In GitHub Actions with \`permissions: id-token:
|
|
756
|
+
write\`, the job's own token works instead, once the repository is connected
|
|
757
|
+
to the space with management (Connected deployments, on its page on
|
|
758
|
+
www.obelism.studio).`;
|
|
746
759
|
const main = async ()=>{
|
|
747
760
|
let parsed;
|
|
748
761
|
try {
|
|
@@ -795,7 +808,7 @@ const main = async ()=>{
|
|
|
795
808
|
const isTypes = group === 'types' && command === undefined;
|
|
796
809
|
const modelCommand = group === 'model' && (command === 'pull' || command === 'plan' || command === 'apply') ? command : null;
|
|
797
810
|
if (!isInit && !isTypes && !modelCommand) throw new CliError(USAGE, 2);
|
|
798
|
-
const token = process.env.CONTENT_MANAGEMENT_TOKEN;
|
|
811
|
+
const token = process.env.CONTENT_MANAGEMENT_TOKEN || (process.env.ACTIONS_ID_TOKEN_REQUEST_URL ? await oidc.githubOidc()() : undefined);
|
|
799
812
|
const url = config.normalizeUrl(values.url ?? process.env.CONTENT_URL ?? config.DEFAULT_URL);
|
|
800
813
|
// With --file, types needs no token.
|
|
801
814
|
if (isTypes) {
|
package/dist/bridge.d.mts
CHANGED
|
@@ -172,6 +172,7 @@ type PromptBoxOptions = {
|
|
|
172
172
|
labels?: Partial<PromptLabels> | undefined;
|
|
173
173
|
actions?: HTMLElement | undefined;
|
|
174
174
|
signOut?: boolean | undefined;
|
|
175
|
+
promptWithoutPage?: boolean | undefined;
|
|
175
176
|
};
|
|
176
177
|
declare const mountPromptBox: (doc: Document, bridge: ContentBridge, options?: PromptBoxOptions) => () => void;
|
|
177
178
|
|
package/dist/bridge.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge.d.mts","sources":["../src/bridge/statsOverlay.ts","../src/bridge/createBridge.ts","../src/bridge/promptBox.ts","../src/bridge.ts"],"mappings":";;AAAA,KAAK,UAAU;AACf;AACA;AACA;AACA;AACA;AACA,KAAK,WAAW;AAChB;AACA;AACA;AACA,cAAc,oBAAoB,EAAE,WAAW;AAc/C,KAAK,YAAY;AACjB,kBAAkB,QAAQ,CAAC,MAAM,SAAS,UAAU;AACpD;AACA;AACA;AACA,cAAc,iBAAiB,QAAQ,MAAM;AAC7C;AACA;AACA,aAAa,OAAO,CAAC,WAAW;AAChC,MAAM,YAAY;;AC5BlB,KAAK,YAAY;AACjB;AACA,eAAe,KAAK;AACpB;AACA;AACA,WAAW,MAAM;AACjB,eAAe,MAAM;AACrB,YAAY,WAAW;AACvB;AACA,KAAK,WAAW,SAAS,YAAY;AACrC,KAAK,cAAc,WAAW,WAAW,cAAc,YAAY;AACnE,KAAK,WAAW;AAChB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW,QAAQ,CAAC,MAAM,SAAS,UAAU;AAC7C;AACA;AACA,KAAK,YAAY;AACjB;AACA;AACA,KAAK,gBAAgB;AACrB;AACA;AACA;AACA;AACA;AACA,KAAK,uBAAuB;AAC5B;AACA;AACA;AACA;AACA,KAAK,0BAA0B,GAAG,uBAAuB;AACzD,KAAK,eAAe;AACpB;AACA,WAAW,MAAM;AACjB;AACA,KAAK,WAAW;AAChB;AACA;AACA;AACA;AACA,KAAK,UAAU;AACf;AACA;AACA,KAAK,QAAQ;AACb;AACA;AACA;AACA;AACA;AACA;AACA,aAAa,WAAW;AACxB,gBAAgB,WAAW;AAC3B;AACA,KAAK,aAAa;AAClB;AACA;AACA;AACA;AACA,sBAAsB,WAAW;AACjC,yBAAyB,WAAW;AACpC,iBAAiB,WAAW,sBAAsB,cAAc;AAChE,gBAAgB,WAAW;AAC3B;AACA;AACA,QAAQ,OAAO,CAAC,YAAY;AAC5B,8CAA8C,OAAO,CAAC,gBAAgB;AACtE,gCAAgC,WAAW,GAAG,OAAO,CAAC,uBAAuB;AAC7E,sCAAsC,WAAW,GAAG,OAAO,CAAC,0BAA0B;AACtF;AACA;AACA,QAAQ,OAAO,CAAC,MAAM;AACtB,uBAAuB,MAAM;AAC7B;AACA,QAAQ,OAAO,CAAC,eAAe;AAC/B,wBAAwB,WAAW,YAAY,WAAW,GAAG,UAAU;AACvE,aAAa,OAAO,CAAC,QAAQ;AAC7B,mBAAmB,QAAQ;AAC3B;AACA,YAAY,OAAO;AACnB,eAAe,OAAO;AACtB;AACA;AACA;AACA;AACA;AAEA,cAAc,aAAa,EAAE,WAAW;;ACjGxC,KAAK,YAAY;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAc,qBAAqB,EAAE,YAAY;AACjD,KAAK,gBAAgB;AACrB,aAAa,OAAO,CAAC,YAAY;AACjC,cAAc,WAAW;AACzB;AACA;AACA,cAAc,cAAc,QAAQ,QAAQ,UAAU,aAAa,YAAY,gBAAgB;;
|
|
1
|
+
{"version":3,"file":"bridge.d.mts","sources":["../src/bridge/statsOverlay.ts","../src/bridge/createBridge.ts","../src/bridge/promptBox.ts","../src/bridge.ts"],"mappings":";;AAAA,KAAK,UAAU;AACf;AACA;AACA;AACA;AACA;AACA,KAAK,WAAW;AAChB;AACA;AACA;AACA,cAAc,oBAAoB,EAAE,WAAW;AAc/C,KAAK,YAAY;AACjB,kBAAkB,QAAQ,CAAC,MAAM,SAAS,UAAU;AACpD;AACA;AACA;AACA,cAAc,iBAAiB,QAAQ,MAAM;AAC7C;AACA;AACA,aAAa,OAAO,CAAC,WAAW;AAChC,MAAM,YAAY;;AC5BlB,KAAK,YAAY;AACjB;AACA,eAAe,KAAK;AACpB;AACA;AACA,WAAW,MAAM;AACjB,eAAe,MAAM;AACrB,YAAY,WAAW;AACvB;AACA,KAAK,WAAW,SAAS,YAAY;AACrC,KAAK,cAAc,WAAW,WAAW,cAAc,YAAY;AACnE,KAAK,WAAW;AAChB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW,QAAQ,CAAC,MAAM,SAAS,UAAU;AAC7C;AACA;AACA,KAAK,YAAY;AACjB;AACA;AACA,KAAK,gBAAgB;AACrB;AACA;AACA;AACA;AACA;AACA,KAAK,uBAAuB;AAC5B;AACA;AACA;AACA;AACA,KAAK,0BAA0B,GAAG,uBAAuB;AACzD,KAAK,eAAe;AACpB;AACA,WAAW,MAAM;AACjB;AACA,KAAK,WAAW;AAChB;AACA;AACA;AACA;AACA,KAAK,UAAU;AACf;AACA;AACA,KAAK,QAAQ;AACb;AACA;AACA;AACA;AACA;AACA;AACA,aAAa,WAAW;AACxB,gBAAgB,WAAW;AAC3B;AACA,KAAK,aAAa;AAClB;AACA;AACA;AACA;AACA,sBAAsB,WAAW;AACjC,yBAAyB,WAAW;AACpC,iBAAiB,WAAW,sBAAsB,cAAc;AAChE,gBAAgB,WAAW;AAC3B;AACA;AACA,QAAQ,OAAO,CAAC,YAAY;AAC5B,8CAA8C,OAAO,CAAC,gBAAgB;AACtE,gCAAgC,WAAW,GAAG,OAAO,CAAC,uBAAuB;AAC7E,sCAAsC,WAAW,GAAG,OAAO,CAAC,0BAA0B;AACtF;AACA;AACA,QAAQ,OAAO,CAAC,MAAM;AACtB,uBAAuB,MAAM;AAC7B;AACA,QAAQ,OAAO,CAAC,eAAe;AAC/B,wBAAwB,WAAW,YAAY,WAAW,GAAG,UAAU;AACvE,aAAa,OAAO,CAAC,QAAQ;AAC7B,mBAAmB,QAAQ;AAC3B;AACA,YAAY,OAAO;AACnB,eAAe,OAAO;AACtB;AACA;AACA;AACA;AACA;AAEA,cAAc,aAAa,EAAE,WAAW;;ACjGxC,KAAK,YAAY;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAc,qBAAqB,EAAE,YAAY;AACjD,KAAK,gBAAgB;AACrB,aAAa,OAAO,CAAC,YAAY;AACjC,cAAc,WAAW;AACzB;AACA;AACA;AACA,cAAc,cAAc,QAAQ,QAAQ,UAAU,aAAa,YAAY,gBAAgB;;ACnD/F,KAAK,aAAa;AAClB;AACA,uBAAuB,gBAAgB;AACvC;AACA;AACA;AACA;AACA,cAAc,iBAAiB,QAAQ,aAAa;AACpD,cAAc,gBAAgB,6DAA6D,aAAa,KAAK,aAAa","names":[]}
|
package/dist/bridge.d.ts
CHANGED
|
@@ -172,6 +172,7 @@ type PromptBoxOptions = {
|
|
|
172
172
|
labels?: Partial<PromptLabels> | undefined;
|
|
173
173
|
actions?: HTMLElement | undefined;
|
|
174
174
|
signOut?: boolean | undefined;
|
|
175
|
+
promptWithoutPage?: boolean | undefined;
|
|
175
176
|
};
|
|
176
177
|
declare const mountPromptBox: (doc: Document, bridge: ContentBridge, options?: PromptBoxOptions) => () => void;
|
|
177
178
|
|
package/dist/bridge.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge.d.ts","sources":["../src/bridge/statsOverlay.ts","../src/bridge/createBridge.ts","../src/bridge/promptBox.ts","../src/bridge.ts"],"mappings":";;AAAA,KAAK,UAAU;AACf;AACA;AACA;AACA;AACA;AACA,KAAK,WAAW;AAChB;AACA;AACA;AACA,cAAc,oBAAoB,EAAE,WAAW;AAc/C,KAAK,YAAY;AACjB,kBAAkB,QAAQ,CAAC,MAAM,SAAS,UAAU;AACpD;AACA;AACA;AACA,cAAc,iBAAiB,QAAQ,MAAM;AAC7C;AACA;AACA,aAAa,OAAO,CAAC,WAAW;AAChC,MAAM,YAAY;;AC5BlB,KAAK,YAAY;AACjB;AACA,eAAe,KAAK;AACpB;AACA;AACA,WAAW,MAAM;AACjB,eAAe,MAAM;AACrB,YAAY,WAAW;AACvB;AACA,KAAK,WAAW,SAAS,YAAY;AACrC,KAAK,cAAc,WAAW,WAAW,cAAc,YAAY;AACnE,KAAK,WAAW;AAChB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW,QAAQ,CAAC,MAAM,SAAS,UAAU;AAC7C;AACA;AACA,KAAK,YAAY;AACjB;AACA;AACA,KAAK,gBAAgB;AACrB;AACA;AACA;AACA;AACA;AACA,KAAK,uBAAuB;AAC5B;AACA;AACA;AACA;AACA,KAAK,0BAA0B,GAAG,uBAAuB;AACzD,KAAK,eAAe;AACpB;AACA,WAAW,MAAM;AACjB;AACA,KAAK,WAAW;AAChB;AACA;AACA;AACA;AACA,KAAK,UAAU;AACf;AACA;AACA,KAAK,QAAQ;AACb;AACA;AACA;AACA;AACA;AACA;AACA,aAAa,WAAW;AACxB,gBAAgB,WAAW;AAC3B;AACA,KAAK,aAAa;AAClB;AACA;AACA;AACA;AACA,sBAAsB,WAAW;AACjC,yBAAyB,WAAW;AACpC,iBAAiB,WAAW,sBAAsB,cAAc;AAChE,gBAAgB,WAAW;AAC3B;AACA;AACA,QAAQ,OAAO,CAAC,YAAY;AAC5B,8CAA8C,OAAO,CAAC,gBAAgB;AACtE,gCAAgC,WAAW,GAAG,OAAO,CAAC,uBAAuB;AAC7E,sCAAsC,WAAW,GAAG,OAAO,CAAC,0BAA0B;AACtF;AACA;AACA,QAAQ,OAAO,CAAC,MAAM;AACtB,uBAAuB,MAAM;AAC7B;AACA,QAAQ,OAAO,CAAC,eAAe;AAC/B,wBAAwB,WAAW,YAAY,WAAW,GAAG,UAAU;AACvE,aAAa,OAAO,CAAC,QAAQ;AAC7B,mBAAmB,QAAQ;AAC3B;AACA,YAAY,OAAO;AACnB,eAAe,OAAO;AACtB;AACA;AACA;AACA;AACA;AAEA,cAAc,aAAa,EAAE,WAAW;;ACjGxC,KAAK,YAAY;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAc,qBAAqB,EAAE,YAAY;AACjD,KAAK,gBAAgB;AACrB,aAAa,OAAO,CAAC,YAAY;AACjC,cAAc,WAAW;AACzB;AACA;AACA,cAAc,cAAc,QAAQ,QAAQ,UAAU,aAAa,YAAY,gBAAgB;;
|
|
1
|
+
{"version":3,"file":"bridge.d.ts","sources":["../src/bridge/statsOverlay.ts","../src/bridge/createBridge.ts","../src/bridge/promptBox.ts","../src/bridge.ts"],"mappings":";;AAAA,KAAK,UAAU;AACf;AACA;AACA;AACA;AACA;AACA,KAAK,WAAW;AAChB;AACA;AACA;AACA,cAAc,oBAAoB,EAAE,WAAW;AAc/C,KAAK,YAAY;AACjB,kBAAkB,QAAQ,CAAC,MAAM,SAAS,UAAU;AACpD;AACA;AACA;AACA,cAAc,iBAAiB,QAAQ,MAAM;AAC7C;AACA;AACA,aAAa,OAAO,CAAC,WAAW;AAChC,MAAM,YAAY;;AC5BlB,KAAK,YAAY;AACjB;AACA,eAAe,KAAK;AACpB;AACA;AACA,WAAW,MAAM;AACjB,eAAe,MAAM;AACrB,YAAY,WAAW;AACvB;AACA,KAAK,WAAW,SAAS,YAAY;AACrC,KAAK,cAAc,WAAW,WAAW,cAAc,YAAY;AACnE,KAAK,WAAW;AAChB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW,QAAQ,CAAC,MAAM,SAAS,UAAU;AAC7C;AACA;AACA,KAAK,YAAY;AACjB;AACA;AACA,KAAK,gBAAgB;AACrB;AACA;AACA;AACA;AACA;AACA,KAAK,uBAAuB;AAC5B;AACA;AACA;AACA;AACA,KAAK,0BAA0B,GAAG,uBAAuB;AACzD,KAAK,eAAe;AACpB;AACA,WAAW,MAAM;AACjB;AACA,KAAK,WAAW;AAChB;AACA;AACA;AACA;AACA,KAAK,UAAU;AACf;AACA;AACA,KAAK,QAAQ;AACb;AACA;AACA;AACA;AACA;AACA;AACA,aAAa,WAAW;AACxB,gBAAgB,WAAW;AAC3B;AACA,KAAK,aAAa;AAClB;AACA;AACA;AACA;AACA,sBAAsB,WAAW;AACjC,yBAAyB,WAAW;AACpC,iBAAiB,WAAW,sBAAsB,cAAc;AAChE,gBAAgB,WAAW;AAC3B;AACA;AACA,QAAQ,OAAO,CAAC,YAAY;AAC5B,8CAA8C,OAAO,CAAC,gBAAgB;AACtE,gCAAgC,WAAW,GAAG,OAAO,CAAC,uBAAuB;AAC7E,sCAAsC,WAAW,GAAG,OAAO,CAAC,0BAA0B;AACtF;AACA;AACA,QAAQ,OAAO,CAAC,MAAM;AACtB,uBAAuB,MAAM;AAC7B;AACA,QAAQ,OAAO,CAAC,eAAe;AAC/B,wBAAwB,WAAW,YAAY,WAAW,GAAG,UAAU;AACvE,aAAa,OAAO,CAAC,QAAQ;AAC7B,mBAAmB,QAAQ;AAC3B;AACA,YAAY,OAAO;AACnB,eAAe,OAAO;AACtB;AACA;AACA;AACA;AACA;AAEA,cAAc,aAAa,EAAE,WAAW;;ACjGxC,KAAK,YAAY;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAc,qBAAqB,EAAE,YAAY;AACjD,KAAK,gBAAgB;AACrB,aAAa,OAAO,CAAC,YAAY;AACjC,cAAc,WAAW;AACzB;AACA;AACA;AACA,cAAc,cAAc,QAAQ,QAAQ,UAAU,aAAa,YAAY,gBAAgB;;ACnD/F,KAAK,aAAa;AAClB;AACA,uBAAuB,gBAAgB;AACvC;AACA;AACA;AACA;AACA,cAAc,iBAAiB,QAAQ,aAAa;AACpD,cAAc,gBAAgB,6DAA6D,aAAa,KAAK,aAAa","names":[]}
|
package/dist/bridge.global.js
CHANGED
|
@@ -257,4 +257,4 @@ button.chip:disabled { opacity: .5; }
|
|
|
257
257
|
.empty { padding: 8px 12px; color: rgb(var(--theme-foreground-muted-rgb)); }
|
|
258
258
|
.empty.error { color: var(--theme-error); }
|
|
259
259
|
[hidden] { display: none !important; }
|
|
260
|
-
`,N=(e,t,r={},...o)=>{let n=e.createElement(t);for(let t of(Object.assign(n,r),o))n.appendChild("string"==typeof t?e.createTextNode(t):t);return n},M=(e,t)=>{let r=N(e,"span",{className:"icon"});return r.setAttribute("aria-hidden","true"),r.innerHTML=`<svg viewBox="0 0 24 24">${L[t]}</svg>`,r},I=(e,t,r={})=>{let o,n={...P,...r.labels},a=N(e,"div");a.setAttribute("data-obelism-content-prompt","");let i=a.attachShadow({mode:"open"}),l="site"===t.mode,s=N(e,"span",{textContent:n.open}),d=N(e,"button",{className:"pill",type:"button"},s,((o=M(e,"mark")).classList.add("mark"),o)),c=N(e,"span",{className:"pill compact"},`${n.viewingDrafts} \xb7 `),p=N(e,"button",{className:"link",type:"button",textContent:n.signOut});c.appendChild(p);let g=N(e,"p",{className:"status"});g.setAttribute("role","status");let u=N(e,"textarea",{placeholder:n.placeholder,rows:1});u.setAttribute("aria-label",n.open);let h=N(e,"div",{className:"form-loader",textContent:n.formLoading});h.setAttribute("role","status");let m=N(e,"div",{className:"form"},h),b=M(e,"page"),f=M(e,"block"),v=N(e,"span"),y=N(e,"button",{type:"button",title:n.clearBlock});y.setAttribute("aria-label",n.clearBlock),y.appendChild(M(e,"close"));let x=N(e,"span",{className:"chip scope"},b,f,v,y),w=N(e,"button",{className:"action chip",type:"button"},M(e,"undo"),n.undo),k=t=>{let r=N(e,"button",{type:"button",textContent:t});return r.setAttribute("aria-pressed","false"),r},E=k(n.modePrompt),C=k(n.form),L=N(e,"span",{className:"modes"},E,C);L.setAttribute("role","group"),L.setAttribute("aria-label",n.modes);let I=N(e,"button",{className:"action chip",type:"button"},M(e,"newPage"),n.newPage),U=N(e,"button",{className:"action chip product",type:"button"},M(e,"newPage"),n.addProductPage),$=N(e,"button",{type:"button",title:n.newPageCancel});$.setAttribute("aria-label",n.newPageCancel),$.appendChild(M(e,"close"));let O=N(e,"span",{className:"chip scope"},M(e,"newPage"),N(e,"span",{textContent:n.newPage}),$),R=N(e,"input",{type:"text",placeholder:n.pathPlaceholder,autocomplete:"off",spellcheck:!1}),j=N(e,"label",{className:"path"},N(e,"span",{textContent:n.path}),R),z=N(e,"button",{className:"close icon-button",type:"button",title:n.close},M(e,"close"));z.setAttribute("aria-label",n.close);let T=M(e,"minimize"),D=M(e,"expand"),F=N(e,"button",{className:"icon-button",type:"button"},T,D),q=N(e,"button",{className:"action primary icon-button",type:"submit"},N(e,"span",{className:"visually-hidden",textContent:n.send}),M(e,"send"));q.title=n.send;let V=N(e,"span",{className:"divider"}),B=N(e,"div",{className:"toolbar"},x,O,L,w,U,I,N(e,"span",{className:"spacer"}),F,z,V,q),H=N(e,"span",{textContent:n.pages}),W=N(e,"button",{className:"chip page-chip",type:"button",title:n.pages},M(e,"page"),H,M(e,"chevrons"));W.setAttribute("aria-haspopup","listbox"),W.setAttribute("aria-expanded","false"),W.setAttribute("aria-controls","obelism-pages");let Y=N(e,"input",{type:"text",placeholder:n.pagesSearch,autocomplete:"off",spellcheck:!1});Y.setAttribute("role","combobox"),Y.setAttribute("aria-label",n.pagesSearch),Y.setAttribute("aria-autocomplete","list"),Y.setAttribute("aria-expanded","true"),Y.setAttribute("aria-controls","obelism-pages");let X=N(e,"ul",{className:"options",id:"obelism-pages"});X.setAttribute("role","listbox"),X.setAttribute("aria-label",n.pages);let _=N(e,"p",{className:"empty"}),J=N(e,"div",{className:"pages"},N(e,"label",{className:"search"},M(e,"search"),Y),X,_),Z=N(e,"slot");Z.name="actions-footer";let K=N(e,"slot");K.name="actions-bar",r.actions&&(r.actions.slot="actions-bar",a.appendChild(r.actions));let G=N(e,"span",{className:"unsaved"});G.appendChild(N(e,"span",{className:"dot"})),G.appendChild(e.createTextNode(n.unsaved));let Q=N(e,"button",{className:"link",type:"button",textContent:n.signOut}),ee=N(e,"button",{className:"action chip",type:"button",textContent:n.save}),et=N(e,"button",{className:"action chip",type:"button",textContent:n.publish}),er=N(e,"div",{className:"footer"},W,G,N(e,"span",{className:"spacer"}),Z,Q,ee,et),eo=N(e,"form",{className:"panel"},g,j,u,m,B,J,er),en=N(e,"div",{className:"root"},N(e,"div",{className:"bar"},d,c,K),eo);i.append(N(e,"style",{textContent:S}),en);let ea=e.defaultView,ei=e=>{"center"===e?delete en.dataset.side:en.dataset.side=e};ei((()=>{try{let e=ea?.localStorage.getItem(A);return"left"===e||"right"===e?e:"center"}catch{return"center"}})());let el=null,es=!1;en.addEventListener("pointerdown",e=>{if(es=!1,0!==e.button||!e.isPrimary)return;let t=e.target.closest("button, input, textarea, select, iframe, a, label, .pages, .form");if(t&&t!==d)return;let{left:r,right:o}=en.getBoundingClientRect();el={id:e.pointerId,startX:e.clientX,x:e.clientX,velocity:0,time:e.timeStamp,moved:!1,min:Math.min(0,16-r),max:Math.max(0,(ea?.innerWidth??0)-16-o)}}),en.addEventListener("pointermove",e=>{if(!el||e.pointerId!==el.id)return;let t=e.clientX-el.startX;if(!el.moved){if(6>Math.abs(t))return;el.moved=!0,en.classList.add("dragging");try{en.setPointerCapture(e.pointerId)}catch{}}let r=e.timeStamp-el.time;r>0&&(el.velocity=(e.clientX-el.x)/r),el.x=e.clientX,el.time=e.timeStamp;let o=Math.min(Math.max(t,el.min),el.max);en.style.translate=`${o+(t-o)/3}px 0`});let ed=e=>{if(!el||e.pointerId!==el.id)return;let{moved:t,x:r,velocity:o,time:n}=el;if(el=null,!t)return;es=!0;let a=en.getBoundingClientRect().left,i=ea?.innerWidth??0,l=r+(e.timeStamp-n>80?0:Math.min(Math.max(150*o,-120),120)),s=l<i/3?"left":l>2*i/3?"right":"center";ei(s),en.style.translate="";let d=en.getBoundingClientRect().left;en.style.translate=`${a-d}px 0`,en.offsetWidth,en.classList.remove("dragging"),en.style.translate="";try{ea?.localStorage.setItem(A,s)}catch{}};en.addEventListener("pointerup",ed),en.addEventListener("pointercancel",ed),en.addEventListener("click",e=>{es&&(es=!1,e.preventDefault(),e.stopPropagation())},!0);let ec=!1,ep=!1,eg=!1,eu=null,eh=!1,em=null,eb=!1,ef=!1,ev=null,ey=null,ex=null,ew=0,ek=e=>({text:e instanceof Error?e.message:String(e),error:!0}),eE=e=>{let o=e.features.includes("prompt"),a=e.saving||e.publishing,i=e.prompting||a;en.hidden=!o&&!l,d.hidden=ec||!o,c.hidden=o||!l,eo.hidden=!ec||!o;let k=l&&e.features.includes("create"),P=l&&null===t.entryId,A=P&&k?t.product?"product":t.collection?"collection":null:null,S=null!==A,N="collection"===A?{add:n.addCollectionPage,adding:n.addingCollectionPage,hint:n.collectionPageHint}:{add:n.addProductPage,adding:n.addingProductPage,hint:n.productPageHint};U.lastChild.textContent=N.add;let M=P&&k&&!S;k||(eg=!1),M&&(eg=!0),(eg||P||!l)&&(eh=!1);let z=ec&&o&&eh;z&&!em?eA():!z&&em&&eL();let Y=S&&!eg;s.textContent=Y?N.add:M?n.newPage:n.open,$.hidden=M,x.hidden=eg||Y,O.hidden=!eg,U.hidden=!Y,U.disabled=i,I.hidden=eg||eh||!k,I.disabled=i,ep&&(ef=!1),j.hidden=!eg||ef||ep,R.disabled=i,u.hidden=eh||ef||ep||Y,m.hidden=!eh||ef||ep,m.classList.toggle("loading",eb),h.hidden=!eb,B.hidden=ef,J.hidden=!ef,u.placeholder=eg?n.newPagePlaceholder:n.placeholder,v.textContent=e.selectedUid?n.scopeBlock:P?n.scopeNoPage:n.scopeEntry,y.hidden=!e.selectedUid,b.hidden=!!e.selectedUid,f.hidden=!e.selectedUid,L.hidden=!l||eg||P||!e.features.includes("form"),E.setAttribute("aria-pressed",String(!eh)),C.setAttribute("aria-pressed",String(eh)),L.querySelectorAll("button").forEach(e=>{e.disabled=i}),w.hidden=eg||!e.canUndo,w.disabled=i,q.hidden=eh||ep||Y,V.hidden=eh||ep||Y;let X=ep?n.expand:n.minimize;F.title=X,F.setAttribute("aria-label",X),F.setAttribute("aria-expanded",String(!ep)),T.hidden=ep,D.hidden=!ep,q.disabled=i||""===u.value.trim()||eg&&""===R.value.trim(),u.disabled=i,ee.hidden=!e.features.includes("save")||P,ee.disabled=i||!e.unsaved,ee.textContent=e.saving?n.saving:n.save,et.hidden=!e.features.includes("publish")||P,et.disabled=i,et.textContent=e.publishing?n.publishing:n.publish,Q.hidden=!l||!1===r.signOut,p.hidden=!1===r.signOut,r.actions&&(r.actions.slot=ec&&o?"actions-footer":"actions-bar"),er.hidden=!l,G.hidden=!e.unsaved,W.hidden=!l,W.setAttribute("aria-expanded",String(ef)),H.textContent=ev?.find(({entryId:e})=>e===t.entryId)?.name??n.pages;let _=eh&&eb&&!ef,Z=e.prompting,K=e.prompting?eg?n.creating:Y?N.adding:n.working:_?"":eu?.text??(Y?N.hint:!l||eg||ef||e.selectedUid?"":n.selectHint);g.textContent=K,g.hidden=!K||ep,g.className=`status${Z?" working":""}${!i&&!_&&eu?.error?" error":""}`},eC=()=>eE(t.getState()),eP=()=>{u.style.height="auto",u.style.height=`${u.scrollHeight}px`},eA=()=>{eb=!0,m.classList.add("loading");let e=t.openForm(m,{title:n.formTitle,onReady:()=>{em===e&&(eb=!1,eu=null,eC())},onError:t=>{em===e&&(eb=!1,eu={text:t,error:!0},eC())}});em=e},eL=()=>{em?.close(),em=null,eb=!1},eS=e=>{eh!==e&&(eh=e,eu=null,eC(),eh||u.focus())},eN=async()=>{if(eh)return;let e=u.value.trim();if(e&&!t.getState().prompting){eu=null;try{if(eg){let r=R.value.trim();if(!r)return R.focus();await t.createPage(r,e),ev=null,ey=null,eu={text:n.created,error:!1}}else{let{summary:r}=await t.prompt(e);eu={text:r,error:!1}}u.value="",eP()}catch(e){eu=ek(e)}eC(),u.focus()}},eM=()=>(ey??(ey=t.pages().then(e=>{ev=e,ex=null,eU(),eC()},e=>{ey=null,ex=ek(e).text,eU()})),ey),eI=()=>{let e=Y.value.trim().toLowerCase();return(ev??[]).filter(t=>!e||t.name.toLowerCase().includes(e)||t.url.toLowerCase().includes(e)||`/${t.path}`.toLowerCase().includes(e))},eU=()=>{let r=eI();ew=Math.max(0,Math.min(ew,r.length-1)),X.textContent="",r.forEach((r,o)=>{let a=r.entryId===t.entryId,i=N(e,"li",{className:`option${o===ew?" active":""}`,id:`obelism-page-${o}`},N(e,"span",{className:"option-text"},N(e,"span",{textContent:r.name}),N(e,"span",{className:"option-path",textContent:r.url})));if(i.setAttribute("role","option"),i.setAttribute("aria-selected",String(o===ew)),"published"!==r.status&&i.appendChild(N(e,"span",{className:"badge",textContent:"draft"===r.status?n.pageDraft:n.pageChanged})),a){i.setAttribute("aria-current","page");let t=M(e,"check");t.removeAttribute("aria-hidden"),t.setAttribute("role","img"),t.setAttribute("aria-label",n.pageCurrent),i.appendChild(t)}i.addEventListener("click",()=>eO(r)),X.appendChild(i)});let o=X.children[ew];o?(Y.setAttribute("aria-activedescendant",o.id),o.scrollIntoView?.({block:"nearest"})):Y.removeAttribute("aria-activedescendant"),_.textContent=(ex??(ev?"":n.pagesLoading))||(0===r.length?n.pagesEmpty:""),_.hidden=!_.textContent,_.className=`empty${ex?" error":""}`},e$=e=>{eu=null,(ef=e)&&(Y.value="",ew=Math.max(0,(ev??[]).findIndex(({entryId:e})=>e===t.entryId)),eM(),eU()),eC(),(ef?Y:W).focus()},eO=e=>{if(e.entryId===t.entryId)return e$(!1);t.openPage(e)},eR=e=>{(ec=e)||(ef=!1,ep=!1),eC(),l&&t.setSelecting(ec&&!eg),ec&&l&&eM()},ej=e=>{eg=e,eu=null,t.setSelecting(ec&&!eg),eg&&t.select(null),eC(),(eg?R:u).focus()},ez=async e=>{eu=null;try{await t[e](),eu={text:"save"===e?n.saved:n.published,error:!1}}catch(e){eu=ek(e)}eC()};d.addEventListener("click",()=>{eR(!0),eh||(eg?R:u).focus()}),z.addEventListener("click",()=>eR(!1)),F.addEventListener("click",()=>{ep=!ep,eC(),ep||(eh?F:u).focus()}),eo.addEventListener("click",e=>{if(!ep)return;let t=e.target.closest("button");t&&t!==F&&t!==z&&(ep=!1,eC())},!0),ee.addEventListener("click",()=>void ez("save")),et.addEventListener("click",()=>void ez("publish")),Q.addEventListener("click",()=>t.signOut()),p.addEventListener("click",()=>t.signOut()),y.addEventListener("click",()=>t.select(null)),I.addEventListener("click",()=>ej(!0)),U.addEventListener("click",async()=>{eu=null;try{t.product?(await t.createProductPage(),eu={text:n.addedProductPage,error:!1}):(await t.createCollectionPage(),eu={text:n.addedCollectionPage,error:!1})}catch(e){eu=ek(e)}eC()}),$.addEventListener("click",()=>ej(!1)),E.addEventListener("click",()=>eS(!1)),C.addEventListener("click",()=>eS(!0)),W.addEventListener("click",()=>e$(!ef)),R.addEventListener("input",eC),R.addEventListener("keydown",e=>{"Enter"!==e.key||e.isComposing?"Escape"===e.key&&eR(!1):(e.preventDefault(),u.focus())}),Y.addEventListener("input",()=>{ew=0,eU()}),Y.addEventListener("keydown",e=>{let t=X.children.length;if("ArrowDown"===e.key||"ArrowUp"===e.key){if(e.preventDefault(),0===t)return;ew=(ew+("ArrowDown"===e.key?1:-1)+t)%t,eU()}else if("Enter"!==e.key||e.isComposing)"Escape"===e.key&&(e.preventDefault(),e$(!1));else{e.preventDefault();let t=eI()[ew];t&&eO(t)}}),w.addEventListener("click",()=>{eu=null,t.undo()}),eo.addEventListener("submit",e=>{e.preventDefault(),eN()}),u.addEventListener("input",()=>{eP(),eC()}),u.addEventListener("keydown",e=>{"Enter"!==e.key||e.shiftKey||e.isComposing?"Escape"===e.key&&eR(!1):(e.preventDefault(),eN())});let eT=t.on("change",eE);return eC(),e.body.appendChild(a),()=>{eT(),eL(),a.remove()}},U="https://content.obelism.studio",$=(e,t)=>JSON.stringify(e)===JSON.stringify(t),O=Symbol.for("@obelism/content/bridge"),R=C({isEditing:!1,entryId:null,on:()=>{}},new URLSearchParams),j=({url:e,prompt:c=!0,pagePath:p,productPath:m,collectionPath:y}={})=>{let x;if("u"<typeof window)return R;let P=window;if(P[O])return P[O];if(P.ObelismBridge)x=C(P.ObelismBridge,new URLSearchParams(P.location.search));else{let C=(x=((e,r)=>{let o,n,c,p,m,y=new URLSearchParams(e.location.search),x=e.parent!==e&&y.has("cms_preview"),C=v(),P=[],A={...f,selecting:!0},L=e=>{A={...A,...e},C.emit("change",A)},S={isEditing:x,mode:x?"editor":null,entryId:y.get("cms_entry"),environment:y.get(a),product:null,collection:null,on:C.on,getState:()=>A,...w,destroy:()=>{P.splice(0).forEach(e=>e())}};if(!x)return S;let N=e.document,M=(t,o={})=>{e.parent.postMessage({source:h,type:t,...o},r)},I=N.createElement("style");I.textContent=b(),N.head.appendChild(I),P.push(()=>I.remove());let U=(e,t)=>{if(N.querySelectorAll("[data-cms-selected]").forEach(e=>{e.removeAttribute("data-cms-selected")}),A.selectedUid!==(e??null)&&L({selectedUid:e??null}),!e)return;let r=N.querySelector(E(e));r&&(r.setAttribute("data-cms-selected",""),t&&r.scrollIntoView({behavior:"smooth",block:"center"}))},$=e=>{let r=e.target,o=r?.closest?.(`[${t}]`);if(!o)return;e.preventDefault(),e.stopPropagation();let n=o.getAttribute(t);U(n,!1),M("select",{uid:n})};N.addEventListener("click",$,!0),P.push(()=>N.removeEventListener("click",$,!0));let O=()=>Math.ceil(Math.max(N.documentElement.scrollHeight,N.body?.scrollHeight??0)),R=0,j=()=>{R=O(),M("ready",{url:e.location.href,height:R})},z=e.ResizeObserver;if("function"==typeof z){let e=new z(()=>{let e=O();e!==R&&(R=e,M("size",{height:e}))});e.observe(N.documentElement),N.body&&e.observe(N.body),P.push(()=>e.disconnect())}let T=new Map,D=0,F=e=>{let t=T.get(e);return t?(clearTimeout(t.timer),T.delete(e),0===T.size&&L({prompting:!1}),t):null};S.prompt=(e,t={})=>{let r=e.trim();if(!r)return Promise.reject(Error("Say what to change"));if(!A.features.includes("prompt"))return Promise.reject(Error("The editor does not offer prompts here"));let o=`prompt_${++D}`,n=void 0===t.uid?A.selectedUid:t.uid;return new Promise((e,t)=>{let a=setTimeout(()=>{F(o)?.reject(Error("The editor did not answer in time"))},12e4);T.set(o,{resolve:e,reject:t,timer:a}),L({prompting:!0}),M("prompt",{id:o,prompt:r,uid:n})})},S.undo=()=>M("undo"),S.select=e=>{U(e,!1),M("select",{uid:e})};let q=null;P.push(()=>q?.destroy()),P.push(()=>{for(let e of T.keys())F(e)?.reject(Error("The bridge was destroyed"))});let V=(o=new WeakSet,n=null,c=null,p=!1,m=()=>{if(null!==n){for(let e of Array.from(N.styleSheets)){let t;if(!o.has(e)){try{t=e.cssRules}catch{continue}o.add(e),u(t,n)}}N.querySelectorAll('[style*="vh"]').forEach(e=>{g(e.style,n)})}},{freeze(e){if(null!==n||!(e>0))return;n=e,m();let t=N.defaultView?.MutationObserver;t&&(c=new t(()=>{if(p)return;p=!0;let e=()=>{p=!1,m()};N.defaultView?.requestAnimationFrame?N.defaultView.requestAnimationFrame(e):e()})).observe(N.documentElement,{childList:!0,subtree:!0})},destroy(){c?.disconnect()}});P.push(()=>V.destroy());let B=t=>{if(t.origin!==r||t.source!==e.parent)return;let o=t.data;if(o&&"obelism-content-editor"===o.source){if("connect"===o.type)j();else if("update"===o.type&&o.entry)C.emit("update",{entry:o.entry,selectedUid:o.selectedUid??null}),e.requestAnimationFrame(()=>U(o.selectedUid,!1)),q?.refresh();else if("select"===o.type)U(o.uid,!0);else if("saved"===o.type||"published"===o.type)C.emit(o.type,{}),0===C.listeners.update.size&&e.location.reload();else if("features"===o.type&&Array.isArray(o.features))L({features:o.features.filter(e=>"string"==typeof e)});else if("stats"===o.type)L({stats:(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return{};let t={};for(let[r,o]of Object.entries(e)){let{clicks:e,clickers:n,viewers:a,rate:i}=o??{};k(e)&&k(n)&&k(a)&&k(i)&&(t[r]={clicks:e,clickers:n,viewers:a,rate:i})}return t})(o.stats),statsVisible:!1!==o.visible}),(q||Object.keys(A.stats).length)&&(q??(q=((e,{selector:t,onSelect:r,labels:o})=>{let n=e.document,a={...i,...o},c=n.createElement("div");c.setAttribute("data-obelism-stats","");let p=c.attachShadow({mode:"open"}),g=n.createElement("style");g.textContent=s;let u=n.createElement("div");u.className="layer",p.append(g,u),n.body.appendChild(c);let h={},m=!1,b=null,f=()=>{if(b=null,u.replaceChildren(),u.hidden=!m,!m)return;let o=e.innerHeight;for(let[i,s]of Object.entries(h)){let c=n.querySelector(t(i));if(!c)continue;let p=c.getBoundingClientRect();if(!p.width&&!p.height||p.bottom<0||p.top>o)continue;let g=n.createElement("button");g.type="button",g.className="badge",g.dataset.uid=i,g.textContent=l(a.clicked,{rate:Math.round(100*s.rate)}),g.title=l(a.title,{clickers:s.clickers,viewers:s.viewers,clicks:s.clicks});let{place:h,top:m,left:b}=d(p,e.innerWidth);g.dataset.place=h,g.style.top=`${m}px`,g.style.left=`${b}px`,g.addEventListener("click",()=>r(i)),u.appendChild(g)}},v=()=>{null===b&&m&&(b=e.requestAnimationFrame(f))};e.addEventListener("scroll",v,{capture:!0,passive:!0}),e.addEventListener("resize",v);let y=e.MutationObserver,x="function"==typeof y?new y(v):null;return x?.observe(n.body,{childList:!0,subtree:!0}),{update(t,r){h=t,m=r,null!==b&&(e.cancelAnimationFrame?.(b),b=null),f()},refresh:v,destroy(){null!==b&&e.cancelAnimationFrame?.(b),e.removeEventListener("scroll",v,{capture:!0}),e.removeEventListener("resize",v),x?.disconnect(),c.remove()}}})(e,{selector:E,onSelect:e=>S.select(e)})),q.update(A.stats,A.statsVisible));else if("viewport"===o.type&&"number"==typeof o.height)V.freeze(o.height);else if("promptState"===o.type)L({canUndo:!0===o.canUndo});else if("promptResult"===o.type&&"string"==typeof o.id){let e=F(o.id);if(!e)return;!0===o.ok?e.resolve({summary:"string"==typeof o.summary?o.summary:""}):e.reject(Error("string"==typeof o.error?o.error:"The prompt failed"))}}};return e.addEventListener("message",B),P.push(()=>e.removeEventListener("message",B)),"loading"===N.readyState?(N.addEventListener("DOMContentLoaded",j,{once:!0}),P.push(()=>N.removeEventListener("DOMContentLoaded",j))):j(),S})(P,new URL(e||U).origin)).isEditing||P.parent!==P?null:(e=>{for(let t of e.cookie.split(";")){let[e,...r]=t.trim().split("=");if("obelism_content_editing"===e)try{let e=decodeURIComponent(r.join("="));return e.startsWith("/")&&!e.startsWith("//")?e:null}catch{break}}return null})(P.document);if(C&&(x=((e,a,{pagePath:i=e=>`/${e}`,productPath:l,collectionPath:s}={})=>{let d=e.document,c=v(),p=[],g=new Map,u=[],m=new Set,y=null,x=null,w=-1/0,k=new Map,C=f,P=e=>{C={...C,...e},c.emit("change",C)},A=()=>P({unsaved:[...g.values()].some(({content:e,saved:t})=>!$(e,t)),canUndo:u.length>0}),L=async(t,r)=>{let o=await e.fetch(`${a}/api/${t}`,void 0===r?{credentials:"same-origin"}:{method:"POST",credentials:"same-origin",headers:{"Content-Type":"application/json","x-obelism-content":"1"},body:JSON.stringify(r)}),n=await o.json().catch(()=>({}));if(401===o.status)throw P({features:[]}),Error("You were signed out. Sign in again to edit.");if(!o.ok)throw Error("string"==typeof n.error?n.error:`Obelism Content answered ${o.status}`);return n},S=()=>d.querySelector(`[${r}]`)?.getAttribute(r)??null,N=()=>{let e=d.querySelector(`[${o}]`),t=e?.getAttribute(o),r=e?.getAttribute("data-cms-product-handle");return t&&r?{id:t,handle:r}:null},M=()=>{let e=d.querySelector(`[${n}]`),t=e?.getAttribute(n),r=e?.getAttribute("data-cms-collection-handle");return t&&r?{id:t,handle:r}:null},I=e=>{let t=e?d.querySelector(E(e)):null;return t?.closest(`[${r}]`)?.getAttribute(r)??S()},U=()=>{if(!y)return;let e=y.space.locales.map(({code:e})=>e),t=d.documentElement.lang;if(e.includes(t))return t;let r=t.split("-")[0]??"";return e.includes(r)?r:y.space.defaultLocale},O=new Map,R=async e=>{let t=g.get(e);if(t)return t;let r=O.get(e);return r||(r=L(`entries/${encodeURIComponent(e)}`).then(t=>{let r=g.get(e)??{content:t.content,saved:t.content,revision:t.draftRevision};return g.set(e,r),r}).finally(()=>O.delete(e)),O.set(e,r)),r},j=e=>{let t=void 0===e?C.selectedUid:e,r=I(t);if(!r)throw Error("Nothing on this page is marked as an entry: add editable(entry)");return{uid:t,entryId:r}},z=e=>{d.querySelectorAll("[data-cms-selected]").forEach(e=>{e.removeAttribute("data-cms-selected")}),C.selectedUid!==e&&P({selectedUid:e}),e&&d.querySelector(E(e))?.setAttribute("data-cms-selected","")},T=async t=>{if(0===c.listeners.update.size)return;let r=g.get(t)?.content,{entry:o}=await L(`entries/${encodeURIComponent(t)}/preview`,{content:r,locale:U()});c.emit("update",{entry:o,selectedUid:C.selectedUid}),e.requestAnimationFrame(()=>z(C.selectedUid))},D=e=>console.error("[@obelism/content bridge]",e),F=t=>{c.emit(t,{}),0===c.listeners.update.size&&e.location.reload()},q=async()=>{for(let[e,t]of g){if($(t.content,t.saved))continue;let{draftRevision:r}=await L(`entries/${encodeURIComponent(e)}/save`,{content:t.content,baseRevision:t.revision});t.saved=t.content,t.revision=r,m.add(e)}u.length=0,w=-1/0,A()},V={isEditing:!0,mode:"site",get entryId(){return S()},get product(){return N()},get collection(){return M()},environment:null,on:c.on,getState:()=>C,async prompt(e,t={}){let r=e.trim();if(!r)throw Error("Say what to change");if(!C.features.includes("prompt"))throw Error("You may not edit content here");let{uid:o,entryId:n}=j(t.uid);P({prompting:!0});try{let e=await R(n),t=await L(`entries/${encodeURIComponent(n)}/prompt`,{prompt:r,content:e.content,locale:U(),uid:o});return u.push({entryId:n,content:e.content}),w=-1/0,e.content=t.content,A(),await T(n),{summary:t.summary}}finally{P({prompting:!1})}},async createPage(t,r){let o=r.trim();if(!o)throw Error("Say what the page is for");if(!t.trim())throw Error("Say where the page goes, like /pricing");if(!C.features.includes("create"))throw Error("You may not add pages here");if(C.unsaved)throw Error("Save or undo your changes before adding a page");P({prompting:!0});try{let r=await L("entries",{path:t,prompt:o,locale:U(),from:S()}),n=i(r.path,U()??"");return e.location.assign(n),{summary:r.summary,entryId:r.entryId,path:r.path,url:n}}finally{P({prompting:!1})}},async createProductPage(t=N()??void 0){if(!t)throw Error("Nothing on this page is marked as a product: add editableProduct(product)");if(!C.features.includes("create"))throw Error("You may not add pages here");if(C.unsaved)throw Error("Save or undo your changes before adding a page");P({prompting:!0});try{let r=await L("product-pages",{product:{id:t.id,handle:t.handle}});return e.location.reload(),r}finally{P({prompting:!1})}},async createCollectionPage(t=M()??void 0){if(!t)throw Error("Nothing on this page is marked as a collection: add editableCollection(collection)");if(!C.features.includes("create"))throw Error("You may not add pages here");if(C.unsaved)throw Error("Save or undo your changes before adding a page");P({prompting:!0});try{let r=await L("collection-pages",{collection:{id:t.id,handle:t.handle}});return e.location.reload(),r}finally{P({prompting:!1})}},async view(e={}){let{uid:t,entryId:r}=j(e.uid),o=await R(r),{view:n}=await L(`entries/${encodeURIComponent(r)}/view`,{content:o.content,locale:U(),uid:t});return n},async applyJson(e,t={}){if(!C.features.includes("prompt"))throw Error("You may not edit content here");if(!e||"object"!=typeof e||Array.isArray(e))throw Error("Send the fields to change as an object");let{uid:r,entryId:o}=j(t.uid);P({prompting:!0});try{let t=await R(o),n=await L(`entries/${encodeURIComponent(o)}/apply`,{changes:e,content:t.content,locale:U(),uid:r});return $(n.content,t.content)||(u.push({entryId:o,content:t.content}),w=-1/0,t.content=n.content,A(),await T(o)),{changed:n.changed??[],...n.view&&{view:n.view}}}finally{P({prompting:!1})}},openForm(t,r={}){let{title:o="Content form",onReady:n,onError:a}=r;x?.();let i=!1,l=null,s=null,d=()=>{},p=e=>{i||a?.(e instanceof Error?e.message:String(e))},m=()=>{i||(i=!0,d(),l?.destroy(),x===m&&(x=null))};x=m;let b=()=>{if(i||!l)return;let e=I(C.selectedUid);if(!e)return;let t=g.get(e);if(!t)return void R(e).then(b,p);let r={entryId:e,content:t.content,locale:U(),selectedUid:C.selectedUid};s&&s.entryId===r.entryId&&s.content===r.content&&s.locale===r.locale&&s.selectedUid===r.selectedUid||(s=r,l.show(r))},f=(e,t)=>{let r=t??s?.entryId,o=void 0===r?void 0:g.get(r);if(i||void 0===r||!o||$(e,o.content))return;let n=Date.now();n-w>=1e3&&u.push({entryId:r,content:o.content}),w=n,o.content=e,s?.entryId===r&&(s={...s,content:e}),A(),clearTimeout(k.get(r)),k.set(r,setTimeout(()=>{k.delete(r),T(r).catch(D)},300))};return(async()=>{if(!C.features.includes("form"))throw Error("You may not edit content here");await R(j(void 0).entryId);let{url:r}=await L("form",{});i||(l=((e,t,r,o,n)=>{let a=null;try{a=new URL(r)}catch{}if(!a||!/^https?:$/.test(a.protocol))throw Error("Obelism Content sent no form to open");let i=a.origin,l=t.ownerDocument.createElement("iframe");l.title=o,l.src=r;let s=!1,d=!1,c=null,p=()=>{s&&c&&l.contentWindow?.postMessage({source:h,type:"content",...c},i)},g=setTimeout(()=>{d||n.onError("The form did not open")},3e4),u=()=>{d=!0,clearTimeout(g),n.onReady()},m=e=>{if(e.origin!==i||!l.contentWindow||e.source!==l.contentWindow)return;let t=e.data;if(t&&"obelism-content-form"===t.source)if("ready"===t.type)s=!0,p(),!0!==t.loading&&u();else if("loaded"===t.type)s&&u();else{let e;if("change"!==t.type||!(e=t.content)||"object"!=typeof e||Array.isArray(e))if("height"===t.type){let e=t.height;if("number"==typeof e&&Number.isFinite(e)){let t=Math.round(Math.min(Math.max(e,80),4e3));l.style.height=`min(${t}px, 60vh)`}}else"error"===t.type&&n.onError("string"==typeof t.message&&t.message?t.message:"The form failed");else n.onChange(t.content,"string"==typeof t.entryId?t.entryId:void 0)}};return e.addEventListener("message",m),t.appendChild(l),{show(e){c=e,p()},destroy(){clearTimeout(g),e.removeEventListener("message",m),l.remove()}}})(e,t,"string"==typeof r?r:"",o,{onReady:()=>n?.(),onChange:f,onError:e=>a?.(e)}),d=c.on("change",b),b())})().catch(p),{close:m}},async pages(){let{pages:e}=await L("pages"),t=[U(),y?.space.defaultLocale];return e.flatMap(e=>{let r,o,n=t.find(t=>void 0!==t&&void 0!==e.paths[t])??Object.keys(e.paths)[0],a=void 0===n?void 0:e.paths[n];return void 0===n||void 0===a?[]:[{entryId:e.entryId,name:e.name,contentType:e.contentType,status:e.status,path:a,url:e.product?(r=e.product.handle,l?l(r,n):(y?.productPath??"/products/{handle}").replaceAll("{handle}",encodeURIComponent(r))):e.collection?(o=e.collection.handle,s?s(o,n):(y?.collectionPath??"/collections/{handle}").replaceAll("{handle}",encodeURIComponent(o))):i(a,n),product:e.product??null,collection:e.collection??null}]})},openPage(t){(!C.unsaved||e.confirm("Leave this page and lose the changes you have not saved?"))&&(g.clear(),u.length=0,A(),e.location.assign(t.url))},undo(){let e=u.pop(),t=e&&g.get(e.entryId);e&&t&&(w=-1/0,t.content=e.content,A(),T(e.entryId).catch(D))},async save(){if(!C.features.includes("save"))throw Error("You may not edit content here");P({saving:!0});try{await q()}finally{P({saving:!1})}F("saved")},async publish(){if(!C.features.includes("publish"))throw Error("You may not publish here");P({publishing:!0});try{await q();let e=S(),t=m.size>0?[...m]:e?[e]:[];if(0===t.length)throw Error("Nothing on this page is marked as an entry: add editable(entry)");for(let e of t)await L(`entries/${encodeURIComponent(e)}/publish`,{}),m.delete(e)}finally{P({publishing:!1})}F("published")},signOut(){if(C.unsaved&&!e.confirm("Sign out and lose the changes you have not saved?"))return;g.clear(),A();let t=e.location.pathname+e.location.search;e.location.href=`${a}/logout?return_to=${encodeURIComponent(t)}`},select(e){z(e)},setSelecting(e){e?d.documentElement.setAttribute("data-cms-selecting",""):d.documentElement.removeAttribute("data-cms-selecting"),P({selecting:e})},destroy(){x?.(),k.forEach(e=>clearTimeout(e)),k.clear(),p.splice(0).forEach(e=>e())}},B=d.createElement("style");B.textContent=b("html[data-cms-selecting] "),d.head.appendChild(B),p.push(()=>B.remove()),p.push(()=>d.documentElement.removeAttribute("data-cms-selecting"));let H=e=>{if(!C.selecting)return;let r=e.target,o=r?.closest?.(`[${t}]`);o&&(e.preventDefault(),e.stopPropagation(),z(o.getAttribute(t)))};d.addEventListener("click",H,!0),p.push(()=>d.removeEventListener("click",H,!0));let W=e=>{C.unsaved&&(e.preventDefault(),e.returnValue="")};return e.addEventListener("beforeunload",W),p.push(()=>e.removeEventListener("beforeunload",W)),L("session").then(e=>{y=e,P({features:e.features})}).catch(e=>console.error("[@obelism/content bridge]",e)),V})(P,C,{pagePath:p,productPath:m,collectionPath:y})),x.isEditing&&c){let e=P.document,t=()=>{},r=!1,o=()=>{r||(t=I(e,x,!0===c?{}:c))};e.body?o():e.addEventListener("DOMContentLoaded",o,{once:!0});let n=x.destroy;x.destroy=()=>{r=!0,e.removeEventListener("DOMContentLoaded",o),t(),n()}}}return P[O]=x,x};(e=window).ObelismBridge=j((e=>{let t=e?.dataset.url,r=t||U;if(!t&&e?.src){let t=new URL(e.src);"/bridge.js"===t.pathname&&(r=t.origin)}return{url:r,prompt:e?.dataset.prompt!=="false"}})(document.currentScript)),e.ObelismContent={getContentBridge:j,mountPromptBox:I}}();
|
|
260
|
+
`,N=(e,t,r={},...o)=>{let n=e.createElement(t);for(let t of(Object.assign(n,r),o))n.appendChild("string"==typeof t?e.createTextNode(t):t);return n},M=(e,t)=>{let r=N(e,"span",{className:"icon"});return r.setAttribute("aria-hidden","true"),r.innerHTML=`<svg viewBox="0 0 24 24">${L[t]}</svg>`,r},I=(e,t,r={})=>{let o,n={...P,...r.labels},a=N(e,"div");a.setAttribute("data-obelism-content-prompt","");let i=a.attachShadow({mode:"open"}),l="site"===t.mode,s=N(e,"span",{textContent:n.open}),d=N(e,"button",{className:"pill",type:"button"},s,((o=M(e,"mark")).classList.add("mark"),o)),c=N(e,"span",{className:"pill compact"},`${n.viewingDrafts} \xb7 `),p=N(e,"button",{className:"link",type:"button",textContent:n.signOut});c.appendChild(p);let g=N(e,"p",{className:"status"});g.setAttribute("role","status");let u=N(e,"textarea",{placeholder:n.placeholder,rows:1});u.setAttribute("aria-label",n.open);let h=N(e,"div",{className:"form-loader",textContent:n.formLoading});h.setAttribute("role","status");let m=N(e,"div",{className:"form"},h),b=M(e,"page"),f=M(e,"block"),v=N(e,"span"),y=N(e,"button",{type:"button",title:n.clearBlock});y.setAttribute("aria-label",n.clearBlock),y.appendChild(M(e,"close"));let x=N(e,"span",{className:"chip scope"},b,f,v,y),w=N(e,"button",{className:"action chip",type:"button"},M(e,"undo"),n.undo),k=t=>{let r=N(e,"button",{type:"button",textContent:t});return r.setAttribute("aria-pressed","false"),r},E=k(n.modePrompt),C=k(n.form),L=N(e,"span",{className:"modes"},E,C);L.setAttribute("role","group"),L.setAttribute("aria-label",n.modes);let I=N(e,"button",{className:"action chip",type:"button"},M(e,"newPage"),n.newPage),U=N(e,"button",{className:"action chip product",type:"button"},M(e,"newPage"),n.addProductPage),$=N(e,"button",{type:"button",title:n.newPageCancel});$.setAttribute("aria-label",n.newPageCancel),$.appendChild(M(e,"close"));let O=N(e,"span",{className:"chip scope"},M(e,"newPage"),N(e,"span",{textContent:n.newPage}),$),R=N(e,"input",{type:"text",placeholder:n.pathPlaceholder,autocomplete:"off",spellcheck:!1}),j=N(e,"label",{className:"path"},N(e,"span",{textContent:n.path}),R),z=N(e,"button",{className:"close icon-button",type:"button",title:n.close},M(e,"close"));z.setAttribute("aria-label",n.close);let T=M(e,"minimize"),D=M(e,"expand"),F=N(e,"button",{className:"icon-button",type:"button"},T,D),q=N(e,"button",{className:"action primary icon-button",type:"submit"},N(e,"span",{className:"visually-hidden",textContent:n.send}),M(e,"send"));q.title=n.send;let V=N(e,"span",{className:"divider"}),B=N(e,"div",{className:"toolbar"},x,O,L,w,U,I,N(e,"span",{className:"spacer"}),F,z,V,q),H=N(e,"span",{textContent:n.pages}),W=N(e,"button",{className:"chip page-chip",type:"button",title:n.pages},M(e,"page"),H,M(e,"chevrons"));W.setAttribute("aria-haspopup","listbox"),W.setAttribute("aria-expanded","false"),W.setAttribute("aria-controls","obelism-pages");let Y=N(e,"input",{type:"text",placeholder:n.pagesSearch,autocomplete:"off",spellcheck:!1});Y.setAttribute("role","combobox"),Y.setAttribute("aria-label",n.pagesSearch),Y.setAttribute("aria-autocomplete","list"),Y.setAttribute("aria-expanded","true"),Y.setAttribute("aria-controls","obelism-pages");let X=N(e,"ul",{className:"options",id:"obelism-pages"});X.setAttribute("role","listbox"),X.setAttribute("aria-label",n.pages);let _=N(e,"p",{className:"empty"}),J=N(e,"div",{className:"pages"},N(e,"label",{className:"search"},M(e,"search"),Y),X,_),Z=N(e,"slot");Z.name="actions-footer";let K=N(e,"slot");K.name="actions-bar",r.actions&&(r.actions.slot="actions-bar",a.appendChild(r.actions));let G=N(e,"span",{className:"unsaved"});G.appendChild(N(e,"span",{className:"dot"})),G.appendChild(e.createTextNode(n.unsaved));let Q=N(e,"button",{className:"link",type:"button",textContent:n.signOut}),ee=N(e,"button",{className:"action chip",type:"button",textContent:n.save}),et=N(e,"button",{className:"action chip",type:"button",textContent:n.publish}),er=N(e,"div",{className:"footer"},W,G,N(e,"span",{className:"spacer"}),Z,Q,ee,et),eo=N(e,"form",{className:"panel"},g,j,u,m,B,J,er),en=N(e,"div",{className:"root"},N(e,"div",{className:"bar"},d,c,K),eo);i.append(N(e,"style",{textContent:S}),en);let ea=e.defaultView,ei=e=>{"center"===e?delete en.dataset.side:en.dataset.side=e};ei((()=>{try{let e=ea?.localStorage.getItem(A);return"left"===e||"right"===e?e:"center"}catch{return"center"}})());let el=null,es=!1;en.addEventListener("pointerdown",e=>{if(es=!1,0!==e.button||!e.isPrimary)return;let t=e.target.closest("button, input, textarea, select, iframe, a, label, .pages, .form");if(t&&t!==d)return;let{left:r,right:o}=en.getBoundingClientRect();el={id:e.pointerId,startX:e.clientX,x:e.clientX,velocity:0,time:e.timeStamp,moved:!1,min:Math.min(0,16-r),max:Math.max(0,(ea?.innerWidth??0)-16-o)}}),en.addEventListener("pointermove",e=>{if(!el||e.pointerId!==el.id)return;let t=e.clientX-el.startX;if(!el.moved){if(6>Math.abs(t))return;el.moved=!0,en.classList.add("dragging");try{en.setPointerCapture(e.pointerId)}catch{}}let r=e.timeStamp-el.time;r>0&&(el.velocity=(e.clientX-el.x)/r),el.x=e.clientX,el.time=e.timeStamp;let o=Math.min(Math.max(t,el.min),el.max);en.style.translate=`${o+(t-o)/3}px 0`});let ed=e=>{if(!el||e.pointerId!==el.id)return;let{moved:t,x:r,velocity:o,time:n}=el;if(el=null,!t)return;es=!0;let a=en.getBoundingClientRect().left,i=ea?.innerWidth??0,l=r+(e.timeStamp-n>80?0:Math.min(Math.max(150*o,-120),120)),s=l<i/3?"left":l>2*i/3?"right":"center";ei(s),en.style.translate="";let d=en.getBoundingClientRect().left;en.style.translate=`${a-d}px 0`,en.offsetWidth,en.classList.remove("dragging"),en.style.translate="";try{ea?.localStorage.setItem(A,s)}catch{}};en.addEventListener("pointerup",ed),en.addEventListener("pointercancel",ed),en.addEventListener("click",e=>{es&&(es=!1,e.preventDefault(),e.stopPropagation())},!0);let ec=!1,ep=!1,eg=!1,eu=null,eh=!1,em=null,eb=!1,ef=!1,ev=null,ey=null,ex=null,ew=0,ek=e=>({text:e instanceof Error?e.message:String(e),error:!0}),eE=e=>{let o=e.features.includes("prompt"),a=e.saving||e.publishing,i=e.prompting||a;en.hidden=!o&&!l,d.hidden=ec||!o,c.hidden=o||!l,eo.hidden=!ec||!o;let k=l&&e.features.includes("create"),P=l&&null===t.entryId,A=P&&k?t.product?"product":t.collection?"collection":null:null,S=null!==A,N="collection"===A?{add:n.addCollectionPage,adding:n.addingCollectionPage,hint:n.collectionPageHint}:{add:n.addProductPage,adding:n.addingProductPage,hint:n.productPageHint};U.lastChild.textContent=N.add;let M=P&&k&&!S&&!r.promptWithoutPage;k||(eg=!1),M&&(eg=!0),(eg||P||!l)&&(eh=!1);let z=ec&&o&&eh;z&&!em?eA():!z&&em&&eL();let Y=S&&!eg;s.textContent=Y?N.add:M?n.newPage:n.open,$.hidden=M,x.hidden=eg||Y,O.hidden=!eg,U.hidden=!Y,U.disabled=i,I.hidden=eg||eh||!k,I.disabled=i,ep&&(ef=!1),j.hidden=!eg||ef||ep,R.disabled=i,u.hidden=eh||ef||ep||Y,m.hidden=!eh||ef||ep,m.classList.toggle("loading",eb),h.hidden=!eb,B.hidden=ef,J.hidden=!ef,u.placeholder=eg?n.newPagePlaceholder:n.placeholder,v.textContent=e.selectedUid?n.scopeBlock:P?n.scopeNoPage:n.scopeEntry,y.hidden=!e.selectedUid,b.hidden=!!e.selectedUid,f.hidden=!e.selectedUid,L.hidden=!l||eg||P||!e.features.includes("form"),E.setAttribute("aria-pressed",String(!eh)),C.setAttribute("aria-pressed",String(eh)),L.querySelectorAll("button").forEach(e=>{e.disabled=i}),w.hidden=eg||!e.canUndo,w.disabled=i,q.hidden=eh||ep||Y,V.hidden=eh||ep||Y;let X=ep?n.expand:n.minimize;F.title=X,F.setAttribute("aria-label",X),F.setAttribute("aria-expanded",String(!ep)),T.hidden=ep,D.hidden=!ep,q.disabled=i||""===u.value.trim()||eg&&""===R.value.trim(),u.disabled=i,ee.hidden=!e.features.includes("save")||P,ee.disabled=i||!e.unsaved,ee.textContent=e.saving?n.saving:n.save,et.hidden=!e.features.includes("publish")||P,et.disabled=i,et.textContent=e.publishing?n.publishing:n.publish,Q.hidden=!l||!1===r.signOut,p.hidden=!1===r.signOut,r.actions&&(r.actions.slot=ec&&o?"actions-footer":"actions-bar"),er.hidden=!l,G.hidden=!e.unsaved,W.hidden=!l,W.setAttribute("aria-expanded",String(ef)),H.textContent=ev?.find(({entryId:e})=>e===t.entryId)?.name??n.pages;let _=eh&&eb&&!ef,Z=e.prompting,K=e.prompting?eg?n.creating:Y?N.adding:n.working:_?"":eu?.text??(Y?N.hint:!l||eg||ef||e.selectedUid?"":n.selectHint);g.textContent=K,g.hidden=!K||ep,g.className=`status${Z?" working":""}${!i&&!_&&eu?.error?" error":""}`},eC=()=>eE(t.getState()),eP=()=>{u.style.height="auto",u.style.height=`${u.scrollHeight}px`},eA=()=>{eb=!0,m.classList.add("loading");let e=t.openForm(m,{title:n.formTitle,onReady:()=>{em===e&&(eb=!1,eu=null,eC())},onError:t=>{em===e&&(eb=!1,eu={text:t,error:!0},eC())}});em=e},eL=()=>{em?.close(),em=null,eb=!1},eS=e=>{eh!==e&&(eh=e,eu=null,eC(),eh||u.focus())},eN=async()=>{if(eh)return;let e=u.value.trim();if(e&&!t.getState().prompting){eu=null;try{if(eg){let r=R.value.trim();if(!r)return R.focus();await t.createPage(r,e),ev=null,ey=null,eu={text:n.created,error:!1}}else{let{summary:r}=await t.prompt(e);eu={text:r,error:!1}}u.value="",eP()}catch(e){eu=ek(e)}eC(),u.focus()}},eM=()=>(ey??(ey=t.pages().then(e=>{ev=e,ex=null,eU(),eC()},e=>{ey=null,ex=ek(e).text,eU()})),ey),eI=()=>{let e=Y.value.trim().toLowerCase();return(ev??[]).filter(t=>!e||t.name.toLowerCase().includes(e)||t.url.toLowerCase().includes(e)||`/${t.path}`.toLowerCase().includes(e))},eU=()=>{let r=eI();ew=Math.max(0,Math.min(ew,r.length-1)),X.textContent="",r.forEach((r,o)=>{let a=r.entryId===t.entryId,i=N(e,"li",{className:`option${o===ew?" active":""}`,id:`obelism-page-${o}`},N(e,"span",{className:"option-text"},N(e,"span",{textContent:r.name}),N(e,"span",{className:"option-path",textContent:r.url})));if(i.setAttribute("role","option"),i.setAttribute("aria-selected",String(o===ew)),"published"!==r.status&&i.appendChild(N(e,"span",{className:"badge",textContent:"draft"===r.status?n.pageDraft:n.pageChanged})),a){i.setAttribute("aria-current","page");let t=M(e,"check");t.removeAttribute("aria-hidden"),t.setAttribute("role","img"),t.setAttribute("aria-label",n.pageCurrent),i.appendChild(t)}i.addEventListener("click",()=>eO(r)),X.appendChild(i)});let o=X.children[ew];o?(Y.setAttribute("aria-activedescendant",o.id),o.scrollIntoView?.({block:"nearest"})):Y.removeAttribute("aria-activedescendant"),_.textContent=(ex??(ev?"":n.pagesLoading))||(0===r.length?n.pagesEmpty:""),_.hidden=!_.textContent,_.className=`empty${ex?" error":""}`},e$=e=>{eu=null,(ef=e)&&(Y.value="",ew=Math.max(0,(ev??[]).findIndex(({entryId:e})=>e===t.entryId)),eM(),eU()),eC(),(ef?Y:W).focus()},eO=e=>{if(e.entryId===t.entryId)return e$(!1);t.openPage(e)},eR=e=>{(ec=e)||(ef=!1,ep=!1),eC(),l&&t.setSelecting(ec&&!eg),ec&&l&&eM()},ej=e=>{eg=e,eu=null,t.setSelecting(ec&&!eg),eg&&t.select(null),eC(),(eg?R:u).focus()},ez=async e=>{eu=null;try{await t[e](),eu={text:"save"===e?n.saved:n.published,error:!1}}catch(e){eu=ek(e)}eC()};d.addEventListener("click",()=>{eR(!0),eh||(eg?R:u).focus()}),z.addEventListener("click",()=>eR(!1)),F.addEventListener("click",()=>{ep=!ep,eC(),ep||(eh?F:u).focus()}),eo.addEventListener("click",e=>{if(!ep)return;let t=e.target.closest("button");t&&t!==F&&t!==z&&(ep=!1,eC())},!0),ee.addEventListener("click",()=>void ez("save")),et.addEventListener("click",()=>void ez("publish")),Q.addEventListener("click",()=>t.signOut()),p.addEventListener("click",()=>t.signOut()),y.addEventListener("click",()=>t.select(null)),I.addEventListener("click",()=>ej(!0)),U.addEventListener("click",async()=>{eu=null;try{t.product?(await t.createProductPage(),eu={text:n.addedProductPage,error:!1}):(await t.createCollectionPage(),eu={text:n.addedCollectionPage,error:!1})}catch(e){eu=ek(e)}eC()}),$.addEventListener("click",()=>ej(!1)),E.addEventListener("click",()=>eS(!1)),C.addEventListener("click",()=>eS(!0)),W.addEventListener("click",()=>e$(!ef)),R.addEventListener("input",eC),R.addEventListener("keydown",e=>{"Enter"!==e.key||e.isComposing?"Escape"===e.key&&eR(!1):(e.preventDefault(),u.focus())}),Y.addEventListener("input",()=>{ew=0,eU()}),Y.addEventListener("keydown",e=>{let t=X.children.length;if("ArrowDown"===e.key||"ArrowUp"===e.key){if(e.preventDefault(),0===t)return;ew=(ew+("ArrowDown"===e.key?1:-1)+t)%t,eU()}else if("Enter"!==e.key||e.isComposing)"Escape"===e.key&&(e.preventDefault(),e$(!1));else{e.preventDefault();let t=eI()[ew];t&&eO(t)}}),w.addEventListener("click",()=>{eu=null,t.undo()}),eo.addEventListener("submit",e=>{e.preventDefault(),eN()}),u.addEventListener("input",()=>{eP(),eC()}),u.addEventListener("keydown",e=>{"Enter"!==e.key||e.shiftKey||e.isComposing?"Escape"===e.key&&eR(!1):(e.preventDefault(),eN())});let eT=t.on("change",eE);return eC(),e.body.appendChild(a),()=>{eT(),eL(),a.remove()}},U="https://content.obelism.studio",$=/^(?:\/[\w.~-]+)+$/,O=e=>{let{protocol:t}=new URL(e,"https://site.invalid");if("https:"!==t&&"http:"!==t)throw Error(`Not a page address: ${e}`);return e},R=(e,t)=>JSON.stringify(e)===JSON.stringify(t),j=Symbol.for("@obelism/content/bridge"),z=C({isEditing:!1,entryId:null,on:()=>{}},new URLSearchParams),T=({url:e,prompt:c=!0,pagePath:p,productPath:m,collectionPath:y}={})=>{let x;if("u"<typeof window)return z;let P=window;if(P[j])return P[j];if(P.ObelismBridge)x=C(P.ObelismBridge,new URLSearchParams(P.location.search));else{let C=(x=((e,r)=>{let o,n,c,p,m,y=new URLSearchParams(e.location.search),x=e.parent!==e&&y.has("cms_preview"),C=v(),P=[],A={...f,selecting:!0},L=e=>{A={...A,...e},C.emit("change",A)},S={isEditing:x,mode:x?"editor":null,entryId:y.get("cms_entry"),environment:y.get(a),product:null,collection:null,on:C.on,getState:()=>A,...w,destroy:()=>{P.splice(0).forEach(e=>e())}};if(!x)return S;let N=e.document,M=(t,o={})=>{e.parent.postMessage({source:h,type:t,...o},r)},I=N.createElement("style");I.textContent=b(),N.head.appendChild(I),P.push(()=>I.remove());let U=(e,t)=>{if(N.querySelectorAll("[data-cms-selected]").forEach(e=>{e.removeAttribute("data-cms-selected")}),A.selectedUid!==(e??null)&&L({selectedUid:e??null}),!e)return;let r=N.querySelector(E(e));r&&(r.setAttribute("data-cms-selected",""),t&&r.scrollIntoView({behavior:"smooth",block:"center"}))},$=e=>{let r=e.target,o=r?.closest?.(`[${t}]`);if(!o)return;e.preventDefault(),e.stopPropagation();let n=o.getAttribute(t);U(n,!1),M("select",{uid:n})};N.addEventListener("click",$,!0),P.push(()=>N.removeEventListener("click",$,!0));let O=()=>Math.ceil(Math.max(N.documentElement.scrollHeight,N.body?.scrollHeight??0)),R=0,j=()=>{R=O(),M("ready",{url:e.location.href,height:R})},z=e.ResizeObserver;if("function"==typeof z){let e=new z(()=>{let e=O();e!==R&&(R=e,M("size",{height:e}))});e.observe(N.documentElement),N.body&&e.observe(N.body),P.push(()=>e.disconnect())}let T=new Map,D=0,F=e=>{let t=T.get(e);return t?(clearTimeout(t.timer),T.delete(e),0===T.size&&L({prompting:!1}),t):null};S.prompt=(e,t={})=>{let r=e.trim();if(!r)return Promise.reject(Error("Say what to change"));if(!A.features.includes("prompt"))return Promise.reject(Error("The editor does not offer prompts here"));let o=`prompt_${++D}`,n=void 0===t.uid?A.selectedUid:t.uid;return new Promise((e,t)=>{let a=setTimeout(()=>{F(o)?.reject(Error("The editor did not answer in time"))},12e4);T.set(o,{resolve:e,reject:t,timer:a}),L({prompting:!0}),M("prompt",{id:o,prompt:r,uid:n})})},S.undo=()=>M("undo"),S.select=e=>{U(e,!1),M("select",{uid:e})};let q=null;P.push(()=>q?.destroy()),P.push(()=>{for(let e of T.keys())F(e)?.reject(Error("The bridge was destroyed"))});let V=(o=new WeakSet,n=null,c=null,p=!1,m=()=>{if(null!==n){for(let e of Array.from(N.styleSheets)){let t;if(!o.has(e)){try{t=e.cssRules}catch{continue}o.add(e),u(t,n)}}N.querySelectorAll('[style*="vh"]').forEach(e=>{g(e.style,n)})}},{freeze(e){if(null!==n||!(e>0))return;n=e,m();let t=N.defaultView?.MutationObserver;t&&(c=new t(()=>{if(p)return;p=!0;let e=()=>{p=!1,m()};N.defaultView?.requestAnimationFrame?N.defaultView.requestAnimationFrame(e):e()})).observe(N.documentElement,{childList:!0,subtree:!0})},destroy(){c?.disconnect()}});P.push(()=>V.destroy());let B=t=>{if(t.origin!==r||t.source!==e.parent)return;let o=t.data;if(o&&"obelism-content-editor"===o.source){if("connect"===o.type)j();else if("update"===o.type&&o.entry)C.emit("update",{entry:o.entry,selectedUid:o.selectedUid??null}),e.requestAnimationFrame(()=>U(o.selectedUid,!1)),q?.refresh();else if("select"===o.type)U(o.uid,!0);else if("saved"===o.type||"published"===o.type)C.emit(o.type,{}),0===C.listeners.update.size&&e.location.reload();else if("features"===o.type&&Array.isArray(o.features))L({features:o.features.filter(e=>"string"==typeof e)});else if("stats"===o.type)L({stats:(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return{};let t={};for(let[r,o]of Object.entries(e)){let{clicks:e,clickers:n,viewers:a,rate:i}=o??{};k(e)&&k(n)&&k(a)&&k(i)&&(t[r]={clicks:e,clickers:n,viewers:a,rate:i})}return t})(o.stats),statsVisible:!1!==o.visible}),(q||Object.keys(A.stats).length)&&(q??(q=((e,{selector:t,onSelect:r,labels:o})=>{let n=e.document,a={...i,...o},c=n.createElement("div");c.setAttribute("data-obelism-stats","");let p=c.attachShadow({mode:"open"}),g=n.createElement("style");g.textContent=s;let u=n.createElement("div");u.className="layer",p.append(g,u),n.body.appendChild(c);let h={},m=!1,b=null,f=()=>{if(b=null,u.replaceChildren(),u.hidden=!m,!m)return;let o=e.innerHeight;for(let[i,s]of Object.entries(h)){let c=n.querySelector(t(i));if(!c)continue;let p=c.getBoundingClientRect();if(!p.width&&!p.height||p.bottom<0||p.top>o)continue;let g=n.createElement("button");g.type="button",g.className="badge",g.dataset.uid=i,g.textContent=l(a.clicked,{rate:Math.round(100*s.rate)}),g.title=l(a.title,{clickers:s.clickers,viewers:s.viewers,clicks:s.clicks});let{place:h,top:m,left:b}=d(p,e.innerWidth);g.dataset.place=h,g.style.top=`${m}px`,g.style.left=`${b}px`,g.addEventListener("click",()=>r(i)),u.appendChild(g)}},v=()=>{null===b&&m&&(b=e.requestAnimationFrame(f))};e.addEventListener("scroll",v,{capture:!0,passive:!0}),e.addEventListener("resize",v);let y=e.MutationObserver,x="function"==typeof y?new y(v):null;return x?.observe(n.body,{childList:!0,subtree:!0}),{update(t,r){h=t,m=r,null!==b&&(e.cancelAnimationFrame?.(b),b=null),f()},refresh:v,destroy(){null!==b&&e.cancelAnimationFrame?.(b),e.removeEventListener("scroll",v,{capture:!0}),e.removeEventListener("resize",v),x?.disconnect(),c.remove()}}})(e,{selector:E,onSelect:e=>S.select(e)})),q.update(A.stats,A.statsVisible));else if("viewport"===o.type&&"number"==typeof o.height)V.freeze(o.height);else if("promptState"===o.type)L({canUndo:!0===o.canUndo});else if("promptResult"===o.type&&"string"==typeof o.id){let e=F(o.id);if(!e)return;!0===o.ok?e.resolve({summary:"string"==typeof o.summary?o.summary:""}):e.reject(Error("string"==typeof o.error?o.error:"The prompt failed"))}}};return e.addEventListener("message",B),P.push(()=>e.removeEventListener("message",B)),"loading"===N.readyState?(N.addEventListener("DOMContentLoaded",j,{once:!0}),P.push(()=>N.removeEventListener("DOMContentLoaded",j))):j(),S})(P,new URL(e||U).origin)).isEditing||P.parent!==P?null:(e=>{for(let t of e.cookie.split(";")){let[e,...r]=t.trim().split("=");if("obelism_content_editing"===e)try{let e=decodeURIComponent(r.join("="));return $.test(e)?e:null}catch{break}}return null})(P.document);if(C&&(x=((e,a,{pagePath:i=e=>`/${e.replace(/^\/+/,"")}`,productPath:l,collectionPath:s}={})=>{let d=e.document,c=v(),p=[],g=new Map,u=[],m=new Set,y=null,x=null,w=-1/0,k=new Map,C=f,P=e=>{C={...C,...e},c.emit("change",C)},A=()=>P({unsaved:[...g.values()].some(({content:e,saved:t})=>!R(e,t)),canUndo:u.length>0}),L=async(t,r)=>{let o=await e.fetch(`${a}/api/${t}`,void 0===r?{credentials:"same-origin"}:{method:"POST",credentials:"same-origin",headers:{"Content-Type":"application/json","x-obelism-content":"1"},body:JSON.stringify(r)}),n=await o.json().catch(()=>({}));if(401===o.status)throw P({features:[]}),Error("You were signed out. Sign in again to edit.");if(!o.ok)throw Error("string"==typeof n.error?n.error:`Obelism Content answered ${o.status}`);return n},S=()=>d.querySelector(`[${r}]`)?.getAttribute(r)??null,N=()=>{let e=d.querySelector(`[${o}]`),t=e?.getAttribute(o),r=e?.getAttribute("data-cms-product-handle");return t&&r?{id:t,handle:r}:null},M=()=>{let e=d.querySelector(`[${n}]`),t=e?.getAttribute(n),r=e?.getAttribute("data-cms-collection-handle");return t&&r?{id:t,handle:r}:null},I=e=>{let t=e?d.querySelector(E(e)):null;return t?.closest(`[${r}]`)?.getAttribute(r)??S()},U=()=>{if(!y)return;let e=y.space.locales.map(({code:e})=>e),t=d.documentElement.lang;if(e.includes(t))return t;let r=t.split("-")[0]??"";return e.includes(r)?r:y.space.defaultLocale},$=new Map,j=async e=>{let t=g.get(e);if(t)return t;let r=$.get(e);return r||(r=L(`entries/${encodeURIComponent(e)}`).then(t=>{let r=g.get(e)??{content:t.content,saved:t.content,revision:t.draftRevision};return g.set(e,r),r}).finally(()=>$.delete(e)),$.set(e,r)),r},z=e=>{let t=void 0===e?C.selectedUid:e,r=I(t);if(!r)throw Error("Nothing on this page is marked as an entry: add editable(entry)");return{uid:t,entryId:r}},T=e=>{d.querySelectorAll("[data-cms-selected]").forEach(e=>{e.removeAttribute("data-cms-selected")}),C.selectedUid!==e&&P({selectedUid:e}),e&&d.querySelector(E(e))?.setAttribute("data-cms-selected","")},D=async t=>{if(0===c.listeners.update.size)return;let r=g.get(t)?.content,{entry:o}=await L(`entries/${encodeURIComponent(t)}/preview`,{content:r,locale:U()});c.emit("update",{entry:o,selectedUid:C.selectedUid}),e.requestAnimationFrame(()=>T(C.selectedUid))},F=e=>console.error("[@obelism/content bridge]",e),q=t=>{c.emit(t,{}),0===c.listeners.update.size&&e.location.reload()},V=async()=>{for(let[e,t]of g){if(R(t.content,t.saved))continue;let{draftRevision:r}=await L(`entries/${encodeURIComponent(e)}/save`,{content:t.content,baseRevision:t.revision});t.saved=t.content,t.revision=r,m.add(e)}u.length=0,w=-1/0,A()},B={isEditing:!0,mode:"site",get entryId(){return S()},get product(){return N()},get collection(){return M()},environment:null,on:c.on,getState:()=>C,async prompt(e,t={}){let r=e.trim();if(!r)throw Error("Say what to change");if(!C.features.includes("prompt"))throw Error("You may not edit content here");let{uid:o,entryId:n}=z(t.uid);P({prompting:!0});try{let e=await j(n),t=await L(`entries/${encodeURIComponent(n)}/prompt`,{prompt:r,content:e.content,locale:U(),uid:o});return u.push({entryId:n,content:e.content}),w=-1/0,e.content=t.content,A(),await D(n),{summary:t.summary}}finally{P({prompting:!1})}},async createPage(t,r){let o=r.trim();if(!o)throw Error("Say what the page is for");if(!t.trim())throw Error("Say where the page goes, like /pricing");if(!C.features.includes("create"))throw Error("You may not add pages here");if(C.unsaved)throw Error("Save or undo your changes before adding a page");P({prompting:!0});try{let r=await L("entries",{path:t,prompt:o,locale:U(),from:S()}),n=i(r.path,U()??"");return e.location.assign(O(n)),{summary:r.summary,entryId:r.entryId,path:r.path,url:n}}finally{P({prompting:!1})}},async createProductPage(t=N()??void 0){if(!t)throw Error("Nothing on this page is marked as a product: add editableProduct(product)");if(!C.features.includes("create"))throw Error("You may not add pages here");if(C.unsaved)throw Error("Save or undo your changes before adding a page");P({prompting:!0});try{let r=await L("product-pages",{product:{id:t.id,handle:t.handle}});return e.location.reload(),r}finally{P({prompting:!1})}},async createCollectionPage(t=M()??void 0){if(!t)throw Error("Nothing on this page is marked as a collection: add editableCollection(collection)");if(!C.features.includes("create"))throw Error("You may not add pages here");if(C.unsaved)throw Error("Save or undo your changes before adding a page");P({prompting:!0});try{let r=await L("collection-pages",{collection:{id:t.id,handle:t.handle}});return e.location.reload(),r}finally{P({prompting:!1})}},async view(e={}){let{uid:t,entryId:r}=z(e.uid),o=await j(r),{view:n}=await L(`entries/${encodeURIComponent(r)}/view`,{content:o.content,locale:U(),uid:t});return n},async applyJson(e,t={}){if(!C.features.includes("prompt"))throw Error("You may not edit content here");if(!e||"object"!=typeof e||Array.isArray(e))throw Error("Send the fields to change as an object");let{uid:r,entryId:o}=z(t.uid);P({prompting:!0});try{let t=await j(o),n=await L(`entries/${encodeURIComponent(o)}/apply`,{changes:e,content:t.content,locale:U(),uid:r});return R(n.content,t.content)||(u.push({entryId:o,content:t.content}),w=-1/0,t.content=n.content,A(),await D(o)),{changed:n.changed??[],...n.view&&{view:n.view}}}finally{P({prompting:!1})}},openForm(t,r={}){let{title:o="Content form",onReady:n,onError:a}=r;x?.();let i=!1,l=null,s=null,d=()=>{},p=e=>{i||a?.(e instanceof Error?e.message:String(e))},m=()=>{i||(i=!0,d(),l?.destroy(),x===m&&(x=null))};x=m;let b=()=>{if(i||!l)return;let e=I(C.selectedUid);if(!e)return;let t=g.get(e);if(!t)return void j(e).then(b,p);let r={entryId:e,content:t.content,locale:U(),selectedUid:C.selectedUid};s&&s.entryId===r.entryId&&s.content===r.content&&s.locale===r.locale&&s.selectedUid===r.selectedUid||(s=r,l.show(r))},f=(e,t)=>{let r=t??s?.entryId,o=void 0===r?void 0:g.get(r);if(i||void 0===r||!o||R(e,o.content))return;let n=Date.now();n-w>=1e3&&u.push({entryId:r,content:o.content}),w=n,o.content=e,s?.entryId===r&&(s={...s,content:e}),A(),clearTimeout(k.get(r)),k.set(r,setTimeout(()=>{k.delete(r),D(r).catch(F)},300))};return(async()=>{if(!C.features.includes("form"))throw Error("You may not edit content here");await j(z(void 0).entryId);let{url:r}=await L("form",{});i||(l=((e,t,r,o,n)=>{let a=null;try{a=new URL(r)}catch{}if(!a||!/^https?:$/.test(a.protocol))throw Error("Obelism Content sent no form to open");let i=a.origin,l=t.ownerDocument.createElement("iframe");l.title=o,l.src=r;let s=!1,d=!1,c=null,p=()=>{s&&c&&l.contentWindow?.postMessage({source:h,type:"content",...c},i)},g=setTimeout(()=>{d||n.onError("The form did not open")},3e4),u=()=>{d=!0,clearTimeout(g),n.onReady()},m=e=>{if(e.origin!==i||!l.contentWindow||e.source!==l.contentWindow)return;let t=e.data;if(t&&"obelism-content-form"===t.source)if("ready"===t.type)s=!0,p(),!0!==t.loading&&u();else if("loaded"===t.type)s&&u();else{let e;if("change"!==t.type||!(e=t.content)||"object"!=typeof e||Array.isArray(e))if("height"===t.type){let e=t.height;if("number"==typeof e&&Number.isFinite(e)){let t=Math.round(Math.min(Math.max(e,80),4e3));l.style.height=`min(${t}px, 60vh)`}}else"error"===t.type&&n.onError("string"==typeof t.message&&t.message?t.message:"The form failed");else n.onChange(t.content,"string"==typeof t.entryId?t.entryId:void 0)}};return e.addEventListener("message",m),t.appendChild(l),{show(e){c=e,p()},destroy(){clearTimeout(g),e.removeEventListener("message",m),l.remove()}}})(e,t,"string"==typeof r?r:"",o,{onReady:()=>n?.(),onChange:f,onError:e=>a?.(e)}),d=c.on("change",b),b())})().catch(p),{close:m}},async pages(){let{pages:e}=await L("pages"),t=[U(),y?.space.defaultLocale];return e.flatMap(e=>{let r,o,n=t.find(t=>void 0!==t&&void 0!==e.paths[t])??Object.keys(e.paths)[0],a=void 0===n?void 0:e.paths[n];return void 0===n||void 0===a?[]:[{entryId:e.entryId,name:e.name,contentType:e.contentType,status:e.status,path:a,url:e.product?(r=e.product.handle,l?l(r,n):(y?.productPath??"/products/{handle}").replaceAll("{handle}",encodeURIComponent(r))):e.collection?(o=e.collection.handle,s?s(o,n):(y?.collectionPath??"/collections/{handle}").replaceAll("{handle}",encodeURIComponent(o))):i(a,n),product:e.product??null,collection:e.collection??null}]})},openPage(t){(!C.unsaved||e.confirm("Leave this page and lose the changes you have not saved?"))&&(g.clear(),u.length=0,A(),e.location.assign(O(t.url)))},undo(){let e=u.pop(),t=e&&g.get(e.entryId);e&&t&&(w=-1/0,t.content=e.content,A(),D(e.entryId).catch(F))},async save(){if(!C.features.includes("save"))throw Error("You may not edit content here");P({saving:!0});try{await V()}finally{P({saving:!1})}q("saved")},async publish(){if(!C.features.includes("publish"))throw Error("You may not publish here");P({publishing:!0});try{await V();let e=S(),t=m.size>0?[...m]:e?[e]:[];if(0===t.length)throw Error("Nothing on this page is marked as an entry: add editable(entry)");for(let e of t)await L(`entries/${encodeURIComponent(e)}/publish`,{}),m.delete(e)}finally{P({publishing:!1})}q("published")},signOut(){if(C.unsaved&&!e.confirm("Sign out and lose the changes you have not saved?"))return;g.clear(),A();let t=e.location.pathname+e.location.search;e.location.href=`${a}/logout?return_to=${encodeURIComponent(t)}`},select(e){T(e)},setSelecting(e){e?d.documentElement.setAttribute("data-cms-selecting",""):d.documentElement.removeAttribute("data-cms-selecting"),P({selecting:e})},destroy(){x?.(),k.forEach(e=>clearTimeout(e)),k.clear(),p.splice(0).forEach(e=>e())}},H=d.createElement("style");H.textContent=b("html[data-cms-selecting] "),d.head.appendChild(H),p.push(()=>H.remove()),p.push(()=>d.documentElement.removeAttribute("data-cms-selecting"));let W=e=>{if(!C.selecting)return;let r=e.target,o=r?.closest?.(`[${t}]`);o&&(e.preventDefault(),e.stopPropagation(),T(o.getAttribute(t)))};d.addEventListener("click",W,!0),p.push(()=>d.removeEventListener("click",W,!0));let Y=e=>{C.unsaved&&(e.preventDefault(),e.returnValue="")};return e.addEventListener("beforeunload",Y),p.push(()=>e.removeEventListener("beforeunload",Y)),L("session").then(e=>{y=e,P({features:e.features})}).catch(e=>console.error("[@obelism/content bridge]",e)),B})(P,C,{pagePath:p,productPath:m,collectionPath:y})),x.isEditing&&c){let e=P.document,t=()=>{},r=!1,o=()=>{r||(t=I(e,x,!0===c?{}:c))};e.body?o():e.addEventListener("DOMContentLoaded",o,{once:!0});let n=x.destroy;x.destroy=()=>{r=!0,e.removeEventListener("DOMContentLoaded",o),t(),n()}}}return P[j]=x,x};(e=window).ObelismBridge=T((e=>{let t=e?.dataset.url,r=t||U;if(!t&&e?.src){let t=new URL(e.src);"/bridge.js"===t.pathname&&(r=t.origin)}return{url:r,prompt:e?.dataset.prompt!=="false"}})(document.currentScript)),e.ObelismContent={getContentBridge:T,mountPromptBox:I}}();
|
package/dist/bridge.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
2
2
|
|
|
3
|
-
var preview = require('./preview-
|
|
3
|
+
var preview = require('./preview-c4giufnr.js');
|
|
4
4
|
var site = require('./site.js');
|
|
5
5
|
var config = require('./config-ci2hxmas.js');
|
|
6
6
|
|
|
@@ -1325,7 +1325,7 @@ const mountPromptBox = (doc, bridge, options = {})=>{
|
|
|
1325
1325
|
hint: labels.productPageHint
|
|
1326
1326
|
};
|
|
1327
1327
|
addProduct.lastChild.textContent = shopCopy.add;
|
|
1328
|
-
const onlyNew = pageless && canCreate && !productHere;
|
|
1328
|
+
const onlyNew = pageless && canCreate && !productHere && !options.promptWithoutPage;
|
|
1329
1329
|
if (!canCreate) creating = false;
|
|
1330
1330
|
if (onlyNew) creating = true;
|
|
1331
1331
|
if (creating || pageless || !site) form = false;
|
|
@@ -1807,6 +1807,18 @@ const mountFormFrame = (win, container, url, title, handlers)=>{
|
|
|
1807
1807
|
// kept in step with the content here, see formFrame.ts), edits JSON (`view`,
|
|
1808
1808
|
// then `applyJson`: the raw alternative), and lists the space's pages to go
|
|
1809
1809
|
// to one.
|
|
1810
|
+
// Plain path segments only: the URL parser drops tabs and newlines and reads
|
|
1811
|
+
// \ as /, so anything looser can resolve to another origin.
|
|
1812
|
+
const BASE_PATH = /^(?:\/[\w.~-]+)+$/;
|
|
1813
|
+
// Page addresses come from the CMS's session and pages: never a javascript:
|
|
1814
|
+
// or data: URL.
|
|
1815
|
+
const webUrl = (url)=>{
|
|
1816
|
+
const { protocol } = new URL(url, 'https://site.invalid');
|
|
1817
|
+
if (protocol !== 'https:' && protocol !== 'http:') {
|
|
1818
|
+
throw new Error(`Not a page address: ${url}`);
|
|
1819
|
+
}
|
|
1820
|
+
return url;
|
|
1821
|
+
};
|
|
1810
1822
|
// The base path of the site's handler while signed in to edit, else null.
|
|
1811
1823
|
const readSiteEditing = (doc)=>{
|
|
1812
1824
|
for (const part of doc.cookie.split(';')){
|
|
@@ -1814,7 +1826,7 @@ const readSiteEditing = (doc)=>{
|
|
|
1814
1826
|
if (name !== site.SITE_EDITING_COOKIE) continue;
|
|
1815
1827
|
try {
|
|
1816
1828
|
const basePath = decodeURIComponent(value.join('='));
|
|
1817
|
-
return
|
|
1829
|
+
return BASE_PATH.test(basePath) ? basePath : null;
|
|
1818
1830
|
} catch {
|
|
1819
1831
|
return null;
|
|
1820
1832
|
}
|
|
@@ -1827,7 +1839,7 @@ const FORM_BURST_MS = 1000;
|
|
|
1827
1839
|
// How long the page waits for the form's edits to settle before it shows
|
|
1828
1840
|
// them.
|
|
1829
1841
|
const FORM_RENDER_MS = 300;
|
|
1830
|
-
const createSiteBridge = (win, basePath, { pagePath = (path)=>`/${path}`, productPath: ownProductPath, collectionPath: ownCollectionPath } = {})=>{
|
|
1842
|
+
const createSiteBridge = (win, basePath, { pagePath = (path)=>`/${path.replace(/^\/+/, '')}`, productPath: ownProductPath, collectionPath: ownCollectionPath } = {})=>{
|
|
1831
1843
|
const doc = win.document;
|
|
1832
1844
|
const emitter = createEmitter();
|
|
1833
1845
|
const cleanup = [];
|
|
@@ -2072,7 +2084,7 @@ const createSiteBridge = (win, basePath, { pagePath = (path)=>`/${path}`, produc
|
|
|
2072
2084
|
from: pageEntryId()
|
|
2073
2085
|
});
|
|
2074
2086
|
const url = pagePath(created.path, locale() ?? '');
|
|
2075
|
-
win.location.assign(url);
|
|
2087
|
+
win.location.assign(webUrl(url));
|
|
2076
2088
|
return {
|
|
2077
2089
|
summary: created.summary,
|
|
2078
2090
|
entryId: created.entryId,
|
|
@@ -2309,7 +2321,7 @@ const createSiteBridge = (win, basePath, { pagePath = (path)=>`/${path}`, produc
|
|
|
2309
2321
|
working.clear();
|
|
2310
2322
|
history.length = 0;
|
|
2311
2323
|
refreshUnsaved();
|
|
2312
|
-
win.location.assign(page.url);
|
|
2324
|
+
win.location.assign(webUrl(page.url));
|
|
2313
2325
|
},
|
|
2314
2326
|
undo () {
|
|
2315
2327
|
const last = history.pop();
|
package/dist/bridge.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as PREVIEW_PARAMS, U as UID_ATTRIBUTE, E as ENTRY_ATTRIBUTE, C as COLLECTION_ATTRIBUTE, a as COLLECTION_HANDLE_ATTRIBUTE, b as PRODUCT_ATTRIBUTE, c as PRODUCT_HANDLE_ATTRIBUTE } from './preview-
|
|
1
|
+
import { P as PREVIEW_PARAMS, U as UID_ATTRIBUTE, E as ENTRY_ATTRIBUTE, C as COLLECTION_ATTRIBUTE, a as COLLECTION_HANDLE_ATTRIBUTE, b as PRODUCT_ATTRIBUTE, c as PRODUCT_HANDLE_ATTRIBUTE } from './preview-el7sfk3h.mjs';
|
|
2
2
|
import { SITE_EDITING_COOKIE, SITE_REQUEST_HEADER } from './site.mjs';
|
|
3
3
|
import { n as normalizeUrl, D as DEFAULT_URL } from './config-c6qktlz6.mjs';
|
|
4
4
|
|
|
@@ -1323,7 +1323,7 @@ const mountPromptBox = (doc, bridge, options = {})=>{
|
|
|
1323
1323
|
hint: labels.productPageHint
|
|
1324
1324
|
};
|
|
1325
1325
|
addProduct.lastChild.textContent = shopCopy.add;
|
|
1326
|
-
const onlyNew = pageless && canCreate && !productHere;
|
|
1326
|
+
const onlyNew = pageless && canCreate && !productHere && !options.promptWithoutPage;
|
|
1327
1327
|
if (!canCreate) creating = false;
|
|
1328
1328
|
if (onlyNew) creating = true;
|
|
1329
1329
|
if (creating || pageless || !site) form = false;
|
|
@@ -1805,6 +1805,18 @@ const mountFormFrame = (win, container, url, title, handlers)=>{
|
|
|
1805
1805
|
// kept in step with the content here, see formFrame.ts), edits JSON (`view`,
|
|
1806
1806
|
// then `applyJson`: the raw alternative), and lists the space's pages to go
|
|
1807
1807
|
// to one.
|
|
1808
|
+
// Plain path segments only: the URL parser drops tabs and newlines and reads
|
|
1809
|
+
// \ as /, so anything looser can resolve to another origin.
|
|
1810
|
+
const BASE_PATH = /^(?:\/[\w.~-]+)+$/;
|
|
1811
|
+
// Page addresses come from the CMS's session and pages: never a javascript:
|
|
1812
|
+
// or data: URL.
|
|
1813
|
+
const webUrl = (url)=>{
|
|
1814
|
+
const { protocol } = new URL(url, 'https://site.invalid');
|
|
1815
|
+
if (protocol !== 'https:' && protocol !== 'http:') {
|
|
1816
|
+
throw new Error(`Not a page address: ${url}`);
|
|
1817
|
+
}
|
|
1818
|
+
return url;
|
|
1819
|
+
};
|
|
1808
1820
|
// The base path of the site's handler while signed in to edit, else null.
|
|
1809
1821
|
const readSiteEditing = (doc)=>{
|
|
1810
1822
|
for (const part of doc.cookie.split(';')){
|
|
@@ -1812,7 +1824,7 @@ const readSiteEditing = (doc)=>{
|
|
|
1812
1824
|
if (name !== SITE_EDITING_COOKIE) continue;
|
|
1813
1825
|
try {
|
|
1814
1826
|
const basePath = decodeURIComponent(value.join('='));
|
|
1815
|
-
return
|
|
1827
|
+
return BASE_PATH.test(basePath) ? basePath : null;
|
|
1816
1828
|
} catch {
|
|
1817
1829
|
return null;
|
|
1818
1830
|
}
|
|
@@ -1825,7 +1837,7 @@ const FORM_BURST_MS = 1000;
|
|
|
1825
1837
|
// How long the page waits for the form's edits to settle before it shows
|
|
1826
1838
|
// them.
|
|
1827
1839
|
const FORM_RENDER_MS = 300;
|
|
1828
|
-
const createSiteBridge = (win, basePath, { pagePath = (path)=>`/${path}`, productPath: ownProductPath, collectionPath: ownCollectionPath } = {})=>{
|
|
1840
|
+
const createSiteBridge = (win, basePath, { pagePath = (path)=>`/${path.replace(/^\/+/, '')}`, productPath: ownProductPath, collectionPath: ownCollectionPath } = {})=>{
|
|
1829
1841
|
const doc = win.document;
|
|
1830
1842
|
const emitter = createEmitter();
|
|
1831
1843
|
const cleanup = [];
|
|
@@ -2070,7 +2082,7 @@ const createSiteBridge = (win, basePath, { pagePath = (path)=>`/${path}`, produc
|
|
|
2070
2082
|
from: pageEntryId()
|
|
2071
2083
|
});
|
|
2072
2084
|
const url = pagePath(created.path, locale() ?? '');
|
|
2073
|
-
win.location.assign(url);
|
|
2085
|
+
win.location.assign(webUrl(url));
|
|
2074
2086
|
return {
|
|
2075
2087
|
summary: created.summary,
|
|
2076
2088
|
entryId: created.entryId,
|
|
@@ -2307,7 +2319,7 @@ const createSiteBridge = (win, basePath, { pagePath = (path)=>`/${path}`, produc
|
|
|
2307
2319
|
working.clear();
|
|
2308
2320
|
history.length = 0;
|
|
2309
2321
|
refreshUnsaved();
|
|
2310
|
-
win.location.assign(page.url);
|
|
2322
|
+
win.location.assign(webUrl(page.url));
|
|
2311
2323
|
},
|
|
2312
2324
|
undo () {
|
|
2313
2325
|
const last = history.pop();
|
package/dist/index.d.mts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
import { TokenSource } from './oidc.mjs';
|
|
1
2
|
import { R as RichTextFormat, E as Entry, a as RedirectList, b as Redirect, c as EntryList, M as ModelFile, A as Asset, B as Block, I as ImproveBlock, S as ShopifyItem, L as LinkTarget, d as Link, e as EntryStub, f as RichTextNode } from './types-mtjco3a5.js';
|
|
2
3
|
export { C as ContentTypeDefinition, g as ContentTypeKind, h as Environment, F as FieldDefinition, i as FieldType, j as RichTextDocument, k as RichTextMark } from './types-mtjco3a5.js';
|
|
3
4
|
|
|
4
5
|
type ContentClientOptions = {
|
|
5
|
-
token:
|
|
6
|
+
token: TokenSource;
|
|
7
|
+
drafts?: boolean | undefined;
|
|
8
|
+
space?: string | undefined;
|
|
9
|
+
environment?: string | undefined;
|
|
6
10
|
url?: string | undefined;
|
|
7
11
|
locale?: string | undefined;
|
|
8
12
|
depth?: number | undefined;
|
|
@@ -15,6 +19,7 @@ type RequestOptions = {
|
|
|
15
19
|
locale?: string | undefined;
|
|
16
20
|
depth?: number | undefined;
|
|
17
21
|
richText?: RichTextFormat | undefined;
|
|
22
|
+
drafts?: boolean | undefined;
|
|
18
23
|
init?: RequestInit | undefined;
|
|
19
24
|
};
|
|
20
25
|
type FieldFilterValue = string | number | boolean;
|
|
@@ -44,7 +49,7 @@ type PageLookup<TEntry extends Entry = Entry> = {
|
|
|
44
49
|
declare class ContentClient {
|
|
45
50
|
#private;
|
|
46
51
|
readonly url: string;
|
|
47
|
-
constructor({ token, url, locale, depth, richText, timeout, init, fetch: fetchImpl, }: ContentClientOptions);
|
|
52
|
+
constructor({ token, drafts, space, environment, url, locale, depth, richText, timeout, init, fetch: fetchImpl, }: ContentClientOptions);
|
|
48
53
|
getPage: <TEntry extends Entry = Entry>(path: string, options?: RequestOptions) => Promise<TEntry | null>;
|
|
49
54
|
findPage: <TEntry extends Entry = Entry>(path: string, options?: RequestOptions) => Promise<PageLookup<TEntry> | null>;
|
|
50
55
|
getRedirects: ({ locale, limit, skip, init, }?: RedirectsQuery) => Promise<RedirectList>;
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","sources":["../src/client.ts","../src/config.ts","../src/editable.ts","../src/errors.ts","../src/images.ts","../src/improve.ts","../src/links.ts","../src/preview.ts","../src/shopify.ts","../src/richText.ts","../src/sitemap.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.mts","sources":["../src/client.ts","../src/config.ts","../src/editable.ts","../src/errors.ts","../src/images.ts","../src/improve.ts","../src/links.ts","../src/preview.ts","../src/shopify.ts","../src/richText.ts","../src/sitemap.ts"],"mappings":"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","names":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
import { TokenSource } from './oidc.js';
|
|
1
2
|
import { R as RichTextFormat, E as Entry, a as RedirectList, b as Redirect, c as EntryList, M as ModelFile, A as Asset, B as Block, I as ImproveBlock, S as ShopifyItem, L as LinkTarget, d as Link, e as EntryStub, f as RichTextNode } from './types-mtjco3a5.js';
|
|
2
3
|
export { C as ContentTypeDefinition, g as ContentTypeKind, h as Environment, F as FieldDefinition, i as FieldType, j as RichTextDocument, k as RichTextMark } from './types-mtjco3a5.js';
|
|
3
4
|
|
|
4
5
|
type ContentClientOptions = {
|
|
5
|
-
token:
|
|
6
|
+
token: TokenSource;
|
|
7
|
+
drafts?: boolean | undefined;
|
|
8
|
+
space?: string | undefined;
|
|
9
|
+
environment?: string | undefined;
|
|
6
10
|
url?: string | undefined;
|
|
7
11
|
locale?: string | undefined;
|
|
8
12
|
depth?: number | undefined;
|
|
@@ -15,6 +19,7 @@ type RequestOptions = {
|
|
|
15
19
|
locale?: string | undefined;
|
|
16
20
|
depth?: number | undefined;
|
|
17
21
|
richText?: RichTextFormat | undefined;
|
|
22
|
+
drafts?: boolean | undefined;
|
|
18
23
|
init?: RequestInit | undefined;
|
|
19
24
|
};
|
|
20
25
|
type FieldFilterValue = string | number | boolean;
|
|
@@ -44,7 +49,7 @@ type PageLookup<TEntry extends Entry = Entry> = {
|
|
|
44
49
|
declare class ContentClient {
|
|
45
50
|
#private;
|
|
46
51
|
readonly url: string;
|
|
47
|
-
constructor({ token, url, locale, depth, richText, timeout, init, fetch: fetchImpl, }: ContentClientOptions);
|
|
52
|
+
constructor({ token, drafts, space, environment, url, locale, depth, richText, timeout, init, fetch: fetchImpl, }: ContentClientOptions);
|
|
48
53
|
getPage: <TEntry extends Entry = Entry>(path: string, options?: RequestOptions) => Promise<TEntry | null>;
|
|
49
54
|
findPage: <TEntry extends Entry = Entry>(path: string, options?: RequestOptions) => Promise<PageLookup<TEntry> | null>;
|
|
50
55
|
getRedirects: ({ locale, limit, skip, init, }?: RedirectsQuery) => Promise<RedirectList>;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sources":["../src/client.ts","../src/config.ts","../src/editable.ts","../src/errors.ts","../src/images.ts","../src/improve.ts","../src/links.ts","../src/preview.ts","../src/shopify.ts","../src/richText.ts","../src/sitemap.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sources":["../src/client.ts","../src/config.ts","../src/editable.ts","../src/errors.ts","../src/images.ts","../src/improve.ts","../src/links.ts","../src/preview.ts","../src/shopify.ts","../src/richText.ts","../src/sitemap.ts"],"mappings":"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","names":[]}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
2
2
|
|
|
3
3
|
var config = require('./config-ci2hxmas.js');
|
|
4
|
-
var preview = require('./preview-
|
|
4
|
+
var preview = require('./preview-c4giufnr.js');
|
|
5
5
|
|
|
6
6
|
// A response from the API that wasn't a success. `message` is the API's own
|
|
7
7
|
// `error` text when it sent one.
|
|
@@ -16,6 +16,10 @@ class ContentApiError extends Error {
|
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
// A token, or a function that gives one per request: a host OIDC token from
|
|
20
|
+
// ./oidc, or anything else that rotates.
|
|
21
|
+
const resolveToken = (token)=>typeof token === 'function' ? token() : token;
|
|
22
|
+
|
|
19
23
|
// `fields` as the API's `fields.<apiId>[op]` parameters.
|
|
20
24
|
const fieldParams = (fields)=>Object.fromEntries(Object.entries(fields ?? {}).map(([key, value])=>{
|
|
21
25
|
if (!Array.isArray(value)) return [
|
|
@@ -30,17 +34,19 @@ const fieldParams = (fields)=>Object.fromEntries(Object.entries(fields ?? {}).ma
|
|
|
30
34
|
}));
|
|
31
35
|
const trimSlashes = (path)=>path.replace(/^\/+|\/+$/g, '');
|
|
32
36
|
// Reads one space environment's content through the delivery API. The token
|
|
33
|
-
// decides the space, the environment and whether drafts are visible
|
|
37
|
+
// decides the space, the environment and whether drafts are visible (for a
|
|
38
|
+
// host token, with `drafts`).
|
|
34
39
|
//
|
|
35
40
|
// const content = new ContentClient({ token: process.env.CONTENT_TOKEN })
|
|
36
41
|
// const page = await content.getPage('blog/hello', { locale: 'nl' })
|
|
37
42
|
class ContentClient {
|
|
38
43
|
#token;
|
|
44
|
+
#place;
|
|
39
45
|
#defaults;
|
|
40
46
|
#timeout;
|
|
41
47
|
#init;
|
|
42
48
|
#fetch;
|
|
43
|
-
constructor({ token, url, locale, depth, richText, timeout, init, fetch: fetchImpl }){
|
|
49
|
+
constructor({ token, drafts, space, environment, url, locale, depth, richText, timeout, init, fetch: fetchImpl }){
|
|
44
50
|
// The page at a path (`blog/hello`), or null when there is none. A site's
|
|
45
51
|
// catch-all route asks for this. The path is looked up in `locale`'s
|
|
46
52
|
// paths (the default locale's when left out or `*`): pages can have a
|
|
@@ -112,10 +118,19 @@ class ContentClient {
|
|
|
112
118
|
});
|
|
113
119
|
this.url = config.normalizeUrl(url || config.DEFAULT_URL);
|
|
114
120
|
this.#token = token;
|
|
121
|
+
this.#place = {
|
|
122
|
+
...space && {
|
|
123
|
+
'Obelism-Space': space
|
|
124
|
+
},
|
|
125
|
+
...environment && {
|
|
126
|
+
'Obelism-Environment': environment
|
|
127
|
+
}
|
|
128
|
+
};
|
|
115
129
|
this.#defaults = {
|
|
116
130
|
locale,
|
|
117
131
|
depth,
|
|
118
|
-
richText
|
|
132
|
+
richText,
|
|
133
|
+
drafts
|
|
119
134
|
};
|
|
120
135
|
this.#timeout = timeout ?? config.DEFAULT_TIMEOUT;
|
|
121
136
|
this.#init = init;
|
|
@@ -160,7 +175,7 @@ class ContentClient {
|
|
|
160
175
|
// Checked here rather than in the constructor, so a module creating a
|
|
161
176
|
// client still loads (and a build still runs) without the variable.
|
|
162
177
|
if (!this.#token) throw new Error('ContentClient needs a token');
|
|
163
|
-
const { locale, depth, richText } = {
|
|
178
|
+
const { locale, depth, richText, drafts } = {
|
|
164
179
|
...defaults && this.#defaults,
|
|
165
180
|
...withoutUndefined(options)
|
|
166
181
|
};
|
|
@@ -189,7 +204,11 @@ class ContentClient {
|
|
|
189
204
|
// Not `Authorization`: Cloudflare never caches a request that
|
|
190
205
|
// carries it, and this header lets the API answer a delivery
|
|
191
206
|
// token from its edge cache.
|
|
192
|
-
'Obelism-Token': this.#token
|
|
207
|
+
'Obelism-Token': await resolveToken(this.#token),
|
|
208
|
+
...this.#place,
|
|
209
|
+
...drafts && {
|
|
210
|
+
'Obelism-Drafts': 'true'
|
|
211
|
+
}
|
|
193
212
|
},
|
|
194
213
|
signal: merged.signal ? AbortSignal.any([
|
|
195
214
|
merged.signal,
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as normalizeUrl, a as DEFAULT_TIMEOUT, b as DELIVERY_PATH, D as DEFAULT_URL } from './config-c6qktlz6.mjs';
|
|
2
|
-
export { E as ENTRY_ATTRIBUTE, P as PREVIEW_PARAMS, b as PRODUCT_ATTRIBUTE, c as PRODUCT_HANDLE_ATTRIBUTE, U as UID_ATTRIBUTE, e as editable, d as editableCollection, f as editableProduct, r as readPreviewParams } from './preview-
|
|
2
|
+
export { E as ENTRY_ATTRIBUTE, P as PREVIEW_PARAMS, b as PRODUCT_ATTRIBUTE, c as PRODUCT_HANDLE_ATTRIBUTE, U as UID_ATTRIBUTE, e as editable, d as editableCollection, f as editableProduct, r as readPreviewParams } from './preview-el7sfk3h.mjs';
|
|
3
3
|
|
|
4
4
|
// A response from the API that wasn't a success. `message` is the API's own
|
|
5
5
|
// `error` text when it sent one.
|
|
@@ -14,6 +14,10 @@ class ContentApiError extends Error {
|
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
// A token, or a function that gives one per request: a host OIDC token from
|
|
18
|
+
// ./oidc, or anything else that rotates.
|
|
19
|
+
const resolveToken = (token)=>typeof token === 'function' ? token() : token;
|
|
20
|
+
|
|
17
21
|
// `fields` as the API's `fields.<apiId>[op]` parameters.
|
|
18
22
|
const fieldParams = (fields)=>Object.fromEntries(Object.entries(fields ?? {}).map(([key, value])=>{
|
|
19
23
|
if (!Array.isArray(value)) return [
|
|
@@ -28,17 +32,19 @@ const fieldParams = (fields)=>Object.fromEntries(Object.entries(fields ?? {}).ma
|
|
|
28
32
|
}));
|
|
29
33
|
const trimSlashes = (path)=>path.replace(/^\/+|\/+$/g, '');
|
|
30
34
|
// Reads one space environment's content through the delivery API. The token
|
|
31
|
-
// decides the space, the environment and whether drafts are visible
|
|
35
|
+
// decides the space, the environment and whether drafts are visible (for a
|
|
36
|
+
// host token, with `drafts`).
|
|
32
37
|
//
|
|
33
38
|
// const content = new ContentClient({ token: process.env.CONTENT_TOKEN })
|
|
34
39
|
// const page = await content.getPage('blog/hello', { locale: 'nl' })
|
|
35
40
|
class ContentClient {
|
|
36
41
|
#token;
|
|
42
|
+
#place;
|
|
37
43
|
#defaults;
|
|
38
44
|
#timeout;
|
|
39
45
|
#init;
|
|
40
46
|
#fetch;
|
|
41
|
-
constructor({ token, url, locale, depth, richText, timeout, init, fetch: fetchImpl }){
|
|
47
|
+
constructor({ token, drafts, space, environment, url, locale, depth, richText, timeout, init, fetch: fetchImpl }){
|
|
42
48
|
// The page at a path (`blog/hello`), or null when there is none. A site's
|
|
43
49
|
// catch-all route asks for this. The path is looked up in `locale`'s
|
|
44
50
|
// paths (the default locale's when left out or `*`): pages can have a
|
|
@@ -110,10 +116,19 @@ class ContentClient {
|
|
|
110
116
|
});
|
|
111
117
|
this.url = normalizeUrl(url || DEFAULT_URL);
|
|
112
118
|
this.#token = token;
|
|
119
|
+
this.#place = {
|
|
120
|
+
...space && {
|
|
121
|
+
'Obelism-Space': space
|
|
122
|
+
},
|
|
123
|
+
...environment && {
|
|
124
|
+
'Obelism-Environment': environment
|
|
125
|
+
}
|
|
126
|
+
};
|
|
113
127
|
this.#defaults = {
|
|
114
128
|
locale,
|
|
115
129
|
depth,
|
|
116
|
-
richText
|
|
130
|
+
richText,
|
|
131
|
+
drafts
|
|
117
132
|
};
|
|
118
133
|
this.#timeout = timeout ?? DEFAULT_TIMEOUT;
|
|
119
134
|
this.#init = init;
|
|
@@ -158,7 +173,7 @@ class ContentClient {
|
|
|
158
173
|
// Checked here rather than in the constructor, so a module creating a
|
|
159
174
|
// client still loads (and a build still runs) without the variable.
|
|
160
175
|
if (!this.#token) throw new Error('ContentClient needs a token');
|
|
161
|
-
const { locale, depth, richText } = {
|
|
176
|
+
const { locale, depth, richText, drafts } = {
|
|
162
177
|
...defaults && this.#defaults,
|
|
163
178
|
...withoutUndefined(options)
|
|
164
179
|
};
|
|
@@ -187,7 +202,11 @@ class ContentClient {
|
|
|
187
202
|
// Not `Authorization`: Cloudflare never caches a request that
|
|
188
203
|
// carries it, and this header lets the API answer a delivery
|
|
189
204
|
// token from its edge cache.
|
|
190
|
-
'Obelism-Token': this.#token
|
|
205
|
+
'Obelism-Token': await resolveToken(this.#token),
|
|
206
|
+
...this.#place,
|
|
207
|
+
...drafts && {
|
|
208
|
+
'Obelism-Drafts': 'true'
|
|
209
|
+
}
|
|
191
210
|
},
|
|
192
211
|
signal: merged.signal ? AbortSignal.any([
|
|
193
212
|
merged.signal,
|
package/dist/oidc.d.mts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { T as TokenSource } from './tokenSource-my2ymemb.js';
|
|
2
|
+
|
|
3
|
+
declare const DEFAULT_AUDIENCE = "https://content.obelism.studio";
|
|
4
|
+
declare const vercelOidc: ({ audience }?: {
|
|
5
|
+
audience?: string | undefined;
|
|
6
|
+
}) => () => Promise<string>;
|
|
7
|
+
declare const githubOidc: ({ audience, fetch: fetchImpl, }?: {
|
|
8
|
+
audience?: string | undefined;
|
|
9
|
+
fetch?: typeof fetch | undefined;
|
|
10
|
+
}) => () => Promise<string>;
|
|
11
|
+
|
|
12
|
+
export { DEFAULT_AUDIENCE, githubOidc, vercelOidc };
|
|
13
|
+
//# sourceMappingURL=oidc.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oidc.d.mts","sources":["../src/oidc.ts"],"mappings":";;AACA,cAAc,gBAAgB;AAC9B,cAAc,UAAU;AACxB;AACA,YAAY,OAAO;AACnB,cAAc,UAAU;AACxB;AACA,mBAAmB,KAAK;AACxB,YAAY,OAAO;;","names":[]}
|
package/dist/oidc.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { T as TokenSource } from './tokenSource-my2ymemb.js';
|
|
2
|
+
|
|
3
|
+
declare const DEFAULT_AUDIENCE = "https://content.obelism.studio";
|
|
4
|
+
declare const vercelOidc: ({ audience }?: {
|
|
5
|
+
audience?: string | undefined;
|
|
6
|
+
}) => () => Promise<string>;
|
|
7
|
+
declare const githubOidc: ({ audience, fetch: fetchImpl, }?: {
|
|
8
|
+
audience?: string | undefined;
|
|
9
|
+
fetch?: typeof fetch | undefined;
|
|
10
|
+
}) => () => Promise<string>;
|
|
11
|
+
|
|
12
|
+
export { DEFAULT_AUDIENCE, githubOidc, vercelOidc };
|
|
13
|
+
//# sourceMappingURL=oidc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oidc.d.ts","sources":["../src/oidc.ts"],"mappings":";;AACA,cAAc,gBAAgB;AAC9B,cAAc,UAAU;AACxB;AACA,YAAY,OAAO;AACnB,cAAc,UAAU;AACxB;AACA,mBAAmB,KAAK;AACxB,YAAY,OAAO;;","names":[]}
|
package/dist/oidc.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
2
|
+
|
|
3
|
+
// A deployment's host OIDC token instead of a stored API token
|
|
4
|
+
// (Obelism's www docs/adr/0016): pass one of these as `token`. The space
|
|
5
|
+
// needs the Vercel project or GitHub repository connected, under Connected
|
|
6
|
+
// deployments on its page on www.obelism.studio. Same as improve's packages/improve/src/oidc.ts.
|
|
7
|
+
//
|
|
8
|
+
// import { vercelOidc } from '@obelism/content/oidc'
|
|
9
|
+
// token: vercelOidc()
|
|
10
|
+
// What the token must be addressed to: this product.
|
|
11
|
+
const DEFAULT_AUDIENCE = 'https://content.obelism.studio';
|
|
12
|
+
// Renewed this long before it expires, so a request never carries one that
|
|
13
|
+
// expires on the way.
|
|
14
|
+
const RENEW_MARGIN_MS = 60_000;
|
|
15
|
+
const expiryOf = (token)=>{
|
|
16
|
+
try {
|
|
17
|
+
const payload = token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/');
|
|
18
|
+
return JSON.parse(atob(payload)).exp * 1000;
|
|
19
|
+
} catch {
|
|
20
|
+
return 0;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
// One token at a time, reused until shortly before it expires; concurrent
|
|
24
|
+
// callers share the request for a new one. For GitHub's, which nothing
|
|
25
|
+
// else caches.
|
|
26
|
+
const reused = (fetchToken)=>{
|
|
27
|
+
let token = '';
|
|
28
|
+
let expiresAt = 0;
|
|
29
|
+
let pending = null;
|
|
30
|
+
return ()=>{
|
|
31
|
+
if (token && Date.now() < expiresAt - RENEW_MARGIN_MS) return Promise.resolve(token);
|
|
32
|
+
pending ??= fetchToken().then((fresh)=>{
|
|
33
|
+
token = fresh;
|
|
34
|
+
expiresAt = expiryOf(fresh);
|
|
35
|
+
return fresh;
|
|
36
|
+
}).finally(()=>{
|
|
37
|
+
pending = null;
|
|
38
|
+
});
|
|
39
|
+
return pending;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
// On Vercel: the deployment's token for this product, from @vercel/oidc
|
|
43
|
+
// (install it next to this package), which caches the exchange for the
|
|
44
|
+
// audience itself. In a function it reads the request's token, so call it
|
|
45
|
+
// during a request, not at module level.
|
|
46
|
+
const vercelOidc = ({ audience = DEFAULT_AUDIENCE } = {})=>async ()=>{
|
|
47
|
+
const { getVercelOidcToken } = await import('@vercel/oidc');
|
|
48
|
+
return getVercelOidcToken({
|
|
49
|
+
audience,
|
|
50
|
+
expirationBufferMs: RENEW_MARGIN_MS
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
// In GitHub Actions: the job's token for this product. The job needs
|
|
54
|
+
// `permissions: id-token: write`.
|
|
55
|
+
const githubOidc = ({ audience = DEFAULT_AUDIENCE, fetch: fetchImpl = fetch } = {})=>reused(async ()=>{
|
|
56
|
+
const env = globalThis.process?.env;
|
|
57
|
+
const url = env?.ACTIONS_ID_TOKEN_REQUEST_URL;
|
|
58
|
+
const bearer = env?.ACTIONS_ID_TOKEN_REQUEST_TOKEN;
|
|
59
|
+
if (!url || !bearer) throw new Error('githubOidc needs a GitHub Actions job with `permissions: id-token: write`');
|
|
60
|
+
const response = await fetchImpl(`${url}&audience=${encodeURIComponent(audience)}`, {
|
|
61
|
+
headers: {
|
|
62
|
+
Authorization: `Bearer ${bearer}`
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
if (!response.ok) throw new Error(`GitHub refused the OIDC token request (${response.status})`);
|
|
66
|
+
return (await response.json()).value;
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
exports.DEFAULT_AUDIENCE = DEFAULT_AUDIENCE;
|
|
70
|
+
exports.githubOidc = githubOidc;
|
|
71
|
+
exports.vercelOidc = vercelOidc;
|
package/dist/oidc.mjs
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// A deployment's host OIDC token instead of a stored API token
|
|
2
|
+
// (Obelism's www docs/adr/0016): pass one of these as `token`. The space
|
|
3
|
+
// needs the Vercel project or GitHub repository connected, under Connected
|
|
4
|
+
// deployments on its page on www.obelism.studio. Same as improve's packages/improve/src/oidc.ts.
|
|
5
|
+
//
|
|
6
|
+
// import { vercelOidc } from '@obelism/content/oidc'
|
|
7
|
+
// token: vercelOidc()
|
|
8
|
+
// What the token must be addressed to: this product.
|
|
9
|
+
const DEFAULT_AUDIENCE = 'https://content.obelism.studio';
|
|
10
|
+
// Renewed this long before it expires, so a request never carries one that
|
|
11
|
+
// expires on the way.
|
|
12
|
+
const RENEW_MARGIN_MS = 60_000;
|
|
13
|
+
const expiryOf = (token)=>{
|
|
14
|
+
try {
|
|
15
|
+
const payload = token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/');
|
|
16
|
+
return JSON.parse(atob(payload)).exp * 1000;
|
|
17
|
+
} catch {
|
|
18
|
+
return 0;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
// One token at a time, reused until shortly before it expires; concurrent
|
|
22
|
+
// callers share the request for a new one. For GitHub's, which nothing
|
|
23
|
+
// else caches.
|
|
24
|
+
const reused = (fetchToken)=>{
|
|
25
|
+
let token = '';
|
|
26
|
+
let expiresAt = 0;
|
|
27
|
+
let pending = null;
|
|
28
|
+
return ()=>{
|
|
29
|
+
if (token && Date.now() < expiresAt - RENEW_MARGIN_MS) return Promise.resolve(token);
|
|
30
|
+
pending ??= fetchToken().then((fresh)=>{
|
|
31
|
+
token = fresh;
|
|
32
|
+
expiresAt = expiryOf(fresh);
|
|
33
|
+
return fresh;
|
|
34
|
+
}).finally(()=>{
|
|
35
|
+
pending = null;
|
|
36
|
+
});
|
|
37
|
+
return pending;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
// On Vercel: the deployment's token for this product, from @vercel/oidc
|
|
41
|
+
// (install it next to this package), which caches the exchange for the
|
|
42
|
+
// audience itself. In a function it reads the request's token, so call it
|
|
43
|
+
// during a request, not at module level.
|
|
44
|
+
const vercelOidc = ({ audience = DEFAULT_AUDIENCE } = {})=>async ()=>{
|
|
45
|
+
const { getVercelOidcToken } = await import('@vercel/oidc');
|
|
46
|
+
return getVercelOidcToken({
|
|
47
|
+
audience,
|
|
48
|
+
expirationBufferMs: RENEW_MARGIN_MS
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
// In GitHub Actions: the job's token for this product. The job needs
|
|
52
|
+
// `permissions: id-token: write`.
|
|
53
|
+
const githubOidc = ({ audience = DEFAULT_AUDIENCE, fetch: fetchImpl = fetch } = {})=>reused(async ()=>{
|
|
54
|
+
const env = globalThis.process?.env;
|
|
55
|
+
const url = env?.ACTIONS_ID_TOKEN_REQUEST_URL;
|
|
56
|
+
const bearer = env?.ACTIONS_ID_TOKEN_REQUEST_TOKEN;
|
|
57
|
+
if (!url || !bearer) throw new Error('githubOidc needs a GitHub Actions job with `permissions: id-token: write`');
|
|
58
|
+
const response = await fetchImpl(`${url}&audience=${encodeURIComponent(audience)}`, {
|
|
59
|
+
headers: {
|
|
60
|
+
Authorization: `Bearer ${bearer}`
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
if (!response.ok) throw new Error(`GitHub refused the OIDC token request (${response.status})`);
|
|
64
|
+
return (await response.json()).value;
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
export { DEFAULT_AUDIENCE, githubOidc, vercelOidc };
|
|
@@ -83,11 +83,13 @@ const toSearchParams = (input)=>{
|
|
|
83
83
|
//
|
|
84
84
|
// const preview = readPreviewParams(request.url)
|
|
85
85
|
// const content = preview?.token
|
|
86
|
-
// ? new ContentClient({ token: preview.token,
|
|
86
|
+
// ? new ContentClient({ token: preview.token, space, environment })
|
|
87
87
|
// : deliveryClient
|
|
88
88
|
//
|
|
89
|
-
//
|
|
90
|
-
//
|
|
89
|
+
// `space` and `environment` are the site's own: anyone can make a cms_token
|
|
90
|
+
// for a space of theirs, and naming yours makes such a token read nothing. A
|
|
91
|
+
// made-up, expired or other space's token makes the client throw a
|
|
92
|
+
// ContentApiError with status 401: answer with `deliveryClient` then.
|
|
91
93
|
const readPreviewParams = (input)=>{
|
|
92
94
|
const params = toSearchParams(input);
|
|
93
95
|
if (!params.has(PREVIEW_PARAMS.preview)) return null;
|
|
@@ -83,11 +83,13 @@ const toSearchParams = (input)=>{
|
|
|
83
83
|
//
|
|
84
84
|
// const preview = readPreviewParams(request.url)
|
|
85
85
|
// const content = preview?.token
|
|
86
|
-
// ? new ContentClient({ token: preview.token,
|
|
86
|
+
// ? new ContentClient({ token: preview.token, space, environment })
|
|
87
87
|
// : deliveryClient
|
|
88
88
|
//
|
|
89
|
-
//
|
|
90
|
-
//
|
|
89
|
+
// `space` and `environment` are the site's own: anyone can make a cms_token
|
|
90
|
+
// for a space of theirs, and naming yours makes such a token read nothing. A
|
|
91
|
+
// made-up, expired or other space's token makes the client throw a
|
|
92
|
+
// ContentApiError with status 401: answer with `deliveryClient` then.
|
|
91
93
|
const readPreviewParams = (input)=>{
|
|
92
94
|
const params = toSearchParams(input);
|
|
93
95
|
if (!params.has(PREVIEW_PARAMS.preview)) return null;
|
package/dist/prompt.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
2
2
|
|
|
3
|
-
var standardWebhooks = require('./standardWebhooks-
|
|
3
|
+
var standardWebhooks = require('./standardWebhooks-leiz4jdn.js');
|
|
4
4
|
|
|
5
5
|
// Your own model for prompt editing in the visual editor. Set the endpoint
|
|
6
6
|
// under Space settings → Prompt editing; the CMS then sends each prompt there
|
package/dist/prompt.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as SECRET_PREFIX, v as verifySignature, D as DEFAULT_TOLERANCE } from './standardWebhooks-
|
|
1
|
+
import { S as SECRET_PREFIX, v as verifySignature, D as DEFAULT_TOLERANCE } from './standardWebhooks-ow7vu8g1.mjs';
|
|
2
2
|
|
|
3
3
|
// Your own model for prompt editing in the visual editor. Set the endpoint
|
|
4
4
|
// under Space settings → Prompt editing; the CMS then sends each prompt there
|
package/dist/site.js
CHANGED
|
@@ -72,8 +72,14 @@ const base64Url = (bytes)=>{
|
|
|
72
72
|
};
|
|
73
73
|
const randomString = (bytes = 32)=>base64Url(crypto.getRandomValues(new Uint8Array(bytes)));
|
|
74
74
|
const pkceChallenge = async (verifier)=>base64Url(new Uint8Array(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier))));
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
const PLACEHOLDER_ORIGIN = 'https://site.invalid';
|
|
76
|
+
// Only a path on this site: never an open redirect. Resolved the way a
|
|
77
|
+
// browser reads Location, which drops tabs and newlines and reads \ as /.
|
|
78
|
+
const safeReturnTo = (value)=>{
|
|
79
|
+
if (!value?.startsWith('/')) return '/';
|
|
80
|
+
const url = new URL(value, PLACEHOLDER_ORIGIN);
|
|
81
|
+
return url.origin === PLACEHOLDER_ORIGIN ? `${url.pathname}${url.search}${url.hash}` : '/';
|
|
82
|
+
};
|
|
77
83
|
const normalizeBasePath = (basePath)=>`/${basePath.replace(/^\/+|\/+$/g, '')}`;
|
|
78
84
|
// What the browser may reach through `/cms/api/…`: reads, and the writes
|
|
79
85
|
// the prompt bar makes. Nothing else of the site API is exposed.
|
package/dist/site.mjs
CHANGED
|
@@ -70,8 +70,14 @@ const base64Url = (bytes)=>{
|
|
|
70
70
|
};
|
|
71
71
|
const randomString = (bytes = 32)=>base64Url(crypto.getRandomValues(new Uint8Array(bytes)));
|
|
72
72
|
const pkceChallenge = async (verifier)=>base64Url(new Uint8Array(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier))));
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
const PLACEHOLDER_ORIGIN = 'https://site.invalid';
|
|
74
|
+
// Only a path on this site: never an open redirect. Resolved the way a
|
|
75
|
+
// browser reads Location, which drops tabs and newlines and reads \ as /.
|
|
76
|
+
const safeReturnTo = (value)=>{
|
|
77
|
+
if (!value?.startsWith('/')) return '/';
|
|
78
|
+
const url = new URL(value, PLACEHOLDER_ORIGIN);
|
|
79
|
+
return url.origin === PLACEHOLDER_ORIGIN ? `${url.pathname}${url.search}${url.hash}` : '/';
|
|
80
|
+
};
|
|
75
81
|
const normalizeBasePath = (basePath)=>`/${basePath.replace(/^\/+|\/+$/g, '')}`;
|
|
76
82
|
// What the browser may reach through `/cms/api/…`: reads, and the writes
|
|
77
83
|
// the prompt bar makes. Nothing else of the site API is exposed.
|
|
@@ -6,15 +6,22 @@
|
|
|
6
6
|
const SECRET_PREFIX = 'whsec_';
|
|
7
7
|
// Seconds a request's timestamp may be off, against replays.
|
|
8
8
|
const DEFAULT_TOLERANCE = 5 * 60;
|
|
9
|
+
// Each signature costs an HMAC over the whole body, and the header is the
|
|
10
|
+
// sender's: a rotation needs two, so anything near this many is not the CMS.
|
|
11
|
+
const MAX_SIGNATURES = 5;
|
|
12
|
+
const SIGNATURE_BYTES = 32;
|
|
9
13
|
const base64ToBytes = (value)=>Uint8Array.from(atob(value), (char)=>char.charCodeAt(0));
|
|
10
14
|
// Checks a message's signature and timestamp; calls `fail` (which throws the
|
|
11
15
|
// caller's own error) when it isn't from the CMS.
|
|
12
16
|
const verifySignature = async ({ body, id, timestamp, signatures }, secret, { tolerance = DEFAULT_TOLERANCE, now = Date.now(), fail })=>{
|
|
13
17
|
if (!id || !timestamp || !signatures) fail('Missing signature headers');
|
|
14
18
|
const seconds = Number(timestamp);
|
|
15
|
-
|
|
19
|
+
// Written so a NaN tolerance rejects rather than skips the check.
|
|
20
|
+
if (!(Math.abs(now / 1000 - seconds) <= tolerance)) {
|
|
16
21
|
fail('Timestamp outside the tolerance');
|
|
17
22
|
}
|
|
23
|
+
const candidates = signatures.split(' ');
|
|
24
|
+
if (candidates.length > MAX_SIGNATURES) fail('Too many signatures');
|
|
18
25
|
const key = await crypto.subtle.importKey('raw', base64ToBytes(secret.slice(SECRET_PREFIX.length)), {
|
|
19
26
|
name: 'HMAC',
|
|
20
27
|
hash: 'SHA-256'
|
|
@@ -23,7 +30,7 @@ const verifySignature = async ({ body, id, timestamp, signatures }, secret, { to
|
|
|
23
30
|
]);
|
|
24
31
|
const signed = new TextEncoder().encode(`${id}.${timestamp}.${body}`);
|
|
25
32
|
let valid = false;
|
|
26
|
-
for (const signature of
|
|
33
|
+
for (const signature of candidates){
|
|
27
34
|
const [version, value] = signature.split(',');
|
|
28
35
|
if (version !== 'v1' || !value) continue;
|
|
29
36
|
let bytes;
|
|
@@ -32,6 +39,7 @@ const verifySignature = async ({ body, id, timestamp, signatures }, secret, { to
|
|
|
32
39
|
} catch {
|
|
33
40
|
continue;
|
|
34
41
|
}
|
|
42
|
+
if (bytes.length !== SIGNATURE_BYTES) continue;
|
|
35
43
|
// crypto.subtle.verify compares in constant time.
|
|
36
44
|
if (await crypto.subtle.verify('HMAC', key, bytes, signed)) valid = true;
|
|
37
45
|
}
|
|
@@ -6,15 +6,22 @@
|
|
|
6
6
|
const SECRET_PREFIX = 'whsec_';
|
|
7
7
|
// Seconds a request's timestamp may be off, against replays.
|
|
8
8
|
const DEFAULT_TOLERANCE = 5 * 60;
|
|
9
|
+
// Each signature costs an HMAC over the whole body, and the header is the
|
|
10
|
+
// sender's: a rotation needs two, so anything near this many is not the CMS.
|
|
11
|
+
const MAX_SIGNATURES = 5;
|
|
12
|
+
const SIGNATURE_BYTES = 32;
|
|
9
13
|
const base64ToBytes = (value)=>Uint8Array.from(atob(value), (char)=>char.charCodeAt(0));
|
|
10
14
|
// Checks a message's signature and timestamp; calls `fail` (which throws the
|
|
11
15
|
// caller's own error) when it isn't from the CMS.
|
|
12
16
|
const verifySignature = async ({ body, id, timestamp, signatures }, secret, { tolerance = DEFAULT_TOLERANCE, now = Date.now(), fail })=>{
|
|
13
17
|
if (!id || !timestamp || !signatures) fail('Missing signature headers');
|
|
14
18
|
const seconds = Number(timestamp);
|
|
15
|
-
|
|
19
|
+
// Written so a NaN tolerance rejects rather than skips the check.
|
|
20
|
+
if (!(Math.abs(now / 1000 - seconds) <= tolerance)) {
|
|
16
21
|
fail('Timestamp outside the tolerance');
|
|
17
22
|
}
|
|
23
|
+
const candidates = signatures.split(' ');
|
|
24
|
+
if (candidates.length > MAX_SIGNATURES) fail('Too many signatures');
|
|
18
25
|
const key = await crypto.subtle.importKey('raw', base64ToBytes(secret.slice(SECRET_PREFIX.length)), {
|
|
19
26
|
name: 'HMAC',
|
|
20
27
|
hash: 'SHA-256'
|
|
@@ -23,7 +30,7 @@ const verifySignature = async ({ body, id, timestamp, signatures }, secret, { to
|
|
|
23
30
|
]);
|
|
24
31
|
const signed = new TextEncoder().encode(`${id}.${timestamp}.${body}`);
|
|
25
32
|
let valid = false;
|
|
26
|
-
for (const signature of
|
|
33
|
+
for (const signature of candidates){
|
|
27
34
|
const [version, value] = signature.split(',');
|
|
28
35
|
if (version !== 'v1' || !value) continue;
|
|
29
36
|
let bytes;
|
|
@@ -32,6 +39,7 @@ const verifySignature = async ({ body, id, timestamp, signatures }, secret, { to
|
|
|
32
39
|
} catch {
|
|
33
40
|
continue;
|
|
34
41
|
}
|
|
42
|
+
if (bytes.length !== SIGNATURE_BYTES) continue;
|
|
35
43
|
// crypto.subtle.verify compares in constant time.
|
|
36
44
|
if (await crypto.subtle.verify('HMAC', key, bytes, signed)) valid = true;
|
|
37
45
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokenSource-my2ymemb.d.ts","sources":["../src/tokenSource.ts"],"mappings":"AAAA,KAAK,WAAW,4BAA4B,OAAO;;","names":[]}
|
package/dist/webhooks.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
2
2
|
|
|
3
|
-
var standardWebhooks = require('./standardWebhooks-
|
|
3
|
+
var standardWebhooks = require('./standardWebhooks-leiz4jdn.js');
|
|
4
4
|
|
|
5
5
|
// Webhooks from Obelism Content (the CMS's docs/guides/webhooks): one signed
|
|
6
6
|
// POST per event (Standard Webhooks), telling your site what the delivery
|
package/dist/webhooks.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as SECRET_PREFIX, v as verifySignature, D as DEFAULT_TOLERANCE } from './standardWebhooks-
|
|
1
|
+
import { S as SECRET_PREFIX, v as verifySignature, D as DEFAULT_TOLERANCE } from './standardWebhooks-ow7vu8g1.mjs';
|
|
2
2
|
|
|
3
3
|
// Webhooks from Obelism Content (the CMS's docs/guides/webhooks): one signed
|
|
4
4
|
// POST per event (Standard Webhooks), telling your site what the delivery
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@obelism/content",
|
|
3
3
|
"description": "Obelism Content SDK: the delivery API client, the visual editor bridge with prompt editing, editing on your own site, webhook verification, and the content model CLI",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.23.0",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cms",
|
|
7
7
|
"headless-cms",
|
|
@@ -73,6 +73,16 @@
|
|
|
73
73
|
"types": "./dist/webhooks.d.ts",
|
|
74
74
|
"default": "./dist/webhooks.js"
|
|
75
75
|
}
|
|
76
|
+
},
|
|
77
|
+
"./oidc": {
|
|
78
|
+
"import": {
|
|
79
|
+
"types": "./dist/oidc.d.mts",
|
|
80
|
+
"default": "./dist/oidc.mjs"
|
|
81
|
+
},
|
|
82
|
+
"require": {
|
|
83
|
+
"types": "./dist/oidc.d.ts",
|
|
84
|
+
"default": "./dist/oidc.js"
|
|
85
|
+
}
|
|
76
86
|
}
|
|
77
87
|
},
|
|
78
88
|
"scripts": {
|
|
@@ -89,18 +99,27 @@
|
|
|
89
99
|
"devDependencies": {
|
|
90
100
|
"@obelism/sdk-typescript-config": "^0.0.0",
|
|
91
101
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
92
|
-
"@types/node": "^24.
|
|
102
|
+
"@types/node": "^24.19.2",
|
|
93
103
|
"@typescript/typescript6": "^6.0.2",
|
|
104
|
+
"@vercel/oidc": "4.0.3",
|
|
94
105
|
"bunchee": "^7.0.2",
|
|
95
|
-
"jsdom": "^30.1.
|
|
96
|
-
"npm-run-all2": "^9.0.
|
|
97
|
-
"oxlint": "^1.
|
|
98
|
-
"rollup": "^4.
|
|
106
|
+
"jsdom": "^30.1.3",
|
|
107
|
+
"npm-run-all2": "^9.0.4",
|
|
108
|
+
"oxlint": "^1.89.0",
|
|
109
|
+
"rollup": "^4.65.0",
|
|
99
110
|
"rollup-plugin-swc3": "^0.12.1",
|
|
100
111
|
"typescript": "^7.0.2",
|
|
101
|
-
"vitest": "^5.0.
|
|
112
|
+
"vitest": "^5.0.5"
|
|
102
113
|
},
|
|
103
114
|
"engines": {
|
|
104
115
|
"node": ">=20"
|
|
116
|
+
},
|
|
117
|
+
"peerDependencies": {
|
|
118
|
+
"@vercel/oidc": "^4.0.0"
|
|
119
|
+
},
|
|
120
|
+
"peerDependenciesMeta": {
|
|
121
|
+
"@vercel/oidc": {
|
|
122
|
+
"optional": true
|
|
123
|
+
}
|
|
105
124
|
}
|
|
106
125
|
}
|