@apollohg/react-native-rich-text-editor 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/README.md +1 -1
  2. package/THIRD_PARTY_NOTICES.md +1 -1
  3. package/android/build.gradle +3 -0
  4. package/app.plugin.js +42 -39
  5. package/dist/AtomHost.js +18 -11
  6. package/dist/EditorAddon.js +4 -2
  7. package/dist/EditorAddonNormalization.js +17 -9
  8. package/dist/EditorMentionThemeNormalization.js +6 -3
  9. package/dist/EditorMentionThemeValidation.js +28 -11
  10. package/dist/EditorStyleSheetNormalization.js +84 -37
  11. package/dist/EditorTheme.d.ts +4 -0
  12. package/dist/EditorTheme.js +5 -3
  13. package/dist/EditorToolbarComponent.d.ts +1 -1
  14. package/dist/EditorToolbarComponent.js +1 -1
  15. package/dist/EditorToolbarRegistry.js +5 -5
  16. package/dist/EditorToolbarTypes.d.ts +12 -12
  17. package/dist/EditorToolbarVisuals.js +1 -1
  18. package/dist/ExternalTextComposition.js +89 -43
  19. package/dist/ImageLoadingPolicy.d.ts +1 -1
  20. package/dist/NativeEditorBoundaryError.d.ts +7 -7
  21. package/dist/NativeEditorBoundaryError.js +9 -5
  22. package/dist/NativeEditorCollaborationTransport.d.ts +7 -7
  23. package/dist/NativeEditorCollaborationTransport.js +28 -15
  24. package/dist/NativeEditorCreateConfig.js +11 -6
  25. package/dist/NativeEditorCreateJson.js +51 -25
  26. package/dist/NativeEditorCreateValidation.js +11 -6
  27. package/dist/NativeEditorDocumentBridge.d.ts +1 -1
  28. package/dist/NativeEditorDocumentBridge.js +32 -18
  29. package/dist/NativeEditorDocumentHandle.d.ts +4 -4
  30. package/dist/NativeEditorDocumentHandle.js +1 -1
  31. package/dist/NativeEditorLocalAwareness.js +25 -13
  32. package/dist/NativeEditorNativeModule.d.ts +8 -1
  33. package/dist/NativeEditorNativeModule.js +7 -5
  34. package/dist/NativeEditorRenderNormalization.js +66 -25
  35. package/dist/NativeEditorResultNormalization.js +53 -29
  36. package/dist/NativeEditorTypes.d.ts +10 -10
  37. package/dist/NativeEditorV2Decimal.js +6 -3
  38. package/dist/NativeProseViewer.js +11 -3
  39. package/dist/ResourceLimits.d.ts +2 -2
  40. package/dist/ResourceLimits.js +7 -2
  41. package/dist/RichTextEditor.js +1 -1
  42. package/dist/RichTextEditorNativeTypes.d.ts +1 -1
  43. package/dist/RichTextEditorNativeView.d.ts +1 -3
  44. package/dist/RichTextEditorSerialization.js +24 -14
  45. package/dist/RichTextEditorTypes.d.ts +1 -1
  46. package/dist/YjsCollaboration.d.ts +7 -7
  47. package/dist/YjsCollaboration.js +42 -26
  48. package/dist/addons.d.ts +4 -4
  49. package/dist/addons.js +3 -3
  50. package/dist/atomInstances.js +6 -3
  51. package/dist/atomUpdates.js +7 -4
  52. package/dist/atoms.js +20 -12
  53. package/dist/attributeValidation.js +55 -24
  54. package/dist/contentExpression.js +80 -42
  55. package/dist/listMarkers.d.ts +1 -1
  56. package/dist/listMarkers.js +1 -1
  57. package/dist/schemaDefinition.d.ts +1 -1
  58. package/dist/schemaDefinition.js +23 -14
  59. package/dist/schemaDocument.js +1 -1
  60. package/dist/schemaDocumentConstruction.js +25 -14
  61. package/dist/schemaNormalization.js +51 -29
  62. package/dist/schemaPresets.d.ts +1 -1
  63. package/dist/schemaPresets.js +9 -4
  64. package/dist/schemaResolution.js +46 -25
  65. package/dist/specs/PreparedProseViewerNativeComponent.d.ts +4 -0
  66. package/dist/useEditorToolbarInteractions.d.ts +2 -2
  67. package/dist/useEditorToolbarInteractions.js +45 -23
  68. package/dist/useEditorToolbarItems.d.ts +1 -1
  69. package/dist/useEditorToolbarItems.js +4 -3
  70. package/dist/useEditorToolbarPresentation.d.ts +3 -3
  71. package/dist/useEditorToolbarPresentation.js +4 -4
  72. package/dist/useEditorToolbarState.d.ts +1 -1
  73. package/dist/useEditorToolbarState.js +1 -1
  74. package/dist/useFocusPreservingFrames.js +11 -8
  75. package/dist/useNativeEditor.d.ts +1 -1
  76. package/dist/useNativeEditor.js +21 -11
  77. package/dist/useRichTextEditorCommands.d.ts +2 -2
  78. package/dist/useRichTextEditorCommands.js +59 -29
  79. package/dist/useRichTextEditorEvents.d.ts +3 -3
  80. package/dist/useRichTextEditorEvents.js +75 -32
  81. package/dist/useRichTextEditorMentions.d.ts +4 -4
  82. package/dist/useRichTextEditorMentions.js +48 -29
  83. package/dist/useRichTextEditorPresentation.d.ts +4 -4
  84. package/dist/useRichTextEditorPresentation.js +25 -23
  85. package/dist/useRichTextEditorState.d.ts +3 -3
  86. package/dist/useRichTextEditorState.js +20 -15
  87. package/dist/useRichTextEditorUpdates.d.ts +1 -1
  88. package/dist/useRichTextEditorUpdates.js +99 -41
  89. package/dist/useViewerAtoms.js +63 -36
  90. package/ios/EditorCore.xcframework/Info.plist +5 -5
  91. package/ios/EditorCore.xcframework/ios-arm64/libeditor_core.a +0 -0
  92. package/ios/EditorCore.xcframework/ios-arm64_x86_64-simulator/libeditor_core.a +0 -0
  93. package/package.json +11 -3
  94. package/react-native.config.js +1 -1
  95. package/rust/android/arm64-v8a/libeditor_core.so +0 -0
  96. package/rust/android/armeabi-v7a/libeditor_core.so +0 -0
  97. package/rust/android/x86/libeditor_core.so +0 -0
  98. package/rust/android/x86_64/libeditor_core.so +0 -0
  99. package/src/AtomHost.tsx +58 -28
  100. package/src/EditorAddon.ts +18 -8
  101. package/src/EditorAddonNormalization.ts +40 -11
  102. package/src/EditorMentionThemeNormalization.ts +15 -4
  103. package/src/EditorMentionThemeValidation.ts +51 -14
  104. package/src/EditorStyleSheet.ts +1 -0
  105. package/src/EditorStyleSheetNormalization.ts +195 -64
  106. package/src/EditorTheme.ts +13 -5
  107. package/src/EditorToolbarComponent.tsx +2 -1
  108. package/src/EditorToolbarRegistry.tsx +23 -13
  109. package/src/EditorToolbarTypes.tsx +12 -12
  110. package/src/EditorToolbarVisuals.tsx +6 -3
  111. package/src/EditorUpdateRevision.ts +1 -0
  112. package/src/ExternalTextComposition.ts +259 -49
  113. package/src/ImageLoadingPolicy.ts +3 -1
  114. package/src/NativeEditorBoundaryError.ts +38 -11
  115. package/src/NativeEditorCollaborationTransport.ts +108 -27
  116. package/src/NativeEditorCreateConfig.ts +92 -19
  117. package/src/NativeEditorCreateJson.ts +163 -26
  118. package/src/NativeEditorCreateValidation.ts +33 -12
  119. package/src/NativeEditorDocumentBridge.ts +111 -19
  120. package/src/NativeEditorDocumentHandle.ts +9 -4
  121. package/src/NativeEditorLocalAwareness.ts +70 -15
  122. package/src/NativeEditorNativeModule.ts +13 -9
  123. package/src/NativeEditorRenderNormalization.ts +128 -29
  124. package/src/NativeEditorResultNormalization.ts +143 -32
  125. package/src/NativeEditorTypes.ts +12 -11
  126. package/src/NativeEditorV2Decimal.ts +12 -3
  127. package/src/NativeProseViewer.tsx +46 -16
  128. package/src/ResourceLimits.ts +15 -8
  129. package/src/RichTextEditor.tsx +3 -1
  130. package/src/RichTextEditorNativeTypes.tsx +1 -1
  131. package/src/RichTextEditorNativeView.tsx +2 -8
  132. package/src/RichTextEditorSerialization.tsx +70 -24
  133. package/src/RichTextEditorTypes.tsx +1 -1
  134. package/src/YjsCollaboration.ts +143 -47
  135. package/src/addons.ts +12 -8
  136. package/src/atomInstances.ts +25 -5
  137. package/src/atomUpdates.ts +23 -6
  138. package/src/atoms.ts +85 -18
  139. package/src/attributeValidation.ts +97 -33
  140. package/src/contentExpression.ts +218 -63
  141. package/src/listMarkers.ts +1 -1
  142. package/src/schemaDefinition.ts +82 -20
  143. package/src/schemaDocument.ts +15 -1
  144. package/src/schemaDocumentConstruction.ts +80 -16
  145. package/src/schemaNormalization.ts +155 -41
  146. package/src/schemaPresets.ts +37 -31
  147. package/src/schemaResolution.ts +126 -27
  148. package/src/specs/PreparedProseViewerNativeComponent.ts +4 -2
  149. package/src/useEditorToolbarInteractions.tsx +85 -36
  150. package/src/useEditorToolbarItems.tsx +50 -22
  151. package/src/useEditorToolbarPresentation.tsx +81 -58
  152. package/src/useEditorToolbarState.tsx +8 -6
  153. package/src/useFocusPreservingFrames.ts +43 -15
  154. package/src/useNativeEditor.ts +111 -51
  155. package/src/useRichTextEditorCommands.tsx +127 -54
  156. package/src/useRichTextEditorEvents.tsx +144 -42
  157. package/src/useRichTextEditorMentions.tsx +118 -37
  158. package/src/useRichTextEditorPresentation.tsx +128 -114
  159. package/src/useRichTextEditorState.tsx +76 -40
  160. package/src/useRichTextEditorUpdates.tsx +207 -56
  161. package/src/useViewerAtoms.tsx +162 -66
@@ -19,8 +19,13 @@ function collectExpressionSymbols(expression: Expression, symbols: Set<string>):
19
19
  if (expression.kind === 'symbol') {
20
20
  symbols.add(expression.symbol);
21
21
  } else if (expression.kind !== 'empty') {
22
- if (expression.kind === 'repeat') collectExpressionSymbols(expression.expression, symbols);
23
- else for (const nested of expression.expressions) collectExpressionSymbols(nested, symbols);
22
+ if (expression.kind === 'repeat') {
23
+ collectExpressionSymbols(expression.expression, symbols);
24
+ } else {
25
+ for (const nested of expression.expressions) {
26
+ collectExpressionSymbols(nested, symbols);
27
+ }
28
+ }
24
29
  }
25
30
  }
26
31
 
@@ -32,7 +37,8 @@ export function contentExpressionSymbols(content: string): string[] | null {
32
37
  compiler.compile(expression);
33
38
  const symbols = new Set<string>();
34
39
  collectExpressionSymbols(expression, symbols);
35
- return [...symbols];
40
+
41
+ return [ ...symbols ];
36
42
  } catch {
37
43
  return null;
38
44
  }
@@ -40,40 +46,66 @@ export function contentExpressionSymbols(content: string): string[] | null {
40
46
 
41
47
  class ContentExpressionParser {
42
48
  private position = 0;
49
+
43
50
  private depth = 0;
44
51
 
45
- constructor(private readonly source: string) {}
52
+ constructor(private readonly source: string) {
53
+ }
46
54
 
47
55
  parse(): Expression {
48
- if (this.source.trim() === '') return { kind: 'empty' };
56
+ if (this.source.trim() === '') {
57
+ return { kind: 'empty' };
58
+ }
59
+
49
60
  const expression = this.parseAlternation();
50
61
  this.skipWhitespace();
51
- if (!this.atEnd()) throw new Error(`unexpected '${this.peek()}'`);
62
+
63
+ if (!this.atEnd()) {
64
+ throw new Error(`unexpected '${this.peek()}'`);
65
+ }
66
+
52
67
  return expression;
53
68
  }
54
69
 
55
70
  private parseAlternation(): Expression {
56
- const expressions = [this.parseSequence()];
71
+ const expressions = [ this.parseSequence() ];
72
+
57
73
  while (true) {
58
74
  this.skipWhitespace();
59
- if (!this.consume('|')) break;
75
+
76
+ if (!this.consume('|')) {
77
+ break;
78
+ }
79
+
60
80
  this.skipWhitespace();
81
+
61
82
  if (this.atEnd() || this.peek() === ')' || this.peek() === '|') {
62
- throw new Error("missing expression after '|'");
83
+ throw new Error('missing expression after \'|\'');
63
84
  }
85
+
64
86
  expressions.push(this.parseSequence());
65
87
  }
88
+
66
89
  return expressions.length === 1 ? expressions[0] : { kind: 'alternation', expressions };
67
90
  }
68
91
 
69
92
  private parseSequence(): Expression {
70
93
  const expressions: Expression[] = [];
94
+
71
95
  while (true) {
72
96
  this.skipWhitespace();
73
- if (this.atEnd() || this.peek() === ')' || this.peek() === '|') break;
97
+
98
+ if (this.atEnd() || this.peek() === ')' || this.peek() === '|') {
99
+ break;
100
+ }
101
+
74
102
  expressions.push(this.parseRepeated());
75
103
  }
76
- if (expressions.length === 0) throw new Error('expected expression');
104
+
105
+ if (expressions.length === 0) {
106
+ throw new Error('expected expression');
107
+ }
108
+
77
109
  return expressions.length === 1 ? expressions[0] : { kind: 'sequence', expressions };
78
110
  }
79
111
 
@@ -81,31 +113,50 @@ class ContentExpressionParser {
81
113
  const atom = this.parseAtom();
82
114
  this.skipWhitespace();
83
115
  let expression = atom;
84
- if (this.consume('?')) expression = { kind: 'repeat', expression: atom, min: 0, max: 1 };
85
- else if (this.consume('*'))
116
+
117
+ if (this.consume('?')) {
118
+ expression = { kind: 'repeat', expression: atom, min: 0, max: 1 };
119
+ } else if (this.consume('*')) {
86
120
  expression = { kind: 'repeat', expression: atom, min: 0, max: null };
87
- else if (this.consume('+'))
121
+ } else if (this.consume('+')) {
88
122
  expression = { kind: 'repeat', expression: atom, min: 1, max: null };
89
- else if (this.consume('{')) expression = this.parseRange(atom);
123
+ } else if (this.consume('{')) {
124
+ expression = this.parseRange(atom);
125
+ }
126
+
90
127
  this.skipWhitespace();
91
- if (['?', '*', '+', '{'].includes(this.peek() ?? '')) {
128
+
129
+ if ([ '?', '*', '+', '{' ].includes(this.peek() ?? '')) {
92
130
  throw new Error('multiple quantifiers');
93
131
  }
132
+
94
133
  return expression;
95
134
  }
96
135
 
97
136
  private parseAtom(): Expression {
98
137
  this.skipWhitespace();
138
+
99
139
  if (this.consume('(')) {
100
- if (this.depth >= CONTENT_EXPRESSION_MAX_DEPTH)
140
+ if (this.depth >= CONTENT_EXPRESSION_MAX_DEPTH) {
101
141
  throw new Error('expression nesting too deep');
142
+ }
143
+
102
144
  this.depth += 1;
145
+
103
146
  try {
104
147
  this.skipWhitespace();
105
- if (this.peek() === ')') throw new Error('empty group');
148
+
149
+ if (this.peek() === ')') {
150
+ throw new Error('empty group');
151
+ }
152
+
106
153
  const expression = this.parseAlternation();
107
154
  this.skipWhitespace();
108
- if (!this.consume(')')) throw new Error("missing ')'");
155
+
156
+ if (!this.consume(')')) {
157
+ throw new Error('missing \')\'');
158
+ }
159
+
109
160
  return expression;
110
161
  } finally {
111
162
  this.depth -= 1;
@@ -113,39 +164,75 @@ class ContentExpressionParser {
113
164
  }
114
165
 
115
166
  const start = this.position;
116
- while (this.peek() != null && /[A-Za-z0-9_-]/.test(this.peek()!)) this.position += 1;
117
- if (start === this.position) throw new Error('expected node or group name');
167
+
168
+ while (this.peek() != null && /[A-Za-z0-9_-]/.test(this.peek()!)) {
169
+ this.position += 1;
170
+ }
171
+
172
+ if (start === this.position) {
173
+ throw new Error('expected node or group name');
174
+ }
175
+
118
176
  return { kind: 'symbol', symbol: this.source.slice(start, this.position) };
119
177
  }
120
178
 
121
179
  private parseRange(expression: Expression): Expression {
122
180
  const min = this.parseNumber();
123
181
  let max: number | null;
124
- if (this.consume('}')) max = min;
125
- else {
126
- if (!this.consume(',')) throw new Error("expected ',' or '}'");
127
- if (this.consume('}')) max = null;
128
- else {
182
+
183
+ if (this.consume('}')) {
184
+ max = min;
185
+ } else {
186
+ if (!this.consume(',')) {
187
+ throw new Error('expected \',\' or \'}\'');
188
+ }
189
+
190
+ if (this.consume('}')) {
191
+ max = null;
192
+ } else {
129
193
  max = this.parseNumber();
130
- if (!this.consume('}')) throw new Error("expected '}'");
194
+
195
+ if (!this.consume('}')) {
196
+ throw new Error('expected \'}\'');
197
+ }
131
198
  }
132
199
  }
133
- if (max != null && max < min) throw new Error('range maximum is smaller than minimum');
134
- if ((max ?? min) > MAX_REPETITION_BOUND) throw new Error('repetition bound too large');
200
+
201
+ if (max != null && max < min) {
202
+ throw new Error('range maximum is smaller than minimum');
203
+ }
204
+
205
+ if ((max ?? min) > MAX_REPETITION_BOUND) {
206
+ throw new Error('repetition bound too large');
207
+ }
208
+
135
209
  return { kind: 'repeat', expression, min, max };
136
210
  }
137
211
 
138
212
  private parseNumber(): number {
139
213
  const start = this.position;
140
- while (this.peek() != null && /[0-9]/.test(this.peek()!)) this.position += 1;
141
- if (start === this.position) throw new Error('expected number');
214
+
215
+ while (this.peek() != null && /[0-9]/.test(this.peek()!)) {
216
+ this.position += 1;
217
+ }
218
+
219
+ if (start === this.position) {
220
+ throw new Error('expected number');
221
+ }
222
+
142
223
  const value = Number(this.source.slice(start, this.position));
143
- if (!Number.isSafeInteger(value) || value > 0xffff_ffff) throw new Error('invalid count');
224
+
225
+ if (!Number.isSafeInteger(value) || value > 0xffff_ffff) {
226
+ throw new Error('invalid count');
227
+ }
228
+
144
229
  return value;
145
230
  }
146
231
 
147
232
  private skipWhitespace(): void {
148
- while (this.peek() != null && /\s/.test(this.peek()!)) this.position += 1;
233
+ while (this.peek() != null && /\s/.test(this.peek()!)) {
234
+ this.position += 1;
235
+ }
149
236
  }
150
237
 
151
238
  private peek(): string | undefined {
@@ -153,8 +240,12 @@ class ContentExpressionParser {
153
240
  }
154
241
 
155
242
  private consume(character: string): boolean {
156
- if (this.peek() !== character) return false;
243
+ if (this.peek() !== character) {
244
+ return false;
245
+ }
246
+
157
247
  this.position += 1;
248
+
158
249
  return true;
159
250
  }
160
251
 
@@ -167,39 +258,52 @@ class ContentExpressionCompiler {
167
258
  readonly states: State[] = [];
168
259
 
169
260
  compile(expression: Expression, depth = 0): [number, number] {
170
- if (depth > CONTENT_EXPRESSION_MAX_DEPTH) throw new Error('expression nesting too deep');
261
+ if (depth > CONTENT_EXPRESSION_MAX_DEPTH) {
262
+ throw new Error('expression nesting too deep');
263
+ }
264
+
171
265
  if (expression.kind === 'empty') {
172
266
  const start = this.state();
173
267
  const end = this.state();
174
268
  this.states[start].epsilon.push(end);
175
- return [start, end];
269
+
270
+ return [ start, end ];
176
271
  }
272
+
177
273
  if (expression.kind === 'symbol') {
178
274
  const start = this.state();
179
275
  const end = this.state();
180
276
  this.states[start].transitions.push({ symbol: expression.symbol, target: end });
181
- return [start, end];
277
+
278
+ return [ start, end ];
182
279
  }
280
+
183
281
  if (expression.kind === 'sequence') {
184
282
  const start = this.state();
185
283
  let tail = start;
284
+
186
285
  for (const nested of expression.expressions) {
187
- const [nestedStart, nestedEnd] = this.compile(nested, depth + 1);
286
+ const [ nestedStart, nestedEnd ] = this.compile(nested, depth + 1);
188
287
  this.states[tail].epsilon.push(nestedStart);
189
288
  tail = nestedEnd;
190
289
  }
191
- return [start, tail];
290
+
291
+ return [ start, tail ];
192
292
  }
293
+
193
294
  if (expression.kind === 'alternation') {
194
295
  const start = this.state();
195
296
  const end = this.state();
297
+
196
298
  for (const nested of expression.expressions) {
197
- const [nestedStart, nestedEnd] = this.compile(nested, depth + 1);
299
+ const [ nestedStart, nestedEnd ] = this.compile(nested, depth + 1);
198
300
  this.states[start].epsilon.push(nestedStart);
199
301
  this.states[nestedEnd].epsilon.push(end);
200
302
  }
201
- return [start, end];
303
+
304
+ return [ start, end ];
202
305
  }
306
+
203
307
  return this.compileRepeat(expression.expression, expression.min, expression.max, depth + 1);
204
308
  }
205
309
 
@@ -212,45 +316,58 @@ class ContentExpressionCompiler {
212
316
  const start = this.state();
213
317
  const end = this.state();
214
318
  let tail = start;
319
+
215
320
  for (let count = 0; count < min; count += 1) {
216
- const [itemStart, itemEnd] = this.compile(expression, depth);
321
+ const [ itemStart, itemEnd ] = this.compile(expression, depth);
217
322
  this.states[tail].epsilon.push(itemStart);
218
323
  tail = itemEnd;
219
324
  }
325
+
220
326
  if (max == null) {
221
327
  this.states[tail].epsilon.push(end);
222
- const [itemStart, itemEnd] = this.compile(expression, depth);
328
+ const [ itemStart, itemEnd ] = this.compile(expression, depth);
223
329
  this.states[tail].epsilon.push(itemStart);
224
330
  this.states[itemEnd].epsilon.push(tail);
225
331
  } else {
226
332
  for (let count = min; count < max; count += 1) {
227
333
  this.states[tail].epsilon.push(end);
228
- const [itemStart, itemEnd] = this.compile(expression, depth);
334
+ const [ itemStart, itemEnd ] = this.compile(expression, depth);
229
335
  this.states[tail].epsilon.push(itemStart);
230
336
  tail = itemEnd;
231
337
  }
338
+
232
339
  this.states[tail].epsilon.push(end);
233
340
  }
234
- return [start, end];
341
+
342
+ return [ start, end ];
235
343
  }
236
344
 
237
345
  private state(): number {
238
- if (this.states.length >= MAX_AUTOMATON_STATES)
346
+ if (this.states.length >= MAX_AUTOMATON_STATES) {
239
347
  throw new Error('too many automaton states');
348
+ }
349
+
240
350
  this.states.push({ epsilon: [], transitions: [] });
351
+
241
352
  return this.states.length - 1;
242
353
  }
243
354
  }
244
355
 
245
356
  function epsilonClosure(states: State[], initial: Iterable<number>): Set<number> {
246
357
  const result = new Set<number>();
247
- const pending = [...initial];
358
+ const pending = [ ...initial ];
359
+
248
360
  while (pending.length > 0) {
249
361
  const state = pending.pop()!;
250
- if (result.has(state)) continue;
362
+
363
+ if (result.has(state)) {
364
+ continue;
365
+ }
366
+
251
367
  result.add(state);
252
368
  pending.push(...states[state].epsilon);
253
369
  }
370
+
254
371
  return result;
255
372
  }
256
373
 
@@ -263,24 +380,32 @@ export function acceptingContentSymbols(
263
380
  try {
264
381
  const expression = new ContentExpressionParser(content).parse();
265
382
  const compiler = new ContentExpressionCompiler();
266
- const [start] = compiler.compile(expression);
267
- let current = epsilonClosure(compiler.states, [start]);
383
+ const [ start ] = compiler.compile(expression);
384
+ let current = epsilonClosure(compiler.states, [ start ]);
385
+
268
386
  for (const childType of existingChildTypes) {
269
387
  const next = new Set<number>();
388
+
270
389
  for (const state of current) {
271
390
  for (const transition of compiler.states[state].transitions) {
272
- if (symbolMatches(childType, transition.symbol)) next.add(transition.target);
391
+ if (symbolMatches(childType, transition.symbol)) {
392
+ next.add(transition.target);
393
+ }
273
394
  }
274
395
  }
396
+
275
397
  current = epsilonClosure(compiler.states, next);
276
398
  }
399
+
277
400
  const symbols = new Set<string>();
401
+
278
402
  for (const state of current) {
279
403
  for (const transition of compiler.states[state].transitions) {
280
404
  symbols.add(transition.symbol);
281
405
  }
282
406
  }
283
- return [...symbols].sort();
407
+
408
+ return [ ...symbols ].sort();
284
409
  } catch {
285
410
  return [];
286
411
  }
@@ -294,43 +419,73 @@ export function minimalContentMatch<T>(
294
419
  try {
295
420
  const expression = new ContentExpressionParser(content).parse();
296
421
  const compiler = new ContentExpressionCompiler();
297
- const [start, accept] = compiler.compile(expression);
422
+ const [ start, accept ] = compiler.compile(expression);
298
423
  interface Path {
299
424
  value: T;
300
425
  previous?: Path;
301
426
  }
302
- let current = new Map<number, Path | undefined>([[start, undefined]]);
427
+ let current = new Map<number, Path | undefined>([ [ start, undefined ] ]);
303
428
  const visited = new Set<number>();
429
+
304
430
  while (current.size > 0) {
305
431
  const closure = new Map<number, Path | undefined>();
306
- const pending = [...current.entries()];
432
+ const pending = [ ...current.entries() ];
433
+
307
434
  while (pending.length > 0) {
308
- if (!consumeWork()) return undefined;
309
- const [state, path] = pending.pop()!;
310
- if (closure.has(state)) continue;
435
+ if (!consumeWork()) {
436
+ return undefined;
437
+ }
438
+
439
+ const [ state, path ] = pending.pop()!;
440
+
441
+ if (closure.has(state)) {
442
+ continue;
443
+ }
444
+
311
445
  closure.set(state, path);
312
- for (const target of compiler.states[state].epsilon) pending.push([target, path]);
446
+
447
+ for (const target of compiler.states[state].epsilon) {
448
+ pending.push([ target, path ]);
449
+ }
313
450
  }
451
+
314
452
  const accepted = closure.get(accept);
453
+
315
454
  if (closure.has(accept)) {
316
455
  const result: T[] = [];
317
- for (let path = accepted; path; path = path.previous) result.push(path.value);
456
+
457
+ for (let path = accepted; path; path = path.previous) {
458
+ result.push(path.value);
459
+ }
460
+
318
461
  return result.reverse();
319
462
  }
463
+
320
464
  const next = new Map<number, Path | undefined>();
321
- for (const [state, path] of closure) {
322
- if (visited.has(state)) continue;
465
+
466
+ for (const [ state, path ] of closure) {
467
+ if (visited.has(state)) {
468
+ continue;
469
+ }
470
+
323
471
  visited.add(state);
472
+
324
473
  for (const transition of compiler.states[state].transitions) {
325
- if (!consumeWork()) return undefined;
474
+ if (!consumeWork()) {
475
+ return undefined;
476
+ }
477
+
326
478
  const value = choose(transition.symbol);
479
+
327
480
  if (value !== undefined && !next.has(transition.target)) {
328
481
  next.set(transition.target, { value, previous: path });
329
482
  }
330
483
  }
331
484
  }
485
+
332
486
  current = next;
333
487
  }
488
+
334
489
  return undefined;
335
490
  } catch {
336
491
  return undefined;
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * CROSS-LAYER CONTRACT: these values must match the Rust core
5
5
  * (rust/editor-core/src/render/mod.rs: task_list_marker_string /
6
- * list_marker_string pinned by marker_strings_are_the_cross_layer_contract
6
+ * list_marker_string : pinned by marker_strings_are_the_cross_layer_contract
7
7
  * in render_test.rs), Android (LayoutConstants.TASK_LIST_MARKER_* /
8
8
  * UNORDERED_LIST_BULLET), and iOS (RenderBridge.listMarkerString). The
9
9
  * marker's scalar length feeds position mapping; a mismatch corrupts