@h-k-dev/angular-email-editor 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/h-k-dev-angular-email-editor-fonts.mjs +144 -0
- package/fesm2022/h-k-dev-angular-email-editor-fonts.mjs.map +1 -0
- package/fesm2022/h-k-dev-angular-email-editor.mjs +76 -111
- package/fesm2022/h-k-dev-angular-email-editor.mjs.map +1 -1
- package/package.json +5 -1
- package/types/h-k-dev-angular-email-editor-fonts.d.ts +110 -0
- package/types/h-k-dev-angular-email-editor.d.ts +22 -40
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The fonts an email is written in — Gmail's set, in Gmail's order — as
|
|
3
|
+
* plain data: no Angular, no ProseMirror. The editor's `textStyle` mark
|
|
4
|
+
* stores and emits only these stacks, the toolbar offers them, and an
|
|
5
|
+
* editor of another kind (summernote's `fontNames`) can offer the same set
|
|
6
|
+
* from the same constant, so a message reads the same font whichever
|
|
7
|
+
* composer wrote it.
|
|
8
|
+
*/
|
|
9
|
+
/** The clients, in the order a picker shows them (G, A, O), with the letter
|
|
10
|
+
and name it shows them by. */
|
|
11
|
+
const fontClients = [
|
|
12
|
+
{ id: 'gmail', letter: 'G', name: 'Gmail' },
|
|
13
|
+
{ id: 'apple-mail', letter: 'A', name: 'Apple Mail' },
|
|
14
|
+
{ id: 'outlook-desktop', letter: 'O', name: 'Outlook' },
|
|
15
|
+
];
|
|
16
|
+
/** The family names of a `font-family` value, unquoted, in order. */
|
|
17
|
+
function familiesOf(stack) {
|
|
18
|
+
return stack
|
|
19
|
+
.split(',')
|
|
20
|
+
.map((family) => family.replace(/["']/g, '').trim())
|
|
21
|
+
.filter(Boolean);
|
|
22
|
+
}
|
|
23
|
+
const G = 'gmail';
|
|
24
|
+
const A = 'apple-mail';
|
|
25
|
+
const O = 'outlook-desktop';
|
|
26
|
+
function font(id, name, stack, clients) {
|
|
27
|
+
return { id, name, stack, face: familiesOf(stack)[0], clients };
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Gmail's fonts, in its menu's order. A stack is the face, then what a
|
|
31
|
+
* client without it should draw instead, then the generic. Each face leads
|
|
32
|
+
* only its own stack, so a single family read back from another editor
|
|
33
|
+
* (`font-family: 'Arial Black'`) finds its font exactly.
|
|
34
|
+
*
|
|
35
|
+
* The first stack naming a family claims it (see {@link matchEmailFont}):
|
|
36
|
+
* `helvetica` and `sans-serif` read as Sans Serif, `times` and `serif` as
|
|
37
|
+
* Serif, `courier` and `monospace` as Fixed width.
|
|
38
|
+
*/
|
|
39
|
+
const emailFontFamilies = [
|
|
40
|
+
font('sans-serif', 'Sans Serif', 'Arial, Helvetica, sans-serif', [G, A, O]),
|
|
41
|
+
font('serif', 'Serif', '"Times New Roman", Times, serif', [G, A, O]),
|
|
42
|
+
font('fixed-width', 'Fixed width', '"Courier New", Courier, monospace', [G, A, O]),
|
|
43
|
+
// Not on iOS.
|
|
44
|
+
font('wide', 'Wide', '"Arial Black", sans-serif', [G, O]),
|
|
45
|
+
// Office's, not Windows' own — nor on iOS.
|
|
46
|
+
font('narrow', 'Narrow', '"Arial Narrow", sans-serif', [O]),
|
|
47
|
+
// Not on iOS.
|
|
48
|
+
font('comic-sans-ms', 'Comic Sans MS', '"Comic Sans MS", sans-serif', [G, O]),
|
|
49
|
+
// Office's only: neither macOS, iOS nor Windows itself has it.
|
|
50
|
+
font('garamond', 'Garamond', 'Garamond, "Times New Roman", serif', [O]),
|
|
51
|
+
font('georgia', 'Georgia', 'Georgia, serif', [G, A, O]),
|
|
52
|
+
// Not on iOS.
|
|
53
|
+
font('tahoma', 'Tahoma', 'Tahoma, sans-serif', [G, O]),
|
|
54
|
+
font('trebuchet-ms', 'Trebuchet MS', '"Trebuchet MS", sans-serif', [G, A, O]),
|
|
55
|
+
font('verdana', 'Verdana', 'Verdana, sans-serif', [G, A, O]),
|
|
56
|
+
];
|
|
57
|
+
/**
|
|
58
|
+
* The font a message is written in until the writer picks another — Gmail's
|
|
59
|
+
* Sans Serif, Arial. Nothing is emitted for it: unstyled text is drawn in
|
|
60
|
+
* the client's own default, as Gmail's is. An editor shows it as its
|
|
61
|
+
* surface font, so what is written looks as it will in Gmail; summernote
|
|
62
|
+
* takes its face (`fontName: emailDefaultFont.face`).
|
|
63
|
+
*/
|
|
64
|
+
const emailDefaultFont = emailFontFamilies[0];
|
|
65
|
+
/**
|
|
66
|
+
* The faces of {@link emailFontFamilies}, in order — the set for an editor
|
|
67
|
+
* that offers single families. For summernote, both lists: `fontNamesIgnoreCheck`
|
|
68
|
+
* keeps a face this machine lacks (Garamond, Arial Narrow) in the menu.
|
|
69
|
+
*
|
|
70
|
+
* ```ts
|
|
71
|
+
* $('#editor').summernote({ fontNames: emailFontFaces, fontNamesIgnoreCheck: emailFontFaces });
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
const emailFontFaces = emailFontFamilies.map((f) => f.face);
|
|
75
|
+
/** Every size the editor stores, in px. */
|
|
76
|
+
const allowedFontSizes = [10, 12, 14, 16, 18, 24, 32];
|
|
77
|
+
/**
|
|
78
|
+
* The sizes a picker offers: the phone-safe subset (≥14px). Below ~13px iOS
|
|
79
|
+
* auto-inflates text and reflows the layout, so they are not *offered* —
|
|
80
|
+
* but every {@link allowedFontSizes} size is still read and kept, because a
|
|
81
|
+
* hand-typed size in the HTML source is the author's own responsibility.
|
|
82
|
+
*/
|
|
83
|
+
const emailFontSizes = [14, 16, 18, 24, 32];
|
|
84
|
+
/** A `font-family` value as a comparison key: lower-cased, quotes dropped,
|
|
85
|
+
whitespace around commas collapsed — so a hand-typed or CSSOM-reserialized
|
|
86
|
+
stack matches a curated one regardless of cosmetic differences. */
|
|
87
|
+
function fontFamilyKey(raw) {
|
|
88
|
+
return raw
|
|
89
|
+
.toLowerCase()
|
|
90
|
+
.replace(/["']/g, '')
|
|
91
|
+
.replace(/\s*,\s*/g, ',')
|
|
92
|
+
.trim();
|
|
93
|
+
}
|
|
94
|
+
const FONT_BY_KEY = new Map(emailFontFamilies.map((f) => [fontFamilyKey(f.stack), f]));
|
|
95
|
+
/** Each family a stack names to the first stack naming it. */
|
|
96
|
+
const FONT_BY_FAMILY = new Map();
|
|
97
|
+
for (const f of emailFontFamilies) {
|
|
98
|
+
for (const family of fontFamilyKey(f.stack).split(',')) {
|
|
99
|
+
if (!FONT_BY_FAMILY.has(family))
|
|
100
|
+
FONT_BY_FAMILY.set(family, f);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/** Whether `value` is exactly one of the stacks, give or take quotes, case
|
|
104
|
+
and spacing. */
|
|
105
|
+
function isEmailFontStack(value) {
|
|
106
|
+
return typeof value === 'string' && FONT_BY_KEY.has(fontFamilyKey(value));
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* The font a `font-family` value is. One of the stacks is itself; a stack of
|
|
110
|
+
* someone else's is the font it falls back to — the first of its families a
|
|
111
|
+
* stack names, its generic last: a builder's web font (`Ubuntu, Helvetica,
|
|
112
|
+
* Arial, sans-serif`) is Sans Serif, the face a client without that font
|
|
113
|
+
* draws anyway, and summernote's `'Comic Sans MS'` is Comic Sans MS.
|
|
114
|
+
* Nothing to fall back to, no font.
|
|
115
|
+
*/
|
|
116
|
+
function matchEmailFont(raw) {
|
|
117
|
+
if (!raw)
|
|
118
|
+
return null;
|
|
119
|
+
const key = fontFamilyKey(raw);
|
|
120
|
+
const exact = FONT_BY_KEY.get(key);
|
|
121
|
+
if (exact)
|
|
122
|
+
return exact;
|
|
123
|
+
for (const family of key.split(',')) {
|
|
124
|
+
const found = FONT_BY_FAMILY.get(family.trim());
|
|
125
|
+
if (found)
|
|
126
|
+
return found;
|
|
127
|
+
}
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/*
|
|
132
|
+
* Public API Surface of @h-k-dev/angular-email-editor/fonts
|
|
133
|
+
*
|
|
134
|
+
* Its own entry because it is plain data: a host whose other composer is
|
|
135
|
+
* not this editor (summernote) shares the font set without pulling in
|
|
136
|
+
* ProseMirror or Angular.
|
|
137
|
+
*/
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Generated bundle index. Do not edit.
|
|
141
|
+
*/
|
|
142
|
+
|
|
143
|
+
export { allowedFontSizes, emailDefaultFont, emailFontFaces, emailFontFamilies, emailFontSizes, fontClients, fontFamilyKey, isEmailFontStack, matchEmailFont };
|
|
144
|
+
//# sourceMappingURL=h-k-dev-angular-email-editor-fonts.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"h-k-dev-angular-email-editor-fonts.mjs","sources":["../../../projects/angular-email-editor/fonts/fonts.ts","../../../projects/angular-email-editor/fonts/public-api.ts","../../../projects/angular-email-editor/fonts/h-k-dev-angular-email-editor-fonts.ts"],"sourcesContent":["/**\n * The fonts an email is written in — Gmail's set, in Gmail's order — as\n * plain data: no Angular, no ProseMirror. The editor's `textStyle` mark\n * stores and emits only these stacks, the toolbar offers them, and an\n * editor of another kind (summernote's `fontNames`) can offer the same set\n * from the same constant, so a message reads the same font whichever\n * composer wrote it.\n */\n\n/**\n * A client a font is checked against — the three a writer's recipients\n * mostly read in, the same ids as the library's `RenderingClient`.\n */\nexport type FontClient = 'gmail' | 'apple-mail' | 'outlook-desktop';\n\n/** The clients, in the order a picker shows them (G, A, O), with the letter\n and name it shows them by. */\nexport const fontClients: readonly { id: FontClient; letter: string; name: string }[] = [\n { id: 'gmail', letter: 'G', name: 'Gmail' },\n { id: 'apple-mail', letter: 'A', name: 'Apple Mail' },\n { id: 'outlook-desktop', letter: 'O', name: 'Outlook' },\n];\n\n/** A font the editor offers: one of {@link emailFontFamilies}. */\nexport interface EmailFont {\n /** Stable, for a host's translation key: `sans-serif`, `fixed-width`, … */\n readonly id: string;\n /** The label, in English — Gmail's words. */\n readonly name: string;\n /**\n * The exact `font-family` value emitted — the canonical stored form. A\n * family name of more than one word is double-quoted: the CSSOM (Chrome's\n * and jsdom's alike) quotes it on reserialization, so the stored bytes are\n * already what comes back and a round trip is stable.\n */\n readonly stack: string;\n /** The face the stack is for — its first family, unquoted: what an editor\n that sets a single family (summernote) offers for it. */\n readonly face: string;\n /**\n * The clients that draw the face itself rather than its fallback — the\n * face is on the machine the client runs on:\n *\n * - `gmail`: Gmail on the web, read on Windows or macOS (it draws with\n * the reader's own fonts; one of them lacking the face is a no).\n * - `apple-mail`: Apple Mail on macOS *and* iOS — a phone lacks Arial\n * Black, Comic Sans, Tahoma.\n * - `outlook-desktop`: Outlook on Windows, which brings Office's fonts\n * (Arial Narrow, Garamond).\n *\n * Elsewhere the stack's fallback draws: the email still reads, in a near\n * face. Curated, conservative — a face only some readers have is a no.\n */\n readonly clients: readonly FontClient[];\n}\n\n/** The family names of a `font-family` value, unquoted, in order. */\nfunction familiesOf(stack: string): string[] {\n return stack\n .split(',')\n .map((family) => family.replace(/[\"']/g, '').trim())\n .filter(Boolean);\n}\n\nconst G: FontClient = 'gmail';\nconst A: FontClient = 'apple-mail';\nconst O: FontClient = 'outlook-desktop';\n\nfunction font(id: string, name: string, stack: string, clients: FontClient[]): EmailFont {\n return { id, name, stack, face: familiesOf(stack)[0], clients };\n}\n\n/**\n * Gmail's fonts, in its menu's order. A stack is the face, then what a\n * client without it should draw instead, then the generic. Each face leads\n * only its own stack, so a single family read back from another editor\n * (`font-family: 'Arial Black'`) finds its font exactly.\n *\n * The first stack naming a family claims it (see {@link matchEmailFont}):\n * `helvetica` and `sans-serif` read as Sans Serif, `times` and `serif` as\n * Serif, `courier` and `monospace` as Fixed width.\n */\nexport const emailFontFamilies: readonly EmailFont[] = [\n font('sans-serif', 'Sans Serif', 'Arial, Helvetica, sans-serif', [G, A, O]),\n font('serif', 'Serif', '\"Times New Roman\", Times, serif', [G, A, O]),\n font('fixed-width', 'Fixed width', '\"Courier New\", Courier, monospace', [G, A, O]),\n // Not on iOS.\n font('wide', 'Wide', '\"Arial Black\", sans-serif', [G, O]),\n // Office's, not Windows' own — nor on iOS.\n font('narrow', 'Narrow', '\"Arial Narrow\", sans-serif', [O]),\n // Not on iOS.\n font('comic-sans-ms', 'Comic Sans MS', '\"Comic Sans MS\", sans-serif', [G, O]),\n // Office's only: neither macOS, iOS nor Windows itself has it.\n font('garamond', 'Garamond', 'Garamond, \"Times New Roman\", serif', [O]),\n font('georgia', 'Georgia', 'Georgia, serif', [G, A, O]),\n // Not on iOS.\n font('tahoma', 'Tahoma', 'Tahoma, sans-serif', [G, O]),\n font('trebuchet-ms', 'Trebuchet MS', '\"Trebuchet MS\", sans-serif', [G, A, O]),\n font('verdana', 'Verdana', 'Verdana, sans-serif', [G, A, O]),\n];\n\n/**\n * The font a message is written in until the writer picks another — Gmail's\n * Sans Serif, Arial. Nothing is emitted for it: unstyled text is drawn in\n * the client's own default, as Gmail's is. An editor shows it as its\n * surface font, so what is written looks as it will in Gmail; summernote\n * takes its face (`fontName: emailDefaultFont.face`).\n */\nexport const emailDefaultFont: EmailFont = emailFontFamilies[0];\n\n/**\n * The faces of {@link emailFontFamilies}, in order — the set for an editor\n * that offers single families. For summernote, both lists: `fontNamesIgnoreCheck`\n * keeps a face this machine lacks (Garamond, Arial Narrow) in the menu.\n *\n * ```ts\n * $('#editor').summernote({ fontNames: emailFontFaces, fontNamesIgnoreCheck: emailFontFaces });\n * ```\n */\nexport const emailFontFaces: readonly string[] = emailFontFamilies.map((f) => f.face);\n\n/** Every size the editor stores, in px. */\nexport const allowedFontSizes = [10, 12, 14, 16, 18, 24, 32] as const;\nexport type FontSize = (typeof allowedFontSizes)[number];\n\n/**\n * The sizes a picker offers: the phone-safe subset (≥14px). Below ~13px iOS\n * auto-inflates text and reflows the layout, so they are not *offered* —\n * but every {@link allowedFontSizes} size is still read and kept, because a\n * hand-typed size in the HTML source is the author's own responsibility.\n */\nexport const emailFontSizes: readonly FontSize[] = [14, 16, 18, 24, 32];\n\n/** A `font-family` value as a comparison key: lower-cased, quotes dropped,\n whitespace around commas collapsed — so a hand-typed or CSSOM-reserialized\n stack matches a curated one regardless of cosmetic differences. */\nexport function fontFamilyKey(raw: string): string {\n return raw\n .toLowerCase()\n .replace(/[\"']/g, '')\n .replace(/\\s*,\\s*/g, ',')\n .trim();\n}\n\nconst FONT_BY_KEY = new Map(emailFontFamilies.map((f) => [fontFamilyKey(f.stack), f]));\n\n/** Each family a stack names to the first stack naming it. */\nconst FONT_BY_FAMILY = new Map<string, EmailFont>();\nfor (const f of emailFontFamilies) {\n for (const family of fontFamilyKey(f.stack).split(',')) {\n if (!FONT_BY_FAMILY.has(family)) FONT_BY_FAMILY.set(family, f);\n }\n}\n\n/** Whether `value` is exactly one of the stacks, give or take quotes, case\n and spacing. */\nexport function isEmailFontStack(value: unknown): value is string {\n return typeof value === 'string' && FONT_BY_KEY.has(fontFamilyKey(value));\n}\n\n/**\n * The font a `font-family` value is. One of the stacks is itself; a stack of\n * someone else's is the font it falls back to — the first of its families a\n * stack names, its generic last: a builder's web font (`Ubuntu, Helvetica,\n * Arial, sans-serif`) is Sans Serif, the face a client without that font\n * draws anyway, and summernote's `'Comic Sans MS'` is Comic Sans MS.\n * Nothing to fall back to, no font.\n */\nexport function matchEmailFont(raw: string | null | undefined): EmailFont | null {\n if (!raw) return null;\n const key = fontFamilyKey(raw);\n const exact = FONT_BY_KEY.get(key);\n if (exact) return exact;\n for (const family of key.split(',')) {\n const found = FONT_BY_FAMILY.get(family.trim());\n if (found) return found;\n }\n return null;\n}\n","/*\n * Public API Surface of @h-k-dev/angular-email-editor/fonts\n *\n * Its own entry because it is plain data: a host whose other composer is\n * not this editor (summernote) shares the font set without pulling in\n * ProseMirror or Angular.\n */\n\nexport * from './fonts';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,8 @@ import { NodeSelection, TextSelection, Plugin, PluginKey, EditorState, Selection
|
|
|
3
3
|
import { keymap } from 'prosemirror-keymap';
|
|
4
4
|
import { splitBlockAs, chainCommands, newlineInCode, createParagraphNear, liftEmptyBlock, setBlockType, exitCode, lift, wrapIn, toggleMark as toggleMark$1, baseKeymap } from 'prosemirror-commands';
|
|
5
5
|
import { tableEditing, fixTables, splitCell, mergeCells, deleteTable, deleteColumn, deleteRow, addRowAfter, addRowBefore, setCellAttr, removeColumn as removeColumn$1, removeRow, addColumn as addColumn$1, addRow, addColumnAfter, addColumnBefore, TableMap, isInTable, selectedRect, CellSelection, nextCell, goToNextCell } from 'prosemirror-tables';
|
|
6
|
+
import { allowedFontSizes, isEmailFontStack, matchEmailFont } from '@h-k-dev/angular-email-editor/fonts';
|
|
7
|
+
export * from '@h-k-dev/angular-email-editor/fonts';
|
|
6
8
|
import { AddMarkStep, RemoveMarkStep, Transform } from 'prosemirror-transform';
|
|
7
9
|
import { closeHistory, redo, undo, history } from 'prosemirror-history';
|
|
8
10
|
import { InputRule, inputRules, wrappingInputRule, textblockTypeInputRule } from 'prosemirror-inputrules';
|
|
@@ -1686,9 +1688,8 @@ function isUppercase(state, schema) {
|
|
|
1686
1688
|
});
|
|
1687
1689
|
return found;
|
|
1688
1690
|
}
|
|
1689
|
-
const ALLOWED_SIZES = [10, 12, 14, 16, 18, 24, 32];
|
|
1690
1691
|
function isSafeFontSize(value) {
|
|
1691
|
-
return
|
|
1692
|
+
return allowedFontSizes.includes(value);
|
|
1692
1693
|
}
|
|
1693
1694
|
/**
|
|
1694
1695
|
* Parse a font-size value from the DOM into one of our allowed sizes.
|
|
@@ -1705,8 +1706,8 @@ function parseFontSize(raw) {
|
|
|
1705
1706
|
// A size off the ladder — a builder's 11px, 13px, 15px — snaps to the
|
|
1706
1707
|
// nearest rung, upward on a tie: read as the size it is nearest to, not
|
|
1707
1708
|
// dropped to the default. (The schema still emits only its own rungs.)
|
|
1708
|
-
let nearest =
|
|
1709
|
-
for (const size of
|
|
1709
|
+
let nearest = allowedFontSizes[0];
|
|
1710
|
+
for (const size of allowedFontSizes) {
|
|
1710
1711
|
const better = Math.abs(size - n) < Math.abs(nearest - n) ||
|
|
1711
1712
|
(Math.abs(size - n) === Math.abs(nearest - n) && size > nearest);
|
|
1712
1713
|
if (better)
|
|
@@ -1714,79 +1715,19 @@ function parseFontSize(raw) {
|
|
|
1714
1715
|
}
|
|
1715
1716
|
return nearest;
|
|
1716
1717
|
}
|
|
1717
|
-
/**
|
|
1718
|
-
* The sizes the toolbar picker offers: the phone-safe subset (≥14px). Below
|
|
1719
|
-
* ~13px iOS auto-inflates text and reflows the layout (responsiveness ledger,
|
|
1720
|
-
* principle 8), so we don't *offer* those — but {@link parseFontSize} still
|
|
1721
|
-
* accepts the full {@link ALLOWED_SIZES} range, because a hand-typed size in
|
|
1722
|
-
* the HTML source pane is the author's own responsibility, exactly like a
|
|
1723
|
-
* hand-typed hex colour.
|
|
1724
|
-
*/
|
|
1725
|
-
const emailFontSizes = [14, 16, 18, 24, 32];
|
|
1726
|
-
/**
|
|
1727
|
-
* The curated font stacks — the picker offers only these, no free-form fonts
|
|
1728
|
-
* (principle 7: if a mainstream client can't render it, we don't emit it).
|
|
1729
|
-
*
|
|
1730
|
-
* Deliberately built from *single-word* family identifiers plus a generic
|
|
1731
|
-
* fallback: a stack like `Courier New` would round-trip through the CSSOM
|
|
1732
|
-
* (serialization builds real elements and re-reads them) and come back quoted
|
|
1733
|
-
* as `"Courier New"` in Chrome but unquoted in jsdom — a byte-instability that
|
|
1734
|
-
* breaks canonical determinism and makes tests disagree with the runtime (the
|
|
1735
|
-
* same trap the longhand/`rgb()` rule guards against). Bare identifiers and
|
|
1736
|
-
* generic keywords serialize identically everywhere.
|
|
1737
|
-
*/
|
|
1738
|
-
const emailFontFamilies = [
|
|
1739
|
-
{ name: 'Sans-serif', stack: 'Arial, Helvetica, sans-serif' },
|
|
1740
|
-
{ name: 'Serif', stack: 'Georgia, Times, serif' },
|
|
1741
|
-
{ name: 'Monospace', stack: 'Courier, monospace' },
|
|
1742
|
-
{ name: 'System', stack: 'system-ui, sans-serif' },
|
|
1743
|
-
];
|
|
1744
|
-
/** Normalise a `font-family` value to a comparison key: lower-cased, quotes
|
|
1745
|
-
dropped, whitespace around commas collapsed. Lets a hand-typed or CSSOM-
|
|
1746
|
-
reserialized stack match a curated one regardless of cosmetic differences. */
|
|
1747
|
-
function fontFamilyKey(raw) {
|
|
1748
|
-
return raw
|
|
1749
|
-
.toLowerCase()
|
|
1750
|
-
.replace(/["']/g, '')
|
|
1751
|
-
.replace(/\s*,\s*/g, ',')
|
|
1752
|
-
.trim();
|
|
1753
|
-
}
|
|
1754
|
-
const FONT_STACK_BY_KEY = new Map(emailFontFamilies.map((f) => [fontFamilyKey(f.stack), f.stack]));
|
|
1755
|
-
/** Each family a curated stack names — a face or its generic — to the first
|
|
1756
|
-
stack naming it: `helvetica` and `sans-serif` to Sans-serif, `times` and
|
|
1757
|
-
`serif` to Serif. */
|
|
1758
|
-
const FONT_STACK_BY_FAMILY = new Map();
|
|
1759
|
-
for (const { stack } of emailFontFamilies) {
|
|
1760
|
-
for (const family of fontFamilyKey(stack).split(',')) {
|
|
1761
|
-
if (!FONT_STACK_BY_FAMILY.has(family))
|
|
1762
|
-
FONT_STACK_BY_FAMILY.set(family, stack);
|
|
1763
|
-
}
|
|
1764
|
-
}
|
|
1718
|
+
/** Whether `value` is one of the curated stacks (`@h-k-dev/angular-email-editor/fonts`). */
|
|
1765
1719
|
function isSafeFontFamily(value) {
|
|
1766
|
-
return
|
|
1720
|
+
return isEmailFontStack(value);
|
|
1767
1721
|
}
|
|
1768
1722
|
/**
|
|
1769
|
-
* Parse a font-family value from the DOM into one of
|
|
1723
|
+
* Parse a font-family value from the DOM into one of the curated stacks,
|
|
1770
1724
|
* returning the *canonical* stack string (so a cosmetically different but
|
|
1771
1725
|
* equivalent input normalises to the exact bytes we emit). A stack of
|
|
1772
|
-
* someone else's reads as the curated one it falls back to
|
|
1773
|
-
*
|
|
1774
|
-
* font (`Ubuntu, Helvetica, Arial, sans-serif`) is Sans-serif, the face a
|
|
1775
|
-
* client without that font draws anyway. Nothing to fall back to, no font.
|
|
1726
|
+
* someone else's reads as the curated one it falls back to
|
|
1727
|
+
* ({@link matchEmailFont}). Nothing to fall back to, no font.
|
|
1776
1728
|
*/
|
|
1777
1729
|
function parseFontFamily(raw) {
|
|
1778
|
-
|
|
1779
|
-
return null;
|
|
1780
|
-
const key = fontFamilyKey(raw);
|
|
1781
|
-
const exact = FONT_STACK_BY_KEY.get(key);
|
|
1782
|
-
if (exact)
|
|
1783
|
-
return exact;
|
|
1784
|
-
for (const family of key.split(',')) {
|
|
1785
|
-
const stack = FONT_STACK_BY_FAMILY.get(family.trim());
|
|
1786
|
-
if (stack)
|
|
1787
|
-
return stack;
|
|
1788
|
-
}
|
|
1789
|
-
return null;
|
|
1730
|
+
return matchEmailFont(raw)?.stack ?? null;
|
|
1790
1731
|
}
|
|
1791
1732
|
/**
|
|
1792
1733
|
* TipTap-style `textStyle` mark: a `<span style="…">` container holding inline
|
|
@@ -15626,12 +15567,16 @@ const createBubbleMenu = (options) => defineExtension({
|
|
|
15626
15567
|
let mouseSelecting = false;
|
|
15627
15568
|
let destroyed = false;
|
|
15628
15569
|
let open = false;
|
|
15570
|
+
// Where the open menu stands (`anchor: 'first'`): the range or the
|
|
15571
|
+
// node it opened over, and the box measured there.
|
|
15572
|
+
let pinned = null;
|
|
15629
15573
|
// Closed is said once: a caret moving through the text, or a press
|
|
15630
15574
|
// elsewhere on the page, is no news to a host that already knows.
|
|
15631
15575
|
const close = () => {
|
|
15632
15576
|
if (!open)
|
|
15633
15577
|
return;
|
|
15634
15578
|
open = false;
|
|
15579
|
+
pinned = null;
|
|
15635
15580
|
options.onStateChange({ isOpen: false, boundingBox: null });
|
|
15636
15581
|
};
|
|
15637
15582
|
// Whether the menu may show: not mid-drag, the host's say-so, and
|
|
@@ -15641,40 +15586,16 @@ const createBubbleMenu = (options) => defineExtension({
|
|
|
15641
15586
|
!mouseSelecting &&
|
|
15642
15587
|
(options.shouldShow || defaultBubbleShouldShow)(view.state) &&
|
|
15643
15588
|
view.hasFocus();
|
|
15644
|
-
//
|
|
15645
|
-
|
|
15646
|
-
|
|
15647
|
-
// have opened something of its own there (a click on a button
|
|
15648
|
-
// opens its link editor) that its `shouldShow` now says no to.
|
|
15649
|
-
if (!canShow())
|
|
15650
|
-
return close();
|
|
15651
|
-
// An image alone, or a button: the menu stands over the node
|
|
15652
|
-
// itself.
|
|
15653
|
-
const image = selectedImage(view.state);
|
|
15654
|
-
const button = image ? null : selectedButton(view.state);
|
|
15655
|
-
const node = image ?? button;
|
|
15656
|
-
const dom = node && view.nodeDOM(node.pos);
|
|
15657
|
-
if (dom && typeof dom.getBoundingClientRect === 'function') {
|
|
15658
|
-
open = true;
|
|
15659
|
-
options.onStateChange({
|
|
15660
|
-
isOpen: true,
|
|
15661
|
-
boundingBox: dom.getBoundingClientRect(),
|
|
15662
|
-
kind: image ? 'image' : 'button',
|
|
15663
|
-
});
|
|
15664
|
-
return;
|
|
15665
|
-
}
|
|
15666
|
-
const { from, to } = view.state.selection;
|
|
15667
|
-
// Get coordinates of the selection boundaries
|
|
15589
|
+
// The box of a range: from its start to its end, over every line it
|
|
15590
|
+
// takes — the virtual DOMRect the host's overlay anchors to.
|
|
15591
|
+
const rangeBox = (from, to) => {
|
|
15668
15592
|
const start = view.coordsAtPos(from);
|
|
15669
15593
|
const end = view.coordsAtPos(to, -1);
|
|
15670
|
-
// Construct a virtual DOMRect representing the text selection.
|
|
15671
|
-
// Angular CDK uses this to anchor the overlay!
|
|
15672
15594
|
const top = Math.min(start.top, end.top);
|
|
15673
15595
|
const bottom = Math.max(start.bottom, end.bottom);
|
|
15674
15596
|
const left = Math.min(start.left, end.left);
|
|
15675
15597
|
const right = Math.max(start.right, end.right);
|
|
15676
|
-
|
|
15677
|
-
const boundingBox = {
|
|
15598
|
+
return {
|
|
15678
15599
|
top,
|
|
15679
15600
|
bottom,
|
|
15680
15601
|
left,
|
|
@@ -15685,8 +15606,51 @@ const createBubbleMenu = (options) => defineExtension({
|
|
|
15685
15606
|
y: top,
|
|
15686
15607
|
toJSON: () => '',
|
|
15687
15608
|
};
|
|
15609
|
+
};
|
|
15610
|
+
// The box of a node: its own element's, while it has one.
|
|
15611
|
+
const nodeBox = (pos) => {
|
|
15612
|
+
const dom = view.nodeDOM(pos);
|
|
15613
|
+
return dom && typeof dom.getBoundingClientRect === 'function'
|
|
15614
|
+
? dom.getBoundingClientRect()
|
|
15615
|
+
: null;
|
|
15616
|
+
};
|
|
15617
|
+
// Reports the menu open over the current selection — standing
|
|
15618
|
+
// where it opened (`anchor: 'first'`), or over the selection of
|
|
15619
|
+
// the moment. `remeasure`: the pinned place has moved on screen
|
|
15620
|
+
// (a scroll), so its box is measured again.
|
|
15621
|
+
const show = (remeasure = false) => {
|
|
15622
|
+
// Asked again once the delay is over: in between, the host may
|
|
15623
|
+
// have opened something of its own there (a click on a button
|
|
15624
|
+
// opens its link editor) that its `shouldShow` now says no to.
|
|
15625
|
+
if (!canShow())
|
|
15626
|
+
return close();
|
|
15627
|
+
// An image alone, or a button: the menu is for the node, and
|
|
15628
|
+
// stands over the node itself — while it has an element to
|
|
15629
|
+
// stand over; text otherwise.
|
|
15630
|
+
const image = selectedImage(view.state);
|
|
15631
|
+
const button = image ? null : selectedButton(view.state);
|
|
15632
|
+
const node = image ?? button;
|
|
15633
|
+
const box = node ? nodeBox(node.pos) : null;
|
|
15634
|
+
const kind = box ? (image ? 'image' : 'button') : 'text';
|
|
15635
|
+
if (pinned && (options.anchor ?? 'first') === 'first') {
|
|
15636
|
+
if (remeasure) {
|
|
15637
|
+
// The same place, where it now is — clamped, in case the
|
|
15638
|
+
// document shrank under it since.
|
|
15639
|
+
const size = view.state.doc.content.size;
|
|
15640
|
+
const from = Math.min(pinned.from, size);
|
|
15641
|
+
pinned.box =
|
|
15642
|
+
(pinned.node ? nodeBox(from) : rangeBox(from, Math.min(pinned.to, size))) ??
|
|
15643
|
+
pinned.box;
|
|
15644
|
+
}
|
|
15645
|
+
options.onStateChange({ isOpen: true, boundingBox: pinned.box, kind });
|
|
15646
|
+
return;
|
|
15647
|
+
}
|
|
15648
|
+
const { from, to } = view.state.selection;
|
|
15649
|
+
pinned = box
|
|
15650
|
+
? { from: node.pos, to: node.pos, node: true, box }
|
|
15651
|
+
: { from, to, node: false, box: rangeBox(from, to) };
|
|
15688
15652
|
open = true;
|
|
15689
|
-
options.onStateChange({ isOpen: true, boundingBox, kind
|
|
15653
|
+
options.onStateChange({ isOpen: true, boundingBox: pinned.box, kind });
|
|
15690
15654
|
};
|
|
15691
15655
|
const refresh = () => {
|
|
15692
15656
|
if (destroyed)
|
|
@@ -15696,16 +15660,17 @@ const createBubbleMenu = (options) => defineExtension({
|
|
|
15696
15660
|
close();
|
|
15697
15661
|
return;
|
|
15698
15662
|
}
|
|
15699
|
-
// Open already: the menu
|
|
15700
|
-
// and its box
|
|
15701
|
-
// so what a host renders from the
|
|
15702
|
-
// from the editor (an image's alt,
|
|
15703
|
-
// disagree. Delayed, the image's menu
|
|
15704
|
-
//
|
|
15705
|
-
//
|
|
15706
|
-
//
|
|
15707
|
-
//
|
|
15708
|
-
//
|
|
15663
|
+
// Open already: the menu answers the selection *now* — its kind
|
|
15664
|
+
// (and, following the selection, its box) changes in the same
|
|
15665
|
+
// transaction the selection did, so what a host renders from the
|
|
15666
|
+
// state and what it reads live from the editor (an image's alt,
|
|
15667
|
+
// an action's enabled) never disagree. Delayed, the image's menu
|
|
15668
|
+
// showed the alt of an image no longer selected alone — empty —
|
|
15669
|
+
// and its image tools disabled, for the delay, before the text's
|
|
15670
|
+
// menu replaced it. The delay is for *opening*: a range passing
|
|
15671
|
+
// through, a drag's intermediate selections, never pop a menu of
|
|
15672
|
+
// their own. Pinned (`anchor: 'first'`), the box stays where the
|
|
15673
|
+
// menu opened.
|
|
15709
15674
|
if (open)
|
|
15710
15675
|
return show();
|
|
15711
15676
|
showTimer = setTimeout(show, options.updateDelay ?? 150);
|
|
@@ -15742,7 +15707,7 @@ const createBubbleMenu = (options) => defineExtension({
|
|
|
15742
15707
|
close,
|
|
15743
15708
|
refresh: () => {
|
|
15744
15709
|
if (open)
|
|
15745
|
-
show();
|
|
15710
|
+
show(true);
|
|
15746
15711
|
},
|
|
15747
15712
|
});
|
|
15748
15713
|
return {
|
|
@@ -18816,5 +18781,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
|
|
|
18816
18781
|
* Generated bundle index. Do not edit.
|
|
18817
18782
|
*/
|
|
18818
18783
|
|
|
18819
|
-
export { AUTHORED_ATTR, AUTHORED_SPEC_KEY, AUTHORED_STYLE_DEFAULTS_KEY, AuthoredEnter, BLOCKQUOTE_STYLE, BLOCK_MENU_FOCUS_KEY, BUTTON_FILL, BUTTON_STYLE, BaseKeymap, Blockquote, Bold, BulletList, Button, CARET_ROOM, CLIENT_LABELS, COMMENT_TAG, CONTENT_ATTRS, CSS_SUPPORT, ClearFormatting, CodeLine, CodeLineIndent, Column, ColumnResize, Columns, ColumnsResize, DOCUMENT_CLASS, DOCUMENT_TAGS, DUAL_BACKGROUND_MIN_RATIO, DUAL_CONTRAST_DARK, DUAL_CONTRAST_LIGHT, DUAL_CONTRAST_MIN_RATIO, Divider, Document$1 as Document, DocumentStyles, EMAIL_ATTRIBUTES, EMAIL_CSS_PROPERTIES, EMAIL_SAFE_STYLE_PROPERTIES, EMAIL_SAFE_TAGS, EMAIL_TAGS, EMAIL_TAG_ATTRIBUTES, EmailParagraph, FILE_CHOOSER_POINTER_WAIT, FILL_TEXT_COLOR, FILL_TEXT_COLOR_LIGHT, FILL_TEXT_COLOR_RGB, FOLD_WIDTH, FORMAT_WIDTH, GMAIL_CLIP_BYTES, GUIDES_ACTIVE_CLASS, GUIDES_PEEK_CLASS, GUIDES_PEEK_DELAY_MS, Gapcursor, HEADING_SIZES, HardBreak, Heading, History, HtmlComment, HtmlCommentInline, HtmlElement, HtmlInline, HtmlLanguage, HtmlRaw, HtmlTextElement, HtmlVoid, HtmlVoidBlock, IMPORT_VIEWPORT_WIDTH, INDENT_MAX, INDENT_STEP, INLINE_TAGS, INLINE_VOID_TAGS, IN_SELECTION_CLASS, Image, InlineAtomSelection, InlineImageStore, InlineImages, Italic, LIST_STYLE, LayoutGuides, Link, ListItem, MAX_COLUMNS, MAX_IMAGE_WIDTH, MAX_MERGE_TAG_LENGTH, MAX_UNBROKEN_RUN, MIN_COLUMN_CAP, MIN_COLUMN_PCT, MIN_FONT_SIZE, MIN_IMAGE_WIDTH, MIN_TABLE_PCT, MJML_WORLDLY_HTML, MergeTag, NoTextDrag, OrderedList, PARSE_SCOPE_KEY, PLACEHOLDER_WIDTH, Paragraph, PasteHygiene, QuotedHistory, REFUSED_TAGS, RENDERING_CLIENTS, SECTION_CONTENT_MAX, SECTION_INSET, SECTION_PADDING, STACK_CLASS, STACK_RULE, Section, SplitKeepingMarks, TABLE_BORDER_COLOR, TABLE_CELL_PADDING, TABLE_SECTION_TAGS, TYPING_REST, Table, TableCell, TableRow, Text, TextStyle, UNSET_BUTTON_HREF, Underline, VOID_TAGS, acceptProposal, addColumn, addColumnAtEnd, addRowAtEnd, analyzeAngularExpression, angularDialect, angularRequiredFields, applyAuthoredAttributes, applyEmailVocabulary, attributeString, authoredAttribute, authoredMarkupOf, authoredViewAttributes, bareButtons, buttonStyle, canonicalHead, canonicalMergeTagInner, canonicalRender, caretCellPos, caretInsideMergeTag, claimedImageFiles, clearCells, clientList, columnCaps, columnWidths, completionContextAt, containerStyle, contrastRatio, correctStoredMistakes, createAngularExpressions, createBlockMenu, createBubbleMenu, createButtonEdit, createContentProposal, createContentStream, createDOMParser, createEditor, createHtmlAutocomplete, createHtmlLanguage, createImageDrag, createInlineImages, createMergeTagResolution, createOffsetMapper, createQuotedHistory, createSchema, createSendIntent, createSourceMarks, createSuggestionMenu, createTableHandles, declarationProperty, declaredBackground, decodeDataUrl, defaultBubbleShouldShow, defineExtension, defineMark, defineNode, deleteColumns, deleteFullySelected, discardProposal, distributePadding, docText, dropDeadOfficeClasses, dropHidden, dropMediaQueries, dropZeroSizedWhitespace, duplicateColumn, duplicateRow, editQuotedHistory, effectiveWidths, emailBackgroundPalette, emailDocument, emailExtensions,
|
|
18784
|
+
export { AUTHORED_ATTR, AUTHORED_SPEC_KEY, AUTHORED_STYLE_DEFAULTS_KEY, AuthoredEnter, BLOCKQUOTE_STYLE, BLOCK_MENU_FOCUS_KEY, BUTTON_FILL, BUTTON_STYLE, BaseKeymap, Blockquote, Bold, BulletList, Button, CARET_ROOM, CLIENT_LABELS, COMMENT_TAG, CONTENT_ATTRS, CSS_SUPPORT, ClearFormatting, CodeLine, CodeLineIndent, Column, ColumnResize, Columns, ColumnsResize, DOCUMENT_CLASS, DOCUMENT_TAGS, DUAL_BACKGROUND_MIN_RATIO, DUAL_CONTRAST_DARK, DUAL_CONTRAST_LIGHT, DUAL_CONTRAST_MIN_RATIO, Divider, Document$1 as Document, DocumentStyles, EMAIL_ATTRIBUTES, EMAIL_CSS_PROPERTIES, EMAIL_SAFE_STYLE_PROPERTIES, EMAIL_SAFE_TAGS, EMAIL_TAGS, EMAIL_TAG_ATTRIBUTES, EmailParagraph, FILE_CHOOSER_POINTER_WAIT, FILL_TEXT_COLOR, FILL_TEXT_COLOR_LIGHT, FILL_TEXT_COLOR_RGB, FOLD_WIDTH, FORMAT_WIDTH, GMAIL_CLIP_BYTES, GUIDES_ACTIVE_CLASS, GUIDES_PEEK_CLASS, GUIDES_PEEK_DELAY_MS, Gapcursor, HEADING_SIZES, HardBreak, Heading, History, HtmlComment, HtmlCommentInline, HtmlElement, HtmlInline, HtmlLanguage, HtmlRaw, HtmlTextElement, HtmlVoid, HtmlVoidBlock, IMPORT_VIEWPORT_WIDTH, INDENT_MAX, INDENT_STEP, INLINE_TAGS, INLINE_VOID_TAGS, IN_SELECTION_CLASS, Image, InlineAtomSelection, InlineImageStore, InlineImages, Italic, LIST_STYLE, LayoutGuides, Link, ListItem, MAX_COLUMNS, MAX_IMAGE_WIDTH, MAX_MERGE_TAG_LENGTH, MAX_UNBROKEN_RUN, MIN_COLUMN_CAP, MIN_COLUMN_PCT, MIN_FONT_SIZE, MIN_IMAGE_WIDTH, MIN_TABLE_PCT, MJML_WORLDLY_HTML, MergeTag, NoTextDrag, OrderedList, PARSE_SCOPE_KEY, PLACEHOLDER_WIDTH, Paragraph, PasteHygiene, QuotedHistory, REFUSED_TAGS, RENDERING_CLIENTS, SECTION_CONTENT_MAX, SECTION_INSET, SECTION_PADDING, STACK_CLASS, STACK_RULE, Section, SplitKeepingMarks, TABLE_BORDER_COLOR, TABLE_CELL_PADDING, TABLE_SECTION_TAGS, TYPING_REST, Table, TableCell, TableRow, Text, TextStyle, UNSET_BUTTON_HREF, Underline, VOID_TAGS, acceptProposal, addColumn, addColumnAtEnd, addRowAtEnd, analyzeAngularExpression, angularDialect, angularRequiredFields, applyAuthoredAttributes, applyEmailVocabulary, attributeString, authoredAttribute, authoredMarkupOf, authoredViewAttributes, bareButtons, buttonStyle, canonicalHead, canonicalMergeTagInner, canonicalRender, caretCellPos, caretInsideMergeTag, claimedImageFiles, clearCells, clientList, columnCaps, columnWidths, completionContextAt, containerStyle, contrastRatio, correctStoredMistakes, createAngularExpressions, createBlockMenu, createBubbleMenu, createButtonEdit, createContentProposal, createContentStream, createDOMParser, createEditor, createHtmlAutocomplete, createHtmlLanguage, createImageDrag, createInlineImages, createMergeTagResolution, createOffsetMapper, createQuotedHistory, createSchema, createSendIntent, createSourceMarks, createSuggestionMenu, createTableHandles, declarationProperty, declaredBackground, decodeDataUrl, defaultBubbleShouldShow, defineExtension, defineMark, defineNode, deleteColumns, deleteFullySelected, discardProposal, distributePadding, docText, dropDeadOfficeClasses, dropHidden, dropMediaQueries, dropZeroSizedWhitespace, duplicateColumn, duplicateRow, editQuotedHistory, effectiveWidths, emailBackgroundPalette, emailDocument, emailExtensions, emailPlainText, emailSizeBudget, emailTextPalette, embedsAsLinks, entitySpans, escapeAttribute$2 as escapeAttribute, escapeText$1 as escapeText, expressionDialect, expressionDialectKey, extensionActions, extensionSuggestions, fillTextColor, filledPlaceholderAttrs, filterEmailStyle, findColumnContext, findColumnsContext, findCssIssues, findListDepth, findSectionContext, findTableContext, fitImageWidth, foldHTML, formatHTML, formatPct, forwardDocument, forwardQuote, hasBlockChildren$1 as hasBlockChildren, hasDocumentEnvelope, headingStyle, holdsBlock, holdsColumn, hrefProblem, htmlSourceExtensions, imageDropTarget, importLoss, importedDocument, inheritTextStyles, inheritedMarkup, inlineBootstrapTableBorders, inlineImageCids, inlineImageRegistry, inlineImagesKey, inlineStyles, insertHTML, insertMergeTag, isActionEnabled, isBlock$1 as isBlock, isBlockLevel, isBlockish, isBooleanAttribute, isEmailAttribute, isEmailCssProperty, isEmailTag, isFillTextColor, isInlineAtom, isMarkActive, isMergeTagExpression, isMergeTagPath, isNodeActive, isPadded, isProposing, isQuotedHistoryFolded, isSafeColor, isSafeFontFamily, isSafeFontSize, isSafeUrl$1 as isSafeUrl, isSectionImageUrl, isStreaming, italicStarInputRegex, italicStarPasteRegex, italicUnderscoreInputRegex, italicUnderscorePasteRegex, keepGmailRules, layoutBlockAt, linkClickPlugin, linkPastePlugin, linkRangeAt, lintHTML, lowerInlinesAroundBlocks, markAttrsOf, markStackingColumns, marksAcrossBreak, materializeComments, measureMenuPlacement, mediaMatches, mergeTagAt, mergeTagExpressions, mergeTagFields, mergeTagRanges, mergeTagResolutionPending, moveColumn, moveRow, normalizeCommentText, normalizeCss, normalizeHref, normalizeMergeTagText, noteOwnWidths, openFileChooser, openTag$1 as openTag, openTags, outlookColumns, paddingOf, parseAngularExpression, parseDocument, parseFontFamily, parseFontSize, parseHTML, parsePadding, parseRules, parseTextTransform, passesDualBackground, passesDualContrast, preserveExtensions, preservedAttributes, promoteInlineImages, promoteMergeTags, proposalRange, proposeContent, quotedHistory, readEnvelope, readImageFile, realizeComments, relativeLuminance, removeColumn, removeQuotedHistory, renderForClient, renderedPath, repairLinkSchemes, repairTables, replaceHTML, replyDocument, replyEnvelope, replyQuote, reviseProposal, rewriteInlineImageSources, richTextExtensions, ruleForScope, ruleScope, sanitizePastedHTML, scanHTML, scanMergeTags, scopeOf$1 as scopeOf, scopedDocumentCss, selectColumn, selectRow, selectedButton, selectedImage, selectedImageAlt, selectedMarkAtom, selectionInsideMergeTag, serializeDocument, serializeToHTML, setCellBackground, setColumnBackground, setColumnBoundary, setColumnsBoundary, setQuotedHistory, setSectionBackground, setSectionImage, setTableBox, setTableWidth, soleInlineAtom, splitDeclarations$2 as splitDeclarations, splitListItemKeepMarks, starInputRegex, starPasteRegex, stopProposal, streamContent, streamedRange, streamingRange, suggestionSectionTitles, tableStyle, textOffsetAt, textRegions, toEmailSafeColor, toInboundMessage, toggleList, trimInlineBoxes, underscoreInputRegex, underscorePasteRegex, unwrapLayoutTables, unwrapOfficeParagraphMarks, verbatimElement, videoPage, watchMenuScroll, withAttribute, withAuthoredMarkup, withQuoted, withQuotedHistory, withStyleDeclaration, withoutAttribute, withoutStyleDeclaration };
|
|
18820
18785
|
//# sourceMappingURL=h-k-dev-angular-email-editor.mjs.map
|