@nerd-bible/wordgard 0.3.3

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.
@@ -0,0 +1,90 @@
1
+ import { Transaction, GardState } from 'wordgard/state';
2
+ import { ChangeSet } from 'wordgard/doc';
3
+ import { Command, Menu } from 'wordgard/command';
4
+
5
+ interface HistoryConfig {
6
+ /**
7
+ The minimum depth (amount of events) to store. Defaults to 100.
8
+ */
9
+ minDepth?: number;
10
+ /**
11
+ The maximum time (in milliseconds) that adjacent events can be
12
+ apart and still be grouped together. Defaults to 500.
13
+ */
14
+ newGroupDelay?: number;
15
+ /**
16
+ By default, when close enough together in time, changes are
17
+ joined into an existing undo event if they touch any of the
18
+ changed ranges from that event. You can pass a custom predicate
19
+ here to influence that logic.
20
+ */
21
+ joinToEvent?: (tr: Transaction, isAdjacent: boolean) => boolean;
22
+ }
23
+ /**
24
+ Create a history extension with the given configuration. Will
25
+ include the state field that tracks history, handlers for the
26
+ {@link undo} and {@link redo} commands that make use of it, and
27
+ the {@link undoButton undo}/{@link redoButton redo} menu buttons.
28
+ */
29
+ declare function history(config?: HistoryConfig): GardState.Extension;
30
+ declare namespace history {
31
+ /**
32
+ The state field used to store the history data. Should probably
33
+ only be used when you want to {@link GardState.toJSON serialize}
34
+ or {@link GardState.fromJSON deserialize} state objects in a
35
+ way that preserves history.
36
+ */
37
+ const field: GardState.Field<unknown>;
38
+ /**
39
+ Transaction annotation that will prevent that transaction from
40
+ being combined with other transactions in the undo history. Given
41
+ `"before"`, it'll prevent merging with previous transactions. With
42
+ `"after"`, subsequent transactions won't be combined with this
43
+ one. With `true`, the transaction is isolated on both sides.
44
+ */
45
+ const isolate: Transaction.Annotation.Type<true | "after" | "before">;
46
+ /**
47
+ This facet provides a way to register functions that, given a
48
+ transaction, provide a set of effects that the history should
49
+ store when inverting the transaction. This can be used to
50
+ integrate specific effects in the history, so that they can be
51
+ undone (and redone again).
52
+ */
53
+ const invertedEffects: GardState.Facet<(tr: Transaction) => readonly Transaction.Effect<any>[], readonly ((tr: Transaction) => readonly Transaction.Effect<any>[])[]>;
54
+ type EventJSON = {
55
+ changes: ChangeSet.JSON;
56
+ selection: unknown;
57
+ };
58
+ type JSON = {
59
+ done: readonly EventJSON[];
60
+ undone: readonly EventJSON[];
61
+ };
62
+ }
63
+ /**
64
+ Undo a single group of history events. Returns false if no group
65
+ is available.
66
+ */
67
+ declare const undo: Command.Pure;
68
+ /**
69
+ Redo a single group of undone history events. Returns false if no
70
+ group is available.
71
+ */
72
+ declare const redo: Command.Pure;
73
+ /**
74
+ The amount of undoable change events available in a given state.
75
+ */
76
+ declare const undoDepth: (state: GardState) => number;
77
+ /**
78
+ The amount of redoable change events available in a given state.
79
+ */
80
+ declare const redoDepth: (state: GardState) => number;
81
+ /**
82
+ A menu button that undoes a change.
83
+ */
84
+ declare const undoButton: Menu.Button;
85
+ /**
86
+ A menu button that redoes an undone change.
87
+ */
88
+ declare const redoButton: Menu.Button;
89
+
90
+ export { history, redo, redoButton, redoDepth, undo, undoButton, undoDepth };
@@ -0,0 +1,278 @@
1
+ import { Transaction, GardState, GardSelection } from 'wordgard/state';
2
+ import { ChangeSet } from 'wordgard/doc';
3
+ import { Command, undo as undo$1, redo as redo$1, Menu } from 'wordgard/command';
4
+ import { phrases } from 'wordgard/phrases';
5
+
6
+ const fromHistory = /*@__PURE__*/Transaction.Annotation.define();
7
+ const historyConfig = /*@__PURE__*/GardState.Facet.define({
8
+ combine(configs) {
9
+ return GardState.Facet.combineConfig(configs, {
10
+ minDepth: 100,
11
+ newGroupDelay: 500,
12
+ joinToEvent: (_t, isAdjacent) => isAdjacent,
13
+ }, {
14
+ minDepth: Math.max,
15
+ newGroupDelay: Math.min,
16
+ joinToEvent: (a, b) => (tr, adj) => a(tr, adj) || b(tr, adj)
17
+ });
18
+ }
19
+ });
20
+ const historyField_ = /*@__PURE__*/GardState.Field.define({
21
+ create() {
22
+ return new HistoryState(null, null);
23
+ },
24
+ update(state, tr) {
25
+ let config = tr.state.facet(historyConfig);
26
+ let fromHist = tr.annotation(fromHistory);
27
+ if (fromHist) {
28
+ let from = fromHist.side, event = eventFromTransaction(tr);
29
+ let other = from == 0 ? state.undone : state.done;
30
+ if (event)
31
+ other = new Branch(event.changes, event.effects, null, tr.startState.selection, other);
32
+ return new HistoryState(from == 0 ? fromHist.rest : other, from == 0 ? other : fromHist.rest);
33
+ }
34
+ let isolate = tr.annotation(history.isolate);
35
+ if (isolate == true || isolate == "before")
36
+ state = state.isolate();
37
+ if (tr.annotation(Transaction.addToHistory) === false)
38
+ return tr.changes.empty ? state : new HistoryState(state.done && state.done.addMapping(tr.changes, tr.startState.doc), state.undone && state.undone.addMapping(tr.changes, tr.startState.doc), state.prevTime, state.prevUserEvent);
39
+ let event = eventFromTransaction(tr);
40
+ let time = tr.annotation(Transaction.time), userEvent = tr.annotation(Transaction.userEvent);
41
+ if (event)
42
+ state = state.addChanges(event, time, userEvent, config, tr);
43
+ if (isolate == true || isolate == "after")
44
+ state = state.isolate();
45
+ return state.clip(config.minDepth);
46
+ },
47
+ toJSON(value, state) {
48
+ let mkJSON = (value) => {
49
+ let events = [];
50
+ for (let cur = value; cur; cur = cur.next)
51
+ events.push({ changes: cur.changes.toJSON(), selection: cur.startSelection.toJSON(state) });
52
+ return events;
53
+ };
54
+ return {
55
+ done: mkJSON(value.done = value.done && value.done.resolveFully(state.config)),
56
+ undone: mkJSON(value.undone = value.undone && value.undone.resolveFully(state.config))
57
+ };
58
+ },
59
+ fromJSON(json, state) {
60
+ if (!json || !Array.isArray(json.done) || !Array.isArray(json.undone))
61
+ throw new RangeError("Invalid history JSON");
62
+ let buildBranch = (json) => {
63
+ let result = null;
64
+ for (let i = json.length - 1; i >= 0; i--)
65
+ result = new Branch(ChangeSet.fromJSON(state.schema, json[i].changes), none, null, GardSelection.fromJSON(state, json[i].selection), result);
66
+ return result;
67
+ };
68
+ return new HistoryState(buildBranch(json.done), buildBranch(json.undone));
69
+ }
70
+ });
71
+ function history(config = {}) {
72
+ return [
73
+ historyField_,
74
+ historyConfig.of(config),
75
+ Command.handler(undo$1, undo),
76
+ Command.handler(redo$1, redo),
77
+ undoButton,
78
+ redoButton,
79
+ ];
80
+ }
81
+ ;history = /*@__PURE__*/(function (history) {
82
+ history.field = historyField_;
83
+ history.isolate = Transaction.Annotation.define();
84
+ history.invertedEffects = GardState.Facet.define();
85
+ ;return history})(history);
86
+ const undo = ({ state }) => {
87
+ let historyState = state.field(historyField_, false);
88
+ if (state.readOnly || !historyState)
89
+ return false;
90
+ return historyState.pop(0, state);
91
+ };
92
+ const redo = ({ state }) => {
93
+ let historyState = state.field(historyField_, false);
94
+ if (state.readOnly || !historyState)
95
+ return false;
96
+ return historyState.pop(1, state);
97
+ };
98
+ function depth(branch) {
99
+ return branch ? branch.depth : 0;
100
+ }
101
+ const undoDepth = (state) => depth(state.field(historyField_, false)?.done);
102
+ const redoDepth = (state) => depth(state.field(historyField_, false)?.undone);
103
+ class Branch {
104
+ changes;
105
+ effects;
106
+ mapped;
107
+ startSelection;
108
+ next;
109
+ depth;
110
+ constructor(
111
+ changes,
112
+ effects,
113
+ mapped,
114
+ startSelection, next) {
115
+ this.changes = changes;
116
+ this.effects = effects;
117
+ this.mapped = mapped;
118
+ this.startSelection = startSelection;
119
+ this.next = next;
120
+ this.depth = depth(next) + 1;
121
+ }
122
+ addChanges(changes, effects) {
123
+ return new Branch(changes.compose(this.changes), conc(Transaction.Effect.mapEffects(effects, this.changes), this.effects), null, this.startSelection, this.next);
124
+ }
125
+ resolve(config) {
126
+ if (!this.mapped)
127
+ return this;
128
+ let { mapped: { change, doc }, next } = this;
129
+ let { a: mappedMapping, b: mappedChanges } = ChangeSet.transform(doc, change, this.changes);
130
+ if (next)
131
+ next = next.addMapping(mappedMapping, next.mapped ? null : this.changes.apply(doc));
132
+ if (mappedChanges.empty && !this.effects.length)
133
+ return next && next.resolve(config);
134
+ let selDoc, selCx = {
135
+ get doc() { return selDoc || (selDoc = mappedChanges.apply(change.apply(doc))); },
136
+ config
137
+ };
138
+ return new Branch(mappedChanges, Transaction.Effect.mapEffects(this.effects, change), null, this.startSelection.map(mappedMapping, selCx), next);
139
+ }
140
+ resolveFully(config) {
141
+ let stack = [];
142
+ for (let head = this; head; head = head.next) {
143
+ head = head.resolve(config);
144
+ if (!head)
145
+ break;
146
+ stack.push(head);
147
+ }
148
+ let result = null;
149
+ for (let i = stack.length - 1; i >= 0; i--) {
150
+ let next = stack[i];
151
+ if (next.next == result)
152
+ result = next;
153
+ else
154
+ result = new Branch(next.changes, next.effects, null, next.startSelection, result);
155
+ }
156
+ return result;
157
+ }
158
+ addMapping(change, startDoc) {
159
+ return new Branch(this.changes, this.effects, this.mapped
160
+ ? { change: this.mapped.change.compose(change), doc: this.mapped.doc }
161
+ : { change, doc: startDoc }, this.startSelection, this.next);
162
+ }
163
+ clip(depth) {
164
+ let stack = [];
165
+ for (let i = 0, cur = this; i < depth && cur; i++, cur = cur.next)
166
+ stack.push(cur);
167
+ let result = null;
168
+ for (let i = stack.length - 1; i >= 0; i--) {
169
+ let event = stack[i];
170
+ result = new Branch(event.changes, event.effects, event.mapped, event.startSelection, result);
171
+ }
172
+ return result;
173
+ }
174
+ }
175
+ function eventFromTransaction(tr) {
176
+ let effects = none;
177
+ for (let invert of tr.startState.facet(history.invertedEffects)) {
178
+ let result = invert(tr);
179
+ if (result.length)
180
+ effects = effects.concat(result);
181
+ }
182
+ if (!effects.length && tr.changes.empty)
183
+ return null;
184
+ return { changes: tr.changes.invert(tr.startState.doc), effects };
185
+ }
186
+ function isAdjacent(a, b) {
187
+ let ranges = [], isAdjacent = false;
188
+ a.iterChangedRanges((f, t) => ranges.push(f, t));
189
+ b.iterChangedRanges((_f, _t, f, t) => {
190
+ for (let i = 0; i < ranges.length;) {
191
+ let from = ranges[i++], to = ranges[i++];
192
+ if (t >= from && f <= to)
193
+ isAdjacent = true;
194
+ }
195
+ });
196
+ return isAdjacent;
197
+ }
198
+ function conc(a, b) {
199
+ return !a.length ? b : !b.length ? a : a.concat(b);
200
+ }
201
+ const none = [];
202
+ const joinableUserEvent = /^(input\.type|delete)($|\.)/;
203
+ class HistoryState {
204
+ done;
205
+ undone;
206
+ prevTime;
207
+ prevUserEvent;
208
+ constructor(
209
+ done,
210
+ undone,
211
+ prevTime = 0,
212
+ prevUserEvent = undefined) {
213
+ this.done = done;
214
+ this.undone = undone;
215
+ this.prevTime = prevTime;
216
+ this.prevUserEvent = prevUserEvent;
217
+ }
218
+ isolate() {
219
+ return this.prevTime ? new HistoryState(this.done, this.undone) : this;
220
+ }
221
+ addChanges(event, time, userEvent, config, tr) {
222
+ let done = this.done && this.done.resolve(tr.startState.config);
223
+ if (done && !done.changes.empty &&
224
+ (!userEvent || joinableUserEvent.test(userEvent) || tr.annotation(Transaction.appended)) &&
225
+ ((time - this.prevTime < config.newGroupDelay &&
226
+ config.joinToEvent(tr, isAdjacent(done.changes, event.changes))) ||
227
+ userEvent == "input.type.compose")) {
228
+ done = done.addChanges(event.changes, event.effects);
229
+ }
230
+ else {
231
+ done = new Branch(event.changes, event.effects, null, tr.startState.selection, done);
232
+ }
233
+ return new HistoryState(done, null, time, userEvent);
234
+ }
235
+ pop(side, state) {
236
+ let branch = side == 0 ? this.done : this.undone;
237
+ if (!branch || !(branch = branch.resolve(state.config)))
238
+ return false;
239
+ return {
240
+ changes: branch.changes,
241
+ selection: branch.startSelection,
242
+ effects: branch.effects,
243
+ annotations: fromHistory.of({ side, rest: branch.next }),
244
+ userEvent: side == 0 ? "undo" : "redo",
245
+ scrollIntoView: true
246
+ };
247
+ }
248
+ clip(minDepth) {
249
+ let max = minDepth * 1.3;
250
+ let done = depth(this.done) > max ? this.done.clip(minDepth) : this.done;
251
+ let undone = depth(this.undone) > max ? this.undone.clip(minDepth) : this.undone;
252
+ if (done != this.done || undone != this.undone)
253
+ return new HistoryState(done, undone, this.prevTime, this.prevUserEvent);
254
+ return this;
255
+ }
256
+ }
257
+ const undoButton = /*@__PURE__*/(() => Menu.Button.define({
258
+ run: undo,
259
+ label: {
260
+ icon: "M69 90c9-16 10-41-24-40v20l-30-30 30-30v19c42-1 46 37 24 61z"
261
+ },
262
+ description: phrases.ref("undo"),
263
+ enable: s => !s.readOnly && undoDepth(s) > 0,
264
+ parent: Menu.Group.commands,
265
+ rank: 10
266
+ }))();
267
+ const redoButton = /*@__PURE__*/(() => Menu.Button.define({
268
+ run: redo,
269
+ label: {
270
+ icon: "M55 29v-19l30 30-30 30v-20c-35-1-33 24-24 40-22-24-17-62 24-61z"
271
+ },
272
+ description: phrases.ref("redo"),
273
+ enable: s => !s.readOnly && redoDepth(s) > 0,
274
+ parent: Menu.Group.commands,
275
+ rank: 20
276
+ }))();
277
+
278
+ export { history, redo, redoButton, redoDepth, undo, undoButton, undoDepth };
@@ -0,0 +1,10 @@
1
+ export * as collab from "wordgard/collab"
2
+ export * as command from "wordgard/command"
3
+ export * as doc from "wordgard/doc"
4
+ export * as editor from "wordgard/editor"
5
+ export * as history from "wordgard/history"
6
+ export * as phrases from "wordgard/phrases"
7
+ export * as schema from "wordgard/schema"
8
+ export * as state from "wordgard/state"
9
+ export * as table from "wordgard/table"
10
+ export * as types from "wordgard/types"
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ export * as collab from "wordgard/collab"
2
+ export * as command from "wordgard/command"
3
+ export * as doc from "wordgard/doc"
4
+ export * as editor from "wordgard/editor"
5
+ export * as history from "wordgard/history"
6
+ export * as phrases from "wordgard/phrases"
7
+ export * as schema from "wordgard/schema"
8
+ export * as state from "wordgard/state"
9
+ export * as table from "wordgard/table"
10
+ export * as types from "wordgard/types"
@@ -0,0 +1,90 @@
1
+ import { GardState } from 'wordgard/state';
2
+
3
+ /**
4
+ A phrase set defines a number of text phrases to display in the
5
+ user interface, and makes translation of those phrases possible.
6
+ It associates each phrase with a tag. The type parameter to this
7
+ class is the set of tag names it defines.
8
+ */
9
+ declare class PhraseSet<Tags extends string> {
10
+ readonly phrases: {
11
+ [tag in Tags]: string;
12
+ };
13
+ private constructor();
14
+ /**
15
+ Look up a translation for phrase with the given tag.
16
+
17
+ If additional arguments are passed, they will be inserted in
18
+ place of markers like `$1` (for the first value) and `$2`, etc.
19
+ A single `$` is equivalent to `$1`, and `$$` will produce a
20
+ literal dollar sign.
21
+ */
22
+ get<Tag extends Tags>(state: GardState, tag: Tag, ...insert: any[]): string;
23
+ /**
24
+ Create a reference to a phrase. Returns a function that can be
25
+ called with an editor state to get the phrase text.
26
+ */
27
+ ref<Tag extends Tags>(tag: Tag): PhraseSet.Ref;
28
+ /**
29
+ Create a translation of this set. Adding the resulting extension
30
+ to an editor configuration will cause access to the phrases in
31
+ the set to return the translated text.
32
+ */
33
+ translate(phrases: {
34
+ [tag in Tags]: string;
35
+ }): GardState.Extension;
36
+ /**
37
+ Create a partial translation of this set. The only difference
38
+ with {@link PhraseSet.translate} is that this method won't cause
39
+ a type error when you omit some tags.
40
+ */
41
+ translatePartial(phrases: {
42
+ [tag in Tags]?: string;
43
+ }): GardState.Extension;
44
+ /**
45
+ Define a new phrase set. Takes an object as argument that
46
+ defines the default (usually English) text for all the tags in
47
+ the set.
48
+ */
49
+ static define<Tags extends string>(phrases: {
50
+ [tag in Tags]: string;
51
+ }): PhraseSet<Tags>;
52
+ /**
53
+ Check whether the phrase set configuration changed between the
54
+ two given states. Can be useful to check whether some part of
55
+ the interface needs to be redrawn.
56
+ */
57
+ static didChange(a: GardState, b: GardState): boolean;
58
+ }
59
+ declare namespace PhraseSet {
60
+ /**
61
+ A reference to a specific phrase. Call it with a state and,
62
+ optionally, the inserted values you'd pass to {@link
63
+ PhraseSet.get `PhraseSet.get`} to get a phrase.
64
+ */
65
+ type Ref = (state: GardState, ...insert: any[]) => string;
66
+ /**
67
+ Get the set of tags defined by a given phrase set, as a type.
68
+ */
69
+ type Tag<Set extends PhraseSet<any>> = Set extends PhraseSet<infer T> ? T : never;
70
+ }
71
+
72
+ /**
73
+ The phrase set for the core package and basic menu items.
74
+ */
75
+ declare const phrases: PhraseSet<"dialog_close" | "overflow_more" | "block_style" | "toggle_strong" | "toggle_em" | "toggle_code" | "toggle_underline" | "toggle_strikethrough" | "toggle_super" | "toggle_sub" | "link_target" | "create_link" | "text_color" | "background_color" | "undo" | "redo" | "paragraph" | "code_block" | "heading_1" | "heading_2" | "heading_3" | "toggle_bullet_list" | "toggle_ordered_list" | "toggle_quote" | "alignment" | "align_start" | "align_end" | "align_center" | "text_dir" | "text_dir_ltr" | "text_dir_rtl" | "text_dir_auto">;
76
+ /**
77
+ Phrases used by the {@link schema.image.button image dialog}.
78
+ */
79
+ declare const imagePhrases: PhraseSet<"inline" | "auto" | "width" | "cancel" | "figure" | "update" | "insert" | "insert_image" | "update_image" | "figure_center" | "figure_end" | "captioned" | "image_style" | "uploading" | "upload_failed" | "upload_image" | "image_source" | "alt_text" | "describe_image">;
80
+ /**
81
+ Phrases (mostly color names) used by the {@link schema.ColorPicker
82
+ color picker}.
83
+ */
84
+ declare const colorNames: PhraseSet<"none" | "lighter" | "black" | "white" | "grey" | "red_berry" | "red" | "orange" | "yellow" | "green" | "cyan" | "cornflower" | "blue" | "purple" | "magenta" | "dark" | "darker" | "darkest" | "light" | "lightest">;
85
+ /**
86
+ Phrases used by [wordgard/table](#table).
87
+ */
88
+ declare const tablePhrases: PhraseSet<"dimensions_title" | "dimensions_live" | "insert_table" | "modify_table" | "toggle_header" | "add_row_above" | "add_row_below" | "delete_row" | "add_col_before" | "add_col_after" | "delete_col" | "merge_cells" | "split_cell">;
89
+
90
+ export { PhraseSet, colorNames, imagePhrases, phrases, tablePhrases };
@@ -0,0 +1,141 @@
1
+ import { GardState } from 'wordgard/state';
2
+
3
+ const phraseOverride = /*@__PURE__*/GardState.Facet.define({
4
+ combine(records) {
5
+ let map = new Map();
6
+ for (let i = records.length - 1; i >= 0; i--) {
7
+ let { set, phrases } = records[i];
8
+ let known = map.get(set);
9
+ map.set(set, known ? { ...known, ...phrases } : phrases);
10
+ }
11
+ return map;
12
+ }
13
+ });
14
+ class PhraseSet {
15
+ phrases;
16
+ constructor(phrases) {
17
+ this.phrases = phrases;
18
+ }
19
+ get(state, tag, ...insert) {
20
+ let override = state.facet(phraseOverride).get(this);
21
+ let phrase = (override && override[tag]) ?? this.phrases[tag];
22
+ if (insert.length)
23
+ phrase = phrase.replace(/\$(\$|\d*)/g, (m, i) => {
24
+ if (i == "$")
25
+ return "$";
26
+ let n = +(i || 1);
27
+ return !n || n > insert.length ? m : insert[n - 1];
28
+ });
29
+ return phrase;
30
+ }
31
+ ref(tag) {
32
+ return (state, ...insert) => this.get(state, tag, ...insert);
33
+ }
34
+ translate(phrases) {
35
+ return phraseOverride.of({ set: this, phrases });
36
+ }
37
+ translatePartial(phrases) {
38
+ return phraseOverride.of({ set: this, phrases: phrases });
39
+ }
40
+ static define(phrases) {
41
+ return new PhraseSet(phrases);
42
+ }
43
+ static didChange(a, b) {
44
+ return a.facet(phraseOverride) != b.facet(phraseOverride);
45
+ }
46
+ }
47
+
48
+ const phrases = /*@__PURE__*/PhraseSet.define({
49
+ dialog_close: "close",
50
+ overflow_more: "More",
51
+ block_style: "Block style",
52
+ toggle_strong: "Toggle strong emphasis",
53
+ toggle_em: "Toggle emphasis",
54
+ toggle_code: "Toggle code font",
55
+ toggle_underline: "Toggle underline",
56
+ toggle_strikethrough: "Toggle strikethrough",
57
+ toggle_super: "Toggle superscript",
58
+ toggle_sub: "Toggle subscript",
59
+ link_target: "Link target",
60
+ create_link: "Create link",
61
+ text_color: "Text color",
62
+ background_color: "Background color",
63
+ undo: "Undo",
64
+ redo: "Redo",
65
+ paragraph: "Paragraph",
66
+ code_block: "Code block",
67
+ heading_1: "Heading 1",
68
+ heading_2: "Heading 2",
69
+ heading_3: "Heading 3",
70
+ toggle_bullet_list: "Toggle bullet list",
71
+ toggle_ordered_list: "Toggle ordered list",
72
+ toggle_quote: "Toggle blockquote",
73
+ alignment: "Alignment",
74
+ align_start: "Align text to block start",
75
+ align_end: "Align text to block end",
76
+ align_center: "Center text",
77
+ text_dir: "Text direction",
78
+ text_dir_ltr: "Left-to-right text",
79
+ text_dir_rtl: "Right-to-left text",
80
+ text_dir_auto: "Automatic text direction",
81
+ });
82
+ const imagePhrases = /*@__PURE__*/PhraseSet.define({
83
+ insert_image: "Insert image",
84
+ update_image: "Update image",
85
+ update: "Update",
86
+ insert: "Insert",
87
+ cancel: "Cancel",
88
+ inline: "Inline",
89
+ figure: "Figure",
90
+ figure_center: "Centered figure",
91
+ figure_end: "Figure aligned to end",
92
+ captioned: "Captioned",
93
+ image_style: "Image style",
94
+ uploading: "Uploading...",
95
+ upload_failed: "Image upload failed",
96
+ width: "Width in pixels",
97
+ upload_image: "Upload an image",
98
+ image_source: "Image source",
99
+ alt_text: "Alternative text",
100
+ describe_image: "Describe the image",
101
+ auto: "automatic"
102
+ });
103
+ const colorNames = /*@__PURE__*/PhraseSet.define({
104
+ none: "none",
105
+ black: "black",
106
+ white: "white",
107
+ grey: "grey",
108
+ red_berry: "red berry",
109
+ red: "red",
110
+ orange: "orange",
111
+ yellow: "yellow",
112
+ green: "green",
113
+ cyan: "cyan",
114
+ cornflower: "cornflower",
115
+ blue: "blue",
116
+ purple: "purple",
117
+ magenta: "magenta",
118
+ dark: "dark",
119
+ darker: "darker",
120
+ darkest: "very dark",
121
+ light: "light",
122
+ lighter: "lighter",
123
+ lightest: "very light",
124
+ });
125
+ const tablePhrases = /*@__PURE__*/PhraseSet.define({
126
+ dimensions_title: "Table dimensions $1 by $2. Use arrow keys to change.",
127
+ dimensions_live: "$1 by $2",
128
+ insert_table: "Insert a table",
129
+ modify_table: "Modify table",
130
+ toggle_header: "Toggle header cells",
131
+ add_row_above: "Add row above",
132
+ add_row_below: "Add row below",
133
+ delete_row: "Delete row",
134
+ add_col_before: "Add column before",
135
+ add_col_after: "Add column before",
136
+ delete_col: "Delete column",
137
+ merge_cells: "Merge cells",
138
+ split_cell: "Split cell"
139
+ });
140
+
141
+ export { PhraseSet, colorNames, imagePhrases, phrases, tablePhrases };