@barocss/math-editor 0.2.1 → 0.5.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.
- package/ADAPTERS.md +25 -14
- package/API-JAVASCRIPT.md +1 -1
- package/API-REACT.md +5 -1
- package/API-SESSION.md +178 -6
- package/API-SOLID.md +1 -1
- package/API-SVELTE.md +1 -1
- package/API-VUE.md +1 -1
- package/API-WEB-COMPONENT.md +3 -1
- package/CHANGELOG.md +106 -0
- package/EDITING-SCENARIOS.md +174 -0
- package/EMBEDDING.md +4 -0
- package/IMPLEMENTATION.md +122 -2
- package/JSON-MODEL.md +1 -0
- package/LATEX-GUIDE.md +30 -1
- package/LATEX-MODEL.md +12 -0
- package/LATEX-SCOPE.md +12 -3
- package/LICENSE +1 -3
- package/README.md +201 -39
- package/RELEASING.md +81 -10
- package/RENDERING-TESTS.md +79 -0
- package/ROADMAP.md +220 -11
- package/STYLING.md +157 -0
- package/SUPPORT.md +24 -12
- package/VALIDATION.md +444 -4
- package/dist/context-tools.d.ts +21 -0
- package/dist/context-tools.js +37 -0
- package/dist/core.d.ts +5 -1
- package/dist/core.js +5 -1
- package/dist/document-codec.d.ts +0 -1
- package/dist/document-codec.js +0 -1
- package/dist/dom/caret-geometry.d.ts +3 -0
- package/dist/dom/caret-geometry.js +41 -0
- package/dist/dom/context-keyboard.d.ts +2 -0
- package/dist/dom/context-keyboard.js +22 -0
- package/dist/dom/elements.d.ts +1 -2
- package/dist/dom/elements.js +2 -3
- package/dist/dom/latex-panel.d.ts +10 -0
- package/dist/dom/latex-panel.js +59 -0
- package/dist/dom/matrix-selection.d.ts +11 -0
- package/dist/dom/matrix-selection.js +30 -0
- package/dist/dom/menu-position.d.ts +17 -2
- package/dist/dom/menu-position.js +129 -16
- package/dist/dom/presentation-controls.d.ts +4 -0
- package/dist/dom/presentation-controls.js +56 -0
- package/dist/dom/quick-panel.d.ts +12 -0
- package/dist/dom/quick-panel.js +102 -0
- package/dist/dom/selection.d.ts +29 -0
- package/dist/dom/selection.js +53 -0
- package/dist/dom/symbol-panel.d.ts +9 -0
- package/dist/dom/symbol-panel.js +146 -0
- package/dist/dom/theme.d.ts +6 -0
- package/dist/dom/theme.js +68 -0
- package/dist/dom/toolbar-catalog.d.ts +10 -0
- package/dist/dom/toolbar-catalog.js +35 -0
- package/dist/dom/toolbar.d.ts +13 -2
- package/dist/dom/toolbar.js +295 -28
- package/dist/dom.d.ts +9 -1
- package/dist/dom.js +682 -151
- package/dist/editor-labels.d.ts +0 -1
- package/dist/editor-labels.js +0 -1
- package/dist/enter-policy.d.ts +0 -1
- package/dist/enter-policy.js +0 -1
- package/dist/fences.d.ts +0 -1
- package/dist/fences.js +0 -1
- package/dist/i18n.d.ts +0 -1
- package/dist/i18n.js +0 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +4 -1
- package/dist/latex-insertion.d.ts +12 -0
- package/dist/latex-insertion.js +26 -0
- package/dist/latex-paste-panel.d.ts +3 -0
- package/dist/latex-paste-panel.js +18 -0
- package/dist/latex.d.ts +0 -1
- package/dist/latex.js +11 -1
- package/dist/lines.d.ts +0 -1
- package/dist/lines.js +0 -1
- package/dist/locales/en.js +39 -1
- package/dist/locales/en.json +39 -1
- package/dist/locales/ko.js +39 -1
- package/dist/locales/ko.json +39 -1
- package/dist/math-editor-toolbar.d.ts +4 -2
- package/dist/math-editor-toolbar.js +3 -4
- package/dist/math-editor.d.ts +7 -2
- package/dist/math-editor.js +661 -308
- package/dist/math-layout.d.ts +12 -0
- package/dist/math-layout.js +59 -0
- package/dist/math-spacing.d.ts +13 -0
- package/dist/math-spacing.js +87 -0
- package/dist/matrix-range.d.ts +40 -0
- package/dist/matrix-range.js +242 -0
- package/dist/matrix.d.ts +0 -1
- package/dist/matrix.js +0 -1
- package/dist/model.d.ts +4 -1
- package/dist/model.js +49 -5
- package/dist/outputs.d.ts +0 -1
- package/dist/outputs.js +0 -1
- package/dist/preferences.d.ts +24 -0
- package/dist/preferences.js +66 -0
- package/dist/presentation-controls.d.ts +10 -0
- package/dist/presentation-controls.js +10 -0
- package/dist/presentation.d.ts +13 -0
- package/dist/presentation.js +86 -0
- package/dist/quick-panel.d.ts +2 -0
- package/dist/quick-panel.js +17 -0
- package/dist/range.d.ts +2 -1
- package/dist/range.js +11 -1
- package/dist/react.d.ts +0 -1
- package/dist/react.js +0 -1
- package/dist/root-transform.d.ts +19 -0
- package/dist/root-transform.js +69 -0
- package/dist/session.d.ts +31 -2
- package/dist/session.js +108 -7
- package/dist/solid.d.ts +0 -1
- package/dist/solid.js +0 -1
- package/dist/suggestions.d.ts +13 -1
- package/dist/suggestions.js +153 -12
- package/dist/svelte.d.ts +0 -1
- package/dist/svelte.js +0 -1
- package/dist/symbol-browser.d.ts +0 -1
- package/dist/symbol-browser.js +0 -1
- package/dist/symbols.d.ts +0 -1
- package/dist/symbols.js +0 -1
- package/dist/templates.d.ts +0 -1
- package/dist/templates.js +0 -1
- package/dist/tokens.d.ts +0 -1
- package/dist/tokens.js +0 -1
- package/dist/vertical-navigation.d.ts +15 -0
- package/dist/vertical-navigation.js +145 -0
- package/dist/vue.d.ts +0 -1
- package/dist/vue.js +0 -1
- package/dist/web-component.d.ts +0 -1
- package/dist/web-component.js +9 -2
- package/package.json +11 -3
- package/src/fonts/KaTeX_Math-Italic.woff2 +0 -0
- package/src/fonts/KaTeX_Size1-Regular.woff2 +0 -0
- package/src/fonts/README.md +18 -0
- package/src/shapes/README.md +21 -0
- package/src/shapes/parenthesis-bottom.svg +1 -0
- package/src/shapes/parenthesis-top.svg +1 -0
- package/src/shapes/parenthesis.svg +1 -0
- package/src/shapes/radical.svg +1 -0
- package/src/style.css +949 -173
- package/dist/core.d.ts.map +0 -1
- package/dist/core.js.map +0 -1
- package/dist/document-codec.d.ts.map +0 -1
- package/dist/document-codec.js.map +0 -1
- package/dist/dom/elements.d.ts.map +0 -1
- package/dist/dom/elements.js.map +0 -1
- package/dist/dom/menu-position.d.ts.map +0 -1
- package/dist/dom/menu-position.js.map +0 -1
- package/dist/dom/toolbar.d.ts.map +0 -1
- package/dist/dom/toolbar.js.map +0 -1
- package/dist/dom.d.ts.map +0 -1
- package/dist/dom.js.map +0 -1
- package/dist/editor-labels.d.ts.map +0 -1
- package/dist/editor-labels.js.map +0 -1
- package/dist/enter-policy.d.ts.map +0 -1
- package/dist/enter-policy.js.map +0 -1
- package/dist/fences.d.ts.map +0 -1
- package/dist/fences.js.map +0 -1
- package/dist/i18n.d.ts.map +0 -1
- package/dist/i18n.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/latex.d.ts.map +0 -1
- package/dist/latex.js.map +0 -1
- package/dist/lines.d.ts.map +0 -1
- package/dist/lines.js.map +0 -1
- package/dist/math-editor-toolbar.d.ts.map +0 -1
- package/dist/math-editor-toolbar.js.map +0 -1
- package/dist/math-editor.d.ts.map +0 -1
- package/dist/math-editor.js.map +0 -1
- package/dist/matrix.d.ts.map +0 -1
- package/dist/matrix.js.map +0 -1
- package/dist/model.d.ts.map +0 -1
- package/dist/model.js.map +0 -1
- package/dist/outputs.d.ts.map +0 -1
- package/dist/outputs.js.map +0 -1
- package/dist/range.d.ts.map +0 -1
- package/dist/range.js.map +0 -1
- package/dist/react.d.ts.map +0 -1
- package/dist/react.js.map +0 -1
- package/dist/session.d.ts.map +0 -1
- package/dist/session.js.map +0 -1
- package/dist/solid.d.ts.map +0 -1
- package/dist/solid.js.map +0 -1
- package/dist/suggestions.d.ts.map +0 -1
- package/dist/suggestions.js.map +0 -1
- package/dist/svelte.d.ts.map +0 -1
- package/dist/svelte.js.map +0 -1
- package/dist/symbol-browser.d.ts.map +0 -1
- package/dist/symbol-browser.js.map +0 -1
- package/dist/symbols.d.ts.map +0 -1
- package/dist/symbols.js.map +0 -1
- package/dist/templates.d.ts.map +0 -1
- package/dist/templates.js.map +0 -1
- package/dist/tokens.d.ts.map +0 -1
- package/dist/tokens.js.map +0 -1
- package/dist/vue.d.ts.map +0 -1
- package/dist/vue.js.map +0 -1
- package/dist/web-component.d.ts.map +0 -1
- package/dist/web-component.js.map +0 -1
package/dist/suggestions.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
import { transformRoot } from './root-transform.js';
|
|
2
|
+
import { structureEditingContext, changeContextFence } from './context-tools.js';
|
|
3
|
+
import { fencePairs } from './fences.js';
|
|
1
4
|
import { mathLocaleAliases, translate, } from './i18n.js';
|
|
2
5
|
import { insertTemplate, mathTemplates } from './templates.js';
|
|
3
|
-
import { insertIdentityMatrix, insertMatrix } from './matrix.js';
|
|
6
|
+
import { activeMatrix, insertIdentityMatrix, insertMatrix, MATRIX_MAX_SIZE } from './matrix.js';
|
|
4
7
|
import { insertStructure, namedFunctions, moveCaret, setText, textNodes, } from './model.js';
|
|
5
8
|
import { mathSymbols } from './symbols.js';
|
|
9
|
+
import { wrappingKinds } from './range.js';
|
|
6
10
|
const structure = (kind, glyph, label, aliases, triggers, detail) => ({
|
|
7
11
|
id: kind,
|
|
8
12
|
kind,
|
|
@@ -129,14 +133,58 @@ const catalog = [
|
|
|
129
133
|
})),
|
|
130
134
|
];
|
|
131
135
|
const triggers = [...new Set(catalog.flatMap((c) => c.triggers))].sort((a, b) => b.length - a.length);
|
|
136
|
+
/** Generate only the requested size, with identity matrices reserved for square shapes. */
|
|
137
|
+
function matrixDimensionSuggestions(rows, columns) {
|
|
138
|
+
const sizeId = rows === columns ? String(rows) : `${rows}x${columns}`;
|
|
139
|
+
const dimensions = { rows, columns };
|
|
140
|
+
const empty = {
|
|
141
|
+
...mathStructures[0],
|
|
142
|
+
id: `matrix-${sizeId}`,
|
|
143
|
+
label: 'matrix.size',
|
|
144
|
+
labelParameters: dimensions,
|
|
145
|
+
detail: 'grid.dimensions',
|
|
146
|
+
detailParameters: dimensions,
|
|
147
|
+
matrixSize: rows,
|
|
148
|
+
matrixColumns: columns,
|
|
149
|
+
};
|
|
150
|
+
const candidates = [empty];
|
|
151
|
+
if (rows === columns) {
|
|
152
|
+
candidates.push({
|
|
153
|
+
...empty,
|
|
154
|
+
id: `identity-${sizeId}`,
|
|
155
|
+
glyph: 'I',
|
|
156
|
+
label: 'matrix.identity',
|
|
157
|
+
detail: 'matrix.identityDetail',
|
|
158
|
+
identity: true,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
candidates.push({
|
|
162
|
+
...empty,
|
|
163
|
+
id: `template-zero-${sizeId}`,
|
|
164
|
+
glyph: '0',
|
|
165
|
+
label: 'matrix.zero',
|
|
166
|
+
zero: true,
|
|
167
|
+
});
|
|
168
|
+
return candidates;
|
|
169
|
+
}
|
|
132
170
|
export function findSuggestions(text, caret, locale = 'ko') {
|
|
133
171
|
const before = text.slice(0, caret);
|
|
172
|
+
// Size shortcuts are complete tokens, not the tail of a number or identifier.
|
|
173
|
+
// They remain ordinary text until the user accepts a matrix candidate.
|
|
174
|
+
const dimensionMatch = /^[\p{L}\p{M}\p{N}_.]/u.test(text.slice(caret))
|
|
175
|
+
? null
|
|
176
|
+
: before.match(/(?<![\p{L}\p{M}\p{N}_.\\])([1-9]\d?)[xX×]([1-9]\d?)$/u);
|
|
177
|
+
const dimension = dimensionMatch &&
|
|
178
|
+
Number(dimensionMatch[1]) <= MATRIX_MAX_SIZE &&
|
|
179
|
+
Number(dimensionMatch[2]) <= MATRIX_MAX_SIZE
|
|
180
|
+
? dimensionMatch
|
|
181
|
+
: null;
|
|
134
182
|
// Recognize the longest symbolic spelling first: E/ must never become a fraction query.
|
|
135
183
|
const trigger = triggers.find((t) => before.endsWith(t) &&
|
|
136
184
|
(t.length > 1 || !/[A-Za-z]/.test(t) || !/[\p{L}\p{N}]/u.test(before.at(-2) ?? '')));
|
|
137
185
|
const word = before.match(/(?:\\)?[\p{L}\p{M}]+$/u)?.[0];
|
|
138
186
|
const operand = before.match(/(?:\d+(?:\.\d+)?|[\p{L}\p{M}]+)$/u)?.[0];
|
|
139
|
-
const query = trigger ?? word ?? operand ?? '';
|
|
187
|
+
const query = dimension?.[0] ?? trigger ?? word ?? operand ?? '';
|
|
140
188
|
if (!query)
|
|
141
189
|
return { query: '', candidates: [] };
|
|
142
190
|
const name = query.replace(/^\\/, '');
|
|
@@ -160,12 +208,16 @@ export function findSuggestions(text, caret, locale = 'ko') {
|
|
|
160
208
|
return 3;
|
|
161
209
|
return 4;
|
|
162
210
|
};
|
|
163
|
-
const candidates =
|
|
164
|
-
?
|
|
165
|
-
:
|
|
166
|
-
?
|
|
167
|
-
:
|
|
211
|
+
const candidates = dimension
|
|
212
|
+
? matrixDimensionSuggestions(Number(dimension[1]), Number(dimension[2]))
|
|
213
|
+
: trigger
|
|
214
|
+
? catalog.filter((item) => item.triggers.includes(trigger))
|
|
215
|
+
: /^\d+(?:\.\d+)?$/.test(name)
|
|
216
|
+
? []
|
|
217
|
+
: catalog.filter((item) => names(item).some((value) => normalize(value).includes(needle)));
|
|
168
218
|
candidates.sort((a, b) => {
|
|
219
|
+
if (dimension)
|
|
220
|
+
return 0;
|
|
169
221
|
if (trigger === '-' || trigger === '->') {
|
|
170
222
|
const preferred = trigger === '-' ? ['−', '→'] : ['→'];
|
|
171
223
|
const order = (item) => {
|
|
@@ -216,6 +268,16 @@ export function findSuggestions(text, caret, locale = 'ko') {
|
|
|
216
268
|
});
|
|
217
269
|
}
|
|
218
270
|
}
|
|
271
|
+
// A partial name after a coefficient is an operand (4ab), not an "absolute"
|
|
272
|
+
// command. Keep explicit commands such as 4abs and \\abs working as before.
|
|
273
|
+
if (!trigger && /^\p{L}+$/u.test(query) && /\d$/.test(before.slice(0, -query.length))) {
|
|
274
|
+
for (let index = 0; index < candidates.length; index++) {
|
|
275
|
+
const item = candidates[index];
|
|
276
|
+
if (item.kind && wrappingKinds.some((kind) => kind === item.kind) && rank(item) >= 3) {
|
|
277
|
+
candidates[index] = { ...item, wrapOperand: true, detail: 'suggestion.wrapOperand' };
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
219
281
|
return {
|
|
220
282
|
query,
|
|
221
283
|
candidates: candidates.map((item) => ({
|
|
@@ -225,11 +287,68 @@ export function findSuggestions(text, caret, locale = 'ko') {
|
|
|
225
287
|
})),
|
|
226
288
|
};
|
|
227
289
|
}
|
|
290
|
+
/** Combine text search with changes available for the current formula structure. */
|
|
291
|
+
export function findStateSuggestions(state, locale = 'ko', caret = state.caret.start) {
|
|
292
|
+
const text = textNodes(state.document).find((node) => node.id === state.caret.id)?.text ?? '';
|
|
293
|
+
const result = findSuggestions(text, caret, locale);
|
|
294
|
+
const context = structureEditingContext(state);
|
|
295
|
+
const root = context?.root;
|
|
296
|
+
const kind = root?.canTransform ? root.target : undefined;
|
|
297
|
+
if (root && kind) {
|
|
298
|
+
const item = mathStructures.find((entry) => entry.kind === kind);
|
|
299
|
+
result.candidates.push({
|
|
300
|
+
...item,
|
|
301
|
+
id: `transform-${kind}`,
|
|
302
|
+
transformRootId: root.id,
|
|
303
|
+
label: translate(locale, 'suggestion.transform', {
|
|
304
|
+
kind: translate(locale, `context.${kind}`),
|
|
305
|
+
}),
|
|
306
|
+
detail: translate(locale, 'suggestion.transformRootDetail'),
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
if (context?.fence) {
|
|
310
|
+
const fence = context.fence;
|
|
311
|
+
const changes = Object.keys(fencePairs)
|
|
312
|
+
.filter((kind) => kind !== fence.type)
|
|
313
|
+
.map((kind) => {
|
|
314
|
+
const item = mathStructures.find((entry) => entry.kind === kind);
|
|
315
|
+
return {
|
|
316
|
+
...item,
|
|
317
|
+
id: `transform-fence-${kind}`,
|
|
318
|
+
transformFenceId: fence.id,
|
|
319
|
+
label: translate(locale, 'suggestion.transformFence', {
|
|
320
|
+
kind: translate(locale, item.label),
|
|
321
|
+
}),
|
|
322
|
+
detail: translate(locale, 'suggestion.transformFenceDetail'),
|
|
323
|
+
};
|
|
324
|
+
});
|
|
325
|
+
// Explicit symbol/command matches stay first. Changes precede new wrapping actions.
|
|
326
|
+
const wrapping = result.candidates.findIndex((item) => item.wrapOperand);
|
|
327
|
+
result.candidates.splice(wrapping < 0 ? result.candidates.length : wrapping, 0, ...changes);
|
|
328
|
+
}
|
|
329
|
+
return result;
|
|
330
|
+
}
|
|
228
331
|
export function acceptSuggestion(state, query, candidate) {
|
|
332
|
+
if (candidate.transformFenceId)
|
|
333
|
+
return candidate.kind
|
|
334
|
+
? changeContextFence(state, candidate.transformFenceId, candidate.kind)
|
|
335
|
+
: state;
|
|
336
|
+
if (candidate.transformRootId) {
|
|
337
|
+
return candidate.kind === 'root' || candidate.kind === 'indexedRoot'
|
|
338
|
+
? transformRoot(state, candidate.transformRootId, candidate.kind)
|
|
339
|
+
: state;
|
|
340
|
+
}
|
|
229
341
|
const node = textNodes(state.document).find((n) => n.id === state.caret.id);
|
|
230
342
|
const start = state.caret.start - query.length;
|
|
231
343
|
if (!node || start < 0 || node.text.slice(start, state.caret.start) !== query)
|
|
232
344
|
return state;
|
|
345
|
+
if (candidate.matrixSize !== undefined) {
|
|
346
|
+
const rows = candidate.matrixSize;
|
|
347
|
+
const columns = candidate.matrixColumns ?? rows;
|
|
348
|
+
if (![rows, columns].every((size) => Number.isInteger(size) && size >= 1 && size <= MATRIX_MAX_SIZE) ||
|
|
349
|
+
(candidate.identity && rows !== columns))
|
|
350
|
+
return state;
|
|
351
|
+
}
|
|
233
352
|
if (candidate.wrapOperand && candidate.kind) {
|
|
234
353
|
const selected = { ...state, caret: { ...state.caret, start, end: state.caret.start } };
|
|
235
354
|
const wrapped = insertStructure(selected, candidate.kind);
|
|
@@ -253,12 +372,34 @@ export function acceptSuggestion(state, query, candidate) {
|
|
|
253
372
|
const inserted = insertStructure(next, 'operatorName');
|
|
254
373
|
return moveCaret(setText(inserted, candidate.operatorName, candidate.operatorName.length), 1);
|
|
255
374
|
}
|
|
256
|
-
if (candidate.templateId)
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
375
|
+
if (candidate.templateId) {
|
|
376
|
+
const inserted = insertTemplate(next, candidate.templateId);
|
|
377
|
+
if (!candidate.templateId.startsWith('zero-') || inserted === next)
|
|
378
|
+
return inserted;
|
|
379
|
+
// Matrix suggestions start cell editing, including populated zero templates.
|
|
380
|
+
// Pasting a template otherwise leaves the caret after its last structure.
|
|
381
|
+
const matrix = activeMatrix(moveCaret(inserted, -1))?.matrix;
|
|
382
|
+
const first = matrix?.slots[0].children[0];
|
|
383
|
+
return first?.type === 'text'
|
|
384
|
+
? { ...inserted, caret: { id: first.id, start: 0, end: 0 } }
|
|
385
|
+
: inserted;
|
|
386
|
+
}
|
|
387
|
+
if (candidate.matrixSize) {
|
|
388
|
+
const inserted = candidate.identity
|
|
389
|
+
? insertIdentityMatrix(next, candidate.matrixSize)
|
|
390
|
+
: insertMatrix(next, candidate.matrixSize, candidate.matrixColumns);
|
|
391
|
+
if (inserted === next)
|
|
392
|
+
return state;
|
|
393
|
+
if (candidate.zero) {
|
|
394
|
+
activeMatrix(inserted)?.matrix.slots.forEach((cell) => {
|
|
395
|
+
const first = cell.children[0];
|
|
396
|
+
if (first.type === 'text')
|
|
397
|
+
first.text = '0';
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
return inserted;
|
|
401
|
+
}
|
|
260
402
|
return candidate.kind
|
|
261
403
|
? insertStructure(next, candidate.kind, ['fraction', 'binomial', 'superscript', 'subscript'].includes(candidate.kind), candidate.mathStyle)
|
|
262
404
|
: next;
|
|
263
405
|
}
|
|
264
|
-
//# sourceMappingURL=suggestions.js.map
|
package/dist/svelte.d.ts
CHANGED
|
@@ -2,4 +2,3 @@ import type { Action } from 'svelte/action';
|
|
|
2
2
|
import { type DOMMathEditorOptions } from './dom.js';
|
|
3
3
|
/** Svelte action: <div use:mathEditor={options} />. */
|
|
4
4
|
export declare const mathEditor: Action<HTMLElement, DOMMathEditorOptions | undefined>;
|
|
5
|
-
//# sourceMappingURL=svelte.d.ts.map
|
package/dist/svelte.js
CHANGED
package/dist/symbol-browser.d.ts
CHANGED
package/dist/symbol-browser.js
CHANGED
|
@@ -29,4 +29,3 @@ export function SymbolBrowser({ locale, onInsert, onClose, }) {
|
|
|
29
29
|
}
|
|
30
30
|
}, children: [_jsxs("div", { className: "me-symbol-browser-heading", children: [_jsxs("strong", { children: [t('symbols.title'), ' ', _jsxs("small", { children: [matches.length, " / ", mathSymbols.length] })] }), _jsx("button", { type: "button", onClick: onClose, children: t('common.close') })] }), _jsxs("label", { className: "me-symbol-search", children: [t('symbols.search'), _jsx("input", { ref: search, type: "search", value: query, onChange: (event) => setQuery(event.target.value), placeholder: t('symbols.searchPlaceholder') })] }), _jsx("p", { className: "me-symbol-help", children: t('symbols.help') }), _jsx("div", { className: "me-symbol-grid", children: matches.map(([glyph, label]) => (_jsxs("button", { type: "button", "aria-label": `${glyph} — ${t(label)}`, title: `${translate('en', label)} / ${translate('ko', label)}`, onClick: () => onInsert(glyph), children: [_jsx("span", { className: "me-symbol-glyph", "aria-hidden": "true", children: glyph }), _jsx("span", { children: t(label) })] }, glyph))) }), !matches.length && _jsx("p", { role: "status", children: t('symbols.noMatches') })] }));
|
|
31
31
|
}
|
|
32
|
-
//# sourceMappingURL=symbol-browser.js.map
|
package/dist/symbols.d.ts
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
1
|
/** One catalog powers discovery and LaTeX export. */
|
|
2
2
|
export declare const mathSymbols: readonly [readonly ["↑", "symbol.upArrow", "uparrow arrow 화살표", "- ->", "\\uparrow"], readonly ["↕", "symbol.upDownArrow", "updownarrow arrow 화살표", "- ->", "\\updownarrow"], readonly ["⇐", "symbol.doubleLeftArrow", "Leftarrow arrow 화살표", "- ->", "\\Leftarrow"], readonly ["⇑", "symbol.doubleUpArrow", "Uparrow arrow 화살표", "- ->", "\\Uparrow"], readonly ["⇓", "symbol.doubleDownArrow", "Downarrow arrow 화살표", "- ->", "\\Downarrow"], readonly ["⇕", "symbol.doubleUpDownArrow", "Updownarrow arrow 화살표", "- ->", "\\Updownarrow"], readonly ["↗", "symbol.northEastArrow", "nearrow arrow 화살표", "- ->", "\\nearrow"], readonly ["↘", "symbol.southEastArrow", "searrow arrow 화살표", "- ->", "\\searrow"], readonly ["↙", "symbol.southWestArrow", "swarrow arrow 화살표", "- ->", "\\swarrow"], readonly ["↖", "symbol.northWestArrow", "nwarrow arrow 화살표", "- ->", "\\nwarrow"], readonly ["⟶", "symbol.longRightArrow", "longrightarrow arrow 화살표", "- ->", "\\longrightarrow"], readonly ["⟵", "symbol.longLeftArrow", "longleftarrow arrow 화살표", "- ->", "\\longleftarrow"], readonly ["⟷", "symbol.longLeftRightArrow", "longleftrightarrow arrow 화살표", "-", "\\longleftrightarrow"], readonly ["⟹", "symbol.longDoubleRightArrow", "Longrightarrow arrow 화살표", "- ->", "\\Longrightarrow"], readonly ["⟸", "symbol.longDoubleLeftArrow", "Longleftarrow arrow 화살표", "- ->", "\\Longleftarrow"], readonly ["⟺", "symbol.longDoubleLeftRightArrow", "Longleftrightarrow arrow 화살표", "", "\\Longleftrightarrow"], readonly ["↪", "symbol.hookRightArrow", "hookrightarrow arrow 화살표", "- ->", "\\hookrightarrow"], readonly ["↩", "symbol.hookLeftArrow", "hookleftarrow arrow 화살표", "- ->", "\\hookleftarrow"], readonly ["⇀", "symbol.rightHarpoonUp", "rightharpoonup arrow 화살표", "- ->", "\\rightharpoonup"], readonly ["↼", "symbol.leftHarpoonUp", "leftharpoonup arrow 화살표", "- ->", "\\leftharpoonup"], readonly ["⇁", "symbol.rightHarpoonDown", "rightharpoondown arrow 화살표", "- ->", "\\rightharpoondown"], readonly ["↽", "symbol.leftHarpoonDown", "leftharpoondown arrow 화살표", "- ->", "\\leftharpoondown"], readonly ["⇌", "symbol.rightLeftHarpoons", "rightleftharpoons arrow 화살표", "- ->", "\\rightleftharpoons"], readonly ["⇋", "symbol.leftRightHarpoons", "leftrightharpoons arrow 화살표", "- ->", "\\leftrightharpoons"], readonly ["↓", "symbol.downArrow", "downarrow down 아래화살표 아래쪽화살표", "- ->", "\\downarrow"], readonly ["⩾", "symbol.greaterOrEqualSlanted", "geqslant", "", "\\geqslant"], readonly ["⩽", "symbol.lessOrEqualSlanted", "leqslant", "", "\\leqslant"], readonly ["∋", "symbol.contains", "ni contains", "", "\\ni"], readonly ["⊃", "symbol.superset", "supset superset", "", "\\supset"], readonly ["⊇", "symbol.supersetOrEqual", "supseteq", "", "\\supseteq"], readonly ["⊈", "symbol.notSubsetOrEqual", "nsubseteq", "", "\\nsubseteq"], readonly ["∖", "symbol.setDifference", "setminus difference", "", "\\setminus"], readonly ["ℕ", "symbol.naturals", "naturals natural", "", "\\mathbb{N}"], readonly ["ℤ", "symbol.integers", "integers integer", "", "\\mathbb{Z}"], readonly ["ℚ", "symbol.rationals", "rationals rational", "", "\\mathbb{Q}"], readonly ["ℝ", "symbol.reals", "reals real", "", "\\mathbb{R}"], readonly ["ℂ", "symbol.complexes", "complexes complex", "", "\\mathbb{C}"], readonly ["⊥", "symbol.perpendicular", "perp perpendicular", "", "\\perp"], readonly ["∥", "symbol.parallel", "parallel", "", "\\parallel"], readonly ["≅", "symbol.congruent", "cong congruent", "", "\\cong"], readonly ["∼", "symbol.similar", "sim similar", "", "\\sim"], readonly ["↦", "symbol.mapsTo", "mapsto maps arrow 화살표", "|-> - ->", "\\mapsto"], readonly ["…", "symbol.ellipsis", "ldots ellipsis", "", "\\ldots"], readonly ["⋯", "symbol.centeredDots", "cdots", "", "\\cdots"], readonly ["⋮", "symbol.verticalDots", "vdots", "", "\\vdots"], readonly ["⋱", "symbol.diagonalDots", "ddots", "", "\\ddots"], readonly ["°", "symbol.degree", "degree degrees 각도", "", "{}^{\\circ}"], readonly ["∠", "symbol.angle", "angle", "", "\\angle"], readonly ["+", "symbol.plus", "plus sum", "+", "+"], readonly ["−", "symbol.minus", "minus", "-", "-"], readonly ["±", "symbol.plusMinus", "plusminus sum", "+- +", "\\pm"], readonly ["∓", "symbol.minusPlus", "minusplus", "-+ -", "\\mp"], readonly ["×", "symbol.times", "times multiply", "*", "\\times"], readonly ["·", "symbol.dot", "dot multiply", "*", "\\cdot"], readonly ["÷", "symbol.divide", "divide division", "/", "\\div"], readonly ["=", "symbol.equal", "equal", "=", "="], readonly ["≠", "symbol.notEqual", "neq unequal", "!= /= =", "\\ne"], readonly ["≈", "symbol.approximatelyEqual", "approx", "~ ~~ =", "\\approx"], readonly ["≡", "symbol.equivalent", "equiv", "=== =", "\\equiv"], readonly ["<", "symbol.lessThan", "less", "<", "<"], readonly [">", "symbol.greaterThan", "greater", ">", ">"], readonly ["≤", "symbol.lessOrEqual", "leq less", "<= <- <", "\\le"], readonly ["≥", "symbol.greaterOrEqual", "geq greater", ">= >- >", "\\ge"], readonly ["∝", "symbol.proportional", "proportional", "~", "\\propto"], readonly ["→", "symbol.rightArrow", "rightarrow arrow", "-> -", "\\to"], readonly ["←", "symbol.leftArrow", "leftarrow arrow", "<- < - ->", "\\leftarrow"], readonly ["↔", "symbol.leftRightArrow", "leftrightarrow arrow", "<-> - ->", "\\leftrightarrow"], readonly ["⇒", "symbol.implies", "implies arrow 화살표", "=> = - ->", "\\Rightarrow"], readonly ["⇔", "symbol.iff", "iff arrow 화살표", "<=> - ->", "\\Leftrightarrow"], readonly ["∈", "symbol.elementOf", "in element", "E", "\\in"], readonly ["∉", "symbol.notElementOf", "notin element", "E/", "\\notin"], readonly ["∀", "symbol.forAll", "forall", "A", "\\forall"], readonly ["∃", "symbol.exists", "exists", "E", "\\exists"], readonly ["∪", "symbol.union", "union", "U", "\\cup"], readonly ["∩", "symbol.intersection", "intersection", "", "\\cap"], readonly ["⊂", "symbol.subset", "subset", "<", "\\subset"], readonly ["⊆", "symbol.subsetOrEqual", "subseteq", "<=", "\\subseteq"], readonly ["∅", "symbol.emptySet", "emptyset", "", "\\emptyset"], readonly ["∞", "symbol.infinity", "infinity infty", "", "\\infty"], readonly ["∂", "symbol.partialDerivative", "partial derivative", "", "\\partial"], readonly ["∇", "symbol.nabla", "nabla gradient", "", "\\nabla"], readonly ["∧", "symbol.logicalAnd", "and wedge", "^", "\\wedge"], readonly ["∨", "symbol.logicalOr", "or vee", "", "\\vee"], readonly ["¬", "symbol.logicalNot", "not neg", "!", "\\neg"], readonly ["α", "symbol.alpha", "alpha", "", "\\alpha"], readonly ["β", "symbol.beta", "beta", "", "\\beta"], readonly ["γ", "symbol.gamma", "gamma", "", "\\gamma"], readonly ["δ", "symbol.delta", "delta", "", "\\delta"], readonly ["ε", "symbol.epsilon", "epsilon", "", "\\epsilon"], readonly ["ζ", "symbol.zeta", "zeta", "", "\\zeta"], readonly ["η", "symbol.eta", "eta", "", "\\eta"], readonly ["θ", "symbol.theta", "theta", "", "\\theta"], readonly ["ι", "symbol.iota", "iota", "", "\\iota"], readonly ["κ", "symbol.kappa", "kappa", "", "\\kappa"], readonly ["λ", "symbol.lambda", "lambda", "", "\\lambda"], readonly ["μ", "symbol.mu", "mu", "", "\\mu"], readonly ["ν", "symbol.nu", "nu", "", "\\nu"], readonly ["ξ", "symbol.xi", "xi", "", "\\xi"], readonly ["π", "symbol.pi", "pi", "", "\\pi"], readonly ["ρ", "symbol.rho", "rho", "", "\\rho"], readonly ["σ", "symbol.sigma", "sigma", "", "\\sigma"], readonly ["τ", "symbol.tau", "tau", "", "\\tau"], readonly ["υ", "symbol.upsilon", "upsilon", "", "\\upsilon"], readonly ["φ", "symbol.phi", "phi", "", "\\phi"], readonly ["χ", "symbol.chi", "chi", "", "\\chi"], readonly ["ψ", "symbol.psi", "psi", "", "\\psi"], readonly ["ω", "symbol.omega", "omega", "", "\\omega"], readonly ["Γ", "symbol.upperGamma", "Gamma", "", "\\Gamma"], readonly ["Δ", "symbol.upperDelta", "Delta", "", "\\Delta"], readonly ["Θ", "symbol.upperTheta", "Theta", "", "\\Theta"], readonly ["Λ", "symbol.upperLambda", "Lambda", "", "\\Lambda"], readonly ["Ξ", "symbol.upperXi", "Xi", "", "\\Xi"], readonly ["Π", "symbol.upperPi", "Pi", "", "\\Pi"], readonly ["Σ", "symbol.upperSigma", "Sigma", "", "\\Sigma"], readonly ["Φ", "symbol.upperPhi", "Phi", "", "\\Phi"], readonly ["Ψ", "symbol.upperPsi", "Psi", "", "\\Psi"], readonly ["Ω", "symbol.upperOmega", "Omega", "", "\\Omega"]];
|
|
3
|
-
//# sourceMappingURL=symbols.d.ts.map
|
package/dist/symbols.js
CHANGED
package/dist/templates.d.ts
CHANGED
|
@@ -13,4 +13,3 @@ export declare const mathTemplates: MathTemplate[];
|
|
|
13
13
|
/** Each call creates independent, editable nodes; templates are not opaque LaTeX. */
|
|
14
14
|
export declare function createTemplate(id: string): MathFragment | undefined;
|
|
15
15
|
export declare function insertTemplate(state: MathState, id: string, range?: MathRange): MathState;
|
|
16
|
-
//# sourceMappingURL=templates.d.ts.map
|
package/dist/templates.js
CHANGED
package/dist/tokens.d.ts
CHANGED
|
@@ -8,4 +8,3 @@ export interface MathToken {
|
|
|
8
8
|
/** Lexical input units, not inferred mathematical definitions (e and c remain variables). */
|
|
9
9
|
export declare function tokenizeMathText(text: string): MathToken[];
|
|
10
10
|
export declare function tokenIndexAt(tokens: MathToken[], offset: number, affinity?: 'forward' | 'backward'): number;
|
|
11
|
-
//# sourceMappingURL=tokens.d.ts.map
|
package/dist/tokens.js
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type MathCaret, type MathState } from './model.js';
|
|
2
|
+
import type { MathPoint } from './range.js';
|
|
3
|
+
type VerticalPoint = MathPoint & Pick<MathCaret, 'affinity'>;
|
|
4
|
+
/** Viewport coordinates of a rendered insertion point, including either side of a token boundary. */
|
|
5
|
+
export type MathCaretGeometry = (point: VerticalPoint) => {
|
|
6
|
+
x: number;
|
|
7
|
+
y: number;
|
|
8
|
+
} | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Move through the nearest vertical structure, then enclosing grids and equation lines.
|
|
11
|
+
* Geometry is optional so the same operation works in headless sessions and either renderer.
|
|
12
|
+
* Native text selections and literal text retain their own arrow-key behavior.
|
|
13
|
+
*/
|
|
14
|
+
export declare function moveVertical(state: MathState, direction: -1 | 1, geometry?: MathCaretGeometry): MathState;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { documentRows, isGrid, isLiteralText, textNodes, } from './model.js';
|
|
2
|
+
/** Candidate slots in semantic order; paired scripts may also move along their shared column. */
|
|
3
|
+
function verticalSlots(node, slot, direction) {
|
|
4
|
+
if (isGrid(node)) {
|
|
5
|
+
const target = slot + direction * node.columns;
|
|
6
|
+
return target >= 0 && target < node.slots.length ? [target] : [];
|
|
7
|
+
}
|
|
8
|
+
switch (node.type) {
|
|
9
|
+
case 'fraction':
|
|
10
|
+
case 'binomial':
|
|
11
|
+
case 'indexedRoot':
|
|
12
|
+
case 'overset':
|
|
13
|
+
case 'overbrace':
|
|
14
|
+
case 'xrightarrow':
|
|
15
|
+
case 'xleftarrow':
|
|
16
|
+
case 'subscript':
|
|
17
|
+
return slot + direction >= 0 && slot + direction < 2 ? [slot + direction] : [];
|
|
18
|
+
case 'underset':
|
|
19
|
+
case 'underbrace':
|
|
20
|
+
return slot - direction >= 0 && slot - direction < 2 ? [slot - direction] : [];
|
|
21
|
+
case 'superscript':
|
|
22
|
+
return slot - direction >= 0 && slot - direction < 2 ? [slot - direction] : [];
|
|
23
|
+
case 'scripts':
|
|
24
|
+
if (slot === 0)
|
|
25
|
+
return [direction === -1 ? 2 : 1];
|
|
26
|
+
if (slot === 1 && direction === -1)
|
|
27
|
+
return [0, 2];
|
|
28
|
+
if (slot === 2 && direction === 1)
|
|
29
|
+
return [0, 1];
|
|
30
|
+
return [];
|
|
31
|
+
case 'limit':
|
|
32
|
+
case 'limsup':
|
|
33
|
+
case 'liminf':
|
|
34
|
+
return slot - direction >= 0 && slot - direction < 2 ? [slot - direction] : [];
|
|
35
|
+
case 'sum':
|
|
36
|
+
case 'product':
|
|
37
|
+
case 'integral':
|
|
38
|
+
case 'doubleIntegral':
|
|
39
|
+
case 'tripleIntegral':
|
|
40
|
+
case 'contourIntegral':
|
|
41
|
+
if (slot === 2)
|
|
42
|
+
return [direction === -1 ? 1 : 0];
|
|
43
|
+
if (slot === 0 && direction === -1)
|
|
44
|
+
return [2, 1];
|
|
45
|
+
if (slot === 1 && direction === 1)
|
|
46
|
+
return [2, 0];
|
|
47
|
+
return [];
|
|
48
|
+
default:
|
|
49
|
+
return [];
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function caretOffsets(text) {
|
|
53
|
+
const offsets = [0];
|
|
54
|
+
for (const character of text)
|
|
55
|
+
offsets.push(offsets.at(-1) + character.length);
|
|
56
|
+
return offsets;
|
|
57
|
+
}
|
|
58
|
+
function focusRows(state, targets, direction, geometry) {
|
|
59
|
+
const nodes = targets.flatMap((root) => textNodes({ version: 1, root }));
|
|
60
|
+
if (!nodes.length)
|
|
61
|
+
return state;
|
|
62
|
+
const origin = geometry?.({
|
|
63
|
+
id: state.caret.id,
|
|
64
|
+
offset: state.caret.start,
|
|
65
|
+
affinity: state.caret.affinity,
|
|
66
|
+
});
|
|
67
|
+
let nearest;
|
|
68
|
+
let horizontal = Infinity;
|
|
69
|
+
let vertical = Infinity;
|
|
70
|
+
if (origin && Number.isFinite(origin.x) && Number.isFinite(origin.y)) {
|
|
71
|
+
for (const node of nodes) {
|
|
72
|
+
for (const offset of caretOffsets(node.text)) {
|
|
73
|
+
// React renders adjacent lexical tokens with distinct physical caret positions.
|
|
74
|
+
for (const affinity of ['backward', 'forward']) {
|
|
75
|
+
const point = { id: node.id, offset, affinity };
|
|
76
|
+
const position = geometry?.(point);
|
|
77
|
+
if (!position || !Number.isFinite(position.x) || !Number.isFinite(position.y))
|
|
78
|
+
continue;
|
|
79
|
+
const dy = (position.y - origin.y) * direction;
|
|
80
|
+
if (dy <= 0)
|
|
81
|
+
continue;
|
|
82
|
+
const dx = Math.abs(position.x - origin.x);
|
|
83
|
+
if (dx < horizontal - 0.5 || (Math.abs(dx - horizontal) <= 0.5 && dy < vertical)) {
|
|
84
|
+
nearest = point;
|
|
85
|
+
horizontal = dx;
|
|
86
|
+
vertical = dy;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Without layout, preserve the existing offset/clamping behavior in the first target slot.
|
|
93
|
+
const fallback = nodes[0];
|
|
94
|
+
const offset = nearest?.offset ??
|
|
95
|
+
caretOffsets(fallback.text)
|
|
96
|
+
.filter((at) => at <= state.caret.start)
|
|
97
|
+
.at(-1);
|
|
98
|
+
return {
|
|
99
|
+
...state,
|
|
100
|
+
caret: {
|
|
101
|
+
id: nearest?.id ?? fallback.id,
|
|
102
|
+
start: offset,
|
|
103
|
+
end: offset,
|
|
104
|
+
...(nearest ? { affinity: nearest.affinity } : {}),
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Move through the nearest vertical structure, then enclosing grids and equation lines.
|
|
110
|
+
* Geometry is optional so the same operation works in headless sessions and either renderer.
|
|
111
|
+
* Native text selections and literal text retain their own arrow-key behavior.
|
|
112
|
+
*/
|
|
113
|
+
export function moveVertical(state, direction, geometry) {
|
|
114
|
+
if (state.caret.start !== state.caret.end || isLiteralText(state.document, state.caret.id))
|
|
115
|
+
return state;
|
|
116
|
+
const path = [];
|
|
117
|
+
const find = (row) => {
|
|
118
|
+
for (const node of row.children) {
|
|
119
|
+
if (node.type === 'text') {
|
|
120
|
+
if (node.id === state.caret.id)
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
for (let slot = 0; slot < node.slots.length; slot++) {
|
|
125
|
+
path.push({ structure: node, slot });
|
|
126
|
+
if (find(node.slots[slot]))
|
|
127
|
+
return true;
|
|
128
|
+
path.pop();
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return false;
|
|
133
|
+
};
|
|
134
|
+
const lines = documentRows(state.document);
|
|
135
|
+
const line = lines.findIndex(find);
|
|
136
|
+
if (line < 0)
|
|
137
|
+
return state;
|
|
138
|
+
for (const { structure, slot } of path.reverse()) {
|
|
139
|
+
const targets = verticalSlots(structure, slot, direction).map((index) => structure.slots[index]);
|
|
140
|
+
if (targets.length)
|
|
141
|
+
return focusRows(state, targets, direction, geometry);
|
|
142
|
+
}
|
|
143
|
+
const target = lines[line + direction];
|
|
144
|
+
return target ? focusRows(state, [target], direction, geometry) : state;
|
|
145
|
+
}
|
package/dist/vue.d.ts
CHANGED
|
@@ -2,4 +2,3 @@ import type { ObjectDirective } from 'vue';
|
|
|
2
2
|
import { type DOMMathEditorOptions } from './dom.js';
|
|
3
3
|
/** Use as v-math-editor. session/defaultValue are mount-only. */
|
|
4
4
|
export declare const vMathEditor: ObjectDirective<HTMLElement, DOMMathEditorOptions>;
|
|
5
|
-
//# sourceMappingURL=vue.d.ts.map
|
package/dist/vue.js
CHANGED
package/dist/web-component.d.ts
CHANGED
|
@@ -7,4 +7,3 @@ export interface MathEditorElement extends HTMLElement {
|
|
|
7
7
|
}
|
|
8
8
|
/** Explicit registration; importing this module is safe without a browser. Uses light DOM. */
|
|
9
9
|
export declare function defineMathEditor(tagName?: string): CustomElementConstructor;
|
|
10
|
-
//# sourceMappingURL=web-component.d.ts.map
|
package/dist/web-component.js
CHANGED
|
@@ -6,7 +6,14 @@ export function defineMathEditor(tagName = 'barocss-math-editor') {
|
|
|
6
6
|
if (existing)
|
|
7
7
|
return existing;
|
|
8
8
|
class EditorElement extends HTMLElement {
|
|
9
|
-
static observedAttributes = [
|
|
9
|
+
static observedAttributes = [
|
|
10
|
+
'locale',
|
|
11
|
+
'mode',
|
|
12
|
+
'toolbar',
|
|
13
|
+
'line-numbers',
|
|
14
|
+
'enter-behavior',
|
|
15
|
+
'context-tools',
|
|
16
|
+
];
|
|
10
17
|
session = createMathSession();
|
|
11
18
|
editor;
|
|
12
19
|
get value() {
|
|
@@ -26,6 +33,7 @@ export function defineMathEditor(tagName = 'barocss-math-editor') {
|
|
|
26
33
|
onCancel: () => this.dispatchEvent(new CustomEvent('math-cancel', { bubbles: true, composed: true })),
|
|
27
34
|
onCommit: (snapshot) => this.dispatchEvent(new CustomEvent('math-commit', { detail: snapshot, bubbles: true, composed: true })),
|
|
28
35
|
showLineNumbers: this.getAttribute('line-numbers') !== 'false',
|
|
36
|
+
contextTools: this.getAttribute('context-tools') !== 'false',
|
|
29
37
|
onChange: (document, latex) => this.dispatchEvent(new CustomEvent('math-change', {
|
|
30
38
|
detail: { document, latex },
|
|
31
39
|
bubbles: true,
|
|
@@ -64,4 +72,3 @@ export function defineMathEditor(tagName = 'barocss-math-editor') {
|
|
|
64
72
|
customElements.define(tagName, EditorElement);
|
|
65
73
|
return EditorElement;
|
|
66
74
|
}
|
|
67
|
-
//# sourceMappingURL=web-component.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barocss/math-editor",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -46,7 +46,8 @@
|
|
|
46
46
|
"src/style.css",
|
|
47
47
|
"*.md",
|
|
48
48
|
"LICENSE",
|
|
49
|
-
"src/fonts"
|
|
49
|
+
"src/fonts",
|
|
50
|
+
"src/shapes"
|
|
50
51
|
],
|
|
51
52
|
"peerDependencies": {
|
|
52
53
|
"react": ">=18",
|
|
@@ -120,6 +121,13 @@
|
|
|
120
121
|
"test": "vitest run",
|
|
121
122
|
"test:run": "vitest run",
|
|
122
123
|
"format": "prettier --write src test \"examples/*.ts\" scripts",
|
|
123
|
-
"format:check": "prettier --check src test \"examples/*.ts\" scripts"
|
|
124
|
+
"format:check": "prettier --check src test \"examples/*.ts\" scripts",
|
|
125
|
+
"test:rendering": "node test/rendering/run.mjs",
|
|
126
|
+
"test:rendering:syntax": "node test/rendering/run.mjs --suite=syntax",
|
|
127
|
+
"test:rendering:combinations": "node test/rendering/run.mjs --suite=combinations",
|
|
128
|
+
"test:rendering:inventory": "vitest run test/rendering-coverage.test.ts",
|
|
129
|
+
"test:rendering:update": "node test/rendering/update.mjs",
|
|
130
|
+
"test:rendering:report": "node test/rendering/coverage-report.mjs",
|
|
131
|
+
"test:editing": "node test/editing/run.mjs"
|
|
124
132
|
}
|
|
125
133
|
}
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Bundled mathematical glyphs
|
|
2
|
+
|
|
3
|
+
The WOFF2 files in this directory come from KaTeX 0.16.28. Their MIT notice is
|
|
4
|
+
preserved in [LICENSE-KaTeX.txt](LICENSE-KaTeX.txt).
|
|
5
|
+
|
|
6
|
+
The editor uses Main Regular for upright mathematics, Math Italic for variables,
|
|
7
|
+
Size1 Regular for inline operators, and Size2 Regular for display operators. Bold, calligraphic and blackboard faces
|
|
8
|
+
support the corresponding alphabet structures. Unsupported characters retain
|
|
9
|
+
system-font fallbacks.
|
|
10
|
+
|
|
11
|
+
The over/underbrace masks in `../style.css` also derive from the `leftbrace`,
|
|
12
|
+
`midbrace` and `rightbrace` paths in KaTeX 0.16.28 `src/svgGeometry.js`, under the
|
|
13
|
+
same MIT license. Three clipped slices preserve the ends and center when the
|
|
14
|
+
brace stretches. These assets do not add a KaTeX JavaScript runtime dependency.
|
|
15
|
+
|
|
16
|
+
Root and parenthesis masks also use KaTeX contours. See
|
|
17
|
+
[../shapes/README.md](../shapes/README.md) for the source glyphs, bounds and
|
|
18
|
+
conversion details.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Mathematical outlines
|
|
2
|
+
|
|
3
|
+
These static SVG masks are derived from KaTeX 0.16.28, under its MIT license.
|
|
4
|
+
The copyright and license notice is preserved in
|
|
5
|
+
[../fonts/LICENSE-KaTeX.txt](../fonts/LICENSE-KaTeX.txt).
|
|
6
|
+
|
|
7
|
+
| Asset | Source | Conversion |
|
|
8
|
+
| ------------------------ | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
|
9
|
+
| `radical.svg` | `src/svgGeometry.js`, `sqrtMain` | Set `extraVinculum` and top padding to zero; crop to the 850 × 1000 radical region. The editable radicand slot draws the horizontal rule. |
|
|
10
|
+
| `parenthesis.svg` | Main Regular, U+0028 | Extract the glyph outline, invert the font Y axis and crop to its ink bounds: (94, −250)–(333, 750). |
|
|
11
|
+
| `parenthesis-top.svg` | Size4 Regular, U+239B | Same conversion, bounds (291, −655)–(843, 1154). |
|
|
12
|
+
| `parenthesis-bottom.svg` | Size4 Regular, U+239D | Same conversion, bounds (291, −644)–(843, 1165). |
|
|
13
|
+
|
|
14
|
+
Font contours were extracted from the distributed TTF files with fontTools
|
|
15
|
+
`SVGPathPen` and `TransformPen`. The masks retain the existing editor layout
|
|
16
|
+
boxes; they do not reproduce KaTeX's full delimiter-size selection algorithm.
|
|
17
|
+
Tall parentheses use bounded end caps and a straight extender. Right parentheses
|
|
18
|
+
mirror the corresponding left outline.
|
|
19
|
+
|
|
20
|
+
These files are packaged with `style.css`. They do not require KaTeX JavaScript,
|
|
21
|
+
fontTools, network requests to a CDN, or code generation in a consuming app.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 552 1809" preserveAspectRatio="none"><path d="M5 1Q7 0 75 0Q118 0 120 1Q124 2 125.0 8.0Q126 14 126 46Q126 290 143 500Q174 908 272.0 1223.0Q370 1538 542 1782Q552 1796 552 1800Q552 1803 546 1809H529Q510 1809 509 1808Q501 1800 494 1791Q130 1349 36 629Q4 384 0 72Q0 21 0.5 12.0Q1 3 5 1Z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 552 1809" preserveAspectRatio="none"><path d="M509 1Q510 0 528 0H546Q552 6 552 9Q552 13 542 27Q339 316 241.5 692.0Q144 1068 129 1574Q126 1730 126 1763Q126 1795 125.0 1801.0Q124 1807 120 1808Q118 1809 75 1809Q8 1809 6 1808Q1 1806 0.5 1797.0Q0 1788 0 1737Q3 1498 24 1283Q104 491 494 18Q501 9 509 1Z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 239 1000" preserveAspectRatio="none"><path d="M239 991Q239 1000 221 1000H208Q201 994 180 976Q0 812 0 500Q0 378 29 277Q75 120 180 24Q187 18 196.0 10.5Q205 3 208 0H221Q233 0 236.0 3.0Q239 6 239 9Q239 13 228 24Q73 188 73.0 500.0Q73 812 228 976Q239 987 239 991Z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 850 1000" preserveAspectRatio="none"><path d="M95,622 c-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14 c0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54 c44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10 s173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429 c69,-144,104.5,-217.7,106.5,-221 l0.0 -0 c5.3,-9.3,12,-14,20,-14 H400000v40H845.2724 s-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7 c-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z M834 0h400000v40h-400000z"/></svg>
|