@lyads/visual-editor 0.0.0-stage → 1.0.1

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 (258) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/LICENSE +201 -0
  3. package/NOTICE +8 -0
  4. package/README.md +135 -2
  5. package/THIRD_PARTY_NOTICES.md +21259 -0
  6. package/dist/application/block-placement.d.ts +30 -0
  7. package/dist/application/block-session.d.ts +135 -0
  8. package/dist/application/content-service.d.ts +73 -0
  9. package/dist/application/document-commands.d.ts +51 -0
  10. package/dist/application/document-metadata.d.ts +30 -0
  11. package/dist/application/document-presentation.d.ts +35 -0
  12. package/dist/application/email-insertion.d.ts +76 -0
  13. package/dist/application/host.d.ts +36 -0
  14. package/dist/application/image-link.d.ts +36 -0
  15. package/dist/application/section-layout.d.ts +25 -0
  16. package/dist/application/session.d.ts +128 -0
  17. package/dist/assets/browser-worker-D56tNvnb.js +1014 -0
  18. package/dist/assets/browser-worker-D56tNvnb.js.map +1 -0
  19. package/dist/block-controller-RjYGvOcn.js +2468 -0
  20. package/dist/block-controller-RjYGvOcn.js.map +1 -0
  21. package/dist/block-factory-C5oHi4Fm.js +5397 -0
  22. package/dist/block-factory-C5oHi4Fm.js.map +1 -0
  23. package/dist/blocks/block-checks.d.ts +34 -0
  24. package/dist/blocks/block-inspector.d.ts +55 -0
  25. package/dist/blocks/block-output.d.ts +28 -0
  26. package/dist/blocks/block-type.d.ts +124 -0
  27. package/dist/blocks/content-guard.d.ts +52 -0
  28. package/dist/blocks/conversion.d.ts +22 -0
  29. package/dist/blocks/definitions.d.ts +43 -0
  30. package/dist/blocks/device-styles.d.ts +31 -0
  31. package/dist/blocks/email-generator.d.ts +22 -0
  32. package/dist/blocks/email-preview.d.ts +23 -0
  33. package/dist/blocks/email-renderer.d.ts +20 -0
  34. package/dist/blocks/fields.d.ts +34 -0
  35. package/dist/blocks/page-generator.d.ts +16 -0
  36. package/dist/blocks/render-context.d.ts +58 -0
  37. package/dist/blocks/styles.d.ts +54 -0
  38. package/dist/blocks/types/embed.d.ts +40 -0
  39. package/dist/blocks/types/layout.d.ts +41 -0
  40. package/dist/blocks/types/media.d.ts +53 -0
  41. package/dist/blocks/types/structure.d.ts +44 -0
  42. package/dist/blocks/types/text.d.ts +88 -0
  43. package/dist/blocks/values.d.ts +64 -0
  44. package/dist/browser.js +69 -0
  45. package/dist/browser.js.map +1 -0
  46. package/dist/canvas-runtime/action-bar.d.ts +19 -0
  47. package/dist/canvas-runtime/auto-scroll.d.ts +10 -0
  48. package/dist/canvas-runtime/block-drag.d.ts +29 -0
  49. package/dist/canvas-runtime/bridge.d.ts +6 -0
  50. package/dist/canvas-runtime/context.d.ts +53 -0
  51. package/dist/canvas-runtime/document-sync.d.ts +21 -0
  52. package/dist/canvas-runtime/drop-targets.d.ts +34 -0
  53. package/dist/canvas-runtime/embed-markers.d.ts +15 -0
  54. package/dist/canvas-runtime/file-guard.d.ts +12 -0
  55. package/dist/canvas-runtime/image-tools.d.ts +31 -0
  56. package/dist/canvas-runtime/keyboard.d.ts +18 -0
  57. package/dist/canvas-runtime/main.d.ts +1 -0
  58. package/dist/canvas-runtime/messages.d.ts +26 -0
  59. package/dist/canvas-runtime/morph.d.ts +21 -0
  60. package/dist/canvas-runtime/navigation.d.ts +29 -0
  61. package/dist/canvas-runtime/overlay.d.ts +15 -0
  62. package/dist/canvas-runtime/pointer-intents.d.ts +14 -0
  63. package/dist/canvas-runtime/selection-layer.d.ts +16 -0
  64. package/dist/canvas-runtime/shared/shortcuts.d.ts +27 -0
  65. package/dist/canvas-runtime/text-editor.d.ts +55 -0
  66. package/dist/canvas-runtime/text-session.d.ts +39 -0
  67. package/dist/canvas-runtime/variable-marks.d.ts +20 -0
  68. package/dist/canvas-runtime/viewport.d.ts +10 -0
  69. package/dist/codecs/css.d.ts +74 -0
  70. package/dist/codecs/html.d.ts +81 -0
  71. package/dist/compilation/browser-compiler.d.ts +14 -0
  72. package/dist/compilation/browser-worker.d.ts +1 -0
  73. package/dist/compilation/compile-lanes.d.ts +18 -0
  74. package/dist/compilation/generated-mjml.d.ts +25 -0
  75. package/dist/compilation/guard.d.ts +40 -0
  76. package/dist/compilation/node-compiler.d.ts +17 -0
  77. package/dist/compilation/node-worker.d.ts +1 -0
  78. package/dist/composition/block-factory.d.ts +84 -0
  79. package/dist/composition/browser.d.ts +48 -0
  80. package/dist/composition/factory.d.ts +48 -0
  81. package/dist/composition/server.d.ts +43 -0
  82. package/dist/core/any-document.d.ts +16 -0
  83. package/dist/core/block-document.d.ts +215 -0
  84. package/dist/core/budget.d.ts +32 -0
  85. package/dist/core/canvas-contract.d.ts +29 -0
  86. package/dist/core/canvas-layout.d.ts +66 -0
  87. package/dist/core/catalog.d.ts +35 -0
  88. package/dist/core/document-presentation.d.ts +21 -0
  89. package/dist/core/document.d.ts +99 -0
  90. package/dist/core/history.d.ts +26 -0
  91. package/dist/core/html-content-model.d.ts +32 -0
  92. package/dist/core/html-escape.d.ts +2 -0
  93. package/dist/core/rich-text-format.d.ts +14 -0
  94. package/dist/core/rich-text-markup.d.ts +28 -0
  95. package/dist/core/section-layout.d.ts +83 -0
  96. package/dist/generated-mjml-CtzE-f3v.js +1235 -0
  97. package/dist/generated-mjml-CtzE-f3v.js.map +1 -0
  98. package/dist/identity-CJHb6l9N.js +13759 -0
  99. package/dist/identity-CJHb6l9N.js.map +1 -0
  100. package/dist/renderers/canvas-bridge.d.ts +75 -0
  101. package/dist/renderers/canvas-icons.d.ts +1 -0
  102. package/dist/renderers/canvas-runtime.generated.d.ts +3 -0
  103. package/dist/renderers/element-source.d.ts +13 -0
  104. package/dist/renderers/email-renderer.d.ts +14 -0
  105. package/dist/renderers/marked-preview.d.ts +34 -0
  106. package/dist/renderers/markup-tree.d.ts +36 -0
  107. package/dist/renderers/page-renderer.d.ts +15 -0
  108. package/dist/renderers/preview-document.d.ts +39 -0
  109. package/dist/renderers/preview-frame.d.ts +102 -0
  110. package/dist/renderers/section-scaffold.d.ts +16 -0
  111. package/dist/renderers/selection-preview.d.ts +47 -0
  112. package/dist/rich-text/command-executor.d.ts +26 -0
  113. package/dist/rich-text/commands.d.ts +36 -0
  114. package/dist/rich-text/document-builder.d.ts +52 -0
  115. package/dist/rich-text/formatting.d.ts +17 -0
  116. package/dist/rich-text/projection-export.d.ts +17 -0
  117. package/dist/rich-text/projection-rules.d.ts +13 -0
  118. package/dist/rich-text/schema.d.ts +50 -0
  119. package/dist/rich-text/whitespace.d.ts +7 -0
  120. package/dist/security/bounded-parser.d.ts +18 -0
  121. package/dist/security/conditional-comment.d.ts +30 -0
  122. package/dist/security/content-inventory.d.ts +78 -0
  123. package/dist/security/email-sanitizer.d.ts +36 -0
  124. package/dist/security/identity.d.ts +6 -0
  125. package/dist/security/markup-rules.d.ts +31 -0
  126. package/dist/security/policy.d.ts +61 -0
  127. package/dist/security/preview-message.d.ts +317 -0
  128. package/dist/security/rich-text-projection.d.ts +19 -0
  129. package/dist/security/sha256.d.ts +6 -0
  130. package/dist/security/source-markup.d.ts +53 -0
  131. package/dist/security/text-presentation.d.ts +19 -0
  132. package/dist/security/url-policy.d.ts +23 -0
  133. package/dist/server-worker.js +17 -0
  134. package/dist/server-worker.js.map +1 -0
  135. package/dist/server.js +79 -0
  136. package/dist/server.js.map +1 -0
  137. package/dist/templates/blank-email.d.ts +6 -0
  138. package/dist/templates/blocks/catalog.d.ts +31 -0
  139. package/dist/templates/catalog.d.ts +31 -0
  140. package/dist/visual-editor.css +2 -0
  141. package/dist/vue/block-controller.d.ts +106 -0
  142. package/dist/vue/block-workbench.d.ts +70 -0
  143. package/dist/vue/canvas/canvas-theme.d.ts +8 -0
  144. package/dist/vue/canvas/file-drop.d.ts +38 -0
  145. package/dist/vue/canvas/frame-window.d.ts +26 -0
  146. package/dist/vue/canvas/inline-text.d.ts +98 -0
  147. package/dist/vue/canvas/palette-drag.d.ts +55 -0
  148. package/dist/vue/canvas/piece-requests.d.ts +48 -0
  149. package/dist/vue/canvas/strip-reserve.d.ts +14 -0
  150. package/dist/vue/canvas-content-label.d.ts +5 -0
  151. package/dist/vue/components/BlockVisualEditor.vue.d.ts +44 -0
  152. package/dist/vue/components/CanvasSurface.vue.d.ts +11 -0
  153. package/dist/vue/components/CodeEditor.vue.d.ts +22 -0
  154. package/dist/vue/components/EditorBlockMenus.vue.d.ts +3 -0
  155. package/dist/vue/components/EditorBlockPalette.vue.d.ts +3 -0
  156. package/dist/vue/components/EditorDiagnostics.vue.d.ts +3 -0
  157. package/dist/vue/components/EditorDialogs.vue.d.ts +16 -0
  158. package/dist/vue/components/EditorDocumentMetadata.vue.d.ts +3 -0
  159. package/dist/vue/components/EditorDocumentStyles.vue.d.ts +15 -0
  160. package/dist/vue/components/EditorImageSizeControls.vue.d.ts +23 -0
  161. package/dist/vue/components/EditorLayoutControls.vue.d.ts +16 -0
  162. package/dist/vue/components/EditorLeftPanel.vue.d.ts +3 -0
  163. package/dist/vue/components/EditorNoticeIndicator.vue.d.ts +3 -0
  164. package/dist/vue/components/EditorPreview.vue.d.ts +8 -0
  165. package/dist/vue/components/EditorProperties.vue.d.ts +14 -0
  166. package/dist/vue/components/EditorRichTextControls.vue.d.ts +25 -0
  167. package/dist/vue/components/EditorSelectionPath.vue.d.ts +11 -0
  168. package/dist/vue/components/EditorShortcutHelp.vue.d.ts +3 -0
  169. package/dist/vue/components/EditorSourcePane.vue.d.ts +3 -0
  170. package/dist/vue/components/EditorStructureTree.vue.d.ts +3 -0
  171. package/dist/vue/components/EditorTemplateGallery.vue.d.ts +15 -0
  172. package/dist/vue/components/EditorTopBar.vue.d.ts +33 -0
  173. package/dist/vue/components/RichTextEditor.vue.d.ts +47 -0
  174. package/dist/vue/components/SelectionPreviewFrame.vue.d.ts +212 -0
  175. package/dist/vue/components/VisualEditor.vue.d.ts +53 -0
  176. package/dist/vue/components/blocks/BlockCanvas.vue.d.ts +15 -0
  177. package/dist/vue/components/blocks/BlockFieldControl.vue.d.ts +39 -0
  178. package/dist/vue/components/blocks/BlockGlobalStyles.vue.d.ts +3 -0
  179. package/dist/vue/components/blocks/BlockPalette.vue.d.ts +6 -0
  180. package/dist/vue/components/blocks/BlockProperties.vue.d.ts +5 -0
  181. package/dist/vue/components/blocks/BlockReview.vue.d.ts +5 -0
  182. package/dist/vue/components/properties/EditorPropertyAdvanced.vue.d.ts +8 -0
  183. package/dist/vue/components/properties/EditorPropertyContent.vue.d.ts +13 -0
  184. package/dist/vue/components/properties/EditorPropertyStyle.vue.d.ts +8 -0
  185. package/dist/vue/components/ui/EditorAnchoredMenu.vue.d.ts +36 -0
  186. package/dist/vue/components/ui/EditorBadge.vue.d.ts +18 -0
  187. package/dist/vue/components/ui/EditorButton.vue.d.ts +28 -0
  188. package/dist/vue/components/ui/EditorCheckbox.vue.d.ts +13 -0
  189. package/dist/vue/components/ui/EditorColorInput.vue.d.ts +27 -0
  190. package/dist/vue/components/ui/EditorConfirmDialog.vue.d.ts +35 -0
  191. package/dist/vue/components/ui/EditorContextMenu.vue.d.ts +27 -0
  192. package/dist/vue/components/ui/EditorContextPopover.vue.d.ts +33 -0
  193. package/dist/vue/components/ui/EditorEmpty.vue.d.ts +8 -0
  194. package/dist/vue/components/ui/EditorField.vue.d.ts +24 -0
  195. package/dist/vue/components/ui/EditorGroup.vue.d.ts +16 -0
  196. package/dist/vue/components/ui/EditorIcon.vue.d.ts +6 -0
  197. package/dist/vue/components/ui/EditorIconButton.vue.d.ts +19 -0
  198. package/dist/vue/components/ui/EditorInput.vue.d.ts +41 -0
  199. package/dist/vue/components/ui/EditorKeys.vue.d.ts +6 -0
  200. package/dist/vue/components/ui/EditorMeasurement.vue.d.ts +34 -0
  201. package/dist/vue/components/ui/EditorMenu.vue.d.ts +56 -0
  202. package/dist/vue/components/ui/EditorNotice.vue.d.ts +30 -0
  203. package/dist/vue/components/ui/EditorPropertyGroup.vue.d.ts +22 -0
  204. package/dist/vue/components/ui/EditorRecoveryDialog.vue.d.ts +23 -0
  205. package/dist/vue/components/ui/EditorScrollArea.vue.d.ts +13 -0
  206. package/dist/vue/components/ui/EditorSelect.vue.d.ts +25 -0
  207. package/dist/vue/components/ui/EditorSeparator.vue.d.ts +8 -0
  208. package/dist/vue/components/ui/EditorSidePanel.vue.d.ts +26 -0
  209. package/dist/vue/components/ui/EditorSwitch.vue.d.ts +12 -0
  210. package/dist/vue/components/ui/EditorTabs.vue.d.ts +28 -0
  211. package/dist/vue/components/ui/EditorTemplatePreview.vue.d.ts +9 -0
  212. package/dist/vue/components/ui/EditorTextToolbar.vue.d.ts +16 -0
  213. package/dist/vue/components/ui/EditorTree.vue.d.ts +37 -0
  214. package/dist/vue/components/ui/EditorUiProvider.vue.d.ts +13 -0
  215. package/dist/vue/components/ui/EditorVariablePicker.vue.d.ts +20 -0
  216. package/dist/vue/components/ui/color-style-value.d.ts +9 -0
  217. package/dist/vue/components/ui/composition-dismissal.d.ts +1 -0
  218. package/dist/vue/components/ui/editor-dialog-focus.d.ts +6 -0
  219. package/dist/vue/components/ui/numeric-style-value.d.ts +15 -0
  220. package/dist/vue/controller.d.ts +115 -0
  221. package/dist/vue/font-options.d.ts +6 -0
  222. package/dist/vue/icon-data.d.ts +233 -0
  223. package/dist/vue/icons.d.ts +5 -0
  224. package/dist/vue/locale.d.ts +7 -0
  225. package/dist/vue/outline.d.ts +26 -0
  226. package/dist/vue/projection-key.d.ts +7 -0
  227. package/dist/vue/properties/selection-properties.d.ts +40 -0
  228. package/dist/vue/properties/style-fields.d.ts +30 -0
  229. package/dist/vue/public.d.ts +14 -0
  230. package/dist/vue/recovery.d.ts +30 -0
  231. package/dist/vue/responsive-panel.d.ts +1 -0
  232. package/dist/vue/rich-text-commands.d.ts +29 -0
  233. package/dist/vue/services/block-command-definitions.d.ts +14 -0
  234. package/dist/vue/services/block-commands.d.ts +114 -0
  235. package/dist/vue/services/block-menu.d.ts +12 -0
  236. package/dist/vue/services/block-palette.d.ts +21 -0
  237. package/dist/vue/services/block-presentation.d.ts +16 -0
  238. package/dist/vue/services/diagnostic-groups.d.ts +25 -0
  239. package/dist/vue/services/image-requests.d.ts +80 -0
  240. package/dist/vue/services/live-change.d.ts +26 -0
  241. package/dist/vue/services/property-commands.d.ts +28 -0
  242. package/dist/vue/services/saved-blocks.d.ts +32 -0
  243. package/dist/vue/services/selection-path.d.ts +20 -0
  244. package/dist/vue/services/shortcuts.d.ts +39 -0
  245. package/dist/vue/services/structure-tree.d.ts +38 -0
  246. package/dist/vue/services/template-application.d.ts +33 -0
  247. package/dist/vue/services/tree-drag.d.ts +28 -0
  248. package/dist/vue/session/blocks.d.ts +44 -0
  249. package/dist/vue/session/guard.d.ts +13 -0
  250. package/dist/vue/session/structure.d.ts +36 -0
  251. package/dist/vue/session/text.d.ts +23 -0
  252. package/dist/vue/session/transfer.d.ts +23 -0
  253. package/dist/vue/theme.d.ts +20 -0
  254. package/dist/vue/variables.d.ts +21 -0
  255. package/dist/vue/workbench.d.ts +100 -0
  256. package/dist/vue.js +71418 -0
  257. package/dist/vue.js.map +1 -0
  258. package/package.json +125 -4
@@ -0,0 +1,53 @@
1
+ import { ActiveMarkupRules } from './markup-rules';
2
+ import type { ActiveMarkup } from './markup-rules';
3
+ /** Where a block of source kept as text would be parsed by whoever renders it. */
4
+ export type SourceContext = 'html' | 'svg' | 'math';
5
+ /** The elements whose content the document keeps as source, and how that source is read. */
6
+ export declare const SOURCE_CONTEXTS: Readonly<Record<string, SourceContext>>;
7
+ /** A conditional comment hides markup which Outlook, or an old browser, does render. */
8
+ export declare function isConditionalComment(value: string): boolean;
9
+ /** Active CSS is removed from a style attribute or sheet; absent, styles are left as written. */
10
+ export interface ActiveStyleRemover {
11
+ stripActive(css: string, context?: 'stylesheet' | 'declarationList'): {
12
+ readonly css: string;
13
+ readonly removed: number;
14
+ };
15
+ }
16
+ export interface SourceElement {
17
+ readonly tag: string;
18
+ readonly attrs: Readonly<Record<string, string>>;
19
+ /** Text directly inside the element, e.g. the code of an inline script. */
20
+ readonly text: string;
21
+ }
22
+ export interface StrippedSource {
23
+ readonly source: string;
24
+ readonly removed: readonly ActiveMarkup[];
25
+ }
26
+ /**
27
+ * Reads markup the document keeps as text: conditional comments, `noscript`, `template` and
28
+ * inline SVG or MathML. It is parsed only to be inspected; what is not removed stays byte for
29
+ * byte, because these blocks are often unbalanced fragments no serializer would reproduce.
30
+ */
31
+ export declare class SourceMarkup {
32
+ #private;
33
+ private readonly rules;
34
+ private readonly styles?;
35
+ constructor(rules?: ActiveMarkupRules, styles?: ActiveStyleRemover | undefined);
36
+ /**
37
+ * Every element in the block, nested templates included. Empty when it has too many nodes;
38
+ * throws `DOCUMENT_TOO_DEEP` when it nests beyond the limit of a document.
39
+ */
40
+ elements(source: string, context?: SourceContext): readonly SourceElement[];
41
+ /**
42
+ * Cuts scripts, embeds, inline handlers and code URLs out of the text by their source
43
+ * positions and checks the result again. Undefined when it could not be made clean: the
44
+ * caller then drops the whole block rather than keep something it cannot vouch for.
45
+ */
46
+ strip(source: string, context?: SourceContext): StrippedSource | undefined;
47
+ private cuts;
48
+ /** A style sheet inside the block which holds active CSS leaves whole. */
49
+ private activeSheet;
50
+ private walk;
51
+ private attributes;
52
+ private name;
53
+ }
@@ -0,0 +1,19 @@
1
+ import * as v from 'valibot';
2
+ export declare const TEXT_FONT_FAMILIES: readonly ["Arial", "Georgia", "Verdana", "Tahoma", "Trebuchet MS", "Times New Roman", "Courier New", "system-ui", "sans-serif", "serif", "monospace"];
3
+ export declare const TEXT_STYLE_LIMITS: Readonly<{
4
+ fontSizePx: 160;
5
+ lineHeightPx: 500;
6
+ lineHeightRatio: 10;
7
+ }>;
8
+ /** What a selected block looks like, as bounded numbers and closed names; never CSS text. */
9
+ export declare const TextPresentationStyleSchema: v.StrictObjectSchema<{
10
+ readonly size: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.FiniteAction<number, undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 160, undefined>]>;
11
+ readonly lineHeight: v.UnionSchema<[v.LiteralSchema<"normal", undefined>, v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.FiniteAction<number, undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 500, undefined>]>], undefined>;
12
+ readonly weight: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.FiniteAction<number, undefined>, v.MinValueAction<number, 100, undefined>, v.MaxValueAction<number, 900, undefined>]>;
13
+ readonly color: v.TupleSchema<[v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.FiniteAction<number, undefined>, v.MinValueAction<number, 0, undefined>, v.MaxValueAction<number, 255, undefined>]>, v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.FiniteAction<number, undefined>, v.MinValueAction<number, 0, undefined>, v.MaxValueAction<number, 255, undefined>]>, v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.FiniteAction<number, undefined>, v.MinValueAction<number, 0, undefined>, v.MaxValueAction<number, 255, undefined>]>, v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.FiniteAction<number, undefined>, v.MinValueAction<number, 0, undefined>, v.MaxValueAction<number, 1, undefined>]>], undefined>;
14
+ readonly family: v.PicklistSchema<["sans-serif", "serif", "monospace"], undefined>;
15
+ readonly font: v.ExactOptionalSchema<v.PicklistSchema<readonly ["Arial", "Georgia", "Verdana", "Tahoma", "Trebuchet MS", "Times New Roman", "Courier New", "system-ui", "sans-serif", "serif", "monospace"], undefined>, undefined>;
16
+ readonly align: v.PicklistSchema<["left", "right", "center", "justify"], undefined>;
17
+ readonly direction: v.PicklistSchema<["ltr", "rtl"], undefined>;
18
+ }, undefined>;
19
+ export type CanvasTextStyle = v.InferOutput<typeof TextPresentationStyleSchema>;
@@ -0,0 +1,23 @@
1
+ export type UrlPurpose = 'link' | 'image';
2
+ export interface UrlPolicyOptions {
3
+ readonly exactUrlPlaceholders?: readonly string[];
4
+ }
5
+ /** URI protocol decisions live here; callers must pass decoded HTML/CSS values. */
6
+ export declare class UrlPolicy {
7
+ #private;
8
+ constructor(options?: UrlPolicyOptions);
9
+ isSafe(input: string, purpose?: UrlPurpose): boolean;
10
+ /**
11
+ * Whether a document URL would run code where it is followed: `javascript:`, `vbscript:`
12
+ * or a `data:` document. Unlike `isSafe`, which decides what the editor itself may write,
13
+ * this only classifies imported content; merge tags and unknown schemes are not active.
14
+ */
15
+ isActive(input: string): boolean;
16
+ /** Unicode separators, zero-width marks and direction controls (NEL, NBSP, ZWSP, BOM...). */
17
+ private invisible;
18
+ /**
19
+ * A space never precedes or sits inside a scheme or authority. It is tolerated only in the
20
+ * path or query of an explicit http(s) URL and after the colon of mailto and tel.
21
+ */
22
+ private spacesOnlyAfterScheme;
23
+ }
@@ -0,0 +1,17 @@
1
+ import { a as e, i as t, n } from "./generated-mjml-CtzE-f3v.js";
2
+ import { parentPort as r, workerData as i } from "node:worker_threads";
3
+ import a from "mjml";
4
+ //#region src/compilation/node-worker.ts
5
+ var o = new t();
6
+ try {
7
+ let t = n(i);
8
+ if (!t) throw Error("INVALID_COMPILE_INPUT");
9
+ o.source(t.source, t.fragments);
10
+ let s = await a(t.source, e);
11
+ r?.postMessage({ html: o.output(s.html) });
12
+ } catch {
13
+ r?.postMessage({ error: "COMPILE_FAILED" });
14
+ }
15
+ //#endregion
16
+
17
+ //# sourceMappingURL=server-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-worker.js","names":["MJML_OPTIONS","CompilationGuard","mjml2html","guard","request","readCompileRequest","workerData","result"],"sources":["../src/compilation/node-worker.ts"],"sourcesContent":["import { parentPort, workerData } from 'node:worker_threads';\nimport mjml2html from 'mjml';\nimport { CompilationGuard, MJML_OPTIONS } from './guard';\nimport { readCompileRequest } from './generated-mjml';\n\nconst guard = new CompilationGuard();\ntry {\n const request = readCompileRequest(workerData);\n if (!request) throw new Error('INVALID_COMPILE_INPUT');\n guard.source(request.source, request.fragments);\n const result = await mjml2html(request.source, MJML_OPTIONS);\n parentPort?.postMessage({ html: guard.output(result.html) });\n} catch {\n parentPort?.postMessage({ error: 'COMPILE_FAILED' });\n}\n"],"mappings":";;;;AAKA,IAAMG,IAAQ,IAAIF,EAAiB;AACnC,IAAI;CACF,IAAMG,IAAUC,EAAmBC,CAAU;CAC7C,IAAI,CAACF,GAAS,MAAU,MAAM,uBAAuB;CACrD,EAAM,OAAOA,EAAQ,QAAQA,EAAQ,SAAS;CAC9C,IAAMG,IAAS,MAAML,EAAUE,EAAQ,QAAQJ,CAAY;CAC3D,GAAY,YAAY,EAAE,MAAMG,EAAM,OAAOI,EAAO,IAAI,EAAE,CAAC;AAC7D,QAAQ;CACN,GAAY,YAAY,EAAE,OAAO,iBAAiB,CAAC;AACrD"}
package/dist/server.js ADDED
@@ -0,0 +1,79 @@
1
+ import { g as e, r as t, s as n, y as r } from "./identity-CJHb6l9N.js";
2
+ import { i, n as a, r as o } from "./block-controller-RjYGvOcn.js";
3
+ import { _ as s, a as c, b as l, c as u, f as d, g as f, h as p, i as m, m as h, n as g, o as _, p as v, r as y, s as b, t as x, u as S, v as C, x as w, y as T } from "./block-factory-C5oHi4Fm.js";
4
+ import { c as E, i as D, o as O, r as k, s as A, t as j } from "./generated-mjml-CtzE-f3v.js";
5
+ import { Worker as M } from "node:worker_threads";
6
+ //#region src/compilation/node-compiler.ts
7
+ var N = class {
8
+ workerUrl;
9
+ timeoutMs;
10
+ guard = new D();
11
+ jobs = /* @__PURE__ */ new Set();
12
+ disposed = !1;
13
+ constructor(e, t = k.timeoutMs) {
14
+ if (this.workerUrl = e, this.timeoutMs = t, !Number.isInteger(t) || t < 1 || t > k.timeoutMs) throw Error("INVALID_COMPILE_TIMEOUT");
15
+ }
16
+ async compile(e) {
17
+ return this.run(e);
18
+ }
19
+ async compileGenerated(e) {
20
+ if (!(e instanceof j)) throw Error("INVALID_COMPILE_INPUT");
21
+ return this.run(e.source, e.fragments);
22
+ }
23
+ async run(e, t) {
24
+ if (this.disposed) throw Error("COMPILER_DISPOSED");
25
+ if (this.guard.source(e, t), this.jobs.size >= k.parallelJobs) throw Error("COMPILER_BUSY");
26
+ let n = t ? {
27
+ source: e,
28
+ fragments: [...t]
29
+ } : e;
30
+ return new Promise((e, t) => {
31
+ let r = new M(this.workerUrl, {
32
+ workerData: n,
33
+ execArgv: [],
34
+ resourceLimits: {
35
+ maxOldGenerationSizeMb: 192,
36
+ maxYoungGenerationSizeMb: 32,
37
+ stackSizeMb: 4
38
+ }
39
+ }), i = () => {
40
+ clearTimeout(o), r.terminate(), this.jobs.delete(a);
41
+ }, a = () => {
42
+ i(), t(/* @__PURE__ */ Error("COMPILER_DISPOSED"));
43
+ }, o = setTimeout(() => {
44
+ i(), t(/* @__PURE__ */ Error("COMPILE_TIMEOUT"));
45
+ }, this.timeoutMs);
46
+ this.jobs.add(a), r.once("message", (n) => {
47
+ try {
48
+ if (!n || typeof n != "object" || !("html" in n)) throw Error("COMPILE_FAILED");
49
+ let t = this.guard.output(n.html);
50
+ i(), e(t);
51
+ } catch (e) {
52
+ i(), t(e);
53
+ }
54
+ }), r.once("error", () => {
55
+ i(), t(/* @__PURE__ */ Error("COMPILE_FAILED"));
56
+ }), r.once("exit", (e) => {
57
+ this.jobs.has(a) && (i(), t(/* @__PURE__ */ Error(`COMPILE_EXIT_${e}`)));
58
+ });
59
+ });
60
+ }
61
+ dispose() {
62
+ this.disposed = !0;
63
+ for (let e of [...this.jobs]) e();
64
+ }
65
+ }, P = () => new N(new URL(
66
+ /* @vite-ignore */
67
+ "./server-worker.js",
68
+ import.meta.url
69
+ ));
70
+ function F(e) {
71
+ return new T(P).create(e);
72
+ }
73
+ function I(e) {
74
+ return new x(P).toolkit(e);
75
+ }
76
+ //#endregion
77
+ export { v as BLOCK_DEVICES, h as BLOCK_DOCUMENT_LIMITS, p as BLOCK_NODE_TYPES, a as BlockChecker, S as BlockContentGuard, y as BlockConversionError, _ as BlockDefinitionRegistry, f as BlockDocument, s as BlockDocumentError, C as BlockDocumentSchema, x as BlockEditorFactory, c as BlockEmailRenderer, u as BlockMjmlGenerator, b as BlockPageGenerator, g as BlockTemplateCatalog, m as BlockToHtmlConversion, A as ContentPolicy, E as ContentPolicyError, t as CssDocumentCodec, e as DOCUMENT_LIMITS, r as EditorDocument, T as EditorFactory, o as GMAIL_CLIP_BYTES, i as GMAIL_NEAR_CLIP_BYTES, j as GeneratedMjml, w as HtmlDocumentAssembler, O as HtmlDocumentCodec, l as InitialDocumentError, N as NodeMjmlCompiler, n as UrlPolicy, I as createServerBlockToolkit, F as createServerEditor, d as parseAnyDocument };
78
+
79
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","names":["DOCUMENT_LIMITS","CssDocumentCodec","UrlPolicy","EditorDocument","BlockChecker","GMAIL_CLIP_BYTES","BlockDocumentError","BlockEmailRenderer","InitialDocumentError","BlockMjmlGenerator","parseAnyDocument","BlockDocument","BLOCK_NODE_TYPES","BlockToHtmlConversion","BLOCK_DOCUMENT_LIMITS","BlockTemplateCatalog","BlockDefinitionRegistry","BLOCK_DEVICES","BlockConversionError","BlockPageGenerator","BlockEditorFactory","BlockContentGuard","BlockDocumentSchema","HtmlDocumentAssembler","EditorFactory","ContentPolicyError","CompilationGuard","HtmlDocumentCodec","COMPILE_LIMITS","ContentPolicy","GeneratedMjml","NodeMjmlCompiler","workerUrl","timeoutMs","source","mjml","fragments","request","worker","Worker","finish","timer","cancel","reject","message","html","resolve","error","code","serverCompiler","createServerEditor","options","createServerBlockToolkit","GMAIL_NEAR_CLIP_BYTES"],"sources":["../src/compilation/node-compiler.ts","../src/composition/server.ts"],"sourcesContent":["import { Worker } from 'node:worker_threads';\nimport type { MjmlCompilerPort } from '../renderers/email-renderer';\nimport { CompilationGuard, COMPILE_LIMITS } from './guard';\nimport { GeneratedMjml } from './generated-mjml';\nimport type { CompileRequest, GeneratedMjmlCompilerPort } from './generated-mjml';\n\nexport class NodeMjmlCompiler implements MjmlCompilerPort, GeneratedMjmlCompilerPort {\n private readonly guard = new CompilationGuard();\n private readonly jobs = new Set<() => void>();\n private disposed = false;\n\n constructor(\n private readonly workerUrl: URL,\n private readonly timeoutMs: number = COMPILE_LIMITS.timeoutMs,\n ) {\n if (!Number.isInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > COMPILE_LIMITS.timeoutMs)\n throw new Error('INVALID_COMPILE_TIMEOUT');\n }\n\n /** MJML from outside: no raw region is accepted. */\n async compile(source: string): Promise<string> {\n return this.run(source);\n }\n\n /** MJML of the block codec, with the raw regions it generated. */\n async compileGenerated(mjml: GeneratedMjml): Promise<string> {\n if (!(mjml instanceof GeneratedMjml)) throw new Error('INVALID_COMPILE_INPUT');\n return this.run(mjml.source, mjml.fragments);\n }\n\n private async run(source: string, fragments?: readonly string[]): Promise<string> {\n if (this.disposed) throw new Error('COMPILER_DISPOSED');\n this.guard.source(source, fragments);\n if (this.jobs.size >= COMPILE_LIMITS.parallelJobs) throw new Error('COMPILER_BUSY');\n const request: CompileRequest = fragments ? { source, fragments: [...fragments] } : source;\n return new Promise<string>((resolve, reject) => {\n const worker = new Worker(this.workerUrl, {\n workerData: request,\n execArgv: [],\n resourceLimits: {\n maxOldGenerationSizeMb: 192,\n maxYoungGenerationSizeMb: 32,\n stackSizeMb: 4,\n },\n });\n const finish = () => {\n clearTimeout(timer);\n void worker.terminate();\n this.jobs.delete(cancel);\n };\n const cancel = () => {\n finish();\n reject(new Error('COMPILER_DISPOSED'));\n };\n const timer = setTimeout(() => {\n finish();\n reject(new Error('COMPILE_TIMEOUT'));\n }, this.timeoutMs);\n this.jobs.add(cancel);\n worker.once('message', (message: unknown) => {\n try {\n if (!message || typeof message !== 'object' || !('html' in message))\n throw new Error('COMPILE_FAILED');\n const html = this.guard.output(message.html);\n finish();\n resolve(html);\n } catch (error) {\n finish();\n reject(error);\n }\n });\n worker.once('error', () => {\n finish();\n reject(new Error('COMPILE_FAILED'));\n });\n worker.once('exit', (code) => {\n if (this.jobs.has(cancel)) {\n finish();\n reject(new Error(`COMPILE_EXIT_${code}`));\n }\n });\n });\n }\n\n dispose(): void {\n this.disposed = true;\n for (const cancel of [...this.jobs]) cancel();\n }\n}\n","import { EditorFactory } from './factory';\nimport type { EditorOptions } from './factory';\nimport { NodeMjmlCompiler } from '../compilation/node-compiler';\nimport { BlockEditorFactory } from './block-factory';\nimport type { BlockToolkit, BlockToolkitOptions } from './block-factory';\n\nconst serverCompiler = (): NodeMjmlCompiler =>\n new NodeMjmlCompiler(new URL(/* @vite-ignore */ './server-worker.js', import.meta.url));\n\nexport function createServerEditor(options?: EditorOptions) {\n return new EditorFactory(serverCompiler).create(options);\n}\n\n/**\n * Parse, generate, compile and convert block pieces (schema 2) on the server, the source of\n * truth: the e-mail is compiled by the isolated Node worker.\n */\nexport function createServerBlockToolkit(options?: BlockToolkitOptions): BlockToolkit {\n return new BlockEditorFactory(serverCompiler).toolkit(options);\n}\nexport { NodeMjmlCompiler } from '../compilation/node-compiler';\nexport { EditorFactory, InitialDocumentError } from './factory';\nexport type { EditorOptions, EditorInstance } from './factory';\nexport { EditorDocument, DOCUMENT_LIMITS } from '../core/document';\nexport type {\n EditorDocumentData,\n DocumentNode,\n SourceInput,\n Diagnostic,\n DiagnosticSeverity,\n} from '../core/document';\nexport type {\n HostAdapters,\n StorePort,\n AssetPort,\n SlotsPort,\n AssetReference,\n} from '../application/host';\nexport { ContentPolicy, ContentPolicyError } from '../security/policy';\nexport type { SanitizedDocument } from '../security/policy';\nexport type { ContentInventory, ExternalReference } from '../security/content-inventory';\nexport { HtmlDocumentCodec } from '../codecs/html';\nexport { CssDocumentCodec } from '../codecs/css';\nexport { UrlPolicy } from '../security/url-policy';\nexport { HtmlDocumentAssembler } from '../renderers/preview-document';\nexport { BlockEditorFactory } from './block-factory';\nexport type { BlockCompiler, BlockToolkit, BlockToolkitOptions } from './block-factory';\nexport {\n BlockDocument,\n BlockDocumentError,\n BlockDocumentSchema,\n BLOCK_DOCUMENT_LIMITS,\n BLOCK_NODE_TYPES,\n} from '../core/block-document';\nexport type {\n Block,\n BlockDocumentData,\n BlockNodeType,\n BlockPropValue,\n BlockProps,\n GlobalStyles,\n} from '../core/block-document';\nexport { parseAnyDocument } from '../core/any-document';\nexport type { AnyDocument } from '../core/any-document';\nexport type { BlockStorePort } from '../application/block-session';\nexport { BlockDefinitionRegistry } from '../blocks/definitions';\nexport { BlockConversionError } from '../blocks/conversion';\nexport type { OutputMode } from '../blocks/block-type';\nexport { GeneratedMjml } from '../compilation/generated-mjml';\nexport { BlockTemplateCatalog } from '../templates/blocks/catalog';\nexport type { BlockTemplateDescriptor } from '../templates/blocks/catalog';\nexport { BlockContentGuard } from '../blocks/content-guard';\nexport { BlockMjmlGenerator } from '../blocks/email-generator';\nexport { BlockPageGenerator } from '../blocks/page-generator';\nexport { BlockEmailRenderer } from '../blocks/email-renderer';\nexport { BlockToHtmlConversion } from '../blocks/conversion';\nexport { BlockChecker, GMAIL_CLIP_BYTES, GMAIL_NEAR_CLIP_BYTES } from '../blocks/block-checks';\nexport type { BlockCheck, BlockCheckCode } from '../blocks/block-checks';\nexport { BLOCK_DEVICES } from '../core/block-document';\nexport type { BlockDevice } from '../core/block-document';\n"],"mappings":";;;;;;AAMA,IAAa+B,IAAb,MAAqF;CAMhE;CACA;CANnB,QAAyB,IAAIL,EAAiB;CAC9C,uBAAwB,IAAI,IAAgB;CAC5C,WAAmB;CAEnB,YACE,GACA,IAAqCE,EAAe,WACpD;EACA,IAHiB,KAAA,YAAAI,GACA,KAAA,YAAAC,GAEb,CAAC,OAAO,UAAUA,CAAS,KAAKA,IAAY,KAAKA,IAAYL,EAAe,WAC9E,MAAU,MAAM,yBAAyB;CAC7C;CAGA,MAAM,QAAQ,GAAiC;EAC7C,OAAO,KAAK,IAAIM,CAAM;CACxB;CAGA,MAAM,iBAAiB,GAAsC;EAC3D,IAAI,EAAEC,aAAgBL,IAAgB,MAAU,MAAM,uBAAuB;EAC7E,OAAO,KAAK,IAAIK,EAAK,QAAQA,EAAK,SAAS;CAC7C;CAEA,MAAc,IAAI,GAAgB,GAAgD;EAChF,IAAI,KAAK,UAAU,MAAU,MAAM,mBAAmB;EAEtD,IADA,KAAK,MAAM,OAAOD,GAAQE,CAAS,GAC/B,KAAK,KAAK,QAAQR,EAAe,cAAc,MAAU,MAAM,eAAe;EAClF,IAAMS,IAA0BD,IAAY;GAAE;GAAQ,WAAW,CAAC,GAAGA,CAAS;EAAE,IAAIF;EACpF,OAAO,IAAI,SAAiB,GAAS,MAAW;GAC9C,IAAMI,IAAS,IAAIC,EAAO,KAAK,WAAW;IACxC,YAAYF;IACZ,UAAU,CAAC;IACX,gBAAgB;KACd,wBAAwB;KACxB,0BAA0B;KAC1B,aAAa;IACf;GACF,CAAC,GACKG,UAAe;IAGnB,AAFA,aAAaC,CAAK,GAClBH,EAAY,UAAU,GACtB,KAAK,KAAK,OAAOI,CAAM;GACzB,GACMA,UAAe;IAEnB,AADAF,EAAO,GACPG,EAAO,gBAAI,MAAM,mBAAmB,CAAC;GACvC,GACMF,IAAQ,iBAAiB;IAE7B,AADAD,EAAO,GACPG,EAAO,gBAAI,MAAM,iBAAiB,CAAC;GACrC,GAAG,KAAK,SAAS;GAkBjB,AAjBA,KAAK,KAAK,IAAID,CAAM,GACpBJ,EAAO,KAAK,YAAY,MAAqB;IAC3C,IAAI;KACF,IAAI,CAACM,KAAW,OAAOA,KAAY,YAAY,EAAE,UAAUA,IACzD,MAAU,MAAM,gBAAgB;KAClC,IAAMC,IAAO,KAAK,MAAM,OAAOD,EAAQ,IAAI;KAE3C,AADAJ,EAAO,GACPM,EAAQD,CAAI;IACd,SAASE,GAAO;KAEd,AADAP,EAAO,GACPG,EAAOI,CAAK;IACd;GACF,CAAC,GACDT,EAAO,KAAK,eAAe;IAEzB,AADAE,EAAO,GACPG,EAAO,gBAAI,MAAM,gBAAgB,CAAC;GACpC,CAAC,GACDL,EAAO,KAAK,SAAS,MAAS;IAC5B,AAAI,KAAK,KAAK,IAAII,CAAM,MACtBF,EAAO,GACPG,EAAO,gBAAI,MAAM,gBAAgBK,GAAM,CAAC;GAE5C,CAAC;EACH,CAAC;CACH;CAEA,UAAgB;EACd,KAAK,WAAW;EAChB,KAAK,IAAMN,KAAU,CAAC,GAAG,KAAK,IAAI,GAAG,EAAO;CAC9C;AACF,GClFMO,UACJ,IAAIlB,EAAiB,IAAI;;CAAuB;CAAsB,YAAY;AAAG,CAAC;AAExF,SAAgBmB,EAAmB,GAAyB;CAC1D,OAAO,IAAI1B,EAAcyB,CAAc,CAAC,CAAC,OAAOE,CAAO;AACzD;AAMA,SAAgBC,EAAyB,GAA6C;CACpF,OAAO,IAAIhC,EAAmB6B,CAAc,CAAC,CAAC,QAAQE,CAAO;AAC/D"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Output of the MJML compiler for `BLANK_EMAIL_MJML`, stored so that an editor can be created
3
+ * without waiting for a compilation. Do not edit by hand: `tests/unit/templates` compares it
4
+ * with what the compiler produces and fails when the two differ.
5
+ */
6
+ export declare const BLANK_EMAIL_HTML = "<!doctype html>\n<html lang=\"und\" dir=\"auto\" xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:o=\"urn:schemas-microsoft-com:office:office\">\n <head>\n <title></title>\n <!--[if !mso]><!-->\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n <!--<![endif]-->\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <style type=\"text/css\">\n #outlook a { padding:0; }\n body { margin:0;padding:0;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%; }\n table, td { border-collapse:collapse;mso-table-lspace:0pt;mso-table-rspace:0pt; }\n img { border:0;height:auto;line-height:100%; outline:none;text-decoration:none;-ms-interpolation-mode:bicubic; }\n p { display:block;margin:13px 0; }\n </style>\n <!--[if mso]>\n <noscript>\n <xml>\n <o:OfficeDocumentSettings>\n <o:AllowPNG/>\n <o:PixelsPerInch>96</o:PixelsPerInch>\n </o:OfficeDocumentSettings>\n </xml>\n </noscript>\n <![endif]-->\n <!--[if lte mso 11]>\n <style type=\"text/css\">\n .mj-outlook-group-fix { width:100% !important; }\n </style>\n <![endif]-->\n \n \n <style type=\"text/css\">\n @media only screen and (min-width:641px) {\n .mj-column-per-100 { width:100% !important; max-width: 100%; }\n }\n </style>\n <style media=\"screen and (min-width:641px)\">\n .moz-text-html .mj-column-per-100 { width:100% !important; max-width: 100%; }\n </style>\n \n \n \n \n \n \n </head>\n \n <body style=\"word-spacing:normal;\">\n \n <div\n aria-roledescription=\"email\" role=\"article\" lang=\"und\" dir=\"auto\" style=\"word-spacing:normal;\"\n >\n \n \n <!--[if mso | IE]><table align=\"center\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" class=\"editor-layout-section-outlook\" role=\"presentation\" style=\"width:600px;\" width=\"600\" ><tr><td style=\"line-height:0px;font-size:0px;mso-line-height-rule:exactly;\"><![endif]-->\n \n \n <div class=\"editor-layout-section\" style=\"margin:0px auto;max-width:600px;\">\n \n <table\n align=\"center\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\" style=\"width:100%;\"\n >\n <tbody>\n <tr>\n <td\n style=\"direction:ltr;font-size:0px;padding:20px 0;text-align:center;\"\n >\n <!--[if mso | IE]><table role=\"presentation\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tr><td class=\"editor-layout-column-outlook\" style=\"vertical-align:top;width:600px;\" ><![endif]-->\n \n <div\n class=\"mj-column-per-100 mj-outlook-group-fix editor-layout-column\" style=\"font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;\"\n >\n \n <table\n border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\" style=\"vertical-align:top;\" width=\"100%\"\n >\n <tbody>\n \n <tr>\n <td\n align=\"left\" style=\"font-size:0px;padding:10px 25px;word-break:break-word;\"\n >\n \n <div\n style=\"font-family:Arial, sans-serif;font-size:16px;line-height:1.65;text-align:left;color:#243746;\"\n >Escreva seu conte\u00FAdo.</div>\n \n </td>\n </tr>\n \n </tbody>\n </table>\n \n </div>\n \n <!--[if mso | IE]></td></tr></table><![endif]-->\n </td>\n </tr>\n </tbody>\n </table>\n \n </div>\n \n \n <!--[if mso | IE]></td></tr></table><![endif]-->\n \n \n </div>\n </body>\n \n</html>\n ";
@@ -0,0 +1,31 @@
1
+ import { BlockDocument } from '../../core/block-document';
2
+ import type { BlockRules } from '../../core/block-document';
3
+ import type { DocumentKind } from '../../core/document';
4
+ export interface BlockTemplateDescriptor {
5
+ readonly id: string;
6
+ readonly kind: DocumentKind;
7
+ readonly titleKey: string;
8
+ readonly descriptionKey: string;
9
+ }
10
+ /** Languages a template is written in besides its own (pt-BR): the texts of its blocks by id. */
11
+ export declare const TEMPLATE_LANGUAGES: readonly ["en", "es"];
12
+ /**
13
+ * Starting points of block pieces (schema 2), stored as JSON. They sit beside the schema 1
14
+ * models of `TemplateCatalog`, which stay as they are. A piece made from a template gets new
15
+ * block ids, so two pieces never share them.
16
+ */
17
+ export declare class BlockTemplateCatalog {
18
+ #private;
19
+ private readonly rules;
20
+ constructor(rules: BlockRules);
21
+ list(kind: DocumentKind): readonly BlockTemplateDescriptor[];
22
+ /** The blank piece of a kind: one section, one column, one text (a page has the same). */
23
+ blank(kind: DocumentKind, documentId: string, nextId: () => string, language?: string): BlockDocument;
24
+ /**
25
+ * A new piece from a template, in the language given (pt-BR, English or Spanish texts; any
26
+ * other language keeps pt-BR). The piece declares the language of its texts.
27
+ */
28
+ create(id: string, documentId: string, nextId: () => string, kind?: DocumentKind, language?: string): BlockDocument;
29
+ private reidentify;
30
+ private entry;
31
+ }
@@ -0,0 +1,31 @@
1
+ import type { DocumentKind, SourceInput } from '../core/document';
2
+ import type { MjmlEmailRenderer } from '../renderers/email-renderer';
3
+ /** A block source; e-mail blocks state whether they are a content row or a whole section. */
4
+ export interface BlockSource extends SourceInput {
5
+ readonly insertion?: 'content' | 'section';
6
+ }
7
+ export interface TemplateDescriptor {
8
+ readonly id: string;
9
+ readonly kind: DocumentKind;
10
+ readonly titleKey: string;
11
+ readonly descriptionKey: string;
12
+ }
13
+ /** The structure a new e-mail starts from: one section, one column, one editable text. */
14
+ export declare const BLANK_EMAIL_MJML = "<mjml><mj-head><mj-breakpoint width=\"641px\" /><mj-attributes><mj-all font-family=\"Arial, sans-serif\" /><mj-text color=\"#243746\" line-height=\"1.65\" font-size=\"16px\" /><mj-button background-color=\"#0d766e\" border-radius=\"8px\" font-size=\"16px\" /></mj-attributes></mj-head><mj-body width=\"600px\"><mj-section css-class=\"editor-layout-section\"><mj-column css-class=\"editor-layout-column\"><mj-text>Escreva seu conte\u00FAdo.</mj-text></mj-column></mj-section></mj-body></mjml>";
15
+ export declare class TemplateCatalog {
16
+ private readonly emailRenderer;
17
+ constructor(emailRenderer: MjmlEmailRenderer);
18
+ list(kind: DocumentKind): readonly TemplateDescriptor[];
19
+ create(id: string): Promise<SourceInput>;
20
+ /**
21
+ * The document an editor opens with when it is given none. The e-mail is the compiled
22
+ * `BLANK_EMAIL_MJML`, stored so that an editor can be created synchronously; a test keeps
23
+ * it equal to what the compiler produces. It has the layout of every generated e-mail, so
24
+ * blocks can be inserted above and below its text and moved.
25
+ */
26
+ blank(kind: DocumentKind): SourceInput;
27
+ blocks(kind: DocumentKind): readonly string[];
28
+ createBlock(type: string, kind: DocumentKind): Promise<BlockSource>;
29
+ private emailLayout;
30
+ private blockDefinitions;
31
+ }
@@ -0,0 +1,2 @@
1
+ .visual-editor{--editor-accent:var(--ui-primary);--editor-surface:var(--ui-bg);--editor-background:var(--ui-bg-muted);--editor-text:var(--ui-text);--editor-muted:var(--ui-text-muted);--editor-border:var(--ui-border);--editor-radius:var(--ui-radius);--editor-left:272px;--editor-right:304px;box-sizing:border-box;height:var(--editor-height,clamp(600px, 100dvh, 1040px));isolation:isolate;min-height:0;color:var(--ui-text);background:var(--ui-bg-muted);border:1px solid var(--ui-border);border-radius:var(--ui-radius);font-family:var(--editor-font,inherit);flex-direction:column;font-size:14px;line-height:1.5;display:flex;overflow:hidden}.visual-editor *,.visual-editor :before,.visual-editor :after{box-sizing:border-box}.visual-editor button:disabled,.visual-editor [aria-disabled=true]{cursor:not-allowed}.visual-editor .editor-toolbar{background:var(--ui-bg);border-bottom:1px solid var(--ui-border);flex-wrap:wrap;flex:none;align-items:center;gap:6px 8px;min-width:0;padding:8px 12px;display:flex}.visual-editor .editor-brand{align-items:center;gap:8px;min-width:0;margin-inline-end:4px;display:flex}.visual-editor .editor-brand-mark{width:28px;height:28px;color:var(--ui-text-inverted);background:var(--ui-primary);border-radius:var(--ui-radius);place-items:center;font-weight:700;display:grid}.visual-editor .editor-brand-name{text-overflow:ellipsis;white-space:nowrap;font-weight:600;overflow:hidden}.visual-editor .editor-history,.visual-editor .editor-preview-controls,.visual-editor .editor-block-actions,.visual-editor .editor-keys{align-items:center;gap:2px;display:flex}.visual-editor .editor-separator{align-self:stretch;height:auto;min-height:20px}.visual-editor .editor-toolbar-space{flex:1 1 0;min-width:0}.visual-editor .editor-status,.visual-editor .editor-source-state{color:var(--ui-text-muted);white-space:nowrap;font-size:12px}.visual-editor .editor-file-input,.visual-editor .editor-mobile-trigger{display:none}.visual-editor .editor-statusbar{height:32px;color:var(--ui-text-muted);background:var(--ui-bg);border-top:1px solid var(--ui-border);flex:none;justify-content:space-between;align-items:center;gap:12px;padding:0 12px;font-size:12px;display:flex}.visual-editor .editor-feedback{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.visual-editor .editor-diagnostics{gap:8px;display:grid}.visual-editor .editor-notice-list{padding:12px}.visual-editor .editor-document-metadata{gap:10px;margin-bottom:12px;display:grid}.visual-editor .editor-diagnostics,.visual-editor .editor-recovery-banner{background:var(--ui-bg);border-bottom:1px solid var(--ui-border);flex:none;max-height:30%;padding:8px 12px;overflow-y:auto}.visual-editor .editor-diagnostic-list{gap:4px;margin:0;padding:0;list-style:none;display:grid}.visual-editor .editor-diagnostic-list li{align-items:baseline;gap:8px;display:flex}.visual-editor .editor-workspace{grid-template-columns:var(--editor-left) minmax(0, 1fr) var(--editor-right);flex:1 1 0;min-height:0;display:grid}.visual-editor.is-html .editor-workspace{grid-template-columns:var(--editor-left) minmax(0, 1fr)}.visual-editor.is-html .editor-side-panel.is-right{display:none}.visual-editor .editor-side-panel{background:var(--ui-bg);flex-direction:column;min-width:0;min-height:0;display:flex;overflow:hidden}.visual-editor .editor-side-panel.is-left{border-inline-end:1px solid var(--ui-border)}.visual-editor .editor-side-panel.is-right{border-inline-start:1px solid var(--ui-border)}.visual-editor .editor-tabs,.visual-editor .editor-properties{flex-direction:column;flex:1 1 0;gap:0;min-width:0;min-height:0;display:flex}.visual-editor .editor-tabs-list{border-bottom:1px solid var(--ui-border);flex:none}.visual-editor .editor-tabs-content{flex:1 1 0;min-height:0}.visual-editor .editor-tabs-content[hidden],.visual-editor .editor-tabs-content[data-state=inactive]{display:none}.visual-editor .editor-scroll{overscroll-behavior:contain;scrollbar-width:thin;scrollbar-color:var(--ui-border-accented) transparent;height:100%;padding:12px}.visual-editor .editor-help,.visual-editor .editor-variable-hint{color:var(--ui-text-muted);margin:6px 0;font-size:12px;line-height:1.5}.visual-editor .editor-variable-hint{margin:0;padding:12px}.visual-editor .editor-control-error,.visual-editor .editor-canvas-error{color:var(--ui-error);font-size:12px}.visual-editor .editor-property-groups [data-slot=content][data-state=closed]{display:none}.visual-editor .editor-palette{gap:4px;display:grid}.visual-editor .editor-palette-position{gap:2px;margin-bottom:4px;display:grid}.visual-editor .editor-palette-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;display:grid}.visual-editor .editor-palette-block{cursor:grab;text-align:center;touch-action:manipulation;-webkit-user-select:none;user-select:none;flex-direction:column;gap:6px;width:100%;min-height:64px;padding:10px 6px}.visual-editor .editor-template-list{gap:12px;margin:0;padding:0;list-style:none;display:grid}.visual-editor .editor-template{width:100%;color:inherit;background:var(--ui-bg);border:1px solid var(--ui-border);border-radius:var(--ui-radius);cursor:pointer;text-align:start;gap:4px;padding:8px;display:grid}.visual-editor .editor-template:hover:not(:disabled){border-color:var(--ui-primary)}.visual-editor .editor-template:focus-visible{outline:2px solid var(--ui-primary);outline-offset:2px}.visual-editor .editor-template>span:last-child{color:var(--ui-text-muted);font-size:12px}.visual-editor .editor-template-thumbnail{background:var(--ui-bg-muted);pointer-events:none;width:100%;height:132px;position:relative;overflow:hidden}.visual-editor .editor-template-thumbnail iframe{transform-origin:0 0;border:0;display:block}.visual-editor .editor-template-skeleton{width:100%;height:100%}.visual-editor .editor-template-confirm-preview{height:240px}.visual-editor .editor-structure{-webkit-user-select:none;user-select:none;position:relative}.visual-editor .editor-tree [data-slot=listWithChildren]{margin-inline-start:8px}.visual-editor .editor-tree ul ul ul ul ul ul ul [data-slot=listWithChildren]{margin-inline-start:0}.visual-editor .editor-structure.is-virtual .editor-tree{scrollbar-width:thin;scrollbar-color:var(--ui-border-accented) transparent;height:min(68dvh,720px)}.visual-editor .editor-tree-row{gap:6px;min-width:0}.visual-editor .editor-tree-label{text-overflow:ellipsis;white-space:nowrap;min-width:0;display:block;overflow:hidden}.visual-editor .editor-tree-detail{color:var(--ui-text-dimmed);margin-inline-start:6px;font-weight:400}.visual-editor .editor-structure-drop{z-index:1;pointer-events:none;background:var(--ui-primary);position:absolute}.visual-editor .editor-structure-drop.is-inside{background:color-mix(in srgb, var(--ui-primary) 14%, transparent);outline:2px solid var(--ui-primary);outline-offset:-2px}.visual-editor .editor-selected{flex:none;align-items:center;gap:8px;min-width:0;padding:10px 12px 6px;display:flex}.visual-editor .editor-selected-text{flex:1 1 0;min-width:0;display:grid}.visual-editor .editor-selected-kind,.visual-editor .editor-selected-title{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.visual-editor h2.editor-selected-kind{font-size:inherit;font-weight:700;line-height:inherit;margin:0}.visual-editor h2.editor-selected-kind:focus-visible,.visual-editor .editor-properties[tabindex="-1"]:focus-visible{outline:2px solid var(--ui-primary);outline-offset:2px}.visual-editor .editor-selected-title{color:var(--ui-text-muted);font-size:12px}.visual-editor .editor-property-content,.visual-editor .editor-property-style,.visual-editor .editor-property-advanced,.visual-editor .editor-richtext-colors,.visual-editor .editor-richtext-link,.visual-editor .editor-color-control,.visual-editor .editor-color-picker,.visual-editor .editor-measurement,.visual-editor .editor-shortcuts{gap:10px;min-width:0;display:grid}.visual-editor .editor-richtext-colors,.visual-editor .editor-richtext-link,.visual-editor .editor-color-picker,.visual-editor .editor-shortcuts{padding:12px}.visual-editor .editor-field{min-width:0}.visual-editor .editor-field-group{border:0;gap:6px;min-width:0;margin:0;padding:0;display:grid}.visual-editor .editor-field-label{padding:0;font-size:12px;font-weight:600}.visual-editor .editor-field-hidden-label [data-slot=labelWrapper]{clip-path:inset(50%);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}.visual-editor .editor-field-hidden-label [data-slot=labelWrapper]+[data-slot=container]{margin-top:0}.visual-editor .editor-input,.visual-editor .editor-select{width:100%;display:flex}.visual-editor .editor-color-inputs{grid-template-columns:auto minmax(0,1fr);gap:6px;display:grid}.visual-editor .editor-measurement-controls{grid-template-columns:minmax(0,1fr) 84px;gap:6px;display:grid}.visual-editor .editor-color-swatch{border:1px solid var(--ui-border-accented);border-radius:calc(var(--ui-radius) * .5);width:18px;height:18px;display:block}.visual-editor .editor-authoring-controls{border:0;border-bottom:1px solid var(--ui-border);min-width:0;margin:0 0 12px;padding:0 0 12px}.visual-editor .editor-column-weights{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;display:grid}.visual-editor .editor-shortcuts dl{gap:6px;margin:0;display:grid}.visual-editor .editor-shortcuts dl>div{justify-content:space-between;align-items:center;gap:12px;display:flex}.visual-editor .editor-shortcuts dd{gap:8px;margin:0;display:flex}.visual-editor .editor-canvas-area,.visual-editor .editor-canvas-surface{flex-direction:column;flex:1 1 0;min-width:0;min-height:0;display:flex}.visual-editor .editor-canvas-surface{position:relative}.visual-editor .editor-canvas-breadcrumb{background:var(--ui-bg);border-bottom:1px solid var(--ui-border);flex:none;align-items:center;min-width:0;height:36px;padding:0 8px;display:flex;overflow:hidden}.visual-editor .editor-path{min-width:0;max-width:100%;overflow:hidden}.visual-editor .editor-path-idle{color:var(--ui-text-dimmed);text-overflow:ellipsis;white-space:nowrap;font-size:12px;overflow:hidden}.visual-editor .editor-canvas-text-bar{z-index:3;background:var(--ui-bg);border-bottom:1px solid var(--ui-border);flex:none;min-height:44px;position:relative}.visual-editor .editor-richtext-toolbar,.visual-editor .editor-text-toolbar,.visual-editor .editor-text-toolbar-group{flex-wrap:wrap;align-items:center;gap:2px;display:flex}.visual-editor .editor-richtext-toolbar{min-height:43px;padding:4px 8px}.visual-editor .editor-text-toolbar-group+.editor-text-toolbar-group{margin-inline-start:6px}.visual-editor .editor-canvas-stage,.visual-editor .editor-preview-area{flex:1 1 0;min-height:0;padding:16px;display:flex;overflow:hidden}.visual-editor .editor-preview-shell{isolation:isolate;border:1px solid var(--ui-border);background:#fff;width:100%;max-width:100%;height:100%;margin:0 auto;position:relative;overflow:hidden}.visual-editor .editor-preview-shell.is-tablet{max-width:768px}.visual-editor .editor-preview-shell.is-mobile{max-width:375px}.visual-editor .editor-preview{pointer-events:none;background:#fff;border:0;width:100%;height:100%;display:block}.visual-editor .editor-selection-preview{pointer-events:auto}.visual-editor .editor-canvas-surface.is-palette-dragging iframe.editor-selection-preview{pointer-events:none}.visual-editor .editor-canvas-failure{z-index:1;color:var(--ui-text);text-align:center;background:var(--ui-bg);flex-direction:column;justify-content:center;align-items:center;gap:12px;padding:24px;display:flex;position:absolute;inset:0;overflow:auto}.visual-editor .editor-file-drop{z-index:2;position:absolute;inset:0}.visual-editor .editor-canvas-error{background:var(--ui-bg);border-top:1px solid var(--ui-border);flex:none;margin:0;padding:6px 12px}.visual-editor .editor-source-pane{background:var(--ui-bg);border-bottom:1px solid var(--ui-border);scrollbar-width:thin;scrollbar-color:var(--ui-border-accented) transparent;flex-direction:column;flex:3 1 0;gap:10px;min-height:0;padding:12px;display:flex;overflow-y:auto}.visual-editor.is-html .editor-preview-area{flex:2 1 0}.visual-editor .editor-source-actions{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.visual-editor .editor-source-state{flex:auto}.visual-editor .editor-code{border:1px solid var(--ui-border-accented);border-radius:var(--ui-radius);overflow:hidden}.visual-editor .editor-code:focus-within{outline:2px solid var(--ui-primary);outline-offset:1px}.visual-editor .editor-code .cm-editor{max-height:46vh;font-size:12.5px}.visual-editor .editor-code .cm-editor.cm-focused{outline:none}.visual-editor .editor-code .cm-scroller{font-family:var(--font-mono,ui-monospace, monospace);scrollbar-width:thin;overflow:auto}.dark .visual-editor .editor-code .cm-line>span,.visual-editor.dark .editor-code .cm-line>span{filter:invert()hue-rotate(180deg)}@media (min-width:1280px){.visual-editor.is-html .editor-canvas-area{flex-direction:row}.visual-editor.is-html .editor-source-pane{border-right:1px solid var(--ui-border);border-bottom:0;flex:1 1 0}.visual-editor.is-html .editor-preview-area{flex:1 1 0}.visual-editor.is-html .editor-code .cm-editor{max-height:60vh}}.visual-editor .editor-richtext{min-width:0}.visual-editor .editor-property-content .editor-richtext{border:1px solid var(--ui-border-accented);border-radius:var(--ui-radius);overflow:hidden}.visual-editor .editor-property-content .editor-richtext:focus-within{outline:2px solid var(--ui-primary);outline-offset:1px}.visual-editor .editor-property-content .editor-richtext-toolbar{border-bottom:1px solid var(--ui-border)}.visual-editor .editor-richtext-content{outline:none;min-height:96px;padding:10px}.visual-editor .editor-richtext-content p{margin:0 0 8px}.visual-editor .editor-richtext-content ul,.visual-editor .editor-richtext-content ol{padding-inline-start:20px}.visual-editor .editor-richtext-content ul{list-style:outside}.visual-editor .editor-richtext-content ol{list-style:decimal}.visual-editor .editor-menu-anchor{pointer-events:none;position:fixed}.visual-editor .editor-menu-content,.visual-editor .editor-context-popover-surface{z-index:110}.visual-editor .editor-context-popover-content{width:min(320px, var(--reka-popper-available-width,320px), calc(100vw - 32px));max-height:min(440px, var(--reka-popper-available-height,440px), calc(100dvh - 48px));overscroll-behavior:contain;scrollbar-width:thin;overflow:auto}.visual-editor .editor-panel-overlay{z-index:98}.visual-editor .editor-panel-dialog{z-index:99;width:min(360px,100vw)}.visual-editor .editor-panel-dialog-body{flex-direction:column;flex:1 1 0;min-height:0;padding:0;display:flex;overflow:hidden}.visual-editor .editor-panel-dialog-content{flex-direction:column;flex:1 1 0;min-width:0;min-height:0;display:flex}.visual-editor .editor-confirm-overlay{z-index:120}.visual-editor .editor-confirm-dialog{z-index:121}.visual-editor .editor-confirm-dialog.is-wide{width:min(820px,100vw - 32px);max-width:none}.visual-editor .editor-confirm-actions{flex-wrap:wrap;justify-content:flex-end;gap:8px}@media (max-width:1180px){.visual-editor{--editor-left:236px;--editor-right:264px}.visual-editor .editor-brand-name,.visual-editor .editor-status{clip-path:inset(50%);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}}@media (max-width:900px){.visual-editor .editor-workspace,.visual-editor.is-html .editor-workspace{grid-template-columns:minmax(0,1fr)}.visual-editor .editor-side-panel{display:none}.visual-editor .editor-mobile-trigger{display:inline-flex}.visual-editor .editor-canvas-stage,.visual-editor .editor-preview-area,.visual-editor .editor-toolbar{padding:8px}}@media (pointer:coarse){.visual-editor button,.visual-editor [role=combobox],.visual-editor [role=tab],.visual-editor [role=treeitem],.visual-editor [role=checkbox],.visual-editor [role=switch],.visual-editor input:not([type=file]){min-width:44px;min-height:44px}}@media (prefers-reduced-motion:reduce){.visual-editor *{scroll-behavior:auto!important;transition:none!important;animation:none!important}}.visual-editor .editor-device-notice{border-bottom:1px solid var(--ui-border);margin:0;padding:8px 12px}.visual-editor .editor-device-marker{margin-top:4px;display:flex}.visual-editor .editor-review{border:1px solid var(--ui-border);border-radius:8px;margin:8px 0 16px;padding:12px}.visual-editor .editor-review:focus-visible{outline:2px solid var(--ui-primary);outline-offset:2px}.visual-editor .editor-review-title{margin:0;font-size:13px;font-weight:600}.visual-editor .editor-review-list{gap:8px;margin:8px 0 0;padding:0;list-style:none;display:grid}.visual-editor .editor-review-item{grid-template-columns:auto minmax(0,1fr) auto;align-items:start;gap:8px;font-size:12px;line-height:1.5;display:grid}.visual-editor .editor-review-item[data-review-severity=error]>.editor-icon{color:var(--ui-error)}.visual-editor .editor-review-item[data-review-severity=warning]>.editor-icon{color:var(--ui-warning)}[data-color-picker-background][data-v-496e2664]{background-image:linear-gradient(0deg,#000 0,#0000),linear-gradient(90deg,#fff 0,#fff0)}[data-color-picker-track][data-v-496e2664]{background-image:linear-gradient(red,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red)}
2
+ /*$vite$:1*/
@@ -0,0 +1,106 @@
1
+ import type { Block, BlockDevice, BlockDocumentData, BlockNodeType, BlockPropValue, BlockProps } from '../core/block-document';
2
+ import type { DocumentKind } from '../core/document';
3
+ import type { BlockEditorSession, BlockEditorState, BlockImageChoice } from '../application/block-session';
4
+ import type { BlockPlacement, BlockPlacementService } from '../application/block-placement';
5
+ import type { BlockPlacementTarget } from '../application/block-placement';
6
+ import type { BlockDefinitionRegistry } from '../blocks/definitions';
7
+ import type { BlockFieldModel, BlockInspector, GlobalStyleGroupModel } from '../blocks/block-inspector';
8
+ import type { BlockOutputRenderer } from '../blocks/block-output';
9
+ import type { BlockCheck } from '../blocks/block-checks';
10
+ import type { BlockPreviewInput } from '../renderers/marked-preview';
11
+ import type { BlockTemplateCatalog, BlockTemplateDescriptor } from '../templates/blocks/catalog';
12
+ import type { UrlPolicy } from '../security/url-policy';
13
+ import type { InlineTextOwner } from './canvas/inline-text';
14
+ export interface BlockEditorControllerParts {
15
+ readonly session: BlockEditorSession;
16
+ readonly registry: BlockDefinitionRegistry;
17
+ readonly inspector: BlockInspector;
18
+ readonly placement: BlockPlacementService;
19
+ readonly templates: BlockTemplateCatalog;
20
+ readonly output: BlockOutputRenderer;
21
+ readonly urls: UrlPolicy;
22
+ }
23
+ export type BlockDestination = {
24
+ readonly targetId: string;
25
+ readonly placement: BlockPlacement;
26
+ };
27
+ /**
28
+ * Facade of a block piece (schema 2) for the Vue shell: queries the panels are generated from,
29
+ * and the commands of the session, each one a step of history. Components never reach the
30
+ * session or the definitions directly.
31
+ */
32
+ export declare class BlockEditorController {
33
+ #private;
34
+ readonly session: BlockEditorSession;
35
+ constructor(parts: BlockEditorControllerParts);
36
+ state(): BlockEditorState;
37
+ subscribe(listener: (state: BlockEditorState) => void): () => void;
38
+ kind(): DocumentKind;
39
+ /** The block types of the palette, in catalog order. */
40
+ types(): readonly {
41
+ readonly type: BlockNodeType;
42
+ readonly labelKey: string;
43
+ }[];
44
+ templates(): readonly BlockTemplateDescriptor[];
45
+ typeOf(id: string): BlockNodeType | undefined;
46
+ labelKey(id: string): string | undefined;
47
+ /** The fields of a block as the given screen shows them. */
48
+ fields(id: string, device?: BlockDevice): readonly BlockFieldModel[];
49
+ globalStyles(): readonly GlobalStyleGroupModel[];
50
+ parentOf(id: string): string | undefined;
51
+ /**
52
+ * The review before sending: what the piece has that a reader would meet broken. For an
53
+ * e-mail the final HTML is generated to measure it against the cut of Gmail.
54
+ */
55
+ review(): Promise<readonly BlockCheck[]>;
56
+ /** The marked preview of the current revision, for the editing frame. */
57
+ preview(): Promise<BlockPreviewInput>;
58
+ movementTargets(id: string): readonly BlockPlacementTarget[];
59
+ insertionTargets(type: BlockNodeType): readonly BlockPlacementTarget[];
60
+ select(id: string | undefined): boolean;
61
+ /**
62
+ * A new block where it fits best: at the destination given, else inside or after the
63
+ * selection (or the first of its ancestors which accepts it), else at the end of the piece. A
64
+ * content block in a piece without a place for it arrives in a new section.
65
+ */
66
+ insert(type: BlockNodeType, destination?: BlockDestination | 'end', props?: BlockProps): boolean;
67
+ /**
68
+ * A block saved in the library of the host, with new ids, where it fits best (as `insert` places a new
69
+ * block). It enters only if the piece accepts it: the document parses and checks it like any
70
+ * block from outside. A content block in a piece without a place for it gets a new section.
71
+ */
72
+ insertSaved(saved: Block): boolean;
73
+ /** A copy of a block to save for later use; a column only exists inside its section. */
74
+ savable(id: string): Block | undefined;
75
+ move(sourceId: string, targetId: string, placement: BlockPlacement): boolean;
76
+ step(id: string, direction: 'up' | 'down'): boolean;
77
+ duplicate(id: string): boolean;
78
+ remove(id: string): boolean;
79
+ /** A value of every screen, or of small screens only when the field is responsive. */
80
+ setField(id: string, key: string, value: BlockPropValue, device?: BlockDevice): boolean;
81
+ restoreField(id: string, key: string, device?: BlockDevice): boolean;
82
+ replaceImage(id: string, choice: BlockImageChoice): boolean;
83
+ setStyle(group: string, key: string, value: string): boolean;
84
+ restoreStyle(group: string, key: string): boolean;
85
+ setLanguage(lang: string): boolean;
86
+ /**
87
+ * The piece starts again from a template: one step of history, same id, kind and language
88
+ * (the texts of the template in that language when it has them).
89
+ */
90
+ applyTemplate(templateId: string): boolean;
91
+ undo(): boolean;
92
+ redo(): boolean;
93
+ save(): Promise<boolean>;
94
+ /** Saves and returns the exact piece the store received, or undefined. */
95
+ saveDocument(): Promise<BlockDocumentData | undefined>;
96
+ /**
97
+ * The text edited in place, in the terms of the coordinator the HTML document also uses: one
98
+ * transaction per text, confirmed as one step of history.
99
+ */
100
+ textOwner(): InlineTextOwner;
101
+ /** The same block with ids of this session, so two copies never share one. */
102
+ private reidentify;
103
+ /** A field without mobile values is edited for every screen, whatever screen is shown. */
104
+ private deviceFor;
105
+ private automaticTarget;
106
+ }
@@ -0,0 +1,70 @@
1
+ import type { ComputedRef, InjectionKey, Ref, ShallowRef } from 'vue';
2
+ import type { BlockDocumentData } from '../core/block-document';
3
+ import type { BlockEditorState } from '../application/block-session';
4
+ import type { BlockEditorController } from './block-controller';
5
+ import { EditorLocale } from './locale';
6
+ import type { EditorMessages } from './locale';
7
+ import type { EditorImagePicker } from './services/image-requests';
8
+ import type { PreviewWidth } from './workbench';
9
+ import type { BlockCheck } from '../blocks/block-checks';
10
+ import type { EditorSavedBlock, EditorSavedBlocks } from './services/saved-blocks';
11
+ /** What the editing area of a block piece offers while it is mounted. */
12
+ export interface BlockCanvasApi {
13
+ /** Concludes the text being edited in the piece; false when it was refused. */
14
+ flush(): Promise<boolean>;
15
+ edit(id: string): void;
16
+ canHistory(direction: 'undo' | 'redo'): boolean;
17
+ history(direction: 'undo' | 'redo'): boolean;
18
+ insertText(value: string): boolean;
19
+ }
20
+ export interface BlockWorkbenchOptions {
21
+ controller(): BlockEditorController;
22
+ messages(): EditorMessages | undefined;
23
+ imagePicker(): EditorImagePicker | undefined;
24
+ /** The library of saved blocks of the host; optional. */
25
+ savedBlocks?(): EditorSavedBlocks | undefined;
26
+ saved(document: BlockDocumentData): void;
27
+ failed(code: string): void;
28
+ }
29
+ /** Everything the components of one mounted block editor share; nothing here is global. */
30
+ export interface BlockWorkbench {
31
+ readonly state: ShallowRef<BlockEditorState>;
32
+ readonly locale: ComputedRef<EditorLocale>;
33
+ readonly feedback: Ref<string>;
34
+ readonly busy: Ref<boolean>;
35
+ readonly width: Ref<PreviewWidth>;
36
+ /** The editing frame shows an approximation of a dark mode of the reader. */
37
+ readonly dark: Ref<boolean>;
38
+ /** The findings of the last review; undefined until one is asked for. */
39
+ readonly review: ShallowRef<readonly BlockCheck[] | undefined>;
40
+ readonly reviewing: Ref<boolean>;
41
+ /** Reviews the piece now; once asked for, every later revision is reviewed again. */
42
+ runReview(): Promise<void>;
43
+ /** The blocks saved in the library of the host, of the kind of the piece; empty without a library. */
44
+ readonly savedBlocks: ShallowRef<readonly EditorSavedBlock[]>;
45
+ readonly hasSavedBlocks: ComputedRef<boolean>;
46
+ readonly canRemoveSavedBlocks: ComputedRef<boolean>;
47
+ loadSavedBlocks(): Promise<void>;
48
+ /** Saves the block under a name; false when the host refused it. */
49
+ saveBlock(id: string, name: string): Promise<boolean>;
50
+ insertSavedBlock(entry: EditorSavedBlock): Promise<boolean>;
51
+ removeSavedBlock(entry: EditorSavedBlock): Promise<boolean>;
52
+ readonly canvas: ShallowRef<BlockCanvasApi | undefined>;
53
+ readonly hasImagePicker: ComputedRef<boolean>;
54
+ controller(): BlockEditorController;
55
+ t(key: string): string;
56
+ /**
57
+ * The one door of a change: the text being edited is concluded first, then the command runs
58
+ * and its outcome is said in the status line (`success` empty: nothing is said).
59
+ */
60
+ run(action: (controller: BlockEditorController) => boolean, success?: string): Promise<boolean>;
61
+ history(direction: 'undo' | 'redo'): void;
62
+ canHistory(direction: 'undo' | 'redo'): boolean;
63
+ save(): Promise<void>;
64
+ /** Asks the host library for an image and puts it in the block, as one step. */
65
+ chooseImage(id: string): Promise<void>;
66
+ dispose(): void;
67
+ }
68
+ export declare const BLOCK_WORKBENCH: InjectionKey<BlockWorkbench>;
69
+ export declare function useBlockWorkbench(): BlockWorkbench;
70
+ export declare function createBlockWorkbench(options: BlockWorkbenchOptions): BlockWorkbench;
@@ -0,0 +1,8 @@
1
+ import type { CanvasBridgeTheme } from '../../renderers/canvas-bridge';
2
+ /**
3
+ * Reads the colors of the host theme as the browser resolved them, for the controls drawn inside
4
+ * the frame of the piece. The frame cannot see the variables of the shell: it receives values.
5
+ */
6
+ export declare class CanvasThemeProbe {
7
+ read(root: HTMLElement): CanvasBridgeTheme | undefined;
8
+ }
@@ -0,0 +1,38 @@
1
+ import type { Ref } from 'vue';
2
+ import type { PaletteFrame } from './palette-drag';
3
+ export interface FileDropPorts {
4
+ frame(): PaletteFrame | undefined;
5
+ /** The host declared an upload and the document can change. */
6
+ enabled(): boolean;
7
+ /** The drag entered the window: the piece learns where a new block may land. */
8
+ begin(): void;
9
+ }
10
+ /**
11
+ * An image file dragged from the desktop to the piece. Over an image it replaces that image;
12
+ * anywhere else it lands as a new image. The frame never receives the file: while the drag
13
+ * lasts a layer of the shell takes the pointer and the frame only answers where the point
14
+ * lands, exactly as it does for a block of the palette.
15
+ */
16
+ export declare class FileDrop {
17
+ #private;
18
+ private readonly ports;
19
+ readonly active: Ref<boolean>;
20
+ constructor(ports: FileDropPorts);
21
+ /** Listens inside the area of one editor: a drag over another editor of the page is not its. */
22
+ listen(area: HTMLElement): void;
23
+ dispose(): void;
24
+ private lower;
25
+ /**
26
+ * The frame says a file from the system is over it: the layer rises above the frame, so the
27
+ * rest of the drag (and the drop) reaches the shell and never the page. Without a drag over the
28
+ * layer soon after, the word of the frame alone does not keep it up.
29
+ */
30
+ external(): void;
31
+ /** The file whose destination the frame has just answered; taken once. */
32
+ take(): File | undefined;
33
+ private point;
34
+ private enter;
35
+ private leave;
36
+ over(event: DragEvent): void;
37
+ drop(event: DragEvent): void;
38
+ }
@@ -0,0 +1,26 @@
1
+ export interface FrameWindowPorts {
2
+ /** Posts the question to whatever is in the window. It carries no secret. */
3
+ ask(challenge: string): void;
4
+ /** The window does not hold the runtime the host wrote into it. */
5
+ lost(): void;
6
+ }
7
+ /**
8
+ * Knows whether the window of the frame still holds the runtime the host wrote into it. The
9
+ * object the host calls `contentWindow` stays the same when the frame navigates, so a page which
10
+ * took the window would receive whatever the host posts next. After every load of the frame the
11
+ * host therefore stops posting and asks a question without any secret; only the runtime can
12
+ * answer it with the secret of the protocol. A window which does not answer is lost.
13
+ */
14
+ export declare class FrameWindowGuard {
15
+ #private;
16
+ private readonly ports;
17
+ constructor(ports: FrameWindowPorts);
18
+ /** The host may not post, and only the answer to its question is heard. */
19
+ get waiting(): boolean;
20
+ /** A new window was written: nothing is expected from the previous one. */
21
+ reset(): void;
22
+ /** The frame finished a load, of what the host wrote or of anything else. */
23
+ loaded(): void;
24
+ /** An authenticated `ready`: whether it answers the question which is open. */
25
+ confirm(challenge: string | undefined): boolean;
26
+ }