@craftware/crafty-sdk 0.2.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/README.md +75 -0
  2. package/dist/attrs.d.ts +42 -0
  3. package/dist/attrs.d.ts.map +1 -0
  4. package/dist/attrs.js +60 -0
  5. package/dist/attrs.js.map +1 -0
  6. package/dist/cdn.d.ts +5 -0
  7. package/dist/cdn.d.ts.map +1 -0
  8. package/dist/cdn.js +5 -0
  9. package/dist/cdn.js.map +1 -0
  10. package/dist/client.d.ts +12 -7
  11. package/dist/client.d.ts.map +1 -1
  12. package/dist/client.js +13 -8
  13. package/dist/client.js.map +1 -1
  14. package/dist/crafty-visual-editing.global.js +4 -0
  15. package/dist/crafty-visual-editing.global.js.map +7 -0
  16. package/dist/http.d.ts +7 -1
  17. package/dist/http.d.ts.map +1 -1
  18. package/dist/http.js +32 -2
  19. package/dist/http.js.map +1 -1
  20. package/dist/index.d.ts +10 -6
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +4 -2
  23. package/dist/index.js.map +1 -1
  24. package/dist/preview.d.ts +56 -0
  25. package/dist/preview.d.ts.map +1 -0
  26. package/dist/preview.js +174 -0
  27. package/dist/preview.js.map +1 -0
  28. package/dist/resources/collections.d.ts +2 -2
  29. package/dist/resources/collections.d.ts.map +1 -1
  30. package/dist/resources/entries.d.ts +3 -2
  31. package/dist/resources/entries.d.ts.map +1 -1
  32. package/dist/resources/entries.js +20 -4
  33. package/dist/resources/entries.js.map +1 -1
  34. package/dist/resources/forms.d.ts +2 -2
  35. package/dist/resources/forms.d.ts.map +1 -1
  36. package/dist/resources/forms.js +1 -1
  37. package/dist/resources/forms.js.map +1 -1
  38. package/dist/resources/mediaCollections.d.ts +2 -2
  39. package/dist/resources/mediaCollections.d.ts.map +1 -1
  40. package/dist/resources/mediaFiles.d.ts +2 -2
  41. package/dist/resources/mediaFiles.d.ts.map +1 -1
  42. package/dist/resources/pages.d.ts +2 -2
  43. package/dist/resources/pages.d.ts.map +1 -1
  44. package/dist/resources/pages.js +4 -0
  45. package/dist/resources/pages.js.map +1 -1
  46. package/dist/types/public.d.ts +11 -2
  47. package/dist/types/public.d.ts.map +1 -1
  48. package/dist/version.d.ts +2 -0
  49. package/dist/version.d.ts.map +1 -0
  50. package/dist/version.js +3 -0
  51. package/dist/version.js.map +1 -0
  52. package/dist/visual-editing/bridge.d.ts +35 -0
  53. package/dist/visual-editing/bridge.d.ts.map +1 -0
  54. package/dist/visual-editing/bridge.js +446 -0
  55. package/dist/visual-editing/bridge.js.map +1 -0
  56. package/dist/visual-editing/index.d.ts +10 -0
  57. package/dist/visual-editing/index.d.ts.map +1 -0
  58. package/dist/visual-editing/index.js +10 -0
  59. package/dist/visual-editing/index.js.map +1 -0
  60. package/dist/visual-editing/live-preview.d.ts +15 -0
  61. package/dist/visual-editing/live-preview.d.ts.map +1 -0
  62. package/dist/visual-editing/live-preview.js +63 -0
  63. package/dist/visual-editing/live-preview.js.map +1 -0
  64. package/dist/visual-editing/markers.d.ts +11 -0
  65. package/dist/visual-editing/markers.d.ts.map +1 -0
  66. package/dist/visual-editing/markers.js +44 -0
  67. package/dist/visual-editing/markers.js.map +1 -0
  68. package/dist/visual-editing/origin.d.ts +10 -0
  69. package/dist/visual-editing/origin.d.ts.map +1 -0
  70. package/dist/visual-editing/origin.js +37 -0
  71. package/dist/visual-editing/origin.js.map +1 -0
  72. package/dist/visual-editing/overlay.d.ts +13 -0
  73. package/dist/visual-editing/overlay.d.ts.map +1 -0
  74. package/dist/visual-editing/overlay.js +107 -0
  75. package/dist/visual-editing/overlay.js.map +1 -0
  76. package/dist/visual-editing/protocol.d.ts +83 -0
  77. package/dist/visual-editing/protocol.d.ts.map +1 -0
  78. package/dist/visual-editing/protocol.js +170 -0
  79. package/dist/visual-editing/protocol.js.map +1 -0
  80. package/package.json +13 -4
  81. package/skills/crafty-cms/SKILL.md +15 -1
  82. package/skills/crafty-cms/references/mcp-configuration.md +7 -0
  83. package/skills/crafty-cms/references/sdk-development.md +13 -1
  84. package/skills/crafty-cms/references/visual-editor.md +297 -0
@@ -0,0 +1,63 @@
1
+ import { MARKED_SELECTOR, readMarkedField, refKey } from "./markers.js";
2
+ /**
3
+ * Plain-text live preview. Values are written with `textContent` (never HTML),
4
+ * and each element's own original text is kept so a reset restores exactly what
5
+ * the site rendered, even for elements rendered after the value was set.
6
+ */
7
+ export function createLivePreview(root) {
8
+ const values = new Map();
9
+ const originals = new Map();
10
+ const matching = (key) => Array.from(root.querySelectorAll(MARKED_SELECTOR)).filter((element) => {
11
+ const field = readMarkedField(element);
12
+ return field !== null && refKey(field) === key;
13
+ });
14
+ const write = (element, value) => {
15
+ if (!originals.has(element)) {
16
+ originals.set(element, element.textContent ?? "");
17
+ }
18
+ if (element.textContent !== value) {
19
+ element.textContent = value;
20
+ }
21
+ };
22
+ const restore = (key) => {
23
+ for (const [element, original] of originals) {
24
+ const field = readMarkedField(element);
25
+ if (key === null || (field !== null && refKey(field) === key)) {
26
+ if (element.textContent !== original) {
27
+ element.textContent = original;
28
+ }
29
+ originals.delete(element);
30
+ }
31
+ }
32
+ };
33
+ return {
34
+ set(ref, value) {
35
+ const key = refKey(ref);
36
+ values.set(key, value);
37
+ matching(key).forEach((element) => write(element, value));
38
+ },
39
+ reset(ref) {
40
+ const key = refKey(ref);
41
+ values.delete(key);
42
+ restore(key);
43
+ },
44
+ reapply() {
45
+ for (const element of [...originals.keys()]) {
46
+ if (!element.isConnected) {
47
+ originals.delete(element);
48
+ }
49
+ }
50
+ for (const [key, value] of values) {
51
+ matching(key).forEach((element) => write(element, value));
52
+ }
53
+ },
54
+ resetAll() {
55
+ values.clear();
56
+ restore(null);
57
+ },
58
+ get size() {
59
+ return values.size;
60
+ }
61
+ };
62
+ }
63
+ //# sourceMappingURL=live-preview.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live-preview.js","sourceRoot":"","sources":["../../src/visual-editing/live-preview.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { type CraftyFieldRef, type CraftyMarkedField } from "./protocol.js";
2
+ export declare const MARKED_SELECTOR = "[data-crafty-field]";
3
+ export type MarkedElement = {
4
+ element: Element;
5
+ field: CraftyMarkedField;
6
+ };
7
+ export declare function readMarkedField(element: Element): CraftyMarkedField | null;
8
+ export declare function refKey(ref: CraftyFieldRef): string;
9
+ export declare function scanMarked(root: ParentNode): MarkedElement[];
10
+ export declare function uniqueFields(marked: MarkedElement[]): CraftyMarkedField[];
11
+ //# sourceMappingURL=markers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markers.d.ts","sourceRoot":"","sources":["../../src/visual-editing/markers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,cAAc,EAAE,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAE9F,eAAO,MAAM,eAAe,wBAAwB,CAAC;AAErD,MAAM,MAAM,aAAa,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,iBAAiB,CAAA;CAAE,CAAC;AAE3E,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,iBAAiB,GAAG,IAAI,CAiB1E;AAED,wBAAgB,MAAM,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,CAElD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,aAAa,EAAE,CAY5D;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,iBAAiB,EAAE,CAczE"}
@@ -0,0 +1,44 @@
1
+ import { parseMarkedField } from "./protocol.js";
2
+ export const MARKED_SELECTOR = "[data-crafty-field]";
3
+ export function readMarkedField(element) {
4
+ const blockId = element.getAttribute("data-crafty-block");
5
+ const entryId = element.getAttribute("data-crafty-entry");
6
+ const rawId = blockId ?? entryId;
7
+ if (rawId === null) {
8
+ return null;
9
+ }
10
+ return parseMarkedField({
11
+ type: blockId !== null ? "block" : "entry",
12
+ id: rawId.trim() === "" ? Number.NaN : Number(rawId),
13
+ field: element.getAttribute("data-crafty-field") ?? "",
14
+ label: element.getAttribute("data-crafty-label"),
15
+ hrefField: element.getAttribute("data-crafty-href-field"),
16
+ hrefLabel: element.getAttribute("data-crafty-href-label")
17
+ });
18
+ }
19
+ export function refKey(ref) {
20
+ return `${ref.type}:${ref.id}:${ref.field}`;
21
+ }
22
+ export function scanMarked(root) {
23
+ const marked = [];
24
+ root.querySelectorAll(MARKED_SELECTOR).forEach((element) => {
25
+ const field = readMarkedField(element);
26
+ if (field !== null) {
27
+ marked.push({ element, field });
28
+ }
29
+ });
30
+ return marked;
31
+ }
32
+ export function uniqueFields(marked) {
33
+ const seen = new Set();
34
+ const fields = [];
35
+ for (const { field } of marked) {
36
+ const key = refKey(field);
37
+ if (!seen.has(key)) {
38
+ seen.add(key);
39
+ fields.push(field);
40
+ }
41
+ }
42
+ return fields;
43
+ }
44
+ //# sourceMappingURL=markers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markers.js","sourceRoot":"","sources":["../../src/visual-editing/markers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAA+C,MAAM,eAAe,CAAC;AAE9F,MAAM,CAAC,MAAM,eAAe,GAAG,qBAAqB,CAAC;AAIrD,MAAM,UAAU,eAAe,CAAC,OAAgB;IAC9C,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC,mBAAmB,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC,mBAAmB,CAAC,CAAC;IAC1D,MAAM,KAAK,GAAG,OAAO,IAAI,OAAO,CAAC;IAEjC,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,gBAAgB,CAAC;QACtB,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO;QAC1C,EAAE,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;QACpD,KAAK,EAAE,OAAO,CAAC,YAAY,CAAC,mBAAmB,CAAC,IAAI,EAAE;QACtD,KAAK,EAAE,OAAO,CAAC,YAAY,CAAC,mBAAmB,CAAC;QAChD,SAAS,EAAE,OAAO,CAAC,YAAY,CAAC,wBAAwB,CAAC;QACzD,SAAS,EAAE,OAAO,CAAC,YAAY,CAAC,wBAAwB,CAAC;KAC1D,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,GAAmB;IACxC,OAAO,GAAG,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAgB;IACzC,MAAM,MAAM,GAAoB,EAAE,CAAC;IAEnC,IAAI,CAAC,gBAAgB,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QACzD,MAAM,KAAK,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;QAEvC,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAClC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAuB;IAClD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,MAAM,GAAwB,EAAE,CAAC;IAEvC,KAAK,MAAM,EAAE,KAAK,EAAE,IAAI,MAAM,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAE1B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACnB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACd,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,10 @@
1
+ /** Crafty admin panels: https://crafty.do and https://<tenant>.crafty.do. */
2
+ export declare const DEFAULT_ADMIN_ORIGINS: ReadonlyArray<string | RegExp>;
3
+ export declare function isAllowedAdminOrigin(origin: string, allowlist: ReadonlyArray<string | RegExp>): boolean;
4
+ /**
5
+ * Origin of the embedding admin. `ancestorOrigins` (Chromium, WebKit) cannot be
6
+ * spoofed by the framed page; Firefox falls back to the referrer the admin sent
7
+ * when it set the iframe `src`.
8
+ */
9
+ export declare function resolveParentOrigin(win: Window): string | null;
10
+ //# sourceMappingURL=origin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"origin.d.ts","sourceRoot":"","sources":["../../src/visual-editing/origin.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,eAAO,MAAM,qBAAqB,EAAE,aAAa,CAAC,MAAM,GAAG,MAAM,CAA6C,CAAC;AAU/G,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,OAAO,CAcvG;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAW9D"}
@@ -0,0 +1,37 @@
1
+ /** Crafty admin panels: https://crafty.do and https://<tenant>.crafty.do. */
2
+ export const DEFAULT_ADMIN_ORIGINS = [/^https:\/\/([a-z0-9-]+\.)*crafty\.do$/];
3
+ function originOf(value) {
4
+ try {
5
+ return new URL(value).origin;
6
+ }
7
+ catch {
8
+ return null;
9
+ }
10
+ }
11
+ export function isAllowedAdminOrigin(origin, allowlist) {
12
+ if (origin === "" || origin === "null") {
13
+ return false;
14
+ }
15
+ return allowlist.some((allowed) => {
16
+ if (typeof allowed === "string") {
17
+ return originOf(allowed) === origin;
18
+ }
19
+ allowed.lastIndex = 0;
20
+ return allowed.test(origin);
21
+ });
22
+ }
23
+ /**
24
+ * Origin of the embedding admin. `ancestorOrigins` (Chromium, WebKit) cannot be
25
+ * spoofed by the framed page; Firefox falls back to the referrer the admin sent
26
+ * when it set the iframe `src`.
27
+ */
28
+ export function resolveParentOrigin(win) {
29
+ const ancestors = win.location.ancestorOrigins;
30
+ const first = ancestors && ancestors.length > 0 ? ancestors[0] : undefined;
31
+ if (typeof first === "string" && first !== "") {
32
+ return first;
33
+ }
34
+ const referrer = win.document.referrer;
35
+ return referrer ? originOf(referrer) : null;
36
+ }
37
+ //# sourceMappingURL=origin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"origin.js","sourceRoot":"","sources":["../../src/visual-editing/origin.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,MAAM,CAAC,MAAM,qBAAqB,GAAmC,CAAC,uCAAuC,CAAC,CAAC;AAE/G,SAAS,QAAQ,CAAC,KAAa;IAC7B,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,MAAc,EAAE,SAAyC;IAC5F,IAAI,MAAM,KAAK,EAAE,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACvC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE;QAChC,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAChC,OAAO,QAAQ,CAAC,OAAO,CAAC,KAAK,MAAM,CAAC;QACtC,CAAC;QAED,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC;QAEtB,OAAO,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,GAAW;IAC7C,MAAM,SAAS,GAAG,GAAG,CAAC,QAAQ,CAAC,eAAgD,CAAC;IAChF,MAAM,KAAK,GAAG,SAAS,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAE3E,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;QAC9C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC;IAEvC,OAAO,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,13 @@
1
+ export declare const FLASH_CLASS = "crafty-ve-flash";
2
+ export type Overlay = {
3
+ show(element: Element, label: string): void;
4
+ hide(): void;
5
+ /** Re-measures the highlighted element, e.g. after its content changed. */
6
+ reposition(): void;
7
+ flash(elements: Element[], durationMs: number): void;
8
+ ensureAttached(): void;
9
+ contains(node: Node | null): boolean;
10
+ destroy(): void;
11
+ };
12
+ export declare function createOverlay(doc: Document): Overlay;
13
+ //# sourceMappingURL=overlay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../../src/visual-editing/overlay.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,WAAW,oBAAoB,CAAC;AAU7C,MAAM,MAAM,OAAO,GAAG;IACpB,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C,IAAI,IAAI,IAAI,CAAC;IACb,2EAA2E;IAC3E,UAAU,IAAI,IAAI,CAAC;IACnB,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACrD,cAAc,IAAI,IAAI,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,OAAO,CAAC;IACrC,OAAO,IAAI,IAAI,CAAC;CACjB,CAAC;AAEF,wBAAgB,aAAa,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAiHpD"}
@@ -0,0 +1,107 @@
1
+ const STYLE_ELEMENT_ID = "crafty-visual-editing-style";
2
+ const ACCENT = "#4f46e5";
3
+ export const FLASH_CLASS = "crafty-ve-flash";
4
+ const STYLES = [
5
+ "[data-crafty-field]{cursor:pointer}",
6
+ `.crafty-ve-box{position:fixed;top:0;left:0;pointer-events:none;z-index:2147483647;box-sizing:border-box;border:2px solid ${ACCENT};border-radius:4px;background:rgba(79,70,229,.06)}`,
7
+ ".crafty-ve-box[hidden]{display:none}",
8
+ `.crafty-ve-label{position:absolute;left:-2px;bottom:100%;margin-bottom:4px;padding:2px 8px;max-width:320px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border-radius:4px;background:${ACCENT};color:#fff;font:500 12px/1.5 system-ui,-apple-system,sans-serif}`,
9
+ `.${FLASH_CLASS}{outline:2px dashed ${ACCENT} !important;outline-offset:2px !important}`
10
+ ].join("\n");
11
+ export function createOverlay(doc) {
12
+ const win = doc.defaultView;
13
+ const style = doc.createElement("style");
14
+ style.id = STYLE_ELEMENT_ID;
15
+ style.textContent = STYLES;
16
+ const box = doc.createElement("div");
17
+ box.setAttribute("data-crafty-overlay", "");
18
+ box.className = "crafty-ve-box";
19
+ box.hidden = true;
20
+ const label = doc.createElement("span");
21
+ label.className = "crafty-ve-label";
22
+ box.appendChild(label);
23
+ let target = null;
24
+ let flashed = [];
25
+ let flashTimer;
26
+ const Observer = win?.ResizeObserver;
27
+ const place = () => {
28
+ if (target === null) {
29
+ return;
30
+ }
31
+ const rect = target.getBoundingClientRect();
32
+ box.style.top = `${rect.top}px`;
33
+ box.style.left = `${rect.left}px`;
34
+ box.style.width = `${rect.width}px`;
35
+ box.style.height = `${rect.height}px`;
36
+ };
37
+ const resizeObserver = typeof Observer === "function" ? new Observer(() => place()) : null;
38
+ const track = (element) => {
39
+ if (target === element) {
40
+ return;
41
+ }
42
+ if (target !== null) {
43
+ resizeObserver?.unobserve(target);
44
+ }
45
+ target = element;
46
+ if (target !== null) {
47
+ resizeObserver?.observe(target);
48
+ }
49
+ };
50
+ const clearFlash = () => {
51
+ flashed.forEach((element) => element.classList.remove(FLASH_CLASS));
52
+ flashed = [];
53
+ if (flashTimer !== undefined) {
54
+ win?.clearTimeout(flashTimer);
55
+ flashTimer = undefined;
56
+ }
57
+ };
58
+ const ensureAttached = () => {
59
+ if (!style.isConnected) {
60
+ (doc.head ?? doc.documentElement).appendChild(style);
61
+ }
62
+ if (!box.isConnected) {
63
+ (doc.body ?? doc.documentElement).appendChild(box);
64
+ }
65
+ };
66
+ ensureAttached();
67
+ win?.addEventListener("scroll", place, { capture: true, passive: true });
68
+ win?.addEventListener("resize", place, { passive: true });
69
+ return {
70
+ show(element, text) {
71
+ ensureAttached();
72
+ track(element);
73
+ if (label.textContent !== text) {
74
+ label.textContent = text;
75
+ }
76
+ box.hidden = false;
77
+ place();
78
+ },
79
+ hide() {
80
+ track(null);
81
+ box.hidden = true;
82
+ },
83
+ reposition() {
84
+ place();
85
+ },
86
+ flash(elements, durationMs) {
87
+ clearFlash();
88
+ flashed = [...elements];
89
+ flashed.forEach((element) => element.classList.add(FLASH_CLASS));
90
+ flashTimer = win?.setTimeout(clearFlash, durationMs);
91
+ },
92
+ ensureAttached,
93
+ contains(node) {
94
+ return node !== null && (box === node || box.contains(node) || style === node || style.contains(node));
95
+ },
96
+ destroy() {
97
+ clearFlash();
98
+ win?.removeEventListener("scroll", place, { capture: true });
99
+ win?.removeEventListener("resize", place);
100
+ resizeObserver?.disconnect();
101
+ box.remove();
102
+ style.remove();
103
+ target = null;
104
+ }
105
+ };
106
+ }
107
+ //# sourceMappingURL=overlay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overlay.js","sourceRoot":"","sources":["../../src/visual-editing/overlay.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ export declare const PROTOCOL_VERSION = 1;
2
+ export type CraftyTargetType = "block" | "entry";
3
+ export type CraftyFieldRef = {
4
+ type: CraftyTargetType;
5
+ id: number;
6
+ field: string;
7
+ };
8
+ /** `hrefField` is the field with the link destination of the same element (same target). */
9
+ export type CraftyMarkedField = CraftyFieldRef & {
10
+ label?: string;
11
+ hrefField?: string;
12
+ hrefLabel?: string;
13
+ };
14
+ export type CraftyShownPage = {
15
+ id: number;
16
+ slug: string;
17
+ };
18
+ export type CraftyShownEntry = {
19
+ id: number;
20
+ collection: string;
21
+ };
22
+ export type ReadyPayload = {
23
+ sdkVersion: string;
24
+ path: string;
25
+ fields: CraftyMarkedField[];
26
+ page: CraftyShownPage | null;
27
+ entries: CraftyShownEntry[];
28
+ };
29
+ type Version = typeof PROTOCOL_VERSION;
30
+ type EmptyPayload = Record<string, never>;
31
+ /** iframe -> admin. `crafty:ready` is a snapshot that may be re-sent; the last one wins. */
32
+ export type OutboundMessage = {
33
+ v: Version;
34
+ type: "crafty:ready";
35
+ payload: ReadyPayload;
36
+ } | {
37
+ v: Version;
38
+ type: "crafty:select";
39
+ payload: CraftyMarkedField;
40
+ } | {
41
+ v: Version;
42
+ type: "crafty:navigate";
43
+ payload: {
44
+ path: string;
45
+ };
46
+ } | {
47
+ v: Version;
48
+ type: "crafty:preview-invalid";
49
+ payload: EmptyPayload;
50
+ };
51
+ /** admin -> iframe. */
52
+ export type InboundMessage = {
53
+ v: Version;
54
+ type: "crafty:token";
55
+ payload: {
56
+ token: string;
57
+ };
58
+ } | {
59
+ v: Version;
60
+ type: "crafty:refresh";
61
+ payload: EmptyPayload;
62
+ } | {
63
+ v: Version;
64
+ type: "crafty:highlight";
65
+ payload: CraftyFieldRef;
66
+ } | {
67
+ v: Version;
68
+ type: "crafty:preview-field";
69
+ payload: CraftyFieldRef & {
70
+ value: string;
71
+ };
72
+ } | {
73
+ v: Version;
74
+ type: "crafty:preview-reset";
75
+ payload: CraftyFieldRef;
76
+ };
77
+ export declare function parseFieldRef(value: unknown): CraftyFieldRef | null;
78
+ /** An invalid `hrefField` is dropped; the text field stays selectable. */
79
+ export declare function parseMarkedField(value: unknown): CraftyMarkedField | null;
80
+ export declare function parseInboundMessage(data: unknown): InboundMessage | null;
81
+ export declare function parseOutboundMessage(data: unknown): OutboundMessage | null;
82
+ export {};
83
+ //# sourceMappingURL=protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/visual-editing/protocol.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,170 @@
1
+ export const PROTOCOL_VERSION = 1;
2
+ /** Same limits as the Crafty admin and backend (content_drafts.field / label). */
3
+ const MAX_FIELD_LENGTH = 255;
4
+ const MAX_LABEL_LENGTH = 120;
5
+ const MAX_TOKEN_LENGTH = 4096;
6
+ const MAX_VALUE_LENGTH = 100_000;
7
+ const MAX_PATH_LENGTH = 2048;
8
+ const FIELD_PATTERN = /^[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+|\[\d+\])*$/;
9
+ const TOKEN_PATTERN = /^[\x21-\x7E]+$/;
10
+ const CONTROL_CHARACTERS = /[\u0000-\u001F\u007F]/;
11
+ const PATH_BASE = "https://crafty.invalid";
12
+ function isRecord(value) {
13
+ return typeof value === "object" && value !== null && !Array.isArray(value);
14
+ }
15
+ function isPositiveInteger(value) {
16
+ return typeof value === "number" && Number.isInteger(value) && value > 0;
17
+ }
18
+ function parseFieldPath(value) {
19
+ if (typeof value !== "string") {
20
+ return null;
21
+ }
22
+ const trimmed = value.trim();
23
+ return trimmed === "" || trimmed.length > MAX_FIELD_LENGTH || !FIELD_PATTERN.test(trimmed) ? null : trimmed;
24
+ }
25
+ function parseLabel(value) {
26
+ return typeof value === "string" ? value.trim().slice(0, MAX_LABEL_LENGTH).trim() : "";
27
+ }
28
+ export function parseFieldRef(value) {
29
+ if (!isRecord(value)) {
30
+ return null;
31
+ }
32
+ const { type, id } = value;
33
+ const field = parseFieldPath(value.field);
34
+ if ((type !== "block" && type !== "entry") || !isPositiveInteger(id) || field === null) {
35
+ return null;
36
+ }
37
+ return { type, id, field };
38
+ }
39
+ /** An invalid `hrefField` is dropped; the text field stays selectable. */
40
+ export function parseMarkedField(value) {
41
+ const ref = parseFieldRef(value);
42
+ if (ref === null || !isRecord(value)) {
43
+ return null;
44
+ }
45
+ const marked = { ...ref };
46
+ const label = parseLabel(value.label);
47
+ const hrefField = parseFieldPath(value.hrefField);
48
+ if (label !== "") {
49
+ marked.label = label;
50
+ }
51
+ if (hrefField !== null) {
52
+ marked.hrefField = hrefField;
53
+ const hrefLabel = parseLabel(value.hrefLabel);
54
+ if (hrefLabel !== "") {
55
+ marked.hrefLabel = hrefLabel;
56
+ }
57
+ }
58
+ return marked;
59
+ }
60
+ function isSameOriginPath(value) {
61
+ if (!value.startsWith("/") || value.startsWith("//") || value.startsWith("/\\")) {
62
+ return false;
63
+ }
64
+ try {
65
+ const url = new URL(value, PATH_BASE);
66
+ // Dot segments can still resolve to a protocol-relative path ("/.//evil.example").
67
+ return url.origin === PATH_BASE && !url.pathname.startsWith("//") && !url.pathname.startsWith("/\\");
68
+ }
69
+ catch {
70
+ return false;
71
+ }
72
+ }
73
+ function parsePath(value) {
74
+ if (typeof value !== "string" || value.length > MAX_PATH_LENGTH || CONTROL_CHARACTERS.test(value)) {
75
+ return null;
76
+ }
77
+ return isSameOriginPath(value) ? value : null;
78
+ }
79
+ function parseShownEntry(value) {
80
+ return isRecord(value) && isPositiveInteger(value.id) && typeof value.collection === "string"
81
+ ? { id: value.id, collection: value.collection }
82
+ : null;
83
+ }
84
+ function readEnvelope(data) {
85
+ if (!isRecord(data) || data.v !== PROTOCOL_VERSION || typeof data.type !== "string") {
86
+ return null;
87
+ }
88
+ const payload = data.payload === undefined ? {} : data.payload;
89
+ return isRecord(payload) ? { type: data.type, payload } : null;
90
+ }
91
+ export function parseInboundMessage(data) {
92
+ const message = readEnvelope(data);
93
+ if (message === null) {
94
+ return null;
95
+ }
96
+ const { payload } = message;
97
+ switch (message.type) {
98
+ case "crafty:token": {
99
+ const token = typeof payload.token === "string" ? payload.token.trim() : "";
100
+ return token !== "" && token.length <= MAX_TOKEN_LENGTH && TOKEN_PATTERN.test(token)
101
+ ? { v: PROTOCOL_VERSION, type: "crafty:token", payload: { token } }
102
+ : null;
103
+ }
104
+ case "crafty:refresh":
105
+ return { v: PROTOCOL_VERSION, type: "crafty:refresh", payload: {} };
106
+ case "crafty:highlight": {
107
+ const ref = parseFieldRef(payload);
108
+ return ref ? { v: PROTOCOL_VERSION, type: "crafty:highlight", payload: ref } : null;
109
+ }
110
+ case "crafty:preview-field": {
111
+ const ref = parseFieldRef(payload);
112
+ const value = payload.value;
113
+ return ref && typeof value === "string" && value.length <= MAX_VALUE_LENGTH
114
+ ? { v: PROTOCOL_VERSION, type: "crafty:preview-field", payload: { ...ref, value } }
115
+ : null;
116
+ }
117
+ case "crafty:preview-reset": {
118
+ const ref = parseFieldRef(payload);
119
+ return ref ? { v: PROTOCOL_VERSION, type: "crafty:preview-reset", payload: ref } : null;
120
+ }
121
+ default:
122
+ return null;
123
+ }
124
+ }
125
+ export function parseOutboundMessage(data) {
126
+ const message = readEnvelope(data);
127
+ if (message === null) {
128
+ return null;
129
+ }
130
+ const { payload } = message;
131
+ switch (message.type) {
132
+ case "crafty:ready": {
133
+ const path = parsePath(payload.path);
134
+ const rawPage = payload.page;
135
+ if (typeof payload.sdkVersion !== "string" || path === null || !Array.isArray(payload.fields) || !Array.isArray(payload.entries)) {
136
+ return null;
137
+ }
138
+ return {
139
+ v: PROTOCOL_VERSION,
140
+ type: "crafty:ready",
141
+ payload: {
142
+ sdkVersion: payload.sdkVersion,
143
+ path,
144
+ fields: payload.fields
145
+ .map((field) => parseMarkedField(field))
146
+ .filter((field) => field !== null),
147
+ page: isRecord(rawPage) && isPositiveInteger(rawPage.id) && typeof rawPage.slug === "string"
148
+ ? { id: rawPage.id, slug: rawPage.slug }
149
+ : null,
150
+ entries: payload.entries
151
+ .map((entry) => parseShownEntry(entry))
152
+ .filter((entry) => entry !== null)
153
+ }
154
+ };
155
+ }
156
+ case "crafty:select": {
157
+ const field = parseMarkedField(payload);
158
+ return field ? { v: PROTOCOL_VERSION, type: "crafty:select", payload: field } : null;
159
+ }
160
+ case "crafty:navigate": {
161
+ const path = parsePath(payload.path);
162
+ return path ? { v: PROTOCOL_VERSION, type: "crafty:navigate", payload: { path } } : null;
163
+ }
164
+ case "crafty:preview-invalid":
165
+ return { v: PROTOCOL_VERSION, type: "crafty:preview-invalid", payload: {} };
166
+ default:
167
+ return null;
168
+ }
169
+ }
170
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/visual-editing/protocol.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@craftware/crafty-sdk",
3
- "version": "0.2.2",
3
+ "version": "0.4.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -12,7 +12,12 @@
12
12
  ".": {
13
13
  "types": "./dist/index.d.ts",
14
14
  "import": "./dist/index.js"
15
- }
15
+ },
16
+ "./visual-editing": {
17
+ "types": "./dist/visual-editing/index.d.ts",
18
+ "import": "./dist/visual-editing/index.js"
19
+ },
20
+ "./package.json": "./package.json"
16
21
  },
17
22
  "main": "./dist/index.js",
18
23
  "module": "./dist/index.js",
@@ -25,14 +30,18 @@
25
30
  "node": ">=20"
26
31
  },
27
32
  "scripts": {
28
- "build": "tsc -p tsconfig.json",
33
+ "build": "node scripts/write-version.mjs && tsc -p tsconfig.json && node scripts/build-cdn.mjs",
29
34
  "typecheck": "tsc -p tsconfig.json --noEmit",
35
+ "test": "npm run build && vitest run",
30
36
  "codegen": "node scripts/codegen.mjs",
31
37
  "changeset": "npx -y @changesets/cli@2.29.7",
32
38
  "changeset:add": "npm run changeset -- add",
33
39
  "changeset:version": "npm run changeset -- version"
34
40
  },
35
41
  "devDependencies": {
36
- "typescript": "^5.8.2"
42
+ "esbuild": "^0.28.2",
43
+ "happy-dom": "^20.14.5",
44
+ "typescript": "^5.8.2",
45
+ "vitest": "^4.1.11"
37
46
  }
38
47
  }