@inkbrick/react 0.0.0-stage → 0.1.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/dist/FormulaPalette-WFRPRHS5.js +320 -0
  2. package/dist/FormulaPalette-WFRPRHS5.js.map +1 -0
  3. package/dist/chunk-TPUX4C45.js +2309 -0
  4. package/dist/chunk-TPUX4C45.js.map +1 -0
  5. package/dist/index.d.ts +1431 -0
  6. package/dist/index.js +4880 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/mathCss-FLPE6QBM.js +361 -0
  9. package/dist/mathCss-FLPE6QBM.js.map +1 -0
  10. package/package.json +46 -3
  11. package/src/block-handle/BlockHandleController.ts +93 -0
  12. package/src/block-handle/BlockHandleHost.tsx +108 -0
  13. package/src/block-handle/DefaultBlockHandle.tsx +71 -0
  14. package/src/block-handle/DefaultBlockMenu.tsx +114 -0
  15. package/src/block-handle/DropIndicatorHost.tsx +58 -0
  16. package/src/block-handle/actions.tsx +146 -0
  17. package/src/block-handle/blockDrag.ts +215 -0
  18. package/src/block-handle/geometry.ts +64 -0
  19. package/src/block-handle/gripGesture.ts +108 -0
  20. package/src/block-handle/types.ts +65 -0
  21. package/src/block-handle/useBlockDrag.ts +21 -0
  22. package/src/block-handle/useBlockHandles.ts +125 -0
  23. package/src/blocks/BlockChildren.tsx +17 -0
  24. package/src/blocks/BlockProps.ts +5 -0
  25. package/src/blocks/CalloutBlock.tsx +61 -0
  26. package/src/blocks/CodeBlock.tsx +96 -0
  27. package/src/blocks/DividerBlock.tsx +15 -0
  28. package/src/blocks/Editable.tsx +84 -0
  29. package/src/blocks/FormulaBlock.tsx +173 -0
  30. package/src/blocks/HeadingBlock.tsx +22 -0
  31. package/src/blocks/ImageBlock.tsx +362 -0
  32. package/src/blocks/ListBlock.tsx +86 -0
  33. package/src/blocks/NoteBlock.tsx +10 -0
  34. package/src/blocks/PageBlock.tsx +10 -0
  35. package/src/blocks/ParagraphBlock.tsx +20 -0
  36. package/src/blocks/QuoteBlock.tsx +18 -0
  37. package/src/blocks/UnknownBlockView.tsx +27 -0
  38. package/src/blocks/defineBlock.ts +49 -0
  39. package/src/clipboard/html/blocks.ts +379 -0
  40. package/src/clipboard/html/inline.ts +92 -0
  41. package/src/clipboard/html/style.ts +92 -0
  42. package/src/clipboard/html/tags.ts +77 -0
  43. package/src/clipboard/htmlToFragment.ts +41 -0
  44. package/src/clipboard/useClipboard.ts +296 -0
  45. package/src/code/highlight.ts +56 -0
  46. package/src/code/languages.ts +236 -0
  47. package/src/code/scan/css.ts +164 -0
  48. package/src/code/scan/generic.ts +328 -0
  49. package/src/code/scan/html.ts +129 -0
  50. package/src/code/scan/markdown.ts +58 -0
  51. package/src/code/scan/shared.ts +81 -0
  52. package/src/code/scan/yaml.ts +34 -0
  53. package/src/code/types.ts +34 -0
  54. package/src/context/EditorContext.ts +9 -0
  55. package/src/context/EditorProvider.tsx +172 -0
  56. package/src/controllers/adapters.tsx +63 -0
  57. package/src/editing/BlockSelectionController.ts +27 -0
  58. package/src/editing/CaretController.ts +27 -0
  59. package/src/editing/EditorView.ts +108 -0
  60. package/src/editing/ViewportController.ts +63 -0
  61. package/src/editing/beforeInput.ts +276 -0
  62. package/src/editing/deleteAtBoundary.ts +16 -0
  63. package/src/editing/inputActions.ts +109 -0
  64. package/src/editing/renderCode.ts +69 -0
  65. package/src/editing/renderInline.ts +144 -0
  66. package/src/editing/selection.ts +262 -0
  67. package/src/editing/useEditorInput.ts +223 -0
  68. package/src/editing/useSelectionState.ts +46 -0
  69. package/src/formula/FormulaController.ts +51 -0
  70. package/src/formula/FormulaPalette.tsx +79 -0
  71. package/src/formula/FormulaPopover.tsx +181 -0
  72. package/src/formula/LazyFormulaPalette.tsx +42 -0
  73. package/src/formula/actions.ts +138 -0
  74. package/src/formula/snippet.ts +70 -0
  75. package/src/formula/symbols.ts +264 -0
  76. package/src/hooks/useBlock.ts +21 -0
  77. package/src/hooks/useBlockController.ts +30 -0
  78. package/src/hooks/useChildren.ts +16 -0
  79. package/src/hooks/useDocument.ts +16 -0
  80. package/src/hooks/useEditor.ts +13 -0
  81. package/src/hooks/useEditorView.ts +13 -0
  82. package/src/hooks/useHistory.ts +46 -0
  83. package/src/hooks/useReadOnly.ts +21 -0
  84. package/src/hooks/useT.ts +10 -0
  85. package/src/i18n/en.ts +182 -0
  86. package/src/i18n/ru.ts +174 -0
  87. package/src/i18n/translate.ts +77 -0
  88. package/src/icons/ICONS_LICENSE.md +50 -0
  89. package/src/icons/Icon.tsx +41 -0
  90. package/src/icons/lucide.ts +234 -0
  91. package/src/images/ImageError.ts +39 -0
  92. package/src/images/UploadTracker.ts +49 -0
  93. package/src/images/insertImages.ts +142 -0
  94. package/src/images/types.ts +22 -0
  95. package/src/images/upload.ts +62 -0
  96. package/src/index.ts +102 -0
  97. package/src/keymap/defaultKeymap.ts +189 -0
  98. package/src/keymap/keymap.ts +42 -0
  99. package/src/keymap/shortcut.ts +105 -0
  100. package/src/keymap/types.ts +40 -0
  101. package/src/math/FormulaView.tsx +62 -0
  102. package/src/math/mathCss.ts +4 -0
  103. package/src/math/renderer.ts +198 -0
  104. package/src/registry/defaultBlockComponents.ts +26 -0
  105. package/src/registry/resolveBlockComponent.ts +14 -0
  106. package/src/renderer/BlockRenderer.tsx +63 -0
  107. package/src/renderer/DocumentRenderer.tsx +33 -0
  108. package/src/renderer/DocumentView.tsx +94 -0
  109. package/src/renderer/virtual/VirtualChildList.tsx +355 -0
  110. package/src/renderer/virtual/estimate.ts +62 -0
  111. package/src/renderer/virtual/virtualRenderer.tsx +35 -0
  112. package/src/slash/DefaultSlashMenu.tsx +119 -0
  113. package/src/slash/SlashMenuController.ts +66 -0
  114. package/src/slash/SlashMenuHost.tsx +48 -0
  115. package/src/slash/applySlashItem.ts +57 -0
  116. package/src/slash/defaultSlashItems.tsx +186 -0
  117. package/src/slash/filter.ts +29 -0
  118. package/src/slash/items.ts +30 -0
  119. package/src/slash/syncSlashMenu.ts +67 -0
  120. package/src/slash/types.ts +21 -0
  121. package/src/toolbar/DefaultToolbar.tsx +281 -0
  122. package/src/toolbar/ToolbarController.ts +100 -0
  123. package/src/toolbar/ToolbarHost.tsx +81 -0
  124. package/src/toolbar/formatting.ts +75 -0
  125. package/src/toolbar/rich.ts +58 -0
  126. package/src/toolbar/syncToolbar.ts +39 -0
  127. package/src/toolbar/types.ts +21 -0
  128. package/src/ui/EditorUIContext.ts +26 -0
  129. package/src/ui/presentation.ts +24 -0
  130. package/src/ui/types.ts +70 -0
  131. package/README.md +0 -3
@@ -0,0 +1,2309 @@
1
+ // src/code/languages.ts
2
+ var JS_KEYWORDS = "break case catch class const continue debugger default delete do else enum export extends finally for function if import in instanceof let new of return static super switch this throw try typeof var void while with yield async await from as implements interface package private protected public readonly abstract declare namespace keyof satisfies override";
3
+ var JS_DECLARATIONS = {
4
+ function: "function",
5
+ class: "type",
6
+ interface: "type",
7
+ enum: "type",
8
+ namespace: "type"
9
+ };
10
+ var javascript = {
11
+ keywords: JS_KEYWORDS,
12
+ constants: "true false null undefined NaN Infinity",
13
+ builtins: "console window document Math JSON Object Array String Number Boolean Promise Map Set WeakMap Date Error RegExp Symbol parseInt parseFloat require module exports process globalThis",
14
+ lineComment: ["//"],
15
+ blockComment: ["/*", "*/"],
16
+ strings: "'\"`",
17
+ multiline: "`",
18
+ regex: true,
19
+ at: true,
20
+ pascalTypes: true,
21
+ declarations: JS_DECLARATIONS
22
+ };
23
+ var typescript = {
24
+ ...javascript,
25
+ types: "string number boolean any unknown never void object bigint symbol Record Partial Required Readonly Pick Omit Awaited ReturnType"
26
+ };
27
+ var python = {
28
+ keywords: "and as assert async await break class continue def del elif else except finally for from global if import in is lambda nonlocal not or pass raise return try while with yield match case",
29
+ constants: "True False None",
30
+ builtins: "print len range int str float bool list dict set tuple type isinstance open enumerate zip map filter sorted sum min max abs any all input super self cls object Exception",
31
+ lineComment: ["#"],
32
+ strings: `'"`,
33
+ triple: true,
34
+ stringPrefixes: true,
35
+ at: true,
36
+ pascalTypes: true,
37
+ declarations: { def: "function", class: "type" }
38
+ };
39
+ var go = {
40
+ keywords: "break case chan const continue default defer else fallthrough for func go goto if import interface map package range return select struct switch type var",
41
+ types: "bool byte complex64 complex128 error float32 float64 int int8 int16 int32 int64 rune string uint uint8 uint16 uint32 uint64 uintptr any",
42
+ constants: "true false nil iota",
43
+ builtins: "append cap close copy delete len make new panic print println recover",
44
+ lineComment: ["//"],
45
+ blockComment: ["/*", "*/"],
46
+ strings: "'\"`",
47
+ multiline: "`",
48
+ pascalTypes: true,
49
+ declarations: { func: "function", type: "type" }
50
+ };
51
+ var rust = {
52
+ keywords: "as async await break const continue crate dyn else enum extern fn for if impl in let loop match mod move mut pub ref return self Self static struct super trait type unsafe use where while",
53
+ types: "i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize f32 f64 bool char str String Vec Option Result Box Rc Arc",
54
+ constants: "true false None Some Ok Err",
55
+ lineComment: ["//"],
56
+ blockComment: ["/*", "*/"],
57
+ strings: '"',
58
+ multiline: '"',
59
+ rustAttributes: true,
60
+ lifetimes: true,
61
+ macros: true,
62
+ pascalTypes: true,
63
+ declarations: { fn: "function", struct: "type", enum: "type", trait: "type", impl: "type" }
64
+ };
65
+ var java = {
66
+ keywords: "abstract assert break case catch class continue default do else enum extends final finally for if implements import instanceof interface native new package private protected public return static strictfp super switch synchronized this throw throws transient try void volatile while var record sealed permits",
67
+ types: "boolean byte char double float int long short String Integer Long Double Boolean Object List Map Set",
68
+ constants: "true false null",
69
+ lineComment: ["//"],
70
+ blockComment: ["/*", "*/"],
71
+ strings: `'"`,
72
+ at: true,
73
+ pascalTypes: true,
74
+ declarations: { class: "type", interface: "type", enum: "type", record: "type" }
75
+ };
76
+ var C_KEYWORDS = "auto break case const continue default do else enum extern for goto if inline register restrict return sizeof static struct switch typedef union volatile while";
77
+ var c = {
78
+ keywords: C_KEYWORDS,
79
+ types: "void char short int long float double signed unsigned size_t bool _Bool int8_t int16_t int32_t int64_t uint8_t uint16_t uint32_t uint64_t FILE",
80
+ constants: "NULL true false EOF",
81
+ lineComment: ["//"],
82
+ blockComment: ["/*", "*/"],
83
+ strings: `'"`,
84
+ preprocessor: true,
85
+ declarations: { struct: "type", enum: "type", union: "type" }
86
+ };
87
+ var cpp = {
88
+ ...c,
89
+ keywords: `${C_KEYWORDS} class namespace template typename public private protected virtual override final new delete this using try catch throw operator constexpr noexcept static_cast dynamic_cast reinterpret_cast const_cast explicit friend mutable decltype`,
90
+ types: `${c.types} string vector map set unique_ptr shared_ptr std`,
91
+ constants: "NULL nullptr true false EOF",
92
+ pascalTypes: true,
93
+ declarations: { class: "type", struct: "type", enum: "type", namespace: "type", union: "type" }
94
+ };
95
+ var bash = {
96
+ keywords: "if then else elif fi for while until do done case esac in function select time return exit break continue export local readonly declare unset source alias set shift",
97
+ builtins: "echo cd ls pwd cat grep sed awk rm cp mv mkdir touch chmod chown curl wget git npm pnpm yarn node python docker sudo kill ps tar test read printf eval exec trap true false",
98
+ lineComment: ["#"],
99
+ commentAtWordStart: true,
100
+ strings: "'\"`",
101
+ multiline: "'\"`",
102
+ dollar: true,
103
+ flags: true
104
+ };
105
+ var sql = {
106
+ ignoreCase: true,
107
+ keywords: "select from where and or not in is like between exists distinct as join inner left right full outer cross on using group by order having limit offset union all insert into values update set delete create alter drop table index view database schema primary key foreign references unique default check constraint add column case when then else end begin commit rollback transaction with returning asc desc if cascade truncate grant revoke",
108
+ types: "int integer bigint smallint tinyint varchar char text boolean bool date time timestamp datetime numeric decimal float double real serial uuid json jsonb blob",
109
+ constants: "true false null",
110
+ builtins: "count sum avg min max coalesce now cast length lower upper trim round abs concat substring",
111
+ lineComment: ["--"],
112
+ blockComment: ["/*", "*/"],
113
+ strings: `'"`
114
+ };
115
+ var json = {
116
+ constants: "true false null",
117
+ lineComment: ["//"],
118
+ blockComment: ["/*", "*/"],
119
+ strings: '"',
120
+ stringKeys: true
121
+ };
122
+ var yaml = {
123
+ constants: "true false null yes no on off ~ True False Null",
124
+ lineComment: ["#"],
125
+ commentAtWordStart: true,
126
+ strings: `'"`
127
+ };
128
+ var LANGUAGES = {
129
+ javascript,
130
+ typescript,
131
+ python,
132
+ go,
133
+ rust,
134
+ java,
135
+ c,
136
+ cpp,
137
+ bash,
138
+ sql,
139
+ json,
140
+ yaml
141
+ };
142
+ var ALIASES = {
143
+ js: "javascript",
144
+ jsx: "javascript",
145
+ mjs: "javascript",
146
+ cjs: "javascript",
147
+ ts: "typescript",
148
+ tsx: "typescript",
149
+ py: "python",
150
+ golang: "go",
151
+ rs: "rust",
152
+ sh: "bash",
153
+ shell: "bash",
154
+ zsh: "bash",
155
+ console: "bash",
156
+ "c++": "cpp",
157
+ cc: "cpp",
158
+ cxx: "cpp",
159
+ hpp: "cpp",
160
+ h: "c",
161
+ jsonc: "json",
162
+ json5: "json",
163
+ yml: "yaml",
164
+ md: "markdown",
165
+ xml: "html",
166
+ svg: "html",
167
+ htm: "html",
168
+ scss: "css",
169
+ less: "css",
170
+ postgres: "sql",
171
+ postgresql: "sql",
172
+ mysql: "sql",
173
+ sqlite: "sql"
174
+ };
175
+
176
+ // src/code/scan/shared.ts
177
+ var IDENT = /[A-Za-z_$À-￿][\w$À-￿]*/y;
178
+ var NUMBER = /(?:0[xX][\da-fA-F_]+|0[bB][01_]+|0[oO][0-7_]+|(?:\d[\d_]*(?:\.[\d_]+)?|\.\d[\d_]*)(?:[eE][+-]?\d+)?)[a-zA-Z]*/y;
179
+ var CHAR_LITERAL = /'(?:\\.|[^'\\\n])'/y;
180
+ var LIFETIME = /'[A-Za-z_]\w*/y;
181
+ var STRING_PREFIX = /^[rRbBfFuU]{1,3}$/;
182
+ var REGEX_AFTER_WORD = new Set(
183
+ "return typeof case delete void throw in of new else do yield await".split(" ")
184
+ );
185
+ var matchAt = (re, code, at) => {
186
+ re.lastIndex = at;
187
+ const match = re.exec(code);
188
+ return match ? match[0] : null;
189
+ };
190
+ var isDigit = (char) => char !== void 0 && char >= "0" && char <= "9";
191
+ var isSpace = (char) => char === " " || char === " " || char === "\n" || char === "\r";
192
+ function lineEnd(code, from, end) {
193
+ const index = code.indexOf("\n", from);
194
+ return index < 0 || index > end ? end : index;
195
+ }
196
+ function nextOnLine(code, from, end) {
197
+ let i = from;
198
+ while (i < end && (code[i] === " " || code[i] === " ")) i++;
199
+ return i;
200
+ }
201
+ function onlyWhitespaceBefore(code, at, start) {
202
+ for (let i = at - 1; i >= start && code[i] !== "\n"; i--) {
203
+ if (code[i] !== " " && code[i] !== " ") return false;
204
+ }
205
+ return true;
206
+ }
207
+ function scanString(code, start, end, quote, triple, multiline) {
208
+ const closing = quote.repeat(3);
209
+ let i = start + (triple ? 3 : 1);
210
+ while (i < end) {
211
+ const char = code[i];
212
+ if (char === "\\") {
213
+ i += 2;
214
+ continue;
215
+ }
216
+ if (triple) {
217
+ if (code.startsWith(closing, i)) return i + 3;
218
+ } else if (char === quote) {
219
+ return i + 1;
220
+ } else if (char === "\n" && !multiline) {
221
+ return i;
222
+ }
223
+ i++;
224
+ }
225
+ return end;
226
+ }
227
+
228
+ // src/code/scan/css.ts
229
+ function scanCss(code, start, end, emit) {
230
+ let i = start;
231
+ let depth = 0;
232
+ let expectProperty = false;
233
+ while (i < end) {
234
+ const char = code[i];
235
+ if (isSpace(char)) {
236
+ i++;
237
+ continue;
238
+ }
239
+ if (code.startsWith("/*", i)) {
240
+ const close = code.indexOf("*/", i + 2);
241
+ const stop = close < 0 || close + 2 > end ? end : close + 2;
242
+ emit(i, stop, "comment");
243
+ i = stop;
244
+ continue;
245
+ }
246
+ if (char === '"' || char === "'") {
247
+ const stop = scanString(code, i, end, char, false, false);
248
+ emit(i, stop, "string");
249
+ i = stop;
250
+ continue;
251
+ }
252
+ if (char === "{") {
253
+ depth++;
254
+ expectProperty = true;
255
+ i++;
256
+ continue;
257
+ }
258
+ if (char === "}") {
259
+ depth = Math.max(0, depth - 1);
260
+ expectProperty = depth > 0;
261
+ i++;
262
+ continue;
263
+ }
264
+ if (char === ";") {
265
+ expectProperty = depth > 0;
266
+ i++;
267
+ continue;
268
+ }
269
+ if (char === "@") {
270
+ const name = matchAt(/@[\w-]+/y, code, i);
271
+ if (name) {
272
+ emit(i, i + name.length, "keyword");
273
+ i += name.length;
274
+ continue;
275
+ }
276
+ }
277
+ const inValue = depth > 0 && !expectProperty;
278
+ if (inValue) {
279
+ const hex = matchAt(/#[\da-fA-F]{3,8}\b/y, code, i);
280
+ if (hex) {
281
+ emit(i, i + hex.length, "number");
282
+ i += hex.length;
283
+ continue;
284
+ }
285
+ const number = matchAt(/-?(?:\d+\.?\d*|\.\d+)(?:%|[a-zA-Z]+)?/y, code, i);
286
+ if (number && (isDigit(char) || char === "." || char === "-")) {
287
+ emit(i, i + number.length, "number");
288
+ i += number.length;
289
+ continue;
290
+ }
291
+ if (code.startsWith("!important", i)) {
292
+ emit(i, i + 10, "keyword");
293
+ i += 10;
294
+ continue;
295
+ }
296
+ const word = matchAt(/[A-Za-z_-][\w-]*/y, code, i);
297
+ if (word) {
298
+ if (code[nextOnLine(code, i + word.length, end)] === "(")
299
+ emit(i, i + word.length, "function");
300
+ i += word.length;
301
+ continue;
302
+ }
303
+ i++;
304
+ continue;
305
+ }
306
+ if (depth > 0 && expectProperty) {
307
+ const property = matchAt(/-{0,2}[A-Za-z_][\w-]*(?=\s*:(?!:))/y, code, i);
308
+ if (property && !isNestedSelector(code, i + property.length, end)) {
309
+ emit(i, i + property.length, "property");
310
+ i += property.length;
311
+ expectProperty = false;
312
+ continue;
313
+ }
314
+ }
315
+ const classOrId = matchAt(/[.#][\w-]+/y, code, i);
316
+ if (classOrId) {
317
+ emit(i, i + classOrId.length, "function");
318
+ i += classOrId.length;
319
+ continue;
320
+ }
321
+ const pseudo = matchAt(/::?[\w-]+/y, code, i);
322
+ if (pseudo) {
323
+ emit(i, i + pseudo.length, "keyword");
324
+ i += pseudo.length;
325
+ continue;
326
+ }
327
+ if (char === "[") {
328
+ const close = code.indexOf("]", i);
329
+ const stop = close < 0 || close >= end ? end : close + 1;
330
+ emit(i, stop, "attribute");
331
+ i = stop;
332
+ continue;
333
+ }
334
+ const tag = matchAt(/[A-Za-z][\w-]*/y, code, i);
335
+ if (tag) {
336
+ emit(i, i + tag.length, "tag");
337
+ i += tag.length;
338
+ continue;
339
+ }
340
+ i++;
341
+ }
342
+ }
343
+ function isNestedSelector(code, from, end) {
344
+ const colon = code.indexOf(":", from);
345
+ if (colon < 0 || colon >= end) return false;
346
+ const brace = code.indexOf("{", colon);
347
+ const semicolon = code.indexOf(";", colon);
348
+ const newline = code.indexOf("\n", colon);
349
+ return brace >= 0 && brace < end && (semicolon < 0 || brace < semicolon) && (newline < 0 || brace < newline);
350
+ }
351
+
352
+ // src/code/scan/generic.ts
353
+ var setsCache = /* @__PURE__ */ new WeakMap();
354
+ function wordSets(lang) {
355
+ let sets = setsCache.get(lang);
356
+ if (!sets) {
357
+ const make = (list = "") => new Set(
358
+ list.split(/\s+/).filter(Boolean).map((word) => lang.ignoreCase ? word.toLowerCase() : word)
359
+ );
360
+ sets = {
361
+ keywords: make(lang.keywords),
362
+ types: make(lang.types),
363
+ builtins: make(lang.builtins),
364
+ constants: make(lang.constants)
365
+ };
366
+ setsCache.set(lang, sets);
367
+ }
368
+ return sets;
369
+ }
370
+ function classify(word, lang, sets, followedByCall, previousWord) {
371
+ const key = lang.ignoreCase ? word.toLowerCase() : word;
372
+ const declared = lang.declarations?.[previousWord];
373
+ if (declared && !sets.keywords.has(key)) return declared;
374
+ if (sets.keywords.has(key)) return "keyword";
375
+ if (sets.constants.has(key)) return "constant";
376
+ if (sets.types.has(key)) return "type";
377
+ if (sets.builtins.has(key)) return "builtin";
378
+ if (followedByCall) return "function";
379
+ if (lang.pascalTypes && /^[A-Z]/.test(word) && /[a-z]/.test(word)) return "type";
380
+ return null;
381
+ }
382
+ function scanGeneric(code, lang, start, end, emit) {
383
+ const sets = wordSets(lang);
384
+ const quotes = lang.strings ?? "";
385
+ let i = start;
386
+ let previousWord = "";
387
+ let last = "";
388
+ while (i < end) {
389
+ const char = code[i];
390
+ if (isSpace(char)) {
391
+ i++;
392
+ continue;
393
+ }
394
+ const lineMarker = lang.lineComment?.find(
395
+ (marker) => code.startsWith(marker, i) && (!lang.commentAtWordStart || i === start || isSpace(code[i - 1]))
396
+ );
397
+ if (lineMarker) {
398
+ const stop = lineEnd(code, i, end);
399
+ emit(i, stop, "comment");
400
+ i = stop;
401
+ previousWord = "";
402
+ continue;
403
+ }
404
+ if (lang.blockComment && code.startsWith(lang.blockComment[0], i)) {
405
+ const close = code.indexOf(lang.blockComment[1], i + lang.blockComment[0].length);
406
+ const stop = close < 0 || close + lang.blockComment[1].length > end ? end : close + lang.blockComment[1].length;
407
+ emit(i, stop, "comment");
408
+ i = stop;
409
+ previousWord = "";
410
+ continue;
411
+ }
412
+ if (lang.preprocessor && char === "#" && onlyWhitespaceBefore(code, i, start)) {
413
+ const stop = lineEnd(code, i, end);
414
+ emit(i, stop, "meta");
415
+ i = stop;
416
+ previousWord = "";
417
+ continue;
418
+ }
419
+ if (lang.rustAttributes && char === "#" && (code[i + 1] === "[" || code.startsWith("![", i + 1))) {
420
+ let depth = 0;
421
+ let stop = i;
422
+ for (; stop < end; stop++) {
423
+ if (code[stop] === "[") depth++;
424
+ else if (code[stop] === "]" && --depth <= 0) {
425
+ stop++;
426
+ break;
427
+ } else if (code[stop] === "\n") break;
428
+ }
429
+ emit(i, stop, "meta");
430
+ i = stop;
431
+ previousWord = "";
432
+ continue;
433
+ }
434
+ if (lang.lifetimes && char === "'") {
435
+ const literal = matchAt(CHAR_LITERAL, code, i);
436
+ if (literal) {
437
+ emit(i, i + literal.length, "string");
438
+ i += literal.length;
439
+ } else {
440
+ const lifetime = matchAt(LIFETIME, code, i);
441
+ if (lifetime) emit(i, i + lifetime.length, "type");
442
+ i += lifetime ? lifetime.length : 1;
443
+ }
444
+ previousWord = "";
445
+ last = "value";
446
+ continue;
447
+ }
448
+ if (quotes.includes(char)) {
449
+ const triple = lang.triple === true && code.startsWith(char.repeat(3), i);
450
+ const stop = scanString(
451
+ code,
452
+ i,
453
+ end,
454
+ char,
455
+ triple,
456
+ triple || (lang.multiline ?? "").includes(char)
457
+ );
458
+ let type = "string";
459
+ if (lang.stringKeys && code[nextOnLine(code, stop, end)] === ":") type = "property";
460
+ emit(i, stop, type);
461
+ i = stop;
462
+ previousWord = "";
463
+ last = "value";
464
+ continue;
465
+ }
466
+ if (isDigit(char) || char === "." && isDigit(code[i + 1])) {
467
+ const number = matchAt(NUMBER, code, i) ?? char;
468
+ emit(i, i + number.length, "number");
469
+ i += number.length;
470
+ previousWord = "";
471
+ last = "value";
472
+ continue;
473
+ }
474
+ if (lang.dollar && char === "$") {
475
+ let stop = i + 1;
476
+ if (code[stop] === "{") {
477
+ const close = code.indexOf("}", stop);
478
+ stop = close < 0 || close >= end ? lineEnd(code, stop, end) : close + 1;
479
+ } else if (/[\w@?#*!$-]/.test(code[stop] ?? "")) {
480
+ const word2 = matchAt(/\w+|[@?#*!$-]/y, code, stop);
481
+ stop += word2 ? word2.length : 1;
482
+ }
483
+ if (stop > i + 1) emit(i, stop, "variable");
484
+ i = Math.max(stop, i + 1);
485
+ previousWord = "";
486
+ last = "value";
487
+ continue;
488
+ }
489
+ if (lang.flags && char === "-" && (i === start || isSpace(code[i - 1])) && /[A-Za-z-]/.test(code[i + 1] ?? "")) {
490
+ let stop = i + 1;
491
+ while (stop < end && !isSpace(code[stop]) && code[stop] !== "=") stop++;
492
+ emit(i, stop, "attribute");
493
+ i = stop;
494
+ previousWord = "";
495
+ continue;
496
+ }
497
+ if (lang.at && char === "@") {
498
+ const name = matchAt(/[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*/y, code, i + 1);
499
+ if (name) {
500
+ emit(i, i + 1 + name.length, "meta");
501
+ i += 1 + name.length;
502
+ previousWord = "";
503
+ continue;
504
+ }
505
+ }
506
+ const word = matchAt(IDENT, code, i);
507
+ if (word) {
508
+ const stop = i + word.length;
509
+ if (lang.stringPrefixes && STRING_PREFIX.test(word) && stop < end && quotes.includes(code[stop])) {
510
+ const quote = code[stop];
511
+ const triple = lang.triple === true && code.startsWith(quote.repeat(3), stop);
512
+ const close = scanString(code, stop, end, quote, triple, triple);
513
+ emit(i, close, "string");
514
+ i = close;
515
+ previousWord = "";
516
+ last = "value";
517
+ continue;
518
+ }
519
+ if (lang.macros && code[stop] === "!" && code[stop + 1] !== "=") {
520
+ emit(i, stop + 1, "function");
521
+ i = stop + 1;
522
+ previousWord = "";
523
+ last = "value";
524
+ continue;
525
+ }
526
+ const followedByCall = code[nextOnLine(code, stop, end)] === "(";
527
+ const type = classify(word, lang, sets, followedByCall, previousWord);
528
+ if (type) emit(i, stop, type);
529
+ previousWord = word;
530
+ last = `word:${word}`;
531
+ i = stop;
532
+ continue;
533
+ }
534
+ if (lang.regex && char === "/") {
535
+ const afterWord = last.startsWith("word:") && REGEX_AFTER_WORD.has(last.slice(5));
536
+ const allowed = last === "" || last.length === 1 || afterWord;
537
+ if (allowed) {
538
+ let stop = i + 1;
539
+ let inClass = false;
540
+ while (stop < end && code[stop] !== "\n") {
541
+ if (code[stop] === "\\") stop++;
542
+ else if (code[stop] === "[") inClass = true;
543
+ else if (code[stop] === "]") inClass = false;
544
+ else if (code[stop] === "/" && !inClass) break;
545
+ stop++;
546
+ }
547
+ if (code[stop] === "/") {
548
+ stop++;
549
+ while (stop < end && /[a-z]/i.test(code[stop])) stop++;
550
+ emit(i, stop, "regex");
551
+ i = stop;
552
+ previousWord = "";
553
+ last = "value";
554
+ continue;
555
+ }
556
+ }
557
+ }
558
+ previousWord = "";
559
+ last = char === ")" || char === "]" || char === "}" ? "value" : char;
560
+ i++;
561
+ }
562
+ }
563
+
564
+ // src/code/scan/html.ts
565
+ var ENTITY = /&(?:#\d+|#x[\da-fA-F]+|[A-Za-z]\w*);/g;
566
+ function emitEntities(code, from, to, emit) {
567
+ ENTITY.lastIndex = from;
568
+ for (let match = ENTITY.exec(code); match && match.index < to; match = ENTITY.exec(code)) {
569
+ if (match.index + match[0].length <= to)
570
+ emit(match.index, match.index + match[0].length, "constant");
571
+ }
572
+ }
573
+ function scanHtml(code, start, end, emit) {
574
+ let i = start;
575
+ while (i < end) {
576
+ const open = code.indexOf("<", i);
577
+ if (open < 0 || open >= end) {
578
+ emitEntities(code, i, end, emit);
579
+ return;
580
+ }
581
+ emitEntities(code, i, open, emit);
582
+ if (code.startsWith("<!--", open)) {
583
+ const close = code.indexOf("-->", open + 4);
584
+ const stop = close < 0 || close + 3 > end ? end : close + 3;
585
+ emit(open, stop, "comment");
586
+ i = stop;
587
+ continue;
588
+ }
589
+ if (code.startsWith("<!", open) || code.startsWith("<?", open)) {
590
+ const close = code.indexOf(">", open);
591
+ const stop = close < 0 || close >= end ? end : close + 1;
592
+ emit(open, stop, "meta");
593
+ i = stop;
594
+ continue;
595
+ }
596
+ const name = matchAt(/<\/?[A-Za-z][\w:.-]*/y, code, open);
597
+ if (!name) {
598
+ i = open + 1;
599
+ continue;
600
+ }
601
+ emit(open, open + name.length, "tag");
602
+ i = open + name.length;
603
+ let selfClosing = false;
604
+ while (i < end) {
605
+ while (i < end && isSpace(code[i])) i++;
606
+ if (code[i] === ">") {
607
+ emit(i, i + 1, "tag");
608
+ i++;
609
+ break;
610
+ }
611
+ if (code.startsWith("/>", i)) {
612
+ emit(i, i + 2, "tag");
613
+ selfClosing = true;
614
+ i += 2;
615
+ break;
616
+ }
617
+ const attribute = matchAt(/[^\s=<>"'/]+/y, code, i);
618
+ if (!attribute) {
619
+ i++;
620
+ continue;
621
+ }
622
+ emit(i, i + attribute.length, "attribute");
623
+ i += attribute.length;
624
+ let after = i;
625
+ while (after < end && isSpace(code[after])) after++;
626
+ if (code[after] !== "=") continue;
627
+ after++;
628
+ while (after < end && isSpace(code[after])) after++;
629
+ const quote = code[after];
630
+ if (quote === '"' || quote === "'") {
631
+ const close = code.indexOf(quote, after + 1);
632
+ const stop = close < 0 || close >= end ? end : close + 1;
633
+ emit(after, stop, "string");
634
+ i = stop;
635
+ } else {
636
+ const value = matchAt(/[^\s>]+/y, code, after);
637
+ if (value) emit(after, after + value.length, "string");
638
+ i = after + (value ? value.length : 0);
639
+ }
640
+ }
641
+ const tag = name.replace(/^<\/?/, "").toLowerCase();
642
+ if (!selfClosing && !name.startsWith("</") && (tag === "script" || tag === "style") && i < end) {
643
+ const close = code.toLowerCase().indexOf(`</${tag}`, i);
644
+ const stop = close < 0 || close > end ? end : close;
645
+ if (tag === "script") scanGeneric(code, LANGUAGES.javascript, i, stop, emit);
646
+ else scanCss(code, i, stop, emit);
647
+ i = stop;
648
+ }
649
+ }
650
+ }
651
+
652
+ // src/code/scan/markdown.ts
653
+ var MARKDOWN_INLINE = /`[^`\n]+`|\*\*[^*\n]+\*\*|__[^_\n]+__|\[[^\]\n]*\]\([^)\n]*\)/g;
654
+ function scanMarkdown(code, start, end, emit) {
655
+ let inFence = false;
656
+ let lineStart = start;
657
+ while (lineStart <= end) {
658
+ const stop = lineEnd(code, lineStart, end);
659
+ const line = code.slice(lineStart, stop);
660
+ if (/^\s*(```|~~~)/.test(line)) {
661
+ emit(lineStart, stop, "meta");
662
+ inFence = !inFence;
663
+ } else if (inFence) {
664
+ emit(lineStart, stop, "string");
665
+ } else if (/^#{1,6}\s/.test(line)) {
666
+ emit(lineStart, stop, "keyword");
667
+ } else if (/^\s*([-*_])(\s*\1){2,}\s*$/.test(line)) {
668
+ emit(lineStart, stop, "meta");
669
+ } else {
670
+ let offset = 0;
671
+ const marker = /^\s*(?:>|[-*+]\s|\d+[.)]\s)/.exec(line);
672
+ if (marker) {
673
+ const length = marker[0].trimEnd().length;
674
+ emit(
675
+ lineStart + marker[0].length - marker[0].trimStart().length,
676
+ lineStart + length,
677
+ "keyword"
678
+ );
679
+ offset = marker[0].length;
680
+ }
681
+ MARKDOWN_INLINE.lastIndex = offset;
682
+ for (let match = MARKDOWN_INLINE.exec(line); match; match = MARKDOWN_INLINE.exec(line)) {
683
+ const from = lineStart + match.index;
684
+ const text = match[0];
685
+ if (text.startsWith("[")) {
686
+ const split = text.indexOf("](");
687
+ emit(from, from + split + 1, "function");
688
+ emit(from + split + 1, from + text.length, "string");
689
+ } else {
690
+ emit(from, from + text.length, text.startsWith("`") ? "string" : "keyword");
691
+ }
692
+ }
693
+ }
694
+ if (stop >= end) break;
695
+ lineStart = stop + 1;
696
+ }
697
+ }
698
+
699
+ // src/code/scan/yaml.ts
700
+ var YAML_KEY = /^(\s*(?:-\s+)*)("[^"]*"|'[^']*'|[^\s#:'"[\]{},&*!|>-][^#:]*?)\s*:(?=\s|$)/;
701
+ function scanYaml(code, start, end, emit) {
702
+ let lineStart = start;
703
+ while (lineStart <= end) {
704
+ const stop = lineEnd(code, lineStart, end);
705
+ const line = code.slice(lineStart, stop);
706
+ if (/^(---|\.\.\.)\s*$/.test(line)) {
707
+ emit(lineStart, stop, "meta");
708
+ } else {
709
+ const key = YAML_KEY.exec(line);
710
+ let restStart = lineStart;
711
+ if (key) {
712
+ const keyFrom = lineStart + key[1].length;
713
+ emit(keyFrom, keyFrom + key[2].length, "property");
714
+ restStart = lineStart + key[0].length;
715
+ }
716
+ scanGeneric(code, LANGUAGES.yaml, restStart, stop, emit);
717
+ }
718
+ if (stop >= end) break;
719
+ lineStart = stop + 1;
720
+ }
721
+ }
722
+
723
+ // src/code/highlight.ts
724
+ var HIGHLIGHT_LIMIT = 1e5;
725
+ function normalizeLanguage(language) {
726
+ const name = language.trim().toLowerCase();
727
+ return ALIASES[name] ?? name;
728
+ }
729
+ var highlightCode = (code, language) => {
730
+ const name = normalizeLanguage(language);
731
+ if (code.length === 0 || code.length > HIGHLIGHT_LIMIT) return [];
732
+ const tokens = [];
733
+ const emit = (from, to, type) => {
734
+ if (to > from) tokens.push({ from, to, type });
735
+ };
736
+ switch (name) {
737
+ case "html":
738
+ scanHtml(code, 0, code.length, emit);
739
+ break;
740
+ case "css":
741
+ scanCss(code, 0, code.length, emit);
742
+ break;
743
+ case "markdown":
744
+ scanMarkdown(code, 0, code.length, emit);
745
+ break;
746
+ case "yaml":
747
+ scanYaml(code, 0, code.length, emit);
748
+ break;
749
+ default: {
750
+ const lang = LANGUAGES[name];
751
+ if (lang) scanGeneric(code, lang, 0, code.length, emit);
752
+ }
753
+ }
754
+ return tokens;
755
+ };
756
+
757
+ // src/i18n/en.ts
758
+ var en = {
759
+ "editor.hint": "Press / to open the menu",
760
+ "editor.label": "Document",
761
+ "block.list.done": "Done",
762
+ "block.code.language": "Code language",
763
+ "block.code.copy": "Copy code",
764
+ "block.code.copied": "Copied",
765
+ "block.callout.label": "Callout style: {tone}. Click to change",
766
+ "block.callout.change": "Change style",
767
+ "block.callout.tone.info": "info",
768
+ "block.callout.tone.warning": "warning",
769
+ "block.callout.tone.success": "success",
770
+ "block.callout.tone.danger": "danger",
771
+ "block.unknown.title": "Unknown block type:",
772
+ "block.unknown.hint": "Register a component for it via",
773
+ "image.options": "Image options",
774
+ "image.align.left": "Align left",
775
+ "image.align.center": "Align center",
776
+ "image.align.right": "Align right",
777
+ "image.width": "Image width",
778
+ "image.alt": "Alt text",
779
+ "image.caption.label": "Caption",
780
+ "image.caption.placeholder": "Write a caption\u2026",
781
+ "image.replace": "Replace image",
782
+ "image.url.label": "Image URL",
783
+ "image.url.placeholder": "Paste an image link\u2026",
784
+ "image.embed": "Embed",
785
+ "image.upload": "Upload",
786
+ "image.status.uploading": "Uploading\u2026",
787
+ "image.status.none": "No image",
788
+ "image.status.unsupported": "This image address is not supported",
789
+ "image.status.failed": "The image could not be loaded",
790
+ "image.status.retry": "Replace",
791
+ "image.error.invalidLink": "Enter a valid http(s) image link",
792
+ "image.error.unsupportedAddress": "This image address is not supported",
793
+ "image.error.type": 'Unsupported image type "{type}"',
794
+ "image.error.size": 'The image is larger than {size} KB. Provide "images.upload" to store larger images.',
795
+ "image.error.uploadAddress": "The upload returned an unsupported image address",
796
+ "image.error.read": "Could not read the file",
797
+ "image.error.generic": "Could not add the image",
798
+ "formula.source": "LaTeX formula",
799
+ "formula.placeholder": "Type LaTeX, e.g. \\frac{a}{b}",
800
+ "formula.hint": "Ctrl+Enter to apply, Esc to cancel",
801
+ "formula.empty": "Add a formula",
802
+ "formula.edit": "Edit formula",
803
+ "formula.inline.title": "Inline formula",
804
+ "formula.apply": "Apply",
805
+ "formula.remove": "Remove formula",
806
+ "formula.cancel": "Cancel",
807
+ "formula.palette.label": "Math symbols",
808
+ "formula.palette.functions": "Functions",
809
+ "formula.palette.structures": "Structures",
810
+ "formula.palette.greek": "Greek letters",
811
+ "formula.palette.operators": "Operators",
812
+ "formula.palette.relations": "Relations",
813
+ "formula.palette.arrows": "Arrows",
814
+ "formula.palette.sets": "Sets and logic",
815
+ "color.black": "Black",
816
+ "color.white": "White",
817
+ "color.gray": "Gray",
818
+ "color.brown": "Brown",
819
+ "color.orange": "Orange",
820
+ "color.yellow": "Yellow",
821
+ "color.green": "Green",
822
+ "color.blue": "Blue",
823
+ "color.purple": "Purple",
824
+ "color.pink": "Pink",
825
+ "color.red": "Red",
826
+ "toolbar.label": "Text formatting",
827
+ "toolbar.bold.label": "Bold",
828
+ "toolbar.bold.title": "Bold (Ctrl+B)",
829
+ "toolbar.italic.label": "Italic",
830
+ "toolbar.italic.title": "Italic (Ctrl+I)",
831
+ "toolbar.underline.label": "Underline",
832
+ "toolbar.underline.title": "Underline (Ctrl+U)",
833
+ "toolbar.strike.label": "Strikethrough",
834
+ "toolbar.strike.title": "Strikethrough (Ctrl+Shift+X)",
835
+ "toolbar.code.label": "Code",
836
+ "toolbar.code.title": "Code (Ctrl+E)",
837
+ "toolbar.formula.label": "Formula",
838
+ "toolbar.formula.title": "Formula (Ctrl+Shift+M)",
839
+ "toolbar.color.label": "Text color",
840
+ "toolbar.color.title": "Text color",
841
+ "toolbar.color.default": "Default color",
842
+ "toolbar.highlight.label": "Highlight color",
843
+ "toolbar.highlight.title": "Highlight",
844
+ "toolbar.highlight.none": "No highlight",
845
+ "toolbar.align.left.label": "Align left",
846
+ "toolbar.align.left.title": "Align left (Ctrl+Shift+L)",
847
+ "toolbar.align.center.label": "Align center",
848
+ "toolbar.align.center.title": "Align center (Ctrl+Shift+E)",
849
+ "toolbar.align.right.label": "Align right",
850
+ "toolbar.align.right.title": "Align right (Ctrl+Shift+R)",
851
+ "toolbar.align.justify.label": "Justify",
852
+ "toolbar.align.justify.title": "Justify (Ctrl+Shift+J)",
853
+ "toolbar.link.label": "Link",
854
+ "toolbar.link.title": "Link (Ctrl+K)",
855
+ "toolbar.link.url": "Link URL",
856
+ "toolbar.link.placeholder": "Paste a link\u2026",
857
+ "toolbar.link.apply": "Apply link",
858
+ "toolbar.link.remove": "Remove link",
859
+ "handle.add": "Add block below",
860
+ "handle.grip": "Drag to move, click for options",
861
+ "menu.label": "Block options",
862
+ "menu.duplicate": "Duplicate",
863
+ "menu.moveUp": "Move up",
864
+ "menu.moveDown": "Move down",
865
+ "menu.delete": "Delete",
866
+ "menu.turnInto": "Turn into",
867
+ "menu.empty": "No actions",
868
+ "history.undo": "Undo",
869
+ "history.redo": "Redo",
870
+ "slash.label": "Insert block",
871
+ "slash.empty": "No results",
872
+ "slash.item.text.title": "Text",
873
+ "slash.item.text.description": "Plain paragraph",
874
+ "slash.item.text.keywords": "paragraph, p",
875
+ "slash.item.heading-1.title": "Heading 1",
876
+ "slash.item.heading-1.description": "Large section heading",
877
+ "slash.item.heading-1.keywords": "h1, title",
878
+ "slash.item.heading-2.title": "Heading 2",
879
+ "slash.item.heading-2.description": "Medium section heading",
880
+ "slash.item.heading-2.keywords": "h2, subtitle",
881
+ "slash.item.heading-3.title": "Heading 3",
882
+ "slash.item.heading-3.description": "Small section heading",
883
+ "slash.item.heading-3.keywords": "h3",
884
+ "slash.item.heading-4.title": "Heading 4",
885
+ "slash.item.heading-4.description": "Subsection heading",
886
+ "slash.item.heading-4.keywords": "h4",
887
+ "slash.item.heading-5.title": "Heading 5",
888
+ "slash.item.heading-5.description": "Minor subsection heading",
889
+ "slash.item.heading-5.keywords": "h5",
890
+ "slash.item.heading-6.title": "Heading 6",
891
+ "slash.item.heading-6.description": "Smallest heading",
892
+ "slash.item.heading-6.keywords": "h6",
893
+ "slash.item.bullet-list.title": "Bulleted list",
894
+ "slash.item.bullet-list.description": "Simple bulleted list",
895
+ "slash.item.bullet-list.keywords": "ul, unordered, list",
896
+ "slash.item.numbered-list.title": "Numbered list",
897
+ "slash.item.numbered-list.description": "List with numbering",
898
+ "slash.item.numbered-list.keywords": "ol, ordered, list",
899
+ "slash.item.todo-list.title": "To-do list",
900
+ "slash.item.todo-list.description": "Track tasks with checkboxes",
901
+ "slash.item.todo-list.keywords": "todo, task, checkbox, check",
902
+ "slash.item.quote.title": "Quote",
903
+ "slash.item.quote.description": "Capture a quote",
904
+ "slash.item.quote.keywords": "blockquote, citation",
905
+ "slash.item.code.title": "Code",
906
+ "slash.item.code.description": "Code snippet with monospace font",
907
+ "slash.item.code.keywords": "snippet, pre, program",
908
+ "slash.item.callout.title": "Callout",
909
+ "slash.item.callout.description": "Highlight important information",
910
+ "slash.item.callout.keywords": "info, note, warning, tip, alert",
911
+ "slash.item.image.title": "Image",
912
+ "slash.item.image.description": "Upload or embed an image",
913
+ "slash.item.image.keywords": "picture, photo, img, upload",
914
+ "slash.item.formula.title": "Formula",
915
+ "slash.item.formula.description": "Display a LaTeX formula",
916
+ "slash.item.formula.keywords": "math, equation, latex, tex",
917
+ "slash.item.divider.title": "Divider",
918
+ "slash.item.divider.description": "Visually separate sections",
919
+ "slash.item.divider.keywords": "hr, line, separator, rule"
920
+ };
921
+
922
+ // src/i18n/ru.ts
923
+ var ru = {
924
+ "editor.hint": "\u041D\u0430\u0436\u043C\u0438\u0442\u0435 \xAB/\xBB, \u0447\u0442\u043E\u0431\u044B \u043E\u0442\u043A\u0440\u044B\u0442\u044C \u043C\u0435\u043D\u044E",
925
+ "editor.label": "\u0414\u043E\u043A\u0443\u043C\u0435\u043D\u0442",
926
+ "block.list.done": "\u0412\u044B\u043F\u043E\u043B\u043D\u0435\u043D\u043E",
927
+ "block.code.language": "\u042F\u0437\u044B\u043A \u043A\u043E\u0434\u0430",
928
+ "block.code.copy": "\u041A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u043A\u043E\u0434",
929
+ "block.code.copied": "\u0421\u043A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u043D\u043E",
930
+ "block.callout.label": "\u0421\u0442\u0438\u043B\u044C \u0437\u0430\u043C\u0435\u0442\u043A\u0438: {tone}. \u041D\u0430\u0436\u043C\u0438\u0442\u0435, \u0447\u0442\u043E\u0431\u044B \u0438\u0437\u043C\u0435\u043D\u0438\u0442\u044C",
931
+ "block.callout.change": "\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u0441\u0442\u0438\u043B\u044C",
932
+ "block.callout.tone.info": "\u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u044F",
933
+ "block.callout.tone.warning": "\u043F\u0440\u0435\u0434\u0443\u043F\u0440\u0435\u0436\u0434\u0435\u043D\u0438\u0435",
934
+ "block.callout.tone.success": "\u0443\u0441\u043F\u0435\u0445",
935
+ "block.callout.tone.danger": "\u043E\u043F\u0430\u0441\u043D\u043E\u0441\u0442\u044C",
936
+ "block.unknown.title": "\u041D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043D\u044B\u0439 \u0442\u0438\u043F \u0431\u043B\u043E\u043A\u0430:",
937
+ "block.unknown.hint": "\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0439\u0442\u0435 \u0434\u043B\u044F \u043D\u0435\u0433\u043E \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442 \u0447\u0435\u0440\u0435\u0437",
938
+ "image.options": "\u041F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u044B \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F",
939
+ "image.align.left": "\u041F\u043E \u043B\u0435\u0432\u043E\u043C\u0443 \u043A\u0440\u0430\u044E",
940
+ "image.align.center": "\u041F\u043E \u0446\u0435\u043D\u0442\u0440\u0443",
941
+ "image.align.right": "\u041F\u043E \u043F\u0440\u0430\u0432\u043E\u043C\u0443 \u043A\u0440\u0430\u044E",
942
+ "image.width": "\u0428\u0438\u0440\u0438\u043D\u0430 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F",
943
+ "image.alt": "\u0410\u043B\u044C\u0442\u0435\u0440\u043D\u0430\u0442\u0438\u0432\u043D\u044B\u0439 \u0442\u0435\u043A\u0441\u0442",
944
+ "image.caption.label": "\u041F\u043E\u0434\u043F\u0438\u0441\u044C",
945
+ "image.caption.placeholder": "\u0414\u043E\u0431\u0430\u0432\u044C\u0442\u0435 \u043F\u043E\u0434\u043F\u0438\u0441\u044C\u2026",
946
+ "image.replace": "\u0417\u0430\u043C\u0435\u043D\u0438\u0442\u044C \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435",
947
+ "image.url.label": "\u0410\u0434\u0440\u0435\u0441 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F",
948
+ "image.url.placeholder": "\u0412\u0441\u0442\u0430\u0432\u044C\u0442\u0435 \u0441\u0441\u044B\u043B\u043A\u0443 \u043D\u0430 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435\u2026",
949
+ "image.embed": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044C",
950
+ "image.upload": "\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C",
951
+ "image.status.uploading": "\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430\u2026",
952
+ "image.status.none": "\u041D\u0435\u0442 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F",
953
+ "image.status.unsupported": "\u042D\u0442\u043E\u0442 \u0430\u0434\u0440\u0435\u0441 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F",
954
+ "image.status.failed": "\u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435",
955
+ "image.status.retry": "\u0417\u0430\u043C\u0435\u043D\u0438\u0442\u044C",
956
+ "image.error.invalidLink": "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043A\u043E\u0440\u0440\u0435\u043A\u0442\u043D\u0443\u044E \u0441\u0441\u044B\u043B\u043A\u0443 \u043D\u0430 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 (http \u0438\u043B\u0438 https)",
957
+ "image.error.unsupportedAddress": "\u042D\u0442\u043E\u0442 \u0430\u0434\u0440\u0435\u0441 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F",
958
+ "image.error.type": "\u041D\u0435\u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043C\u044B\u0439 \u0442\u0438\u043F \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F \xAB{type}\xBB",
959
+ "image.error.size": "\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u0431\u043E\u043B\u044C\u0448\u0435 {size} \u041A\u0411. \u0427\u0442\u043E\u0431\u044B \u0445\u0440\u0430\u043D\u0438\u0442\u044C \u0431\u043E\u043B\u044C\u0448\u0438\u0435 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F, \u0437\u0430\u0434\u0430\u0439\u0442\u0435 \xABimages.upload\xBB.",
960
+ "image.error.uploadAddress": "\u0417\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043A \u0432\u0435\u0440\u043D\u0443\u043B \u043D\u0435\u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043C\u044B\u0439 \u0430\u0434\u0440\u0435\u0441 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F",
961
+ "image.error.read": "\u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u043F\u0440\u043E\u0447\u0438\u0442\u0430\u0442\u044C \u0444\u0430\u0439\u043B",
962
+ "image.error.generic": "\u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u0434\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435",
963
+ "formula.source": "\u0424\u043E\u0440\u043C\u0443\u043B\u0430 LaTeX",
964
+ "formula.placeholder": "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 LaTeX, \u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440 \\frac{a}{b}",
965
+ "formula.hint": "Ctrl+Enter \u2014 \u043F\u0440\u0438\u043C\u0435\u043D\u0438\u0442\u044C, Esc \u2014 \u043E\u0442\u043C\u0435\u043D\u0430",
966
+ "formula.empty": "\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0444\u043E\u0440\u043C\u0443\u043B\u0443",
967
+ "formula.edit": "\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u0444\u043E\u0440\u043C\u0443\u043B\u0443",
968
+ "formula.inline.title": "\u0412\u0441\u0442\u0440\u043E\u0435\u043D\u043D\u0430\u044F \u0444\u043E\u0440\u043C\u0443\u043B\u0430",
969
+ "formula.apply": "\u041F\u0440\u0438\u043C\u0435\u043D\u0438\u0442\u044C",
970
+ "formula.remove": "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0444\u043E\u0440\u043C\u0443\u043B\u0443",
971
+ "formula.cancel": "\u041E\u0442\u043C\u0435\u043D\u0430",
972
+ "formula.palette.label": "\u041C\u0430\u0442\u0435\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0438\u0435 \u0441\u0438\u043C\u0432\u043E\u043B\u044B",
973
+ "formula.palette.functions": "\u0424\u0443\u043D\u043A\u0446\u0438\u0438",
974
+ "formula.palette.structures": "\u041A\u043E\u043D\u0441\u0442\u0440\u0443\u043A\u0446\u0438\u0438",
975
+ "formula.palette.greek": "\u0413\u0440\u0435\u0447\u0435\u0441\u043A\u0438\u0435 \u0431\u0443\u043A\u0432\u044B",
976
+ "formula.palette.operators": "\u041E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u044B",
977
+ "formula.palette.relations": "\u041E\u0442\u043D\u043E\u0448\u0435\u043D\u0438\u044F",
978
+ "formula.palette.arrows": "\u0421\u0442\u0440\u0435\u043B\u043A\u0438",
979
+ "formula.palette.sets": "\u041C\u043D\u043E\u0436\u0435\u0441\u0442\u0432\u0430 \u0438 \u043B\u043E\u0433\u0438\u043A\u0430",
980
+ "color.black": "\u0427\u0451\u0440\u043D\u044B\u0439",
981
+ "color.white": "\u0411\u0435\u043B\u044B\u0439",
982
+ "color.gray": "\u0421\u0435\u0440\u044B\u0439",
983
+ "color.brown": "\u041A\u043E\u0440\u0438\u0447\u043D\u0435\u0432\u044B\u0439",
984
+ "color.orange": "\u041E\u0440\u0430\u043D\u0436\u0435\u0432\u044B\u0439",
985
+ "color.yellow": "\u0416\u0451\u043B\u0442\u044B\u0439",
986
+ "color.green": "\u0417\u0435\u043B\u0451\u043D\u044B\u0439",
987
+ "color.blue": "\u0421\u0438\u043D\u0438\u0439",
988
+ "color.purple": "\u0424\u0438\u043E\u043B\u0435\u0442\u043E\u0432\u044B\u0439",
989
+ "color.pink": "\u0420\u043E\u0437\u043E\u0432\u044B\u0439",
990
+ "color.red": "\u041A\u0440\u0430\u0441\u043D\u044B\u0439",
991
+ "toolbar.label": "\u0424\u043E\u0440\u043C\u0430\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u0435 \u0442\u0435\u043A\u0441\u0442\u0430",
992
+ "toolbar.bold.label": "\u0416\u0438\u0440\u043D\u044B\u0439",
993
+ "toolbar.bold.title": "\u0416\u0438\u0440\u043D\u044B\u0439 (Ctrl+B)",
994
+ "toolbar.italic.label": "\u041A\u0443\u0440\u0441\u0438\u0432",
995
+ "toolbar.italic.title": "\u041A\u0443\u0440\u0441\u0438\u0432 (Ctrl+I)",
996
+ "toolbar.underline.label": "\u041F\u043E\u0434\u0447\u0451\u0440\u043A\u043D\u0443\u0442\u044B\u0439",
997
+ "toolbar.underline.title": "\u041F\u043E\u0434\u0447\u0451\u0440\u043A\u043D\u0443\u0442\u044B\u0439 (Ctrl+U)",
998
+ "toolbar.strike.label": "\u0417\u0430\u0447\u0451\u0440\u043A\u043D\u0443\u0442\u044B\u0439",
999
+ "toolbar.strike.title": "\u0417\u0430\u0447\u0451\u0440\u043A\u043D\u0443\u0442\u044B\u0439 (Ctrl+Shift+X)",
1000
+ "toolbar.code.label": "\u041A\u043E\u0434",
1001
+ "toolbar.code.title": "\u041A\u043E\u0434 (Ctrl+E)",
1002
+ "toolbar.formula.label": "\u0424\u043E\u0440\u043C\u0443\u043B\u0430",
1003
+ "toolbar.formula.title": "\u0424\u043E\u0440\u043C\u0443\u043B\u0430 (Ctrl+Shift+M)",
1004
+ "toolbar.color.label": "\u0426\u0432\u0435\u0442 \u0442\u0435\u043A\u0441\u0442\u0430",
1005
+ "toolbar.color.title": "\u0426\u0432\u0435\u0442 \u0442\u0435\u043A\u0441\u0442\u0430",
1006
+ "toolbar.color.default": "\u0426\u0432\u0435\u0442 \u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E",
1007
+ "toolbar.highlight.label": "\u0426\u0432\u0435\u0442 \u0444\u043E\u043D\u0430",
1008
+ "toolbar.highlight.title": "\u0412\u044B\u0434\u0435\u043B\u0435\u043D\u0438\u0435 \u0446\u0432\u0435\u0442\u043E\u043C",
1009
+ "toolbar.highlight.none": "\u0411\u0435\u0437 \u0432\u044B\u0434\u0435\u043B\u0435\u043D\u0438\u044F",
1010
+ "toolbar.align.left.label": "\u041F\u043E \u043B\u0435\u0432\u043E\u043C\u0443 \u043A\u0440\u0430\u044E",
1011
+ "toolbar.align.left.title": "\u041F\u043E \u043B\u0435\u0432\u043E\u043C\u0443 \u043A\u0440\u0430\u044E (Ctrl+Shift+L)",
1012
+ "toolbar.align.center.label": "\u041F\u043E \u0446\u0435\u043D\u0442\u0440\u0443",
1013
+ "toolbar.align.center.title": "\u041F\u043E \u0446\u0435\u043D\u0442\u0440\u0443 (Ctrl+Shift+E)",
1014
+ "toolbar.align.right.label": "\u041F\u043E \u043F\u0440\u0430\u0432\u043E\u043C\u0443 \u043A\u0440\u0430\u044E",
1015
+ "toolbar.align.right.title": "\u041F\u043E \u043F\u0440\u0430\u0432\u043E\u043C\u0443 \u043A\u0440\u0430\u044E (Ctrl+Shift+R)",
1016
+ "toolbar.align.justify.label": "\u041F\u043E \u0448\u0438\u0440\u0438\u043D\u0435",
1017
+ "toolbar.align.justify.title": "\u041F\u043E \u0448\u0438\u0440\u0438\u043D\u0435 (Ctrl+Shift+J)",
1018
+ "toolbar.link.label": "\u0421\u0441\u044B\u043B\u043A\u0430",
1019
+ "toolbar.link.title": "\u0421\u0441\u044B\u043B\u043A\u0430 (Ctrl+K)",
1020
+ "toolbar.link.url": "\u0410\u0434\u0440\u0435\u0441 \u0441\u0441\u044B\u043B\u043A\u0438",
1021
+ "toolbar.link.placeholder": "\u0412\u0441\u0442\u0430\u0432\u044C\u0442\u0435 \u0441\u0441\u044B\u043B\u043A\u0443\u2026",
1022
+ "toolbar.link.apply": "\u041F\u0440\u0438\u043C\u0435\u043D\u0438\u0442\u044C \u0441\u0441\u044B\u043B\u043A\u0443",
1023
+ "toolbar.link.remove": "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0441\u0441\u044B\u043B\u043A\u0443",
1024
+ "handle.add": "\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0431\u043B\u043E\u043A \u043D\u0438\u0436\u0435",
1025
+ "handle.grip": "\u041F\u0435\u0440\u0435\u0442\u0430\u0449\u0438\u0442\u0435, \u0447\u0442\u043E\u0431\u044B \u043F\u0435\u0440\u0435\u043C\u0435\u0441\u0442\u0438\u0442\u044C, \u0438\u043B\u0438 \u043D\u0430\u0436\u043C\u0438\u0442\u0435 \u0434\u043B\u044F \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u043E\u0432",
1026
+ "menu.label": "\u041F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u044B \u0431\u043B\u043E\u043A\u0430",
1027
+ "menu.duplicate": "\u0414\u0443\u0431\u043B\u0438\u0440\u043E\u0432\u0430\u0442\u044C",
1028
+ "menu.moveUp": "\u041F\u0435\u0440\u0435\u043C\u0435\u0441\u0442\u0438\u0442\u044C \u0432\u0432\u0435\u0440\u0445",
1029
+ "menu.moveDown": "\u041F\u0435\u0440\u0435\u043C\u0435\u0441\u0442\u0438\u0442\u044C \u0432\u043D\u0438\u0437",
1030
+ "menu.delete": "\u0423\u0434\u0430\u043B\u0438\u0442\u044C",
1031
+ "menu.turnInto": "\u041F\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u0442\u044C \u0432",
1032
+ "menu.empty": "\u041D\u0435\u0442 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439",
1033
+ "history.undo": "\u041E\u0442\u043C\u0435\u043D\u0438\u0442\u044C",
1034
+ "history.redo": "\u041F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u044C",
1035
+ "slash.label": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044C \u0431\u043B\u043E\u043A",
1036
+ "slash.empty": "\u041D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E",
1037
+ "slash.item.text.title": "\u0422\u0435\u043A\u0441\u0442",
1038
+ "slash.item.text.description": "\u041E\u0431\u044B\u0447\u043D\u044B\u0439 \u0430\u0431\u0437\u0430\u0446",
1039
+ "slash.item.text.keywords": "\u0430\u0431\u0437\u0430\u0446, \u043F\u0430\u0440\u0430\u0433\u0440\u0430\u0444, \u0442\u0435\u043A\u0441\u0442, paragraph",
1040
+ "slash.item.heading-1.title": "\u0417\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A 1",
1041
+ "slash.item.heading-1.description": "\u041A\u0440\u0443\u043F\u043D\u044B\u0439 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A \u0440\u0430\u0437\u0434\u0435\u043B\u0430",
1042
+ "slash.item.heading-1.keywords": "\u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A, h1, title",
1043
+ "slash.item.heading-2.title": "\u0417\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A 2",
1044
+ "slash.item.heading-2.description": "\u0421\u0440\u0435\u0434\u043D\u0438\u0439 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A \u0440\u0430\u0437\u0434\u0435\u043B\u0430",
1045
+ "slash.item.heading-2.keywords": "\u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A, \u043F\u043E\u0434\u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A, h2",
1046
+ "slash.item.heading-3.title": "\u0417\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A 3",
1047
+ "slash.item.heading-3.description": "\u041D\u0435\u0431\u043E\u043B\u044C\u0448\u043E\u0439 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A \u0440\u0430\u0437\u0434\u0435\u043B\u0430",
1048
+ "slash.item.heading-3.keywords": "\u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A, h3",
1049
+ "slash.item.heading-4.title": "\u0417\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A 4",
1050
+ "slash.item.heading-4.description": "\u0417\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A \u043F\u043E\u0434\u0440\u0430\u0437\u0434\u0435\u043B\u0430",
1051
+ "slash.item.heading-4.keywords": "\u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A, h4",
1052
+ "slash.item.heading-5.title": "\u0417\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A 5",
1053
+ "slash.item.heading-5.description": "\u041C\u0435\u043B\u043A\u0438\u0439 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A \u043F\u043E\u0434\u0440\u0430\u0437\u0434\u0435\u043B\u0430",
1054
+ "slash.item.heading-5.keywords": "\u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A, h5",
1055
+ "slash.item.heading-6.title": "\u0417\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A 6",
1056
+ "slash.item.heading-6.description": "\u0421\u0430\u043C\u044B\u0439 \u043C\u0435\u043B\u043A\u0438\u0439 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A",
1057
+ "slash.item.heading-6.keywords": "\u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A, h6",
1058
+ "slash.item.bullet-list.title": "\u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u044B\u0439 \u0441\u043F\u0438\u0441\u043E\u043A",
1059
+ "slash.item.bullet-list.description": "\u041F\u0440\u043E\u0441\u0442\u043E\u0439 \u0441\u043F\u0438\u0441\u043E\u043A \u0441 \u043C\u0430\u0440\u043A\u0435\u0440\u0430\u043C\u0438",
1060
+ "slash.item.bullet-list.keywords": "\u0441\u043F\u0438\u0441\u043E\u043A, \u043C\u0430\u0440\u043A\u0435\u0440, ul, list",
1061
+ "slash.item.numbered-list.title": "\u041D\u0443\u043C\u0435\u0440\u043E\u0432\u0430\u043D\u043D\u044B\u0439 \u0441\u043F\u0438\u0441\u043E\u043A",
1062
+ "slash.item.numbered-list.description": "\u0421\u043F\u0438\u0441\u043E\u043A \u0441 \u043D\u0443\u043C\u0435\u0440\u0430\u0446\u0438\u0435\u0439",
1063
+ "slash.item.numbered-list.keywords": "\u0441\u043F\u0438\u0441\u043E\u043A, \u043D\u0443\u043C\u0435\u0440\u0430\u0446\u0438\u044F, ol, list",
1064
+ "slash.item.todo-list.title": "\u0421\u043F\u0438\u0441\u043E\u043A \u0437\u0430\u0434\u0430\u0447",
1065
+ "slash.item.todo-list.description": "\u0417\u0430\u0434\u0430\u0447\u0438 \u0441 \u0444\u043B\u0430\u0436\u043A\u0430\u043C\u0438",
1066
+ "slash.item.todo-list.keywords": "\u0437\u0430\u0434\u0430\u0447\u0438, \u0447\u0435\u043A\u0431\u043E\u043A\u0441, \u0444\u043B\u0430\u0436\u043E\u043A, todo, task",
1067
+ "slash.item.quote.title": "\u0426\u0438\u0442\u0430\u0442\u0430",
1068
+ "slash.item.quote.description": "\u0412\u044B\u0434\u0435\u043B\u0438\u0442\u044C \u0446\u0438\u0442\u0430\u0442\u0443",
1069
+ "slash.item.quote.keywords": "\u0446\u0438\u0442\u0430\u0442\u0430, blockquote",
1070
+ "slash.item.code.title": "\u041A\u043E\u0434",
1071
+ "slash.item.code.description": "\u0424\u0440\u0430\u0433\u043C\u0435\u043D\u0442 \u043A\u043E\u0434\u0430 \u043C\u043E\u043D\u043E\u0448\u0438\u0440\u0438\u043D\u043D\u044B\u043C \u0448\u0440\u0438\u0444\u0442\u043E\u043C",
1072
+ "slash.item.code.keywords": "\u043A\u043E\u0434, \u0441\u043D\u0438\u043F\u043F\u0435\u0442, \u043F\u0440\u043E\u0433\u0440\u0430\u043C\u043C\u0430, snippet",
1073
+ "slash.item.callout.title": "\u0417\u0430\u043C\u0435\u0442\u043A\u0430",
1074
+ "slash.item.callout.description": "\u0412\u044B\u0434\u0435\u043B\u0438\u0442\u044C \u0432\u0430\u0436\u043D\u0443\u044E \u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u044E",
1075
+ "slash.item.callout.keywords": "\u0437\u0430\u043C\u0435\u0442\u043A\u0430, \u0432\u0430\u0436\u043D\u043E, \u043F\u0440\u0435\u0434\u0443\u043F\u0440\u0435\u0436\u0434\u0435\u043D\u0438\u0435, \u043F\u043E\u0434\u0441\u043A\u0430\u0437\u043A\u0430, callout, info",
1076
+ "slash.item.image.title": "\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435",
1077
+ "slash.item.image.description": "\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u0438\u043B\u0438 \u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044C \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435",
1078
+ "slash.item.image.keywords": "\u043A\u0430\u0440\u0442\u0438\u043D\u043A\u0430, \u0444\u043E\u0442\u043E, \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435, image, img",
1079
+ "slash.item.formula.title": "\u0424\u043E\u0440\u043C\u0443\u043B\u0430",
1080
+ "slash.item.formula.description": "\u0424\u043E\u0440\u043C\u0443\u043B\u0430 LaTeX \u043E\u0442\u0434\u0435\u043B\u044C\u043D\u043E\u0439 \u0441\u0442\u0440\u043E\u043A\u043E\u0439",
1081
+ "slash.item.formula.keywords": "\u0444\u043E\u0440\u043C\u0443\u043B\u0430, \u043C\u0430\u0442\u0435\u043C\u0430\u0442\u0438\u043A\u0430, \u0443\u0440\u0430\u0432\u043D\u0435\u043D\u0438\u0435, latex",
1082
+ "slash.item.divider.title": "\u0420\u0430\u0437\u0434\u0435\u043B\u0438\u0442\u0435\u043B\u044C",
1083
+ "slash.item.divider.description": "\u0412\u0438\u0437\u0443\u0430\u043B\u044C\u043D\u043E \u0440\u0430\u0437\u0434\u0435\u043B\u0438\u0442\u044C \u0440\u0430\u0437\u0434\u0435\u043B\u044B",
1084
+ "slash.item.divider.keywords": "\u043B\u0438\u043D\u0438\u044F, \u0440\u0430\u0437\u0434\u0435\u043B\u0438\u0442\u0435\u043B\u044C, \u0447\u0435\u0440\u0442\u0430, hr"
1085
+ };
1086
+
1087
+ // src/i18n/translate.ts
1088
+ var registry = /* @__PURE__ */ new Map([
1089
+ ["en", en],
1090
+ ["ru", ru]
1091
+ ]);
1092
+ function registerLocale(code, messages) {
1093
+ registry.set(normalize(code), messages);
1094
+ }
1095
+ function getLocales() {
1096
+ return [...registry.keys()];
1097
+ }
1098
+ var normalize = (code) => code.trim().toLowerCase();
1099
+ function lookup(code, locales) {
1100
+ const wanted = normalize(code);
1101
+ const own = locales ? Object.fromEntries(Object.entries(locales).map(([key, value]) => [normalize(key), value])) : void 0;
1102
+ for (const candidate of [wanted, wanted.split("-")[0]]) {
1103
+ const found = own?.[candidate] ?? registry.get(candidate);
1104
+ if (found) return found;
1105
+ }
1106
+ return void 0;
1107
+ }
1108
+ function resolveMessages(options = {}) {
1109
+ const base = options.locale ? lookup(options.locale, options.locales) : void 0;
1110
+ return { ...en, ...stripEmpty(base), ...stripEmpty(options.messages) };
1111
+ }
1112
+ function stripEmpty(messages) {
1113
+ if (!messages) return {};
1114
+ return Object.fromEntries(
1115
+ Object.entries(messages).filter(([, value]) => typeof value === "string")
1116
+ );
1117
+ }
1118
+ function interpolate(template, params) {
1119
+ if (!params) return template;
1120
+ return template.replace(
1121
+ /\{(\w+)\}/g,
1122
+ (match, name) => name in params ? String(params[name]) : match
1123
+ );
1124
+ }
1125
+ function createTranslator(messages) {
1126
+ return (key, params) => interpolate(messages[key] ?? en[key], params);
1127
+ }
1128
+ var defaultT = createTranslator(en);
1129
+
1130
+ // src/math/renderer.ts
1131
+ var temml;
1132
+ var loadTemml = () => temml ??= import("temml").then((module) => module.default);
1133
+ var temmlRenderer = async (latex, target, { display }) => {
1134
+ const api = await loadTemml();
1135
+ api.render(latex, target, {
1136
+ displayMode: display,
1137
+ throwOnError: true,
1138
+ trust: false,
1139
+ strict: false,
1140
+ maxExpand: 1e3
1141
+ });
1142
+ };
1143
+ var mathCss;
1144
+ var loadMathCss = () => mathCss ??= import("./mathCss-FLPE6QBM.js").then((module) => module.MATH_CSS);
1145
+ var shadowSheet;
1146
+ function constructableSheet(css) {
1147
+ if (shadowSheet !== void 0) return shadowSheet;
1148
+ try {
1149
+ if (typeof CSSStyleSheet !== "undefined" && "replaceSync" in CSSStyleSheet.prototype) {
1150
+ shadowSheet = new CSSStyleSheet();
1151
+ shadowSheet.replaceSync(css);
1152
+ return shadowSheet;
1153
+ }
1154
+ } catch {
1155
+ }
1156
+ return shadowSheet = null;
1157
+ }
1158
+ var styled = /* @__PURE__ */ new WeakSet();
1159
+ function applyMathStyles(scope, css) {
1160
+ if (typeof ShadowRoot !== "undefined" && scope instanceof ShadowRoot) {
1161
+ const sheet = constructableSheet(css);
1162
+ if (sheet && Array.isArray(scope.adoptedStyleSheets)) {
1163
+ scope.adoptedStyleSheets = [...scope.adoptedStyleSheets, sheet];
1164
+ } else {
1165
+ const style2 = globalThis.document.createElement("style");
1166
+ style2.textContent = css;
1167
+ scope.appendChild(style2);
1168
+ }
1169
+ return;
1170
+ }
1171
+ const doc = scope;
1172
+ if (doc.head.querySelector("style[data-inkbrick-math]")) return;
1173
+ const style = doc.createElement("style");
1174
+ style.setAttribute("data-inkbrick-math", "");
1175
+ style.textContent = `@layer inkbrick.math {
1176
+ ${css}
1177
+ }`;
1178
+ doc.head.appendChild(style);
1179
+ }
1180
+ function ensureMathStyles(scope) {
1181
+ if (styled.has(scope)) return;
1182
+ styled.add(scope);
1183
+ void loadMathCss().then((css) => applyMathStyles(scope, css));
1184
+ }
1185
+ var MAX_CACHE = 500;
1186
+ var caches = /* @__PURE__ */ new WeakMap();
1187
+ function cacheOf(renderer) {
1188
+ let cache = caches.get(renderer);
1189
+ if (!cache) caches.set(renderer, cache = /* @__PURE__ */ new Map());
1190
+ return cache;
1191
+ }
1192
+ function mountFormula(target, latex, { display, renderer, onSettled }) {
1193
+ const source = latex.trim();
1194
+ if (source === "") {
1195
+ target.replaceChildren();
1196
+ target.setAttribute("data-state", "empty");
1197
+ return () => void 0;
1198
+ }
1199
+ if (!renderer) {
1200
+ target.textContent = latex;
1201
+ target.setAttribute("data-state", "source");
1202
+ return () => void 0;
1203
+ }
1204
+ const key = `${display ? "d" : "i"}:${latex}`;
1205
+ const cache = cacheOf(renderer);
1206
+ const cached = cache.get(key);
1207
+ if (cached) {
1208
+ target.replaceChildren(...cached.map((node) => node.cloneNode(true)));
1209
+ target.setAttribute("data-state", "ready");
1210
+ onSettled?.("ready");
1211
+ return () => void 0;
1212
+ }
1213
+ let cancelled = false;
1214
+ target.textContent = latex;
1215
+ target.setAttribute("data-state", "loading");
1216
+ const scratch = globalThis.document.createElement("span");
1217
+ void (async () => {
1218
+ try {
1219
+ await renderer(latex, scratch, { display });
1220
+ if (cancelled) return;
1221
+ const nodes = [...scratch.childNodes];
1222
+ if (cache.size >= MAX_CACHE) cache.delete(cache.keys().next().value);
1223
+ cache.set(
1224
+ key,
1225
+ nodes.map((node) => node.cloneNode(true))
1226
+ );
1227
+ target.replaceChildren(...nodes);
1228
+ target.setAttribute("data-state", "ready");
1229
+ onSettled?.("ready");
1230
+ } catch (error) {
1231
+ if (cancelled) return;
1232
+ target.textContent = latex;
1233
+ target.setAttribute("data-state", "error");
1234
+ onSettled?.("error", error instanceof Error ? error.message : String(error));
1235
+ }
1236
+ })();
1237
+ return () => {
1238
+ cancelled = true;
1239
+ };
1240
+ }
1241
+
1242
+ // src/slash/filter.ts
1243
+ function score(item, query) {
1244
+ const title = item.title.toLowerCase();
1245
+ const words = [
1246
+ title,
1247
+ ...title.split(/\s+/),
1248
+ ...(item.keywords ?? []).map((k) => k.toLowerCase()),
1249
+ item.id.toLowerCase()
1250
+ ];
1251
+ if (title.startsWith(query)) return 4;
1252
+ if (words.some((w) => w.startsWith(query))) return 3;
1253
+ if (words.some((w) => w.includes(query))) return 1;
1254
+ return 0;
1255
+ }
1256
+ function filterSlashItems(items, query) {
1257
+ const q = query.trim().toLowerCase();
1258
+ if (q === "") return [...items];
1259
+ return items.map((item, index) => ({ item, index, score: score(item, q) })).filter((entry) => entry.score > 0).sort((a, b) => b.score - a.score || a.index - b.index).map((entry) => entry.item);
1260
+ }
1261
+
1262
+ // src/slash/applySlashItem.ts
1263
+ import { flushSync } from "react-dom";
1264
+
1265
+ // src/editing/selection.ts
1266
+ var EDITABLE = ".editable[data-id]";
1267
+ var ISLAND = '[data-block-id][contenteditable="false"]';
1268
+ function getOffsetIn(editable, node, offset) {
1269
+ const range = globalThis.document.createRange();
1270
+ range.selectNodeContents(editable);
1271
+ range.setEnd(node, offset);
1272
+ return range.toString().length;
1273
+ }
1274
+ function editableOf(node) {
1275
+ const element = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
1276
+ return element?.closest(EDITABLE) ?? null;
1277
+ }
1278
+ function textLength(editable) {
1279
+ return editable.textContent?.length ?? 0;
1280
+ }
1281
+ function leafPoint(el, where) {
1282
+ return el.matches(ISLAND) ? { blockId: el.getAttribute("data-block-id"), offset: 0 } : { blockId: el.dataset.id, offset: where === "start" ? 0 : textLength(el) };
1283
+ }
1284
+ function resolveContainerPoint(root, node, offset, bias, includeIslands) {
1285
+ const editables = [
1286
+ ...root.querySelectorAll(includeIslands ? `${EDITABLE}, ${ISLAND}` : EDITABLE)
1287
+ ];
1288
+ if (editables.length === 0) return null;
1289
+ const probe = globalThis.document.createRange();
1290
+ probe.setStart(node, offset);
1291
+ probe.collapse(true);
1292
+ let previous = null;
1293
+ for (const editable of editables) {
1294
+ if (probe.comparePoint(editable, 0) >= 0) {
1295
+ if (bias === "forward") return leafPoint(editable, "start");
1296
+ break;
1297
+ }
1298
+ previous = editable;
1299
+ }
1300
+ if (bias === "backward")
1301
+ return previous ? leafPoint(previous, "end") : leafPoint(editables[0], "start");
1302
+ return leafPoint(editables[editables.length - 1], "end");
1303
+ }
1304
+ function resolvePoint(root, node, offset, bias, includeIslands) {
1305
+ const editable = editableOf(node);
1306
+ if (editable && root.contains(editable)) {
1307
+ return { blockId: editable.dataset.id, offset: getOffsetIn(editable, node, offset) };
1308
+ }
1309
+ return resolveContainerPoint(root, node, offset, bias, includeIslands);
1310
+ }
1311
+ function readDocSelection(root) {
1312
+ const selection = globalThis.getSelection();
1313
+ if (!selection || selection.rangeCount === 0) return null;
1314
+ const range = selection.getRangeAt(0);
1315
+ if (!root.contains(range.commonAncestorContainer)) return null;
1316
+ const from = resolvePoint(
1317
+ root,
1318
+ range.startContainer,
1319
+ range.startOffset,
1320
+ "forward",
1321
+ !range.collapsed
1322
+ );
1323
+ let to = range.collapsed ? from : resolvePoint(root, range.endContainer, range.endOffset, "backward", true);
1324
+ if (!from || !to) return null;
1325
+ const remembered = fullSelections.get(root);
1326
+ if (remembered && !range.collapsed && sameRange(remembered, range)) {
1327
+ const leaves = root.querySelectorAll(`${EDITABLE}, ${ISLAND}`);
1328
+ return {
1329
+ from: leafPoint(leaves[0], "start"),
1330
+ to: leafPoint(leaves[leaves.length - 1], "end"),
1331
+ collapsed: false
1332
+ };
1333
+ }
1334
+ if (from.blockId === to.blockId ? from.offset > to.offset : isAfter(root, from.blockId, to.blockId)) {
1335
+ to = from;
1336
+ }
1337
+ return {
1338
+ from,
1339
+ to,
1340
+ collapsed: from.blockId === to.blockId && from.offset === to.offset
1341
+ };
1342
+ }
1343
+ function isAfter(root, a, b) {
1344
+ const elementA = root.querySelector(`.editable[data-id="${CSS.escape(a)}"]`);
1345
+ const elementB = root.querySelector(`.editable[data-id="${CSS.escape(b)}"]`);
1346
+ if (!elementA || !elementB) return false;
1347
+ return !!(elementA.compareDocumentPosition(elementB) & Node.DOCUMENT_POSITION_PRECEDING);
1348
+ }
1349
+ function outsideFormula(node, offset) {
1350
+ const host = node.parentElement?.closest("[data-inkbrick-formula]");
1351
+ const parent = host?.parentNode;
1352
+ if (!host || !parent) return { node, offset };
1353
+ const index = Array.prototype.indexOf.call(parent.childNodes, host);
1354
+ return { node: parent, offset: offset === 0 ? index : index + 1 };
1355
+ }
1356
+ function findPoint(editable, offset) {
1357
+ const walker = globalThis.document.createTreeWalker(editable, NodeFilter.SHOW_TEXT);
1358
+ let remaining = offset;
1359
+ let node = walker.nextNode();
1360
+ while (node) {
1361
+ const length = node.textContent?.length ?? 0;
1362
+ if (remaining <= length) {
1363
+ return outsideFormula(node, remaining);
1364
+ }
1365
+ remaining -= length;
1366
+ node = walker.nextNode();
1367
+ }
1368
+ return null;
1369
+ }
1370
+ var fullSelections = /* @__PURE__ */ new WeakMap();
1371
+ function sameRange(a, b) {
1372
+ return a.startContainer === b.startContainer && a.startOffset === b.startOffset && a.endContainer === b.endContainer && a.endOffset === b.endOffset;
1373
+ }
1374
+ function selectAllText(root) {
1375
+ const editables = root.querySelectorAll(EDITABLE);
1376
+ if (editables.length === 0) {
1377
+ if (!root.querySelector(ISLAND)) return false;
1378
+ const selection2 = globalThis.getSelection();
1379
+ const range = globalThis.document.createRange();
1380
+ range.selectNodeContents(root);
1381
+ selection2?.removeAllRanges();
1382
+ selection2?.addRange(range);
1383
+ return true;
1384
+ }
1385
+ setDomSelection(
1386
+ editables[0],
1387
+ 0,
1388
+ editables[editables.length - 1],
1389
+ textLength(editables[editables.length - 1])
1390
+ );
1391
+ const selection = globalThis.getSelection();
1392
+ if (selection && selection.rangeCount > 0)
1393
+ fullSelections.set(root, selection.getRangeAt(0).cloneRange());
1394
+ return true;
1395
+ }
1396
+ function setDomSelection(start, startOffset, end = start, endOffset = startOffset) {
1397
+ const selection = globalThis.getSelection();
1398
+ if (!selection) return;
1399
+ const range = globalThis.document.createRange();
1400
+ const from = findPoint(start, startOffset);
1401
+ const to = start === end && startOffset === endOffset ? from : findPoint(end, endOffset);
1402
+ if (from) range.setStart(from.node, from.offset);
1403
+ else range.setStart(start, 0);
1404
+ if (to) range.setEnd(to.node, to.offset);
1405
+ else range.setEnd(end, 0);
1406
+ selection.removeAllRanges();
1407
+ selection.addRange(range);
1408
+ }
1409
+
1410
+ // src/slash/applySlashItem.ts
1411
+ function applySlashItem(editor, view, item) {
1412
+ const state = view.slash.getState();
1413
+ if (!state.open || !state.blockId) return;
1414
+ const { blockId, slashOffset } = state;
1415
+ const root = view.getRoot();
1416
+ const selection = root ? readDocSelection(root) : null;
1417
+ const end = selection?.collapsed && selection.from.blockId === blockId ? selection.from.offset : slashOffset + 1 + state.query.length;
1418
+ view.slash.close();
1419
+ let caret;
1420
+ try {
1421
+ flushSync(() => {
1422
+ caret = editor.batch(() => {
1423
+ editor.dispatch({ type: "deleteText", payload: { blockId, from: slashOffset, to: end } });
1424
+ const result = editor.dispatch({
1425
+ type: "convertBlock",
1426
+ payload: {
1427
+ blockId,
1428
+ flavour: item.flavour,
1429
+ props: item.props,
1430
+ offset: slashOffset
1431
+ }
1432
+ });
1433
+ if (!result) throw new Error("convert-failed");
1434
+ return result;
1435
+ });
1436
+ });
1437
+ } catch (error) {
1438
+ if (!(error instanceof Error) || error.message !== "convert-failed") throw error;
1439
+ return;
1440
+ }
1441
+ if (caret) view.placeCaret(caret.blockId, caret.offset);
1442
+ }
1443
+
1444
+ // src/slash/items.ts
1445
+ function availableSlashItems(editor, items, blockId) {
1446
+ const block = editor.store.getBlock(blockId);
1447
+ const parent = block?.parentId ? editor.store.getBlock(block.parentId) : void 0;
1448
+ if (!block || !parent) return [];
1449
+ return items.filter(
1450
+ (item) => editor.schema.hasBlock(item.flavour) && editor.schema.validateRelation(parent.flavour, item.flavour)
1451
+ );
1452
+ }
1453
+ function visibleSlashItems(editor, items, blockId, query) {
1454
+ return filterSlashItems(availableSlashItems(editor, items, blockId), query);
1455
+ }
1456
+
1457
+ // src/toolbar/formatting.ts
1458
+ import { flushSync as flushSync2 } from "react-dom";
1459
+ import { normalizeLinkUrl } from "@inkbrick/document";
1460
+ var isSingleBlock = (selection) => selection.from.blockId === selection.to.blockId;
1461
+ function isFormattable(editor, selection) {
1462
+ return !(isSingleBlock(selection) && editor.store.getBlock(selection.from.blockId)?.flavour === "block:code");
1463
+ }
1464
+ function toggleFormatInSelection(editor, view, selection, format) {
1465
+ if (selection.collapsed || !isFormattable(editor, selection)) return;
1466
+ flushSync2(() => {
1467
+ if (isSingleBlock(selection)) {
1468
+ editor.dispatch({
1469
+ type: "toggleFormat",
1470
+ payload: {
1471
+ blockId: selection.from.blockId,
1472
+ from: selection.from.offset,
1473
+ to: selection.to.offset,
1474
+ format
1475
+ }
1476
+ });
1477
+ } else {
1478
+ editor.dispatch({
1479
+ type: "toggleFormatRange",
1480
+ payload: { from: selection.from, to: selection.to, format }
1481
+ });
1482
+ }
1483
+ });
1484
+ view.placeSelection(selection.from, selection.to);
1485
+ }
1486
+ function setLinkInSelection(editor, view, selection, input) {
1487
+ if (selection.collapsed || !isFormattable(editor, selection)) return false;
1488
+ const remove = input === null || input.trim() === "";
1489
+ const link = remove ? void 0 : normalizeLinkUrl(input) ?? null;
1490
+ if (link === null) return false;
1491
+ flushSync2(() => {
1492
+ editor.dispatch({
1493
+ type: "setInlineAttributes",
1494
+ payload: { from: selection.from, to: selection.to, attributes: { link } }
1495
+ });
1496
+ });
1497
+ view.placeSelection(selection.from, selection.to);
1498
+ return true;
1499
+ }
1500
+
1501
+ // src/toolbar/syncToolbar.ts
1502
+ function syncToolbar(editor, view) {
1503
+ const state = view.toolbar.getState();
1504
+ if (state.linkOpen) return;
1505
+ const root = view.getRoot();
1506
+ const selection = root ? readDocSelection(root) : null;
1507
+ const native = globalThis.getSelection();
1508
+ if (view.pointerDown || !selection || selection.collapsed || !isFormattable(editor, selection) || !native || native.rangeCount === 0) {
1509
+ view.toolbar.hide();
1510
+ return;
1511
+ }
1512
+ const rect = native.getRangeAt(0).getBoundingClientRect();
1513
+ if (rect.width === 0 && rect.height === 0) {
1514
+ view.toolbar.hide();
1515
+ return;
1516
+ }
1517
+ view.toolbar.show(selection, editor.formatsAt(selection.from, selection.to), {
1518
+ x: rect.left + rect.width / 2,
1519
+ y: rect.top
1520
+ });
1521
+ }
1522
+
1523
+ // src/formula/actions.ts
1524
+ import { flushSync as flushSync3 } from "react-dom";
1525
+ import { FORMULA_CHAR, MAX_FORMULA_LENGTH } from "@inkbrick/document";
1526
+ function anchorOf(rect, fallback) {
1527
+ const box = rect.width === 0 && rect.height === 0 && fallback ? fallback.getBoundingClientRect() : rect;
1528
+ return { x: box.left + box.width / 2, y: box.bottom, top: box.top };
1529
+ }
1530
+ function selectedLatex(editor, blockId, from, to) {
1531
+ const block = editor.store.getBlock(blockId);
1532
+ if (!block || from === to) return "";
1533
+ const text = block.content.map((node) => node.insert).join("");
1534
+ return text.slice(from, to).split(FORMULA_CHAR).join("").trim();
1535
+ }
1536
+ function openInlineFormula(editor, view) {
1537
+ const root = view.getRoot();
1538
+ const selection = root ? readDocSelection(root) : null;
1539
+ if (!selection || selection.from.blockId !== selection.to.blockId) return false;
1540
+ if (!isFormattable(editor, selection)) return false;
1541
+ const block = editor.store.getBlock(selection.from.blockId);
1542
+ if (!block || editor.schema.getBlockSchema(block.flavour)?.inline === false) return false;
1543
+ const native = globalThis.getSelection();
1544
+ const rect = native && native.rangeCount > 0 ? native.getRangeAt(0).getBoundingClientRect() : new DOMRect();
1545
+ const { blockId } = selection.from;
1546
+ view.toolbar.hide();
1547
+ view.formula.open({
1548
+ mode: "insert",
1549
+ blockId,
1550
+ from: selection.from.offset,
1551
+ to: selection.to.offset,
1552
+ latex: selectedLatex(editor, blockId, selection.from.offset, selection.to.offset),
1553
+ position: anchorOf(rect, view.getElement(blockId) ?? null)
1554
+ });
1555
+ return true;
1556
+ }
1557
+ function openFormulaAt(view, host) {
1558
+ const editable = host.closest(".editable[data-id]");
1559
+ const blockId = editable?.dataset.id;
1560
+ if (!editable || !blockId) return false;
1561
+ const offset = getOffsetIn(editable, host, 0);
1562
+ view.toolbar.hide();
1563
+ view.formula.open({
1564
+ mode: "edit",
1565
+ blockId,
1566
+ from: offset,
1567
+ to: offset + 1,
1568
+ latex: host.getAttribute("data-latex") ?? "",
1569
+ position: anchorOf(host.getBoundingClientRect(), editable)
1570
+ });
1571
+ return true;
1572
+ }
1573
+ function applyInlineFormula(editor, view, state, latex) {
1574
+ const code = latex.trim();
1575
+ const { blockId, from, to } = state;
1576
+ if (code.length > MAX_FORMULA_LENGTH) return false;
1577
+ if (state.mode === "insert" && code === "") return false;
1578
+ flushSync3(() => {
1579
+ if (state.mode === "insert") {
1580
+ editor.dispatch({ type: "insertFormula", payload: { blockId, from, to, latex: code } });
1581
+ } else if (code === "") {
1582
+ editor.dispatch({ type: "deleteText", payload: { blockId, from, to } });
1583
+ } else {
1584
+ editor.dispatch({
1585
+ type: "setInlineAttributes",
1586
+ payload: {
1587
+ from: { blockId, offset: from },
1588
+ to: { blockId, offset: to },
1589
+ attributes: { formula: code }
1590
+ }
1591
+ });
1592
+ }
1593
+ });
1594
+ view.placeCaret(blockId, state.mode === "edit" && code === "" ? from : Math.min(from, to) + 1);
1595
+ return true;
1596
+ }
1597
+ function matchInlineFormula(before) {
1598
+ const start = before.lastIndexOf("$");
1599
+ if (start < 0 || before[start - 1] === "\\") return null;
1600
+ const latex = before.slice(start + 1);
1601
+ if (latex === "" || /^\s|\s$/.test(latex) || latex.includes(FORMULA_CHAR)) return null;
1602
+ return { from: start, latex };
1603
+ }
1604
+
1605
+ // src/toolbar/rich.ts
1606
+ import { flushSync as flushSync4 } from "react-dom";
1607
+ function setColorInSelection(editor, view, selection, kind, value) {
1608
+ if (selection.collapsed || !isFormattable(editor, selection)) return false;
1609
+ const payload = {
1610
+ from: selection.from,
1611
+ to: selection.to,
1612
+ attributes: { [kind]: value ?? void 0 }
1613
+ };
1614
+ if (!editor.can("setInlineAttributes", payload)) return false;
1615
+ flushSync4(() => {
1616
+ editor.dispatch({ type: "setInlineAttributes", payload });
1617
+ });
1618
+ view.placeSelection(selection.from, selection.to);
1619
+ return true;
1620
+ }
1621
+ function setAlignInSelection(editor, view, selection, align2) {
1622
+ if (!editor.can("setAlign", { from: selection.from, to: selection.to, align: align2 })) return false;
1623
+ flushSync4(() => {
1624
+ editor.dispatch({
1625
+ type: "setAlign",
1626
+ payload: { from: selection.from, to: selection.to, align: align2 }
1627
+ });
1628
+ });
1629
+ view.placeSelection(selection.from, selection.to);
1630
+ return true;
1631
+ }
1632
+
1633
+ // src/editing/deleteAtBoundary.ts
1634
+ function deleteForwardAtEnd(editor, blockId) {
1635
+ const next = editor.document.getNextSibling(blockId);
1636
+ if (!next || editor.schema.getBlockSchema(next.flavour)?.inline === false) return void 0;
1637
+ return editor.dispatch({
1638
+ type: "deleteBackward",
1639
+ payload: { blockId: next.id, offset: 0 }
1640
+ });
1641
+ }
1642
+
1643
+ // src/keymap/defaultKeymap.ts
1644
+ var caretAtEdge = (edge) => ({ editor, event, selection }) => {
1645
+ const current = selection();
1646
+ if (event.isComposing || !current?.collapsed) return false;
1647
+ if (edge === "start") return current.from.offset === 0;
1648
+ const block = editor.store.getBlock(current.from.blockId);
1649
+ return !!block && current.from.offset === editor.engine.inline.length(block.content);
1650
+ };
1651
+ var slashOpen = ({ view }) => {
1652
+ const state = view.slash.getState();
1653
+ return state.open && state.blockId !== null;
1654
+ };
1655
+ function visibleItems({ editor, view, slashItems }) {
1656
+ const state = view.slash.getState();
1657
+ return visibleSlashItems(editor, slashItems, state.blockId, state.query);
1658
+ }
1659
+ var slashMove = (direction) => (context) => {
1660
+ const visible = visibleItems(context);
1661
+ if (visible.length === 0) return false;
1662
+ context.view.slash.move(direction, visible.length);
1663
+ };
1664
+ function indent(context) {
1665
+ const { editor, event } = context;
1666
+ const selection = context.selection();
1667
+ if (!selection || selection.from.blockId !== selection.to.blockId) return;
1668
+ const block = editor.store.getBlock(selection.from.blockId);
1669
+ if (!block) return;
1670
+ if (block.flavour === "block:code") {
1671
+ if (!event.shiftKey) context.run(() => context.replaceSelection(selection, " "));
1672
+ return;
1673
+ }
1674
+ context.run(() => {
1675
+ context.exec({
1676
+ type: event.shiftKey ? "outdentBlock" : "indentBlock",
1677
+ payload: { blockId: block.id }
1678
+ });
1679
+ return { blockId: block.id, offset: selection.from.offset };
1680
+ });
1681
+ }
1682
+ var toggle = (format) => (context) => context.toggleFormat(format);
1683
+ var align = (value) => (context) => {
1684
+ const selection = context.selection();
1685
+ if (!selection || !setAlignInSelection(context.editor, context.view, selection, value))
1686
+ return false;
1687
+ };
1688
+ var defaultKeymap = [
1689
+ {
1690
+ id: "slash.next",
1691
+ keys: ["ArrowDown", "Shift-ArrowDown"],
1692
+ when: slashOpen,
1693
+ run: slashMove(1)
1694
+ },
1695
+ {
1696
+ id: "slash.previous",
1697
+ keys: ["ArrowUp", "Shift-ArrowUp"],
1698
+ when: slashOpen,
1699
+ run: slashMove(-1)
1700
+ },
1701
+ {
1702
+ id: "slash.accept",
1703
+ keys: ["Enter", "Shift-Enter", "Tab", "Shift-Tab"],
1704
+ when: slashOpen,
1705
+ run: (context) => {
1706
+ const state = context.view.slash.getState();
1707
+ const visible = visibleItems(context);
1708
+ const item = visible[Math.min(state.activeIndex, visible.length - 1)];
1709
+ if (item) {
1710
+ applySlashItem(context.editor, context.view, item);
1711
+ return;
1712
+ }
1713
+ context.view.slash.close();
1714
+ return false;
1715
+ }
1716
+ },
1717
+ {
1718
+ id: "slash.close",
1719
+ keys: ["Escape", "Shift-Escape"],
1720
+ when: slashOpen,
1721
+ run: ({ view }) => view.slash.close()
1722
+ },
1723
+ // Выделить всё: нативное поведение ненадёжно для документа, начинающегося с нередактируемого блока.
1724
+ { id: "selectAll", keys: "Mod-a", run: ({ root }) => selectAllText(root) },
1725
+ { id: "undo", keys: "Mod-z", run: (context) => context.undo() },
1726
+ { id: "redo", keys: ["Mod-Shift-z", "Mod-y"], run: (context) => context.redo() },
1727
+ {
1728
+ id: "link",
1729
+ keys: "Mod-k",
1730
+ run: (context) => {
1731
+ const selection = context.selection();
1732
+ if (!selection || selection.collapsed || !isFormattable(context.editor, selection)) {
1733
+ return false;
1734
+ }
1735
+ syncToolbar(context.editor, context.view);
1736
+ context.view.toolbar.openLink();
1737
+ }
1738
+ },
1739
+ { id: "format.bold", keys: "Mod-b", run: toggle("bold") },
1740
+ { id: "format.italic", keys: "Mod-i", run: toggle("italic") },
1741
+ { id: "format.underline", keys: "Mod-u", run: toggle("underline") },
1742
+ { id: "format.code", keys: "Mod-e", run: toggle("code") },
1743
+ { id: "format.strike", keys: "Mod-Shift-x", run: toggle("strike") },
1744
+ { id: "align.left", keys: "Mod-Shift-l", run: align("left") },
1745
+ { id: "align.center", keys: "Mod-Shift-e", run: align("center") },
1746
+ { id: "align.right", keys: "Mod-Shift-r", run: align("right") },
1747
+ { id: "align.justify", keys: "Mod-Shift-j", run: align("justify") },
1748
+ {
1749
+ id: "formula.inline",
1750
+ keys: "Mod-Shift-m",
1751
+ run: ({ editor, view }) => openInlineFormula(editor, view)
1752
+ },
1753
+ { id: "indent", keys: ["Tab", "Shift-Tab"], run: indent },
1754
+ /*
1755
+ * Backspace в начале и Delete в конце блока обрабатываются уже на keydown: Safari не присылает beforeinput,
1756
+ * если сам считает, что удалять нечего (пустой блок, соседний блок без текста), и клавиша бы не сработала.
1757
+ */
1758
+ {
1759
+ id: "delete.blockStart",
1760
+ keys: "Backspace",
1761
+ when: caretAtEdge("start"),
1762
+ run: (context) => {
1763
+ const { blockId } = context.selection().from;
1764
+ context.run(
1765
+ () => context.exec({ type: "deleteBackward", payload: { blockId, offset: 0 } })
1766
+ );
1767
+ }
1768
+ },
1769
+ {
1770
+ id: "delete.blockEnd",
1771
+ keys: "Delete",
1772
+ when: caretAtEdge("end"),
1773
+ run: (context) => {
1774
+ const { blockId } = context.selection().from;
1775
+ context.run(() => deleteForwardAtEnd(context.editor, blockId));
1776
+ }
1777
+ }
1778
+ ];
1779
+
1780
+ // src/icons/lucide.ts
1781
+ var ICON_SHAPES = {
1782
+ bold: [["path", { d: "M6 12h9a4 4 0 010 8H7a1 1 0 01-1-1V5a1 1 0 011-1h7a4 4 0 010 8" }]],
1783
+ italic: [
1784
+ ["line", { x1: "19", x2: "10", y1: "4", y2: "4" }],
1785
+ ["line", { x1: "14", x2: "5", y1: "20", y2: "20" }],
1786
+ ["line", { x1: "15", x2: "9", y1: "4", y2: "20" }]
1787
+ ],
1788
+ underline: [
1789
+ ["path", { d: "M6 4v6a6 6 0 0 0 12 0V4" }],
1790
+ ["line", { x1: "4", x2: "20", y1: "20", y2: "20" }]
1791
+ ],
1792
+ strike: [
1793
+ ["path", { d: "M16 4H9a3 3 0 0 0-2.83 4" }],
1794
+ ["path", { d: "M14 12a4 4 0 0 1 0 8H6" }],
1795
+ ["line", { x1: "4", x2: "20", y1: "12", y2: "12" }]
1796
+ ],
1797
+ code: [
1798
+ ["path", { d: "m18 16 4-4-4-4" }],
1799
+ ["path", { d: "m6 8-4 4 4 4" }],
1800
+ ["path", { d: "m14.5 4-5 16" }]
1801
+ ],
1802
+ link: [
1803
+ ["path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }],
1804
+ ["path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" }]
1805
+ ],
1806
+ unlink: [
1807
+ [
1808
+ "path",
1809
+ {
1810
+ d: "m18.84 12.25 1.72-1.71h-.02a5.004 5.004 0 0 0-.12-7.07 5.006 5.006 0 0 0-6.95 0l-1.72 1.71"
1811
+ }
1812
+ ],
1813
+ [
1814
+ "path",
1815
+ { d: "m5.17 11.75-1.71 1.71a5.004 5.004 0 0 0 .12 7.07 5.006 5.006 0 0 0 6.95 0l1.71-1.71" }
1816
+ ],
1817
+ ["line", { x1: "8", x2: "8", y1: "2", y2: "5" }],
1818
+ ["line", { x1: "2", x2: "5", y1: "8", y2: "8" }],
1819
+ ["line", { x1: "16", x2: "16", y1: "19", y2: "22" }],
1820
+ ["line", { x1: "19", x2: "22", y1: "16", y2: "16" }]
1821
+ ],
1822
+ check: [["path", { d: "M20 6 9 17l-5-5" }]],
1823
+ x: [
1824
+ ["path", { d: "M18 6 6 18" }],
1825
+ ["path", { d: "m6 6 12 12" }]
1826
+ ],
1827
+ plus: [
1828
+ ["path", { d: "M5 12h14" }],
1829
+ ["path", { d: "M12 5v14" }]
1830
+ ],
1831
+ grip: [
1832
+ ["circle", { cx: "9", cy: "12", r: "1" }],
1833
+ ["circle", { cx: "9", cy: "5", r: "1" }],
1834
+ ["circle", { cx: "9", cy: "19", r: "1" }],
1835
+ ["circle", { cx: "15", cy: "12", r: "1" }],
1836
+ ["circle", { cx: "15", cy: "5", r: "1" }],
1837
+ ["circle", { cx: "15", cy: "19", r: "1" }]
1838
+ ],
1839
+ trash: [
1840
+ ["path", { d: "M10 11v6" }],
1841
+ ["path", { d: "M14 11v6" }],
1842
+ ["path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" }],
1843
+ ["path", { d: "M3 6h18" }],
1844
+ ["path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" }]
1845
+ ],
1846
+ copy: [
1847
+ ["rect", { width: "14", height: "14", x: "8", y: "8", rx: "2", ry: "2" }],
1848
+ ["path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" }]
1849
+ ],
1850
+ "arrow-up": [
1851
+ ["path", { d: "m5 12 7-7 7 7" }],
1852
+ ["path", { d: "M12 19V5" }]
1853
+ ],
1854
+ "arrow-down": [
1855
+ ["path", { d: "M12 5v14" }],
1856
+ ["path", { d: "m19 12-7 7-7-7" }]
1857
+ ],
1858
+ "chevron-down": [["path", { d: "m6 9 6 6 6-6" }]],
1859
+ text: [
1860
+ ["path", { d: "M13 4v16" }],
1861
+ ["path", { d: "M17 4v16" }],
1862
+ ["path", { d: "M19 4H9.5a4.5 4.5 0 0 0 0 9H13" }]
1863
+ ],
1864
+ "heading-1": [
1865
+ ["path", { d: "M4 12h8" }],
1866
+ ["path", { d: "M4 18V6" }],
1867
+ ["path", { d: "M12 18V6" }],
1868
+ ["path", { d: "m17 12 3-2v8" }]
1869
+ ],
1870
+ "heading-2": [
1871
+ ["path", { d: "M4 12h8" }],
1872
+ ["path", { d: "M4 18V6" }],
1873
+ ["path", { d: "M12 18V6" }],
1874
+ ["path", { d: "M21 18h-4c0-4 4-3 4-6 0-1.5-2-2.5-4-1" }]
1875
+ ],
1876
+ "heading-3": [
1877
+ ["path", { d: "M4 12h8" }],
1878
+ ["path", { d: "M4 18V6" }],
1879
+ ["path", { d: "M12 18V6" }],
1880
+ ["path", { d: "M17.5 10.5c1.7-1 3.5 0 3.5 1.5a2 2 0 0 1-2 2" }],
1881
+ ["path", { d: "M17 17.5c2 1.5 4 .3 4-1.5a2 2 0 0 0-2-2" }]
1882
+ ],
1883
+ "heading-4": [
1884
+ ["path", { d: "M12 18V6" }],
1885
+ ["path", { d: "M17 10v3a1 1 0 0 0 1 1h3" }],
1886
+ ["path", { d: "M21 10v8" }],
1887
+ ["path", { d: "M4 12h8" }],
1888
+ ["path", { d: "M4 18V6" }]
1889
+ ],
1890
+ "heading-5": [
1891
+ ["path", { d: "M4 12h8" }],
1892
+ ["path", { d: "M4 18V6" }],
1893
+ ["path", { d: "M12 18V6" }],
1894
+ ["path", { d: "M17 13v-3h4" }],
1895
+ ["path", { d: "M17 17.7c.4.2.8.3 1.3.3 1.5 0 2.7-1.1 2.7-2.5S19.8 13 18.3 13H17" }]
1896
+ ],
1897
+ "heading-6": [
1898
+ ["path", { d: "M4 12h8" }],
1899
+ ["path", { d: "M4 18V6" }],
1900
+ ["path", { d: "M12 18V6" }],
1901
+ ["circle", { cx: "19", cy: "16", r: "2" }],
1902
+ ["path", { d: "M20 10c-2 2-3 3.5-3 6" }]
1903
+ ],
1904
+ list: [
1905
+ ["path", { d: "M3 5h.01" }],
1906
+ ["path", { d: "M3 12h.01" }],
1907
+ ["path", { d: "M3 19h.01" }],
1908
+ ["path", { d: "M8 5h13" }],
1909
+ ["path", { d: "M8 12h13" }],
1910
+ ["path", { d: "M8 19h13" }]
1911
+ ],
1912
+ "list-ordered": [
1913
+ ["path", { d: "M11 5h10" }],
1914
+ ["path", { d: "M11 12h10" }],
1915
+ ["path", { d: "M11 19h10" }],
1916
+ ["path", { d: "M4 4h1v5" }],
1917
+ ["path", { d: "M4 9h2" }],
1918
+ ["path", { d: "M6.5 20H3.4c0-1 2.6-1.925 2.6-3.5a1.5 1.5 0 0 0-2.6-1.02" }]
1919
+ ],
1920
+ "list-todo": [
1921
+ ["path", { d: "M13 5h8" }],
1922
+ ["path", { d: "M13 12h8" }],
1923
+ ["path", { d: "M13 19h8" }],
1924
+ ["path", { d: "m3 17 2 2 4-4" }],
1925
+ ["path", { d: "m3 7 2 2 4-4" }]
1926
+ ],
1927
+ quote: [
1928
+ ["path", { d: "M17 5H3" }],
1929
+ ["path", { d: "M21 12H8" }],
1930
+ ["path", { d: "M21 19H8" }],
1931
+ ["path", { d: "M3 12v7" }]
1932
+ ],
1933
+ divider: [["path", { d: "M5 12h14" }]],
1934
+ info: [
1935
+ ["circle", { cx: "12", cy: "12", r: "10" }],
1936
+ ["path", { d: "M12 16v-4" }],
1937
+ ["path", { d: "M12 8h.01" }]
1938
+ ],
1939
+ warning: [
1940
+ ["path", { d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" }],
1941
+ ["path", { d: "M12 9v4" }],
1942
+ ["path", { d: "M12 17h.01" }]
1943
+ ],
1944
+ success: [
1945
+ ["circle", { cx: "12", cy: "12", r: "10" }],
1946
+ ["path", { d: "m16 9-5.5 5.5L8 12" }]
1947
+ ],
1948
+ danger: [
1949
+ ["path", { d: "m15 9-6 6" }],
1950
+ [
1951
+ "path",
1952
+ {
1953
+ d: "M2.586 16.726A2 2 0 0 1 2 15.312V8.688a2 2 0 0 1 .586-1.414l4.688-4.688A2 2 0 0 1 8.688 2h6.624a2 2 0 0 1 1.414.586l4.688 4.688A2 2 0 0 1 22 8.688v6.624a2 2 0 0 1-.586 1.414l-4.688 4.688a2 2 0 0 1-1.414.586H8.688a2 2 0 0 1-1.414-.586z"
1954
+ }
1955
+ ],
1956
+ ["path", { d: "m9 9 6 6" }]
1957
+ ],
1958
+ image: [
1959
+ ["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2" }],
1960
+ ["circle", { cx: "9", cy: "9", r: "2" }],
1961
+ ["path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21" }]
1962
+ ],
1963
+ replace: [
1964
+ ["path", { d: "M14 4a1 1 0 0 1 1-1" }],
1965
+ ["path", { d: "M15 10a1 1 0 0 1-1-1" }],
1966
+ ["path", { d: "M21 4a1 1 0 0 0-1-1" }],
1967
+ ["path", { d: "M21 9a1 1 0 0 1-1 1" }],
1968
+ ["path", { d: "m3 7 3 3 3-3" }],
1969
+ ["path", { d: "M6 10V5a2 2 0 0 1 2-2h2" }],
1970
+ ["rect", { x: "3", y: "14", width: "7", height: "7", rx: "1" }]
1971
+ ],
1972
+ "align-left": [
1973
+ ["path", { d: "M21 5H3" }],
1974
+ ["path", { d: "M15 12H3" }],
1975
+ ["path", { d: "M17 19H3" }]
1976
+ ],
1977
+ "align-center": [
1978
+ ["path", { d: "M21 5H3" }],
1979
+ ["path", { d: "M17 12H7" }],
1980
+ ["path", { d: "M19 19H5" }]
1981
+ ],
1982
+ "align-right": [
1983
+ ["path", { d: "M21 5H3" }],
1984
+ ["path", { d: "M21 12H9" }],
1985
+ ["path", { d: "M21 19H7" }]
1986
+ ],
1987
+ "align-justify": [
1988
+ ["path", { d: "M3 5h18" }],
1989
+ ["path", { d: "M3 12h18" }],
1990
+ ["path", { d: "M3 19h18" }]
1991
+ ],
1992
+ baseline: [
1993
+ ["path", { d: "M4 20h16" }],
1994
+ ["path", { d: "m6 16 6-12 6 12" }],
1995
+ ["path", { d: "M8 12h8" }]
1996
+ ],
1997
+ highlighter: [
1998
+ ["path", { d: "m9 11-6 6v3h9l3-3" }],
1999
+ ["path", { d: "m22 12-4.6 4.6a2 2 0 0 1-2.8 0l-5.2-5.2a2 2 0 0 1 0-2.8L14 4" }]
2000
+ ],
2001
+ sigma: [
2002
+ [
2003
+ "path",
2004
+ {
2005
+ d: "M18 7V5a1 1 0 0 0-1-1H6.5a.5.5 0 0 0-.4.8l4.5 6a2 2 0 0 1 0 2.4l-4.5 6a.5.5 0 0 0 .4.8H17a1 1 0 0 0 1-1v-2"
2006
+ }
2007
+ ]
2008
+ ]
2009
+ };
2010
+
2011
+ // src/icons/Icon.tsx
2012
+ import { jsx } from "react/jsx-runtime";
2013
+ function Icon({ name, ...props }) {
2014
+ const shapes = ICON_SHAPES[name];
2015
+ return /* @__PURE__ */ jsx(
2016
+ "svg",
2017
+ {
2018
+ xmlns: "http://www.w3.org/2000/svg",
2019
+ width: 16,
2020
+ height: 16,
2021
+ viewBox: "0 0 24 24",
2022
+ fill: "none",
2023
+ stroke: "currentColor",
2024
+ strokeWidth: 2,
2025
+ strokeLinecap: "round",
2026
+ strokeLinejoin: "round",
2027
+ "aria-hidden": "true",
2028
+ focusable: "false",
2029
+ "data-inkbrick-icon": name,
2030
+ ...props,
2031
+ children: shapes.map(([tag, attributes], index) => {
2032
+ const Shape = tag;
2033
+ return /* @__PURE__ */ jsx(Shape, { ...attributes }, index);
2034
+ })
2035
+ }
2036
+ );
2037
+ }
2038
+
2039
+ // src/slash/defaultSlashItems.tsx
2040
+ import { jsx as jsx2 } from "react/jsx-runtime";
2041
+ var defaultSlashItems = Object.freeze([
2042
+ {
2043
+ id: "text",
2044
+ title: "Text",
2045
+ description: "Plain paragraph",
2046
+ keywords: ["paragraph", "p"],
2047
+ icon: /* @__PURE__ */ jsx2(Icon, { name: "text" }),
2048
+ flavour: "block:paragraph"
2049
+ },
2050
+ {
2051
+ id: "heading-1",
2052
+ title: "Heading 1",
2053
+ description: "Large section heading",
2054
+ keywords: ["h1", "title"],
2055
+ icon: /* @__PURE__ */ jsx2(Icon, { name: "heading-1" }),
2056
+ flavour: "block:heading",
2057
+ props: { level: 1 }
2058
+ },
2059
+ {
2060
+ id: "heading-2",
2061
+ title: "Heading 2",
2062
+ description: "Medium section heading",
2063
+ keywords: ["h2", "subtitle"],
2064
+ icon: /* @__PURE__ */ jsx2(Icon, { name: "heading-2" }),
2065
+ flavour: "block:heading",
2066
+ props: { level: 2 }
2067
+ },
2068
+ {
2069
+ id: "heading-3",
2070
+ title: "Heading 3",
2071
+ description: "Small section heading",
2072
+ keywords: ["h3"],
2073
+ icon: /* @__PURE__ */ jsx2(Icon, { name: "heading-3" }),
2074
+ flavour: "block:heading",
2075
+ props: { level: 3 }
2076
+ },
2077
+ {
2078
+ id: "heading-4",
2079
+ title: "Heading 4",
2080
+ description: "Subsection heading",
2081
+ keywords: ["h4"],
2082
+ icon: /* @__PURE__ */ jsx2(Icon, { name: "heading-4" }),
2083
+ flavour: "block:heading",
2084
+ props: { level: 4 }
2085
+ },
2086
+ {
2087
+ id: "heading-5",
2088
+ title: "Heading 5",
2089
+ description: "Minor subsection heading",
2090
+ keywords: ["h5"],
2091
+ icon: /* @__PURE__ */ jsx2(Icon, { name: "heading-5" }),
2092
+ flavour: "block:heading",
2093
+ props: { level: 5 }
2094
+ },
2095
+ {
2096
+ id: "heading-6",
2097
+ title: "Heading 6",
2098
+ description: "Smallest heading",
2099
+ keywords: ["h6"],
2100
+ icon: /* @__PURE__ */ jsx2(Icon, { name: "heading-6" }),
2101
+ flavour: "block:heading",
2102
+ props: { level: 6 }
2103
+ },
2104
+ {
2105
+ id: "bullet-list",
2106
+ title: "Bulleted list",
2107
+ description: "Simple bulleted list",
2108
+ keywords: ["ul", "unordered", "list"],
2109
+ icon: /* @__PURE__ */ jsx2(Icon, { name: "list" }),
2110
+ flavour: "block:list",
2111
+ props: { type: "bullet" }
2112
+ },
2113
+ {
2114
+ id: "numbered-list",
2115
+ title: "Numbered list",
2116
+ description: "List with numbering",
2117
+ keywords: ["ol", "ordered", "list"],
2118
+ icon: /* @__PURE__ */ jsx2(Icon, { name: "list-ordered" }),
2119
+ flavour: "block:list",
2120
+ props: { type: "ordered" }
2121
+ },
2122
+ {
2123
+ id: "todo-list",
2124
+ title: "To-do list",
2125
+ description: "Track tasks with checkboxes",
2126
+ keywords: ["todo", "task", "checkbox", "check"],
2127
+ icon: /* @__PURE__ */ jsx2(Icon, { name: "list-todo" }),
2128
+ flavour: "block:list",
2129
+ props: { type: "todo", checked: false }
2130
+ },
2131
+ {
2132
+ id: "quote",
2133
+ title: "Quote",
2134
+ description: "Capture a quote",
2135
+ keywords: ["blockquote", "citation"],
2136
+ icon: /* @__PURE__ */ jsx2(Icon, { name: "quote" }),
2137
+ flavour: "block:quote"
2138
+ },
2139
+ {
2140
+ id: "code",
2141
+ title: "Code",
2142
+ description: "Code snippet with monospace font",
2143
+ keywords: ["snippet", "pre", "program"],
2144
+ icon: /* @__PURE__ */ jsx2(Icon, { name: "code" }),
2145
+ flavour: "block:code"
2146
+ },
2147
+ {
2148
+ id: "callout",
2149
+ title: "Callout",
2150
+ description: "Highlight important information",
2151
+ keywords: ["info", "note", "warning", "tip", "alert"],
2152
+ icon: /* @__PURE__ */ jsx2(Icon, { name: "info" }),
2153
+ flavour: "block:callout"
2154
+ },
2155
+ {
2156
+ id: "image",
2157
+ title: "Image",
2158
+ description: "Upload or embed an image",
2159
+ keywords: ["picture", "photo", "img", "upload"],
2160
+ icon: /* @__PURE__ */ jsx2(Icon, { name: "image" }),
2161
+ flavour: "block:image"
2162
+ },
2163
+ {
2164
+ id: "formula",
2165
+ title: "Formula",
2166
+ description: "Display a LaTeX formula",
2167
+ keywords: ["math", "equation", "latex", "tex"],
2168
+ icon: /* @__PURE__ */ jsx2(Icon, { name: "sigma" }),
2169
+ flavour: "block:formula"
2170
+ },
2171
+ {
2172
+ id: "divider",
2173
+ title: "Divider",
2174
+ description: "Visually separate sections",
2175
+ keywords: ["hr", "line", "separator", "rule"],
2176
+ icon: /* @__PURE__ */ jsx2(Icon, { name: "divider" }),
2177
+ flavour: "block:divider"
2178
+ }
2179
+ ]);
2180
+ var messageKey = (id, part) => `slash.item.${id}.${part}`;
2181
+ var splitKeywords = (value) => value.split(",").map((word) => word.trim()).filter(Boolean);
2182
+ function localizeSlashItems(t) {
2183
+ return defaultSlashItems.map((item) => ({
2184
+ ...item,
2185
+ title: t(messageKey(item.id, "title")),
2186
+ description: t(messageKey(item.id, "description")),
2187
+ // Английские слова остаются в поиске: «h1», «todo» и т. п. работают на любом языке.
2188
+ keywords: [
2189
+ .../* @__PURE__ */ new Set([...item.keywords ?? [], ...splitKeywords(t(messageKey(item.id, "keywords")))])
2190
+ ]
2191
+ }));
2192
+ }
2193
+ function resolveSlashItems(custom, t) {
2194
+ if (custom === false) return [];
2195
+ const defaults = t ? localizeSlashItems(t) : defaultSlashItems;
2196
+ if (!custom || custom.length === 0) return defaults;
2197
+ const overrides = new Map(custom.map((item) => [item.id, item]));
2198
+ const merged = defaults.map((item) => overrides.get(item.id) ?? item);
2199
+ const extra = custom.filter((item) => !defaultSlashItems.some((d) => d.id === item.id));
2200
+ return [...merged, ...extra];
2201
+ }
2202
+
2203
+ // src/ui/EditorUIContext.ts
2204
+ import { createContext, useContext } from "react";
2205
+ var EMPTY_UI_CONFIG = Object.freeze({
2206
+ components: Object.freeze({}),
2207
+ slots: Object.freeze({}),
2208
+ slashItems: defaultSlashItems,
2209
+ keymap: defaultKeymap,
2210
+ highlighter: highlightCode,
2211
+ formulaRenderer: temmlRenderer,
2212
+ locale: "en",
2213
+ t: defaultT,
2214
+ images: Object.freeze({})
2215
+ });
2216
+ var EditorUIContext = createContext(EMPTY_UI_CONFIG);
2217
+ function useEditorUI() {
2218
+ return useContext(EditorUIContext);
2219
+ }
2220
+
2221
+ // src/hooks/useT.ts
2222
+ function useT() {
2223
+ return useEditorUI().t;
2224
+ }
2225
+ function useLocale() {
2226
+ return useEditorUI().locale;
2227
+ }
2228
+
2229
+ // src/formula/snippet.ts
2230
+ import { useLayoutEffect, useRef } from "react";
2231
+ var CARET = "\u2316";
2232
+ function applySnippet(value, start, end, snippet) {
2233
+ const from = Math.max(0, Math.min(start, end, value.length));
2234
+ const to = Math.max(from, Math.min(Math.max(start, end), value.length));
2235
+ const selected = value.slice(from, to);
2236
+ const marker = snippet.indexOf(CARET);
2237
+ const body = snippet.split(CARET).join("");
2238
+ if (marker < 0) {
2239
+ return { value: value.slice(0, from) + body + value.slice(to), caret: from + body.length };
2240
+ }
2241
+ const before = snippet.slice(0, marker).split(CARET).join("");
2242
+ const after = snippet.slice(marker + 1).split(CARET).join("");
2243
+ const inserted = before + selected + after;
2244
+ return {
2245
+ value: value.slice(0, from) + inserted + value.slice(to),
2246
+ caret: from + before.length + selected.length
2247
+ };
2248
+ }
2249
+ function useSnippetInsert(field, value, setValue) {
2250
+ const caret = useRef(null);
2251
+ useLayoutEffect(() => {
2252
+ const element = field.current;
2253
+ if (caret.current === null || !element) return;
2254
+ element.setSelectionRange(caret.current, caret.current);
2255
+ caret.current = null;
2256
+ }, [field, value]);
2257
+ return (snippet) => {
2258
+ const element = field.current;
2259
+ const start = element?.selectionStart ?? value.length;
2260
+ const end = element?.selectionEnd ?? value.length;
2261
+ const result = applySnippet(value, start, end, snippet);
2262
+ caret.current = result.caret;
2263
+ setValue(result.value);
2264
+ element?.focus();
2265
+ };
2266
+ }
2267
+
2268
+ export {
2269
+ readDocSelection,
2270
+ setDomSelection,
2271
+ HIGHLIGHT_LIMIT,
2272
+ normalizeLanguage,
2273
+ highlightCode,
2274
+ en,
2275
+ ru,
2276
+ registerLocale,
2277
+ getLocales,
2278
+ resolveMessages,
2279
+ createTranslator,
2280
+ temmlRenderer,
2281
+ ensureMathStyles,
2282
+ mountFormula,
2283
+ applySlashItem,
2284
+ filterSlashItems,
2285
+ availableSlashItems,
2286
+ visibleSlashItems,
2287
+ toggleFormatInSelection,
2288
+ setLinkInSelection,
2289
+ syncToolbar,
2290
+ openInlineFormula,
2291
+ openFormulaAt,
2292
+ applyInlineFormula,
2293
+ matchInlineFormula,
2294
+ setColorInSelection,
2295
+ setAlignInSelection,
2296
+ deleteForwardAtEnd,
2297
+ defaultKeymap,
2298
+ ICON_SHAPES,
2299
+ Icon,
2300
+ defaultSlashItems,
2301
+ resolveSlashItems,
2302
+ EditorUIContext,
2303
+ useEditorUI,
2304
+ useT,
2305
+ useLocale,
2306
+ CARET,
2307
+ useSnippetInsert
2308
+ };
2309
+ //# sourceMappingURL=chunk-TPUX4C45.js.map