@craftware/crafty-sdk 0.6.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -4
- package/dist/client.d.ts +11 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +12 -1
- package/dist/client.js.map +1 -1
- package/dist/crafty-visual-editing.global.js +1 -1
- package/dist/crafty-visual-editing.global.js.map +1 -1
- package/dist/http.d.ts +8 -1
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +50 -11
- package/dist/http.js.map +1 -1
- package/dist/image.d.ts +27 -0
- package/dist/image.d.ts.map +1 -0
- package/dist/image.js +110 -0
- package/dist/image.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/resources/assistant.d.ts +30 -0
- package/dist/resources/assistant.d.ts.map +1 -0
- package/dist/resources/assistant.js +51 -0
- package/dist/resources/assistant.js.map +1 -0
- package/dist/resources/captcha.d.ts +20 -0
- package/dist/resources/captcha.d.ts.map +1 -0
- package/dist/resources/captcha.js +100 -0
- package/dist/resources/captcha.js.map +1 -0
- package/dist/resources/entries.js +2 -2
- package/dist/resources/entries.js.map +1 -1
- package/dist/resources/forms.d.ts +11 -2
- package/dist/resources/forms.d.ts.map +1 -1
- package/dist/resources/forms.js +23 -4
- package/dist/resources/forms.js.map +1 -1
- package/dist/resources/pages.js +2 -2
- package/dist/resources/pages.js.map +1 -1
- package/dist/resources/site.d.ts +12 -0
- package/dist/resources/site.d.ts.map +1 -0
- package/dist/resources/site.js +15 -0
- package/dist/resources/site.js.map +1 -0
- package/dist/structured-data.d.ts +41 -0
- package/dist/structured-data.d.ts.map +1 -0
- package/dist/structured-data.js +91 -0
- package/dist/structured-data.js.map +1 -0
- package/dist/types/public.d.ts +138 -1
- package/dist/types/public.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/skills/crafty-cms/SKILL.md +48 -7
- package/skills/crafty-cms/references/mcp-configuration.md +23 -7
- package/skills/crafty-cms/references/migrate-to-crafty.md +93 -0
- package/skills/crafty-cms/references/sdk-development.md +84 -7
package/dist/http.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { CraftyClientConfig, RequestOptions } from "./types/public.js";
|
|
2
2
|
type QueryValue = string | number | boolean | null | undefined;
|
|
3
3
|
type QueryParams = Record<string, QueryValue>;
|
|
4
|
-
type HttpRequestOptions = RequestOptions & {
|
|
4
|
+
export type HttpRequestOptions = RequestOptions & {
|
|
5
5
|
query?: QueryParams;
|
|
6
6
|
};
|
|
7
7
|
type RequiredTransportConfig = {
|
|
@@ -13,6 +13,7 @@ type RequiredTransportConfig = {
|
|
|
13
13
|
timeoutMs: number | undefined;
|
|
14
14
|
preview: string | false | null | undefined;
|
|
15
15
|
onPreviewInvalid: (() => void) | undefined;
|
|
16
|
+
locale?: string | undefined;
|
|
16
17
|
};
|
|
17
18
|
export declare class HttpClient {
|
|
18
19
|
private readonly apiBaseUrl;
|
|
@@ -23,8 +24,14 @@ export declare class HttpClient {
|
|
|
23
24
|
private readonly defaultTimeoutMs;
|
|
24
25
|
private readonly preview;
|
|
25
26
|
private readonly onPreviewInvalid;
|
|
27
|
+
private readonly locale;
|
|
26
28
|
constructor(config: RequiredTransportConfig);
|
|
27
29
|
static fromClientConfig(config: CraftyClientConfig): HttpClient;
|
|
30
|
+
/**
|
|
31
|
+
* Adds the `locale` query parameter for localized content: the request's
|
|
32
|
+
* own locale, else the client default. Requests without one are unchanged.
|
|
33
|
+
*/
|
|
34
|
+
withLocale(options?: HttpRequestOptions): HttpRequestOptions | undefined;
|
|
28
35
|
getSiteSlug(): string | undefined;
|
|
29
36
|
/** Token to send as `X-Crafty-Preview`, or null when not previewing. */
|
|
30
37
|
previewToken(): string | null;
|
package/dist/http.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,kBAAkB,EAAc,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExF,KAAK,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC;AAC/D,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAE9C,
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,kBAAkB,EAAc,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExF,KAAK,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC;AAC/D,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAE9C,MAAM,MAAM,kBAAkB,GAAG,cAAc,GAAG;IAChD,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB,CAAC;AAEF,KAAK,uBAAuB,GAAG;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,OAAO,KAAK,CAAC;IACxB,cAAc,EAAE,WAAW,GAAG,SAAS,CAAC;IACxC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,OAAO,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,CAAC;IAC3C,gBAAgB,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IAC3C,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B,CAAC;AAEF,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA0B;IACzD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAqB;IACtD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoC;IAC5D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA2B;IAC5D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;gBAEzB,MAAM,EAAE,uBAAuB;WAYpC,gBAAgB,CAAC,MAAM,EAAE,kBAAkB,GAAG,UAAU;IA4BtE;;;OAGG;IACI,UAAU,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,kBAAkB,GAAG,SAAS;IAUxE,WAAW,IAAI,MAAM,GAAG,SAAS;IAIxC,wEAAwE;IACjE,YAAY,IAAI,MAAM,GAAG,IAAI;IAYvB,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,CAAC,CAAC;IAI9D,IAAI,CAAC,CAAC,EACjB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,OAAO,EACb,OAAO,CAAC,EAAE,kBAAkB,GAAG;QAAE,UAAU,CAAC,EAAE,OAAO,CAAA;KAAE,GACtD,OAAO,CAAC,CAAC,CAAC;IAcA,OAAO,CAAC,CAAC,EACpB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,kBAAkB,GAAG;QAC5B,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;QACpD,IAAI,CAAC,EAAE,OAAO,CAAC;QACf,UAAU,CAAC,EAAE,OAAO,CAAC;KACtB,GACA,OAAO,CAAC,CAAC,CAAC;IA2Hb,OAAO,CAAC,QAAQ;CAejB"}
|
package/dist/http.js
CHANGED
|
@@ -9,6 +9,7 @@ export class HttpClient {
|
|
|
9
9
|
defaultTimeoutMs;
|
|
10
10
|
preview;
|
|
11
11
|
onPreviewInvalid;
|
|
12
|
+
locale;
|
|
12
13
|
constructor(config) {
|
|
13
14
|
this.apiBaseUrl = config.apiBaseUrl;
|
|
14
15
|
this.fetchImpl = config.fetchImpl;
|
|
@@ -18,6 +19,7 @@ export class HttpClient {
|
|
|
18
19
|
this.defaultTimeoutMs = config.timeoutMs;
|
|
19
20
|
this.preview = config.preview;
|
|
20
21
|
this.onPreviewInvalid = config.onPreviewInvalid;
|
|
22
|
+
this.locale = config.locale;
|
|
21
23
|
}
|
|
22
24
|
static fromClientConfig(config) {
|
|
23
25
|
const fetchImpl = config.fetch ?? getBoundGlobalFetch();
|
|
@@ -39,9 +41,21 @@ export class HttpClient {
|
|
|
39
41
|
siteSlug: config.siteSlug,
|
|
40
42
|
timeoutMs: config.timeoutMs,
|
|
41
43
|
preview: config.preview,
|
|
42
|
-
onPreviewInvalid: config.onPreviewInvalid
|
|
44
|
+
onPreviewInvalid: config.onPreviewInvalid,
|
|
45
|
+
locale: config.locale
|
|
43
46
|
});
|
|
44
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Adds the `locale` query parameter for localized content: the request's
|
|
50
|
+
* own locale, else the client default. Requests without one are unchanged.
|
|
51
|
+
*/
|
|
52
|
+
withLocale(options) {
|
|
53
|
+
const locale = options?.locale ?? this.locale;
|
|
54
|
+
if (typeof locale !== "string" || locale.trim() === "") {
|
|
55
|
+
return options;
|
|
56
|
+
}
|
|
57
|
+
return { ...options, query: { ...options?.query, locale: locale.trim() } };
|
|
58
|
+
}
|
|
45
59
|
getSiteSlug() {
|
|
46
60
|
return this.siteSlug;
|
|
47
61
|
}
|
|
@@ -117,7 +131,15 @@ export class HttpClient {
|
|
|
117
131
|
else if (previewStatus === "active") {
|
|
118
132
|
notifyPreviewActive();
|
|
119
133
|
}
|
|
120
|
-
const
|
|
134
|
+
const parsed = await parseResponsePayload(response);
|
|
135
|
+
if (parsed === INVALID_JSON && response.ok) {
|
|
136
|
+
throw new CraftyError({
|
|
137
|
+
code: "UNKNOWN_ERROR",
|
|
138
|
+
message: "Response body was not valid JSON.",
|
|
139
|
+
status: response.status
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
const payload = parsed === INVALID_JSON ? null : parsed;
|
|
121
143
|
if (!response.ok) {
|
|
122
144
|
const requestId = response.headers.get("x-request-id") ?? undefined;
|
|
123
145
|
const message = extractErrorMessage(payload) ?? (response.statusText || "Request failed");
|
|
@@ -137,12 +159,17 @@ export class HttpClient {
|
|
|
137
159
|
if (error instanceof CraftyError) {
|
|
138
160
|
throw error;
|
|
139
161
|
}
|
|
140
|
-
if (
|
|
141
|
-
const code = timeoutController?.signal.aborted ? "TIMEOUT" : "NETWORK_ERROR";
|
|
142
|
-
const message = code === "TIMEOUT" ? "Request timed out." : "Request was aborted.";
|
|
162
|
+
if (timeoutController?.signal.aborted) {
|
|
143
163
|
throw new CraftyError({
|
|
144
|
-
code,
|
|
145
|
-
message,
|
|
164
|
+
code: "TIMEOUT",
|
|
165
|
+
message: "Request timed out.",
|
|
166
|
+
cause: error
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
if (options.signal?.aborted || isAbortError(error)) {
|
|
170
|
+
throw new CraftyError({
|
|
171
|
+
code: "NETWORK_ERROR",
|
|
172
|
+
message: "Request was aborted.",
|
|
146
173
|
cause: error
|
|
147
174
|
});
|
|
148
175
|
}
|
|
@@ -203,15 +230,27 @@ function mergeSignals(a, b) {
|
|
|
203
230
|
b.addEventListener("abort", () => abort(b), { once: true });
|
|
204
231
|
return controller.signal;
|
|
205
232
|
}
|
|
233
|
+
/** Marks a JSON response whose body could not be parsed. */
|
|
234
|
+
const INVALID_JSON = Symbol("invalid-json");
|
|
235
|
+
/**
|
|
236
|
+
* Reads the body as text and parses JSON when possible. An empty body yields
|
|
237
|
+
* null; a body labelled JSON that fails to parse yields INVALID_JSON so the
|
|
238
|
+
* caller can build an error carrying the HTTP status.
|
|
239
|
+
*/
|
|
206
240
|
async function parseResponsePayload(response) {
|
|
207
241
|
const contentType = response.headers.get("content-type") ?? "";
|
|
208
|
-
if (contentType.includes("application/json")) {
|
|
209
|
-
return response.json();
|
|
210
|
-
}
|
|
211
242
|
const text = await response.text();
|
|
212
|
-
if (text === "") {
|
|
243
|
+
if (text.trim() === "") {
|
|
213
244
|
return null;
|
|
214
245
|
}
|
|
246
|
+
if (contentType.includes("application/json")) {
|
|
247
|
+
try {
|
|
248
|
+
return JSON.parse(text);
|
|
249
|
+
}
|
|
250
|
+
catch {
|
|
251
|
+
return INVALID_JSON;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
215
254
|
try {
|
|
216
255
|
return JSON.parse(text);
|
|
217
256
|
}
|
package/dist/http.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,oBAAoB,EACpB,gBAAgB,EACjB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,oBAAoB,EACpB,gBAAgB,EACjB,MAAM,cAAc,CAAC;AAsBtB,MAAM,OAAO,UAAU;IACJ,UAAU,CAAS;IACnB,SAAS,CAAe;IACxB,cAAc,CAA0B;IACxC,MAAM,CAAqB;IAC3B,QAAQ,CAAqB;IAC7B,gBAAgB,CAAqB;IACrC,OAAO,CAAoC;IAC3C,gBAAgB,CAA2B;IAC3C,MAAM,CAAqB;IAE5C,YAAmB,MAA+B;QAChD,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;QACpC,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;QAClC,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;QAC5C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;QAChC,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC,SAAS,CAAC;QACzC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAC9B,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,CAAC;QAChD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAC9B,CAAC;IAEM,MAAM,CAAC,gBAAgB,CAAC,MAA0B;QACvD,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,IAAI,mBAAmB,EAAE,CAAC;QAExD,IAAI,OAAO,SAAS,KAAK,UAAU,EAAE,CAAC;YACpC,MAAM,IAAI,WAAW,CAAC;gBACpB,IAAI,EAAE,eAAe;gBACrB,OAAO,EAAE,6EAA6E;aACvF,CAAC,CAAC;QACL,CAAC;QAED,MAAM,iBAAiB,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC7D,MAAM,UAAU,GAAG,iBAAiB,CAAC,QAAQ,CAAC,SAAS,CAAC;YACtD,CAAC,CAAC,iBAAiB;YACnB,CAAC,CAAC,GAAG,iBAAiB,SAAS,CAAC;QAElC,OAAO,IAAI,UAAU,CAAC;YACpB,UAAU;YACV,SAAS;YACT,cAAc,EAAE,MAAM,CAAC,OAAO;YAC9B,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;YACzC,MAAM,EAAE,MAAM,CAAC,MAAM;SACtB,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACI,UAAU,CAAC,OAA4B;QAC5C,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC;QAE9C,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACvD,OAAO,OAAO,CAAC;QACjB,CAAC;QAED,OAAO,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC;IAC7E,CAAC;IAEM,WAAW;QAChB,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,wEAAwE;IACjE,YAAY;QACjB,IAAI,IAAI,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;YAC3B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACnE,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QAC7B,CAAC;QAED,OAAO,gBAAgB,EAAE,CAAC;IAC5B,CAAC;IAEM,KAAK,CAAC,GAAG,CAAI,IAAY,EAAE,OAA4B;QAC5D,OAAO,IAAI,CAAC,OAAO,CAAI,IAAI,EAAE,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9D,CAAC;IAEM,KAAK,CAAC,IAAI,CACf,IAAY,EACZ,IAAa,EACb,OAAuD;QAEvD,MAAM,cAAc,GAAyC;YAC3D,GAAG,OAAO;YACV,MAAM,EAAE,MAAe;YACvB,IAAI;SACL,CAAC;QAEF,IAAI,OAAO,EAAE,UAAU,EAAE,CAAC;YACxB,cAAc,CAAC,UAAU,GAAG,IAAI,CAAC;QACnC,CAAC;QAED,OAAO,IAAI,CAAC,OAAO,CAAI,IAAI,EAAE,cAAc,CAAC,CAAC;IAC/C,CAAC;IAEM,KAAK,CAAC,OAAO,CAClB,IAAY,EACZ,OAIC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;QAC/C,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAEjD,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,YAAY,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAClD,YAAY,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;QAChE,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAC;QAC5C,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;YACpE,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QACxC,CAAC;QACD,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,CAAC;YAC/D,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;QAClD,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QAEzC,IAAI,YAAY,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,CAAC;YAC1D,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC;QAC5C,CAAC;QAED,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC,gBAAgB,CAAC;QAC7D,MAAM,iBAAiB,GAAG,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,GAAG,CAAC;YACtE,CAAC,CAAC,IAAI,eAAe,EAAE;YACvB,CAAC,CAAC,IAAI,CAAC;QACT,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,MAAM,EAAE,iBAAiB,EAAE,MAAM,CAAC,CAAC;QAEvE,IAAI,aAAwD,CAAC;QAC7D,IAAI,iBAAiB,IAAI,SAAS,EAAE,CAAC;YACnC,aAAa,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,iBAAiB,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC,CAAC;QAClF,CAAC;QAED,IAAI,CAAC;YACH,MAAM,SAAS,GAAgB;gBAC7B,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,OAAO;gBACP,MAAM,EAAE,MAAM,IAAI,IAAI;aACvB,CAAC;YAEF,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC/B,SAAS,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAChD,CAAC;YAED,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;YAEtD,MAAM,aAAa,GAAG,YAAY,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAEjG,IAAI,aAAa,KAAK,SAAS,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;gBACzD,mBAAmB,CAAC,YAAY,CAAC,CAAC;gBAClC,IAAI,CAAC,gBAAgB,EAAE,EAAE,CAAC;gBAC1B,oBAAoB,EAAE,CAAC;YACzB,CAAC;iBAAM,IAAI,aAAa,KAAK,QAAQ,EAAE,CAAC;gBACtC,mBAAmB,EAAE,CAAC;YACxB,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,QAAQ,CAAC,CAAC;YAEpD,IAAI,MAAM,KAAK,YAAY,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;gBAC3C,MAAM,IAAI,WAAW,CAAC;oBACpB,IAAI,EAAE,eAAe;oBACrB,OAAO,EAAE,mCAAmC;oBAC5C,MAAM,EAAE,QAAQ,CAAC,MAAM;iBACxB,CAAC,CAAC;YACL,CAAC;YAED,MAAM,OAAO,GAAG,MAAM,KAAK,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;YAExD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,SAAS,CAAC;gBACpE,MAAM,OAAO,GAAG,mBAAmB,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,IAAI,gBAAgB,CAAC,CAAC;gBAE1F,MAAM,YAAY,GAAG;oBACnB,IAAI,EAAE,oBAAoB,CAAC,QAAQ,CAAC,MAAM,CAAC;oBAC3C,OAAO;oBACP,MAAM,EAAE,QAAQ,CAAC,MAAM;oBACvB,OAAO,EAAE,OAAO;iBACR,CAAC;gBAEX,MAAM,IAAI,WAAW,CACnB,SAAS;oBACP,CAAC,CAAC,EAAE,GAAG,YAAY,EAAE,SAAS,EAAE;oBAChC,CAAC,CAAC,YAAY,CACjB,CAAC;YACJ,CAAC;YAED,OAAO,OAAY,CAAC;QACtB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;gBACjC,MAAM,KAAK,CAAC;YACd,CAAC;YAED,IAAI,iBAAiB,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;gBACtC,MAAM,IAAI,WAAW,CAAC;oBACpB,IAAI,EAAE,SAAS;oBACf,OAAO,EAAE,oBAAoB;oBAC7B,KAAK,EAAE,KAAK;iBACb,CAAC,CAAC;YACL,CAAC;YAED,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO,IAAI,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;gBACnD,MAAM,IAAI,WAAW,CAAC;oBACpB,IAAI,EAAE,eAAe;oBACrB,OAAO,EAAE,sBAAsB;oBAC/B,KAAK,EAAE,KAAK;iBACb,CAAC,CAAC;YACL,CAAC;YAED,MAAM,IAAI,WAAW,CAAC;gBACpB,IAAI,EAAE,eAAe;gBACrB,OAAO,EAAE,yBAAyB;gBAClC,KAAK,EAAE,KAAK;aACb,CAAC,CAAC;QACL,CAAC;gBAAS,CAAC;YACT,IAAI,aAAa,EAAE,CAAC;gBAClB,YAAY,CAAC,aAAa,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC;IACH,CAAC;IAEO,QAAQ,CAAC,IAAY,EAAE,KAAmB;QAChD,MAAM,cAAc,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;QAChE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,UAAU,GAAG,cAAc,EAAE,CAAC,CAAC;QAE3D,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACjD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;oBAC1C,SAAS;gBACX,CAAC;gBACD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;QAED,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;IACxB,CAAC;CACF;AAED,SAAS,mBAAmB;IAC1B,IAAI,OAAO,UAAU,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;QAC3C,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAiB,CAAC;AAC3D,CAAC;AAED,SAAS,YAAY,CACnB,CAAe,EACf,CAAe;IAEf,IAAI,CAAC,CAAC,EAAE,CAAC;QACP,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,CAAC,CAAC,EAAE,CAAC;QACP,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IAEzC,MAAM,KAAK,GAAG,CAAC,MAAmB,EAAQ,EAAE;QAC1C,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YAC/B,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAClC,CAAC;IACH,CAAC,CAAC;IAEF,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;QACd,KAAK,CAAC,CAAC,CAAC,CAAC;QACT,OAAO,UAAU,CAAC,MAAM,CAAC;IAC3B,CAAC;IACD,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;QACd,KAAK,CAAC,CAAC,CAAC,CAAC;QACT,OAAO,UAAU,CAAC,MAAM,CAAC;IAC3B,CAAC;IAED,CAAC,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,CAAC,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAE5D,OAAO,UAAU,CAAC,MAAM,CAAC;AAC3B,CAAC;AAED,4DAA4D;AAC5D,MAAM,YAAY,GAAkB,MAAM,CAAC,cAAc,CAAC,CAAC;AAE3D;;;;GAIG;AACH,KAAK,UAAU,oBAAoB,CAAC,QAAkB;IACpD,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;IAC/D,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAEnC,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,WAAW,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;QAC7C,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAY,CAAC;QACrC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,YAAY,CAAC;QACtB,CAAC;IACH,CAAC;IAED,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAe,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,OAAgB;IAC3C,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC5C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,YAAY,GAAI,OAAiC,CAAC,OAAO,CAAC;IAChE,OAAO,OAAO,YAAY,KAAK,QAAQ,IAAI,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9F,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,OAAO,KAAK,YAAY,YAAY;QAClC,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,YAAY;QAC7B,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ;YACvB,KAAK,KAAK,IAAI;YACd,MAAM,IAAI,KAAK;YACd,KAA4B,CAAC,IAAI,KAAK,YAAY,CAAC;AAC5D,CAAC"}
|
package/dist/image.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { CraftyImageOptions, CraftyImageSource } from "./types/public.js";
|
|
2
|
+
/**
|
|
3
|
+
* URL of a resized / re-encoded version of a Crafty image, served by
|
|
4
|
+
* Cloudflare Image Transformations (`<base>/cdn-cgi/image/<options>/<source>`).
|
|
5
|
+
*
|
|
6
|
+
* Falls back to the original `url` when the media has no
|
|
7
|
+
* `image_transform_base` (transformations disabled on the server, private
|
|
8
|
+
* media, SVGs or non-images), so it is always safe to use as `src`.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* <img src={crafty.image(block.data.image_media, { width: 800, format: "auto" })} />
|
|
12
|
+
*/
|
|
13
|
+
export declare function imageUrl(media: CraftyImageSource, options?: CraftyImageOptions): string;
|
|
14
|
+
/**
|
|
15
|
+
* `srcset` value with one transformed URL per width (`<url> 400w, <url> 800w`).
|
|
16
|
+
* Widths are clamped to 1..4096, de-duplicated and sorted. Returns an empty
|
|
17
|
+
* string when the image cannot be transformed: browsers then use `src`.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* <img
|
|
21
|
+
* src={crafty.image(media, { width: 800, format: "auto" })}
|
|
22
|
+
* srcSet={crafty.srcset(media, [400, 800, 1200], { format: "auto" })}
|
|
23
|
+
* sizes="(min-width: 768px) 50vw, 100vw"
|
|
24
|
+
* />
|
|
25
|
+
*/
|
|
26
|
+
export declare function imageSrcSet(media: CraftyImageSource, widths: readonly number[], options?: Omit<CraftyImageOptions, "width">): string;
|
|
27
|
+
//# sourceMappingURL=image.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../src/image.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAqC,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAMlH;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,iBAAiB,EAAE,OAAO,GAAE,kBAAuB,GAAG,MAAM,CAe3F;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,iBAAiB,EACxB,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,OAAO,GAAE,IAAI,CAAC,kBAAkB,EAAE,OAAO,CAAM,GAC9C,MAAM,CAUR"}
|
package/dist/image.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
const MAX_DIMENSION = 4096;
|
|
2
|
+
const FITS = ["scale-down", "contain", "cover", "crop", "pad"];
|
|
3
|
+
const FORMATS = ["auto", "webp", "avif", "jpeg", "png"];
|
|
4
|
+
/**
|
|
5
|
+
* URL of a resized / re-encoded version of a Crafty image, served by
|
|
6
|
+
* Cloudflare Image Transformations (`<base>/cdn-cgi/image/<options>/<source>`).
|
|
7
|
+
*
|
|
8
|
+
* Falls back to the original `url` when the media has no
|
|
9
|
+
* `image_transform_base` (transformations disabled on the server, private
|
|
10
|
+
* media, SVGs or non-images), so it is always safe to use as `src`.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* <img src={crafty.image(block.data.image_media, { width: 800, format: "auto" })} />
|
|
14
|
+
*/
|
|
15
|
+
export function imageUrl(media, options = {}) {
|
|
16
|
+
const url = sourceUrl(media);
|
|
17
|
+
if (url === "") {
|
|
18
|
+
return "";
|
|
19
|
+
}
|
|
20
|
+
const base = transformBase(media);
|
|
21
|
+
const params = transformParams(options);
|
|
22
|
+
if (base === null || params === "") {
|
|
23
|
+
return url;
|
|
24
|
+
}
|
|
25
|
+
return `${base}/cdn-cgi/image/${params}/${sourceForBase(url, base)}`;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* `srcset` value with one transformed URL per width (`<url> 400w, <url> 800w`).
|
|
29
|
+
* Widths are clamped to 1..4096, de-duplicated and sorted. Returns an empty
|
|
30
|
+
* string when the image cannot be transformed: browsers then use `src`.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* <img
|
|
34
|
+
* src={crafty.image(media, { width: 800, format: "auto" })}
|
|
35
|
+
* srcSet={crafty.srcset(media, [400, 800, 1200], { format: "auto" })}
|
|
36
|
+
* sizes="(min-width: 768px) 50vw, 100vw"
|
|
37
|
+
* />
|
|
38
|
+
*/
|
|
39
|
+
export function imageSrcSet(media, widths, options = {}) {
|
|
40
|
+
if (sourceUrl(media) === "" || transformBase(media) === null) {
|
|
41
|
+
return "";
|
|
42
|
+
}
|
|
43
|
+
const uniqueWidths = [
|
|
44
|
+
...new Set(widths.map((width) => clampInteger(width, 1, MAX_DIMENSION)).filter((width) => width !== null))
|
|
45
|
+
].sort((a, b) => a - b);
|
|
46
|
+
return uniqueWidths.map((width) => `${imageUrl(media, { ...options, width })} ${width}w`).join(", ");
|
|
47
|
+
}
|
|
48
|
+
function sourceUrl(media) {
|
|
49
|
+
if (typeof media === "string") {
|
|
50
|
+
return media;
|
|
51
|
+
}
|
|
52
|
+
return media !== null && typeof media === "object" && typeof media.url === "string" ? media.url : "";
|
|
53
|
+
}
|
|
54
|
+
function transformBase(media) {
|
|
55
|
+
if (media === null || typeof media !== "object") {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
const base = media.image_transform_base;
|
|
59
|
+
if (typeof base !== "string" || !/^https?:\/\/[^/\s]+\/?$/i.test(base)) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
return base.replace(/\/$/, "");
|
|
63
|
+
}
|
|
64
|
+
/** Same origin as the zone: a root-relative path; otherwise the absolute URL. */
|
|
65
|
+
function sourceForBase(url, base) {
|
|
66
|
+
try {
|
|
67
|
+
const source = new URL(url);
|
|
68
|
+
if (source.origin === new URL(base).origin) {
|
|
69
|
+
return source.pathname.replace(/^\//, "") + source.search;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return url;
|
|
74
|
+
}
|
|
75
|
+
return url;
|
|
76
|
+
}
|
|
77
|
+
function transformParams(options) {
|
|
78
|
+
const params = [];
|
|
79
|
+
const width = clampInteger(options.width, 1, MAX_DIMENSION);
|
|
80
|
+
const height = clampInteger(options.height, 1, MAX_DIMENSION);
|
|
81
|
+
const quality = clampInteger(options.quality, 1, 100);
|
|
82
|
+
if (width !== null) {
|
|
83
|
+
params.push(`width=${width}`);
|
|
84
|
+
}
|
|
85
|
+
if (height !== null) {
|
|
86
|
+
params.push(`height=${height}`);
|
|
87
|
+
}
|
|
88
|
+
if (options.fit !== undefined && FITS.includes(options.fit)) {
|
|
89
|
+
params.push(`fit=${options.fit}`);
|
|
90
|
+
}
|
|
91
|
+
if (quality !== null) {
|
|
92
|
+
params.push(`quality=${quality}`);
|
|
93
|
+
}
|
|
94
|
+
if (options.format !== undefined && FORMATS.includes(options.format)) {
|
|
95
|
+
params.push(`format=${options.format}`);
|
|
96
|
+
}
|
|
97
|
+
if (params.length === 0) {
|
|
98
|
+
return "";
|
|
99
|
+
}
|
|
100
|
+
// Serve the original image instead of an error page if a transform fails.
|
|
101
|
+
params.push("onerror=redirect");
|
|
102
|
+
return params.join(",");
|
|
103
|
+
}
|
|
104
|
+
function clampInteger(value, min, max) {
|
|
105
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
return Math.min(max, Math.max(min, Math.round(value)));
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=image.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image.js","sourceRoot":"","sources":["../src/image.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,10 +4,16 @@ export { CraftyError } from "./errors.js";
|
|
|
4
4
|
export type { CraftyErrorCode } from "./errors.js";
|
|
5
5
|
export { attrs, attrsHtml } from "./attrs.js";
|
|
6
6
|
export type { CraftyAttrsOptions, CraftyEditAttributes, CraftyEditTarget, CraftyEditTargetType } from "./attrs.js";
|
|
7
|
+
export { imageSrcSet, imageUrl } from "./image.js";
|
|
8
|
+
export { faqPage, jsonLd, serializeJsonLd, structuredData } from "./structured-data.js";
|
|
9
|
+
export type { FaqItem, StructuredDataSource } from "./structured-data.js";
|
|
7
10
|
export { PREVIEW_HEADER, PREVIEW_INVALID_EVENT, PREVIEW_QUERY_PARAM, PREVIEW_STATUS_HEADER, clearPreviewToken, previewFromRequest, readPreviewToken, storePreviewToken } from "./preview.js";
|
|
8
11
|
export type { PreviewContent, PreviewEntry, PreviewPage, PreviewRequestLike } from "./preview.js";
|
|
9
12
|
export { ANALYTICS_FLAG } from "./resources/analytics.js";
|
|
10
13
|
export type { AnalyticsLoadResult } from "./resources/analytics.js";
|
|
14
|
+
export { ASSISTANT_FLAG } from "./resources/assistant.js";
|
|
15
|
+
export type { AssistantLoadResult } from "./resources/assistant.js";
|
|
16
|
+
export type { CraftyFormCaptcha } from "./resources/captcha.js";
|
|
11
17
|
export type { LlmsHandlerOptions, LlmsLinkTag } from "./resources/llms.js";
|
|
12
18
|
export type * from "./types/public.js";
|
|
13
19
|
export type * from "./types/blocks.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC9C,YAAY,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEnH,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,mBAAmB,EACnB,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElG,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,YAAY,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,YAAY,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAE3E,mBAAmB,mBAAmB,CAAC;AACvC,mBAAmB,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC9C,YAAY,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEnH,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEnD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACxF,YAAY,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE1E,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,mBAAmB,EACnB,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElG,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,YAAY,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,YAAY,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,YAAY,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,YAAY,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAE3E,mBAAmB,mBAAmB,CAAC;AACvC,mBAAmB,mBAAmB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
export { createCraftyClient } from "./client.js";
|
|
2
2
|
export { CraftyError } from "./errors.js";
|
|
3
3
|
export { attrs, attrsHtml } from "./attrs.js";
|
|
4
|
+
export { imageSrcSet, imageUrl } from "./image.js";
|
|
5
|
+
export { faqPage, jsonLd, serializeJsonLd, structuredData } from "./structured-data.js";
|
|
4
6
|
export { PREVIEW_HEADER, PREVIEW_INVALID_EVENT, PREVIEW_QUERY_PARAM, PREVIEW_STATUS_HEADER, clearPreviewToken, previewFromRequest, readPreviewToken, storePreviewToken } from "./preview.js";
|
|
5
7
|
export { ANALYTICS_FLAG } from "./resources/analytics.js";
|
|
8
|
+
export { ASSISTANT_FLAG } from "./resources/assistant.js";
|
|
6
9
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGjD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG1C,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG9C,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,mBAAmB,EACnB,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGjD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG1C,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG9C,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEnD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGxF,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,mBAAmB,EACnB,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { HttpClient } from "../http.js";
|
|
2
|
+
import type { CraftyAssistant, RequestOptions } from "../types/public.js";
|
|
3
|
+
/** Global the site assistant widget sets once it starts, so a second loader does nothing. */
|
|
4
|
+
export declare const ASSISTANT_FLAG = "__CRAFTY_ASSISTANT__";
|
|
5
|
+
export type AssistantLoadResult =
|
|
6
|
+
/** The SDK inserted the widget loader. */
|
|
7
|
+
"loaded"
|
|
8
|
+
/** The page already carries the widget (Crafty Hosting deploy, SSR, or an earlier load). */
|
|
9
|
+
| "already-loaded"
|
|
10
|
+
/** The assistant is not set up for this environment. */
|
|
11
|
+
| "not-installed"
|
|
12
|
+
/** Not running in a browser. */
|
|
13
|
+
| "unavailable";
|
|
14
|
+
export declare class AssistantResource {
|
|
15
|
+
private readonly http;
|
|
16
|
+
constructor(http: HttpClient);
|
|
17
|
+
/**
|
|
18
|
+
* Whether the environment shows the assistant, plus the ready-made loader
|
|
19
|
+
* `html`. For SSR, render `html` right before `</body>`.
|
|
20
|
+
*/
|
|
21
|
+
get(options?: RequestOptions): Promise<CraftyAssistant>;
|
|
22
|
+
/**
|
|
23
|
+
* Browser loader for sites that render on the client. Skips when the page
|
|
24
|
+
* already carries the widget, so on Crafty Hosting the loader the deploy
|
|
25
|
+
* injected always wins. The widget reads its settings live, so changes in
|
|
26
|
+
* the panel apply without reloading the SDK.
|
|
27
|
+
*/
|
|
28
|
+
load(options?: RequestOptions): Promise<AssistantLoadResult>;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=assistant.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assistant.d.ts","sourceRoot":"","sources":["../../src/resources/assistant.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,eAAe,EAA2B,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEnG,6FAA6F;AAC7F,eAAO,MAAM,cAAc,yBAAyB,CAAC;AAErD,MAAM,MAAM,mBAAmB;AAC7B,0CAA0C;AACxC,QAAQ;AACV,4FAA4F;GAC1F,gBAAgB;AAClB,wDAAwD;GACtD,eAAe;AACjB,gCAAgC;GAC9B,aAAa,CAAC;AAMlB,qBAAa,iBAAiB;IACT,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAEpD;;;OAGG;IACU,GAAG,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IAMpE;;;;;OAKG;IACU,IAAI,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,mBAAmB,CAAC;CA8B1E"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/** Global the site assistant widget sets once it starts, so a second loader does nothing. */
|
|
2
|
+
export const ASSISTANT_FLAG = "__CRAFTY_ASSISTANT__";
|
|
3
|
+
const LOADER_SELECTOR = "script[data-crafty-assistant]";
|
|
4
|
+
export class AssistantResource {
|
|
5
|
+
http;
|
|
6
|
+
constructor(http) {
|
|
7
|
+
this.http = http;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Whether the environment shows the assistant, plus the ready-made loader
|
|
11
|
+
* `html`. For SSR, render `html` right before `</body>`.
|
|
12
|
+
*/
|
|
13
|
+
async get(options) {
|
|
14
|
+
const response = await this.http.get("/assistant", options);
|
|
15
|
+
return response.data;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Browser loader for sites that render on the client. Skips when the page
|
|
19
|
+
* already carries the widget, so on Crafty Hosting the loader the deploy
|
|
20
|
+
* injected always wins. The widget reads its settings live, so changes in
|
|
21
|
+
* the panel apply without reloading the SDK.
|
|
22
|
+
*/
|
|
23
|
+
async load(options) {
|
|
24
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
25
|
+
return "unavailable";
|
|
26
|
+
}
|
|
27
|
+
if (isLoaded()) {
|
|
28
|
+
return "already-loaded";
|
|
29
|
+
}
|
|
30
|
+
const assistant = await this.get(options);
|
|
31
|
+
if (isLoaded()) {
|
|
32
|
+
return "already-loaded";
|
|
33
|
+
}
|
|
34
|
+
if (!assistant.installed) {
|
|
35
|
+
return "not-installed";
|
|
36
|
+
}
|
|
37
|
+
const script = document.createElement("script");
|
|
38
|
+
script.src = assistant.script_url;
|
|
39
|
+
script.async = true;
|
|
40
|
+
script.setAttribute("data-crafty-assistant", "");
|
|
41
|
+
script.setAttribute("data-site", assistant.site);
|
|
42
|
+
script.setAttribute("data-environment", assistant.environment);
|
|
43
|
+
script.setAttribute("data-api", assistant.api_url);
|
|
44
|
+
document.body.appendChild(script);
|
|
45
|
+
return "loaded";
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function isLoaded() {
|
|
49
|
+
return window[ASSISTANT_FLAG] !== undefined || document.querySelector(LOADER_SELECTOR) !== null;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=assistant.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assistant.js","sourceRoot":"","sources":["../../src/resources/assistant.ts"],"names":[],"mappings":"AAGA,6FAA6F;AAC7F,MAAM,CAAC,MAAM,cAAc,GAAG,sBAAsB,CAAC;AAcrD,MAAM,eAAe,GAAG,+BAA+B,CAAC;AAExD,MAAM,OAAO,iBAAiB;IACQ;IAApC,YAAoC,IAAgB;QAAhB,SAAI,GAAJ,IAAI,CAAY;IAAG,CAAC;IAExD;;;OAGG;IACI,KAAK,CAAC,GAAG,CAAC,OAAwB;QACvC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAA0B,YAAY,EAAE,OAAO,CAAC,CAAC;QAErF,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,IAAI,CAAC,OAAwB;QACxC,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,CAAC;YACrE,OAAO,aAAa,CAAC;QACvB,CAAC;QAED,IAAI,QAAQ,EAAE,EAAE,CAAC;YACf,OAAO,gBAAgB,CAAC;QAC1B,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAE1C,IAAI,QAAQ,EAAE,EAAE,CAAC;YACf,OAAO,gBAAgB,CAAC;QAC1B,CAAC;QAED,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC;YACzB,OAAO,eAAe,CAAC;QACzB,CAAC;QAED,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAChD,MAAM,CAAC,GAAG,GAAG,SAAS,CAAC,UAAU,CAAC;QAClC,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC;QACpB,MAAM,CAAC,YAAY,CAAC,uBAAuB,EAAE,EAAE,CAAC,CAAC;QACjD,MAAM,CAAC,YAAY,CAAC,WAAW,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;QACjD,MAAM,CAAC,YAAY,CAAC,kBAAkB,EAAE,SAAS,CAAC,WAAW,CAAC,CAAC;QAC/D,MAAM,CAAC,YAAY,CAAC,UAAU,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;QACnD,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAElC,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF;AAED,SAAS,QAAQ;IACf,OAAQ,MAAwB,CAAC,cAAc,CAAC,KAAK,SAAS,IAAI,QAAQ,CAAC,aAAa,CAAC,eAAe,CAAC,KAAK,IAAI,CAAC;AACrH,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { CraftyFormCaptchaConfig } from "../types/public.js";
|
|
2
|
+
/** A rendered captcha widget whose token goes with one form submission. */
|
|
3
|
+
export type CraftyFormCaptcha = {
|
|
4
|
+
provider: CraftyFormCaptchaConfig["provider"];
|
|
5
|
+
/** Request field the token is posted in. */
|
|
6
|
+
field: string;
|
|
7
|
+
/** Runs the challenge (invisible for Turnstile) and resolves with a fresh token. */
|
|
8
|
+
token(): Promise<string>;
|
|
9
|
+
/** Clears the widget so the next submission gets a new token. */
|
|
10
|
+
reset(): void;
|
|
11
|
+
/** Removes the widget from the page. */
|
|
12
|
+
remove(): void;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Renders the form's captcha widget into `container`. Turnstile runs
|
|
16
|
+
* invisibly and only shows a challenge when Cloudflare is unsure of the
|
|
17
|
+
* visitor; hCaptcha shows its checkbox.
|
|
18
|
+
*/
|
|
19
|
+
export declare function renderCaptcha(config: CraftyFormCaptchaConfig, container: HTMLElement): Promise<CraftyFormCaptcha>;
|
|
20
|
+
//# sourceMappingURL=captcha.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"captcha.d.ts","sourceRoot":"","sources":["../../src/resources/captcha.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAElE,2EAA2E;AAC3E,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,uBAAuB,CAAC,UAAU,CAAC,CAAC;IAC9C,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,oFAAoF;IACpF,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IACzB,iEAAiE;IACjE,KAAK,IAAI,IAAI,CAAC;IACd,wCAAwC;IACxC,MAAM,IAAI,IAAI,CAAC;CAChB,CAAC;AAyDF;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,uBAAuB,EAAE,SAAS,EAAE,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAmEvH"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { CraftyError } from "../errors.js";
|
|
2
|
+
const SCRIPTS = {
|
|
3
|
+
turnstile: "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit",
|
|
4
|
+
hcaptcha: "https://js.hcaptcha.com/1/api.js?render=explicit"
|
|
5
|
+
};
|
|
6
|
+
const loading = new Map();
|
|
7
|
+
function loadApi(provider) {
|
|
8
|
+
const win = window;
|
|
9
|
+
const ready = win[provider];
|
|
10
|
+
if (ready) {
|
|
11
|
+
return Promise.resolve(ready);
|
|
12
|
+
}
|
|
13
|
+
const pending = loading.get(provider);
|
|
14
|
+
if (pending) {
|
|
15
|
+
return pending;
|
|
16
|
+
}
|
|
17
|
+
const promise = new Promise((resolve, reject) => {
|
|
18
|
+
const script = document.createElement("script");
|
|
19
|
+
script.src = SCRIPTS[provider];
|
|
20
|
+
script.async = true;
|
|
21
|
+
script.dataset.craftyCaptcha = provider;
|
|
22
|
+
script.addEventListener("load", () => {
|
|
23
|
+
const api = window[provider];
|
|
24
|
+
if (api) {
|
|
25
|
+
resolve(api);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
reject(new Error(`${provider} script loaded without its API.`));
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
script.addEventListener("error", () => reject(new Error(`Could not load the ${provider} script.`)));
|
|
32
|
+
document.head.appendChild(script);
|
|
33
|
+
});
|
|
34
|
+
promise.catch(() => loading.delete(provider));
|
|
35
|
+
loading.set(provider, promise);
|
|
36
|
+
return promise;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Renders the form's captcha widget into `container`. Turnstile runs
|
|
40
|
+
* invisibly and only shows a challenge when Cloudflare is unsure of the
|
|
41
|
+
* visitor; hCaptcha shows its checkbox.
|
|
42
|
+
*/
|
|
43
|
+
export async function renderCaptcha(config, container) {
|
|
44
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
45
|
+
throw new CraftyError({ code: "BAD_REQUEST", message: "The form captcha can only be rendered in a browser." });
|
|
46
|
+
}
|
|
47
|
+
let api;
|
|
48
|
+
try {
|
|
49
|
+
api = await loadApi(config.provider);
|
|
50
|
+
}
|
|
51
|
+
catch (cause) {
|
|
52
|
+
throw new CraftyError({ code: "NETWORK_ERROR", message: `Could not load the ${config.provider} captcha.`, cause });
|
|
53
|
+
}
|
|
54
|
+
let waiting = null;
|
|
55
|
+
const settle = (token, error) => {
|
|
56
|
+
const current = waiting;
|
|
57
|
+
waiting = null;
|
|
58
|
+
if (current && token) {
|
|
59
|
+
current.resolve(token);
|
|
60
|
+
}
|
|
61
|
+
else if (current) {
|
|
62
|
+
current.reject(error ?? new Error("Captcha failed."));
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
const params = {
|
|
66
|
+
sitekey: config.site_key,
|
|
67
|
+
callback: (token) => settle(token),
|
|
68
|
+
"error-callback": () => settle(null, new Error("Captcha failed.")),
|
|
69
|
+
"expired-callback": () => api.reset(widgetId)
|
|
70
|
+
};
|
|
71
|
+
if (config.provider === "turnstile") {
|
|
72
|
+
params.execution = "execute";
|
|
73
|
+
params.appearance = "interaction-only";
|
|
74
|
+
}
|
|
75
|
+
const widgetId = api.render(container, params);
|
|
76
|
+
return {
|
|
77
|
+
provider: config.provider,
|
|
78
|
+
field: config.token_field,
|
|
79
|
+
token() {
|
|
80
|
+
const existing = api.getResponse(widgetId);
|
|
81
|
+
if (existing) {
|
|
82
|
+
return Promise.resolve(existing);
|
|
83
|
+
}
|
|
84
|
+
if (config.provider === "hcaptcha") {
|
|
85
|
+
return Promise.reject(new CraftyError({ code: "BAD_REQUEST", message: "Complete the captcha before submitting." }));
|
|
86
|
+
}
|
|
87
|
+
return new Promise((resolve, reject) => {
|
|
88
|
+
waiting = { resolve, reject };
|
|
89
|
+
api.execute(widgetId);
|
|
90
|
+
});
|
|
91
|
+
},
|
|
92
|
+
reset() {
|
|
93
|
+
api.reset(widgetId);
|
|
94
|
+
},
|
|
95
|
+
remove() {
|
|
96
|
+
api.remove(widgetId);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=captcha.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"captcha.js","sourceRoot":"","sources":["../../src/resources/captcha.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,12 +6,12 @@ export class EntriesResource {
|
|
|
6
6
|
}
|
|
7
7
|
async list(collectionSlug, query, options) {
|
|
8
8
|
const requestOptions = query ? { ...options, query } : options;
|
|
9
|
-
const response = await this.http.get(`/collections/${encodeURIComponent(collectionSlug)}/entries`, requestOptions);
|
|
9
|
+
const response = await this.http.get(`/collections/${encodeURIComponent(collectionSlug)}/entries`, this.http.withLocale(requestOptions));
|
|
10
10
|
this.recordShown(collectionSlug, Array.isArray(response?.data) ? response.data : []);
|
|
11
11
|
return response;
|
|
12
12
|
}
|
|
13
13
|
async get(collectionSlug, id, options) {
|
|
14
|
-
const response = await this.http.get(`/collections/${encodeURIComponent(collectionSlug)}/entries/${encodeURIComponent(String(id))}`, options);
|
|
14
|
+
const response = await this.http.get(`/collections/${encodeURIComponent(collectionSlug)}/entries/${encodeURIComponent(String(id))}`, this.http.withLocale(options));
|
|
15
15
|
this.recordShown(collectionSlug, response?.data ? [response.data] : []);
|
|
16
16
|
return response;
|
|
17
17
|
}
|