@barocss/math-editor 0.5.0 → 0.6.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.
- package/API-SESSION.md +25 -1
- package/CHANGELOG.md +48 -0
- package/CLIPBOARD.md +54 -0
- package/EDITING-SCENARIOS.md +55 -20
- package/GETTING-STARTED.md +54 -0
- package/IMPLEMENTATION.md +10 -0
- package/KEYBOARD.md +41 -0
- package/LATEX-GUIDE.md +30 -2
- package/README.md +52 -10
- package/RELEASING.md +22 -8
- package/ROADMAP.md +106 -1
- package/STYLING.md +28 -1
- package/TEXT-EDITORS.md +157 -0
- package/VALIDATION.md +102 -0
- package/dist/dom/caret-geometry.js +1 -1
- package/dist/dom/help.d.ts +5 -0
- package/dist/dom/help.js +104 -0
- package/dist/dom/menu-position.js +4 -3
- package/dist/dom/readable-layout.d.ts +3 -0
- package/dist/dom/readable-layout.js +52 -0
- package/dist/dom/toolbar-catalog.d.ts +1 -1
- package/dist/dom/toolbar.d.ts +2 -0
- package/dist/dom/toolbar.js +8 -1
- package/dist/dom.d.ts +11 -1
- package/dist/dom.js +138 -15
- package/dist/enter-policy.js +1 -1
- package/dist/lines.d.ts +2 -0
- package/dist/lines.js +15 -0
- package/dist/locales/en.js +21 -3
- package/dist/locales/en.json +21 -3
- package/dist/locales/ko.js +21 -3
- package/dist/locales/ko.json +21 -3
- package/dist/math-editor-toolbar.js +2 -1
- package/dist/math-editor.d.ts +1 -0
- package/dist/math-editor.js +135 -39
- package/dist/model.d.ts +2 -0
- package/dist/model.js +23 -1
- package/dist/range.d.ts +10 -2
- package/dist/range.js +31 -6
- package/dist/selection-shortcuts.d.ts +13 -0
- package/dist/selection-shortcuts.js +35 -0
- package/dist/session.d.ts +1 -0
- package/dist/session.js +1 -1
- package/dist/symbols.d.ts +1 -1
- package/dist/symbols.js +1 -0
- package/dist/vertical-navigation.d.ts +5 -0
- package/dist/vertical-navigation.js +33 -0
- package/package.json +1 -1
- package/src/style.css +227 -57
package/dist/math-editor.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export interface MathEditorHandle {
|
|
|
8
8
|
/** Replace with supported LaTeX as one undoable edit; failures preserve all editor state. */
|
|
9
9
|
importLatex(source: string): LatexParseResult;
|
|
10
10
|
pasteLatex(source: string): LatexInsertionResult;
|
|
11
|
+
showHelp(): void;
|
|
11
12
|
}
|
|
12
13
|
export interface MathEditorProps {
|
|
13
14
|
preferences?: MathPreferences;
|
package/dist/math-editor.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { followReadableMathLayout } from './dom/readable-layout.js';
|
|
3
|
+
import { attachMathHelp, requestMathHelp } from './dom/help.js';
|
|
4
|
+
import { mathEnterAction } from './enter-policy.js';
|
|
2
5
|
import { mathLayout } from './math-layout.js';
|
|
6
|
+
import { wrapSelectionShortcut } from './selection-shortcuts.js';
|
|
3
7
|
import { transformRoot } from './root-transform.js';
|
|
4
8
|
import { structureEditingContext, changeContextFence } from './context-tools.js';
|
|
5
9
|
import { focusContextAction } from './dom/context-keyboard.js';
|
|
@@ -20,18 +24,18 @@ import { MathEditorToolbar } from './math-editor-toolbar.js';
|
|
|
20
24
|
import { SymbolBrowser } from './symbol-browser.js';
|
|
21
25
|
import { insertTemplate } from './templates.js';
|
|
22
26
|
import { translate, mathLocaleDirection, } from './i18n.js';
|
|
23
|
-
import { extendKeyboardRange, collapseKeyboardRange, wrapRange, wrappingKinds, copyRange, deleteRange, fragmentLatex, MATH_CLIPBOARD_TYPE, parseFragment, pasteFragment, resolveRange, } from './range.js';
|
|
27
|
+
import { extendKeyboardRange, isTokenNavigationKey, collapseKeyboardRange, wrapRange, wrappingKinds, copyRange, deleteRange, fragmentLatex, MATH_CLIPBOARD_TYPE, parseFragment, pasteFragment, resolveRange, } from './range.js';
|
|
24
28
|
import { mathRunSpacing } from './math-spacing.js';
|
|
25
29
|
import { tokenizeMathText, tokenIndexAt } from './tokens.js';
|
|
26
|
-
import { splitLine, joinPreviousLine } from './lines.js';
|
|
27
|
-
import {
|
|
30
|
+
import { splitLine, joinPreviousLine, joinNextLine } from './lines.js';
|
|
31
|
+
import { createVerticalNavigation } from './vertical-navigation.js';
|
|
28
32
|
import { renderedCaretGeometry } from './dom/caret-geometry.js';
|
|
29
33
|
import { insertIdentityMatrix, insertMatrix, activeGrid, MATRIX_MAX_SIZE, matrixEnvironments, resizeMatrix, setMatrixEnvironment, } from './matrix.js';
|
|
30
34
|
import { MATH_MATRIX_CLIPBOARD_TYPE, parseMatrixFragment, matrixFragment, matrixFromTSV, matrixRangeBetween, resolveMatrixRange, extendMatrixRange, focusMatrixCell, copyMatrixRange, clearMatrixRange, pasteMatrixFragment, transposeMatrix, } from './matrix-range.js';
|
|
31
35
|
import { createPortal } from 'react-dom';
|
|
32
36
|
import { acceptSuggestion, findStateSuggestions, mathStructures } from './suggestions.js';
|
|
33
37
|
import { useId, useImperativeHandle, useLayoutEffect, useRef, useState, } from 'react';
|
|
34
|
-
import { gridDeletionTarget, removeGrid, row, documentRows, isLiteralText, isGrid, commit, createHistory, initialState, insertStructure, moveCaret, redo, setText, textNodes, toLatex, undo, unwrapPrevious, unwrapEmptySlot, } from './model.js';
|
|
38
|
+
import { gridDeletionTarget, removeGrid, row, documentRows, isLiteralText, isGrid, commit, createHistory, initialState, insertStructure, moveCaret, redo, setText, textNodes, toLatex, undo, unwrapPrevious, unwrapNext, unwrapEmptySlot, } from './model.js';
|
|
35
39
|
const structures = mathStructures;
|
|
36
40
|
/** Native text fields own IME and local text selection; the tree owns structural editing. */
|
|
37
41
|
export function MathEditor({ preferences: suppliedPreferences, apiRef, autoFocus = false, enterBehavior = 'newline', onCommit, onCancel, showPopovers = true, defaultValue, excludedStructures = [], multiline = true, onChange, onExit, label, locale = 'ko', showLineNumbers = true, toolbar = true, toolbarMaxItems = 8, contextTools = true, toolbarEnd, showTokenLegend = true, }) {
|
|
@@ -52,6 +56,15 @@ export function MathEditor({ preferences: suppliedPreferences, apiRef, autoFocus
|
|
|
52
56
|
const [matrixRange, setMatrixRange] = useState();
|
|
53
57
|
const [clipboardMessage, setClipboardMessage] = useState('');
|
|
54
58
|
const surface = useRef(null);
|
|
59
|
+
useLayoutEffect(() => {
|
|
60
|
+
if (surface.current)
|
|
61
|
+
return followReadableMathLayout(surface.current);
|
|
62
|
+
}, []);
|
|
63
|
+
useLayoutEffect(() => {
|
|
64
|
+
const root = surface.current?.closest('.me-editor');
|
|
65
|
+
if (root)
|
|
66
|
+
return attachMathHelp(root, () => locale);
|
|
67
|
+
}, [locale]);
|
|
55
68
|
const drag = useRef(undefined);
|
|
56
69
|
const [focused, setFocused] = useState(false);
|
|
57
70
|
const [selectedGrid, setSelectedGrid] = useState();
|
|
@@ -110,9 +123,11 @@ export function MathEditor({ preferences: suppliedPreferences, apiRef, autoFocus
|
|
|
110
123
|
: [];
|
|
111
124
|
const selectedIndex = Math.min(candidateIndex, Math.max(0, candidates.length - 1));
|
|
112
125
|
// All React history updates pass here. Caret movement must not produce host save events.
|
|
126
|
+
const verticalNavigation = useRef(createVerticalNavigation());
|
|
113
127
|
const publish = (next, focus = false, notify = true) => {
|
|
114
128
|
const changed = next.present.document !== historyRef.current.present.document;
|
|
115
129
|
if (changed) {
|
|
130
|
+
verticalNavigation.current.reset();
|
|
116
131
|
setSelectedGrid(undefined);
|
|
117
132
|
setRange(undefined);
|
|
118
133
|
setMatrixRange(undefined);
|
|
@@ -153,6 +168,11 @@ export function MathEditor({ preferences: suppliedPreferences, apiRef, autoFocus
|
|
|
153
168
|
};
|
|
154
169
|
useImperativeHandle(apiRef, () => ({
|
|
155
170
|
pasteLatex,
|
|
171
|
+
showHelp() {
|
|
172
|
+
const root = surface.current?.closest('.me-editor');
|
|
173
|
+
if (root)
|
|
174
|
+
requestMathHelp(root);
|
|
175
|
+
},
|
|
156
176
|
importLatex(source) {
|
|
157
177
|
const result = parseLatex(source, { multiline, excludedStructures });
|
|
158
178
|
if (!result.ok)
|
|
@@ -240,10 +260,11 @@ export function MathEditor({ preferences: suppliedPreferences, apiRef, autoFocus
|
|
|
240
260
|
if (option && list) {
|
|
241
261
|
const itemRect = option.getBoundingClientRect();
|
|
242
262
|
const listRect = list.getBoundingClientRect();
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
263
|
+
const scaleY = listRect.height / list.offsetHeight || 1;
|
|
264
|
+
list.scrollTop +=
|
|
265
|
+
(itemRect.top + itemRect.height / 2 - listRect.top) / scaleY -
|
|
266
|
+
list.clientTop -
|
|
267
|
+
list.clientHeight / 2;
|
|
247
268
|
}
|
|
248
269
|
}, [selectedIndex, queryKey]);
|
|
249
270
|
const choose = (index) => {
|
|
@@ -464,6 +485,12 @@ export function MathEditor({ preferences: suppliedPreferences, apiRef, autoFocus
|
|
|
464
485
|
return;
|
|
465
486
|
const source = event.clipboardData.getData(MATH_CLIPBOARD_TYPE);
|
|
466
487
|
const fragment = source ? parseFragment(source) : undefined;
|
|
488
|
+
if (source && !fragment) {
|
|
489
|
+
event.preventDefault();
|
|
490
|
+
event.stopPropagation();
|
|
491
|
+
setClipboardMessage('clipboard.invalid');
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
467
494
|
const text = event.clipboardData.getData('text/plain');
|
|
468
495
|
const matrixSource = event.clipboardData.getData(MATH_MATRIX_CLIPBOARD_TYPE);
|
|
469
496
|
const cells = matrixSource ? parseMatrixFragment(matrixSource) : matrixFromTSV(text);
|
|
@@ -510,6 +537,10 @@ export function MathEditor({ preferences: suppliedPreferences, apiRef, autoFocus
|
|
|
510
537
|
.split('\n')
|
|
511
538
|
.map((value) => row(value)),
|
|
512
539
|
};
|
|
540
|
+
if (!multiline && payload.rows.length > 1) {
|
|
541
|
+
setClipboardMessage('clipboard.multilineRejected');
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
513
544
|
const next = pasteFragment(historyRef.current.present, payload, range);
|
|
514
545
|
if (next === historyRef.current.present) {
|
|
515
546
|
setClipboardMessage('clipboard.multilineRejected');
|
|
@@ -555,6 +586,35 @@ export function MathEditor({ preferences: suppliedPreferences, apiRef, autoFocus
|
|
|
555
586
|
}
|
|
556
587
|
return false;
|
|
557
588
|
};
|
|
589
|
+
const tokenNavigation = (event) => {
|
|
590
|
+
if (compositionStart.current ||
|
|
591
|
+
event.nativeEvent.isComposing ||
|
|
592
|
+
matrixRange ||
|
|
593
|
+
!isTokenNavigationKey(event, event.currentTarget.ownerDocument.defaultView.navigator.platform))
|
|
594
|
+
return false;
|
|
595
|
+
event.preventDefault();
|
|
596
|
+
event.stopPropagation();
|
|
597
|
+
verticalNavigation.current.reset();
|
|
598
|
+
const state = historyRef.current.present;
|
|
599
|
+
const selection = range ??
|
|
600
|
+
(state.caret.start !== state.caret.end
|
|
601
|
+
? {
|
|
602
|
+
anchor: { id: state.caret.id, offset: state.caret.start },
|
|
603
|
+
focus: { id: state.caret.id, offset: state.caret.end },
|
|
604
|
+
}
|
|
605
|
+
: undefined);
|
|
606
|
+
if (event.shiftKey) {
|
|
607
|
+
setRange(extendKeyboardRange(state, selection, event.key, 'token'));
|
|
608
|
+
setEditing(false);
|
|
609
|
+
surface.current?.focus();
|
|
610
|
+
}
|
|
611
|
+
else {
|
|
612
|
+
const point = collapseKeyboardRange(state.document, selection, event.key) ??
|
|
613
|
+
extendKeyboardRange(state, undefined, event.key, 'token').focus;
|
|
614
|
+
activate({ ...point, affinity: event.key === 'ArrowLeft' ? 'forward' : 'backward' });
|
|
615
|
+
}
|
|
616
|
+
return true;
|
|
617
|
+
};
|
|
558
618
|
const keyboardSelect = (event) => {
|
|
559
619
|
if (!event.shiftKey ||
|
|
560
620
|
event.altKey ||
|
|
@@ -568,10 +628,26 @@ export function MathEditor({ preferences: suppliedPreferences, apiRef, autoFocus
|
|
|
568
628
|
surface.current?.focus();
|
|
569
629
|
return true;
|
|
570
630
|
};
|
|
631
|
+
const directSelectionKey = (event) => {
|
|
632
|
+
if (compositionStart.current || event.nativeEvent.isComposing)
|
|
633
|
+
return false;
|
|
634
|
+
const current = historyRef.current.present;
|
|
635
|
+
const next = wrapSelectionShortcut(current, range, event);
|
|
636
|
+
if (!next)
|
|
637
|
+
return false;
|
|
638
|
+
event.preventDefault();
|
|
639
|
+
event.stopPropagation();
|
|
640
|
+
if (next !== current)
|
|
641
|
+
apply(next);
|
|
642
|
+
return true;
|
|
643
|
+
};
|
|
571
644
|
const selectionKey = (event) => {
|
|
572
645
|
if (event.target instanceof HTMLInputElement || compositionStart.current)
|
|
573
646
|
return;
|
|
574
|
-
if (matrixSelectionKey(event) ||
|
|
647
|
+
if (matrixSelectionKey(event) ||
|
|
648
|
+
tokenNavigation(event) ||
|
|
649
|
+
keyboardSelect(event) ||
|
|
650
|
+
directSelectionKey(event))
|
|
575
651
|
return;
|
|
576
652
|
const current = historyRef.current.present, nodes = textNodes(current.document);
|
|
577
653
|
if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === 'a') {
|
|
@@ -631,13 +707,13 @@ export function MathEditor({ preferences: suppliedPreferences, apiRef, autoFocus
|
|
|
631
707
|
};
|
|
632
708
|
const selectedRange = matrixRange
|
|
633
709
|
? undefined
|
|
634
|
-
: range ??
|
|
710
|
+
: (range ??
|
|
635
711
|
(state.caret.start !== state.caret.end
|
|
636
712
|
? {
|
|
637
713
|
anchor: { id: state.caret.id, offset: state.caret.start },
|
|
638
714
|
focus: { id: state.caret.id, offset: state.caret.end },
|
|
639
715
|
}
|
|
640
|
-
: undefined);
|
|
716
|
+
: undefined));
|
|
641
717
|
const selectionFragment = selectedRange ? copyRange(state.document, selectedRange) : undefined;
|
|
642
718
|
const canWrap = selectionFragment?.rows.length === 1 &&
|
|
643
719
|
!isLiteralText(state.document, selectedRange.anchor.id);
|
|
@@ -705,10 +781,9 @@ export function MathEditor({ preferences: suppliedPreferences, apiRef, autoFocus
|
|
|
705
781
|
if (!list || !option)
|
|
706
782
|
return;
|
|
707
783
|
const item = option.getBoundingClientRect(), box = list.getBoundingClientRect();
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
list.scrollTop += item.bottom - box.bottom;
|
|
784
|
+
const scaleY = box.height / list.offsetHeight || 1;
|
|
785
|
+
list.scrollTop +=
|
|
786
|
+
(item.top + item.height / 2 - box.top) / scaleY - list.clientTop - list.clientHeight / 2;
|
|
712
787
|
}, [selectionIndex]);
|
|
713
788
|
const insertTool = (kind) => {
|
|
714
789
|
if (excludedStructures.includes(kind) || matrixRange)
|
|
@@ -859,7 +934,13 @@ export function MathEditor({ preferences: suppliedPreferences, apiRef, autoFocus
|
|
|
859
934
|
compositionStart.current ||
|
|
860
935
|
event.keyCode === 229)
|
|
861
936
|
return;
|
|
862
|
-
|
|
937
|
+
// A held arrow can reach this handler before React emits onSelect.
|
|
938
|
+
// Boundary navigation must use the input's current native selection.
|
|
939
|
+
select(caretFrom(event.currentTarget));
|
|
940
|
+
if (matrixSelectionKey(event) ||
|
|
941
|
+
tokenNavigation(event) ||
|
|
942
|
+
keyboardSelect(event) ||
|
|
943
|
+
directSelectionKey(event))
|
|
863
944
|
return;
|
|
864
945
|
const current = historyRef.current.present;
|
|
865
946
|
if (!event.shiftKey &&
|
|
@@ -917,7 +998,7 @@ export function MathEditor({ preferences: suppliedPreferences, apiRef, autoFocus
|
|
|
917
998
|
!event.ctrlKey &&
|
|
918
999
|
!event.metaKey &&
|
|
919
1000
|
activeGrid(current) &&
|
|
920
|
-
['ArrowUp', '
|
|
1001
|
+
['ArrowUp', 'Backspace'].includes(event.key)) {
|
|
921
1002
|
event.preventDefault();
|
|
922
1003
|
apply(resizeMatrix(current, event.key === 'ArrowUp' ? 'row' : 'column', 'delete'));
|
|
923
1004
|
return;
|
|
@@ -974,28 +1055,27 @@ export function MathEditor({ preferences: suppliedPreferences, apiRef, autoFocus
|
|
|
974
1055
|
candidates.length);
|
|
975
1056
|
return;
|
|
976
1057
|
}
|
|
977
|
-
if (event.key === 'Enter' &&
|
|
978
|
-
candidates.length &&
|
|
979
|
-
((!candidates[0].wrapOperand &&
|
|
980
|
-
!candidates[0].transformRootId &&
|
|
981
|
-
!candidates[0].transformFenceId) ||
|
|
982
|
-
operandMenuKey.current === queryKey)) {
|
|
983
|
-
event.preventDefault();
|
|
984
|
-
choose(selectedIndex);
|
|
985
|
-
return;
|
|
986
|
-
}
|
|
987
1058
|
if (event.key === 'Enter') {
|
|
988
1059
|
event.preventDefault();
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
1060
|
+
const action = mathEnterAction({
|
|
1061
|
+
mode: multiline ? 'block' : 'inline',
|
|
1062
|
+
behavior: enterBehavior,
|
|
1063
|
+
shiftKey: event.shiftKey,
|
|
1064
|
+
gridKind: activeGrid(current)?.matrix.type,
|
|
1065
|
+
hasSuggestion: candidates.length > 0 &&
|
|
1066
|
+
((!candidates[0].wrapOperand &&
|
|
1067
|
+
!candidates[0].transformRootId &&
|
|
1068
|
+
!candidates[0].transformFenceId) ||
|
|
1069
|
+
operandMenuKey.current === queryKey),
|
|
1070
|
+
});
|
|
1071
|
+
if (action === 'suggestion')
|
|
1072
|
+
choose(selectedIndex);
|
|
1073
|
+
else if (action === 'grid-row')
|
|
1074
|
+
apply(resizeMatrix(current, 'row', 'insert'));
|
|
1075
|
+
else if (action === 'newline')
|
|
998
1076
|
apply(splitLine(current));
|
|
1077
|
+
else if (action === 'commit')
|
|
1078
|
+
onCommit?.();
|
|
999
1079
|
return;
|
|
1000
1080
|
}
|
|
1001
1081
|
if (event.key === 'Escape') {
|
|
@@ -1013,7 +1093,7 @@ export function MathEditor({ preferences: suppliedPreferences, apiRef, autoFocus
|
|
|
1013
1093
|
if (!event.shiftKey &&
|
|
1014
1094
|
current.caret.start === current.caret.end &&
|
|
1015
1095
|
['ArrowUp', 'ArrowDown'].includes(event.key)) {
|
|
1016
|
-
const next =
|
|
1096
|
+
const next = verticalNavigation.current.move(current, event.key === 'ArrowUp' ? -1 : 1, surface.current ? renderedCaretGeometry(surface.current) : undefined);
|
|
1017
1097
|
if (next !== current) {
|
|
1018
1098
|
event.preventDefault();
|
|
1019
1099
|
publish({ ...historyRef.current, present: next }, true);
|
|
@@ -1051,6 +1131,14 @@ export function MathEditor({ preferences: suppliedPreferences, apiRef, autoFocus
|
|
|
1051
1131
|
apply(setText(current, node.text.slice(0, token.end) + node.text.slice(token.end + count), token.end));
|
|
1052
1132
|
return;
|
|
1053
1133
|
}
|
|
1134
|
+
if (event.key === 'Delete' && current.caret.end === node.text.length) {
|
|
1135
|
+
const joined = joinNextLine(current);
|
|
1136
|
+
const next = joined !== current ? joined : unwrapNext(current);
|
|
1137
|
+
if (next !== current) {
|
|
1138
|
+
event.preventDefault();
|
|
1139
|
+
apply(next);
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1054
1142
|
if (event.key === 'Backspace' && current.caret.start === 0) {
|
|
1055
1143
|
const joined = joinPreviousLine(current);
|
|
1056
1144
|
const next = joined !== current ? joined : unwrapPrevious(current);
|
|
@@ -1063,7 +1151,15 @@ export function MathEditor({ preferences: suppliedPreferences, apiRef, autoFocus
|
|
|
1063
1151
|
});
|
|
1064
1152
|
}) }, r.id));
|
|
1065
1153
|
};
|
|
1066
|
-
return (_jsxs("div", { className: "me-editor", "data-math-editor-owner": suggestionId, onKeyDownCapture: (event) => {
|
|
1154
|
+
return (_jsxs("div", { className: "me-editor", "data-math-editor-owner": suggestionId, onPointerDownCapture: () => verticalNavigation.current.reset(), onKeyDownCapture: (event) => {
|
|
1155
|
+
if (event.target.closest('.me-help'))
|
|
1156
|
+
return;
|
|
1157
|
+
if (!['ArrowUp', 'ArrowDown', 'Escape'].includes(event.key) ||
|
|
1158
|
+
event.shiftKey ||
|
|
1159
|
+
event.altKey ||
|
|
1160
|
+
event.ctrlKey ||
|
|
1161
|
+
event.metaKey)
|
|
1162
|
+
verticalNavigation.current.reset();
|
|
1067
1163
|
if (event.key === 'F6' &&
|
|
1068
1164
|
structureContext &&
|
|
1069
1165
|
!composing &&
|
|
@@ -1179,7 +1275,7 @@ export function MathEditor({ preferences: suppliedPreferences, apiRef, autoFocus
|
|
|
1179
1275
|
: undefined, "aria-keyshortcuts": action === 'delete'
|
|
1180
1276
|
? axis === 'row'
|
|
1181
1277
|
? 'Alt+Shift+ArrowUp'
|
|
1182
|
-
: 'Alt+Shift+
|
|
1278
|
+
: 'Alt+Shift+Backspace'
|
|
1183
1279
|
: undefined, disabled: composing ||
|
|
1184
1280
|
!!matrixRange ||
|
|
1185
1281
|
!!range ||
|
package/dist/model.d.ts
CHANGED
|
@@ -70,6 +70,8 @@ export declare function moveCaret(state: MathState, direction: -1 | 1): MathStat
|
|
|
70
70
|
export declare function unwrapEmptySlot(state: MathState): MathState;
|
|
71
71
|
/** At the right edge of a structure, unwrap it instead of silently deleting its contents. */
|
|
72
72
|
export declare function unwrapPrevious(state: MathState): MathState;
|
|
73
|
+
/** Delete before a structure unwraps it and keeps the caret before its retained contents. */
|
|
74
|
+
export declare function unwrapNext(state: MathState): MathState;
|
|
73
75
|
export declare function toLatex(document: MathDocument): string;
|
|
74
76
|
export interface MathHistory {
|
|
75
77
|
past: MathState[];
|
package/dist/model.js
CHANGED
|
@@ -81,7 +81,7 @@ const escapeLiteral = (text) => text.replace(/[\\{}_%$#&^~]/g, (char) => ({
|
|
|
81
81
|
'\\': '\\textbackslash{}',
|
|
82
82
|
'^': '\\textasciicircum{}',
|
|
83
83
|
'~': '\\textasciitilde{}',
|
|
84
|
-
}[char] ?? `\\${char}`)
|
|
84
|
+
})[char] ?? `\\${char}`);
|
|
85
85
|
/** Wrap the selection, or the preceding simple operand; never swallow a preceding + or =. */
|
|
86
86
|
export function insertStructure(state, kind, consumeOperand = false, mathStyle) {
|
|
87
87
|
if (isLiteralText(state.document, state.caret.id))
|
|
@@ -339,6 +339,28 @@ export function unwrapPrevious(state) {
|
|
|
339
339
|
const offset = target.text.length - current.text.length;
|
|
340
340
|
return { document, caret: { id: target.id, start: offset, end: offset } };
|
|
341
341
|
}
|
|
342
|
+
/** Delete before a structure unwraps it and keeps the caret before its retained contents. */
|
|
343
|
+
export function unwrapNext(state) {
|
|
344
|
+
if (state.caret.start !== state.caret.end)
|
|
345
|
+
return state;
|
|
346
|
+
const at = documentRows(state.document)
|
|
347
|
+
.map((line) => locate(line, state.caret.id))
|
|
348
|
+
.find(Boolean);
|
|
349
|
+
if (!at)
|
|
350
|
+
return state;
|
|
351
|
+
const current = at.row.children[at.index];
|
|
352
|
+
const structure = at.row.children[at.index + 1];
|
|
353
|
+
const after = at.row.children[at.index + 2];
|
|
354
|
+
if (current.type !== 'text' ||
|
|
355
|
+
state.caret.end !== current.text.length ||
|
|
356
|
+
!structure ||
|
|
357
|
+
structure.type === 'text' ||
|
|
358
|
+
isGrid(structure) ||
|
|
359
|
+
after?.type !== 'text')
|
|
360
|
+
return state;
|
|
361
|
+
const next = unwrapPrevious({ ...state, caret: { id: after.id, start: 0, end: 0 } });
|
|
362
|
+
return next.document === state.document ? state : { ...next, caret: { ...state.caret } };
|
|
363
|
+
}
|
|
342
364
|
const symbols = Object.fromEntries(mathSymbols
|
|
343
365
|
.filter(([value, , , , latex]) => value !== latex)
|
|
344
366
|
.map(([value, , , , latex]) => [value, `${latex} `]));
|
package/dist/range.d.ts
CHANGED
|
@@ -28,6 +28,14 @@ export declare function parseFragment(source: string): MathFragment | undefined;
|
|
|
28
28
|
export declare const wrappingKinds: readonly ["bold", "calligraphic", "blackboard", "fraction", "binomial", "root", "vec", "hat", "tilde", "bar", "dot", "ddot", "widehat", "widetilde", "overline", "indexedRoot", "norm", "braces", "angle", "openClosed", "closedOpen", "overbrace", "underbrace", "overset", "underset", "superscript", "subscript", "parentheses", "brackets", "absolute"];
|
|
29
29
|
export type WrappingKind = (typeof wrappingKinds)[number];
|
|
30
30
|
/** Wrap one balanced row. Cross-slot ranges expand to their common structure. */
|
|
31
|
-
export declare function wrapRange(state: MathState, range: MathRange, kind: WrappingKind): MathState;
|
|
31
|
+
export declare function wrapRange(state: MathState, range: MathRange, kind: WrappingKind, fractionSlot?: 'numerator' | 'denominator'): MathState;
|
|
32
32
|
/** Keyboard ranges share drag-selection normalization. Cross a structure as one atom. */
|
|
33
|
-
export declare function extendKeyboardRange(state: MathState, range: MathRange | undefined, key: string): MathRange;
|
|
33
|
+
export declare function extendKeyboardRange(state: MathState, range: MathRange | undefined, key: string, unit?: 'character' | 'token'): MathRange;
|
|
34
|
+
/** Match host-platform word movement without taking AltGr or OS shortcuts. */
|
|
35
|
+
export declare function isTokenNavigationKey(event: {
|
|
36
|
+
key: string;
|
|
37
|
+
altKey: boolean;
|
|
38
|
+
ctrlKey: boolean;
|
|
39
|
+
metaKey: boolean;
|
|
40
|
+
isComposing?: boolean;
|
|
41
|
+
}, platform: string): boolean;
|
package/dist/range.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { tokenizeMathText } from './tokens.js';
|
|
1
2
|
import { fenceCharacters } from './fences.js';
|
|
2
3
|
import { documentRows, isLiteralText, row, textNode, textNodes, } from './model.js';
|
|
3
4
|
const size = (node) => (node.type === 'text' ? node.text.length : 1);
|
|
@@ -353,7 +354,7 @@ export const wrappingKinds = [
|
|
|
353
354
|
'absolute',
|
|
354
355
|
];
|
|
355
356
|
/** Wrap one balanced row. Cross-slot ranges expand to their common structure. */
|
|
356
|
-
export function wrapRange(state, range, kind) {
|
|
357
|
+
export function wrapRange(state, range, kind, fractionSlot = 'numerator') {
|
|
357
358
|
if (isLiteralText(state.document, range.anchor.id))
|
|
358
359
|
return state;
|
|
359
360
|
const fragment = copyRange(state.document, range);
|
|
@@ -367,7 +368,8 @@ export function wrapRange(state, range, kind) {
|
|
|
367
368
|
: ['parentheses', 'brackets', 'absolute', 'root', 'matrix'].includes(meaningful[0].type));
|
|
368
369
|
if (kind === 'superscript' && !grouped)
|
|
369
370
|
content = normalize([{ type: 'parentheses', id: row().id, slots: [content] }]);
|
|
370
|
-
const
|
|
371
|
+
const denominator = kind === 'fraction' && fractionSlot === 'denominator';
|
|
372
|
+
const slots = denominator || ['indexedRoot', 'overset', 'underset', 'overbrace', 'underbrace'].includes(kind)
|
|
371
373
|
? [row(), content]
|
|
372
374
|
: ['fraction', 'binomial', 'superscript', 'subscript'].includes(kind)
|
|
373
375
|
? [content, row()]
|
|
@@ -390,11 +392,14 @@ export function wrapRange(state, range, kind) {
|
|
|
390
392
|
const wrapper = location?.row.children[location.index - 1];
|
|
391
393
|
if (!wrapper || wrapper.type === 'text')
|
|
392
394
|
return next;
|
|
393
|
-
const target = wrapper.slots[
|
|
395
|
+
const target = wrapper.slots[denominator ||
|
|
396
|
+
['indexedRoot', 'overset', 'underset', 'overbrace', 'underbrace'].includes(kind)
|
|
397
|
+
? 0
|
|
398
|
+
: 1].children[0];
|
|
394
399
|
return { ...next, caret: { id: target.id, start: 0, end: 0 } };
|
|
395
400
|
}
|
|
396
401
|
/** Keyboard ranges share drag-selection normalization. Cross a structure as one atom. */
|
|
397
|
-
export function extendKeyboardRange(state, range, key) {
|
|
402
|
+
export function extendKeyboardRange(state, range, key, unit = 'character') {
|
|
398
403
|
const anchor = range?.anchor ?? { id: state.caret.id, offset: state.caret.start };
|
|
399
404
|
const point = range?.focus ?? { id: state.caret.id, offset: state.caret.end };
|
|
400
405
|
const at = address(state.document, point);
|
|
@@ -414,11 +419,20 @@ export function extendKeyboardRange(state, range, key) {
|
|
|
414
419
|
const node = local.row.children[local.index];
|
|
415
420
|
if (node.type !== 'text')
|
|
416
421
|
return { anchor, focus: point };
|
|
422
|
+
if (unit === 'token') {
|
|
423
|
+
const tokens = tokenizeMathText(node.text).filter((token) => token.kind !== 'space');
|
|
424
|
+
const token = direction < 0
|
|
425
|
+
? tokens.reverse().find((token) => token.start < point.offset)
|
|
426
|
+
: tokens.find((token) => token.end > point.offset);
|
|
427
|
+
if (token)
|
|
428
|
+
return { anchor, focus: { id: point.id, offset: direction < 0 ? token.start : token.end } };
|
|
429
|
+
// Skip remaining whitespace before crossing a structure or leaving this slot.
|
|
430
|
+
}
|
|
417
431
|
const chars = direction < 0
|
|
418
432
|
? Array.from(node.text.slice(0, point.offset))
|
|
419
433
|
: Array.from(node.text.slice(point.offset));
|
|
420
434
|
const char = direction < 0 ? chars.at(-1) : chars[0];
|
|
421
|
-
if (char)
|
|
435
|
+
if (char && unit === 'character')
|
|
422
436
|
return { anchor, focus: { id: point.id, offset: point.offset + direction * char.length } };
|
|
423
437
|
// A sibling structure is skipped intact; leaving a nested slot selects its enclosing structure.
|
|
424
438
|
for (let depth = at.path.length - 1; depth >= 0; depth--) {
|
|
@@ -434,8 +448,19 @@ export function extendKeyboardRange(state, range, key) {
|
|
|
434
448
|
}
|
|
435
449
|
const line = documentRows(state.document)[at.line + direction];
|
|
436
450
|
if (!line)
|
|
437
|
-
return {
|
|
451
|
+
return {
|
|
452
|
+
anchor,
|
|
453
|
+
focus: unit === 'token' ? { id: point.id, offset: direction < 0 ? 0 : node.text.length } : point,
|
|
454
|
+
};
|
|
438
455
|
const nodes = textNodes({ version: 1, root: line });
|
|
439
456
|
const target = direction < 0 ? nodes.at(-1) : nodes[0];
|
|
440
457
|
return { anchor, focus: { id: target.id, offset: direction < 0 ? target.text.length : 0 } };
|
|
441
458
|
}
|
|
459
|
+
/** Match host-platform word movement without taking AltGr or OS shortcuts. */
|
|
460
|
+
export function isTokenNavigationKey(event, platform) {
|
|
461
|
+
if (event.isComposing || event.metaKey || !['ArrowLeft', 'ArrowRight'].includes(event.key))
|
|
462
|
+
return false;
|
|
463
|
+
return /Mac|iPhone|iPad|iPod/.test(platform)
|
|
464
|
+
? event.altKey && !event.ctrlKey
|
|
465
|
+
: event.ctrlKey && !event.altKey;
|
|
466
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { MathState } from './model.js';
|
|
2
|
+
import { type MathRange } from './range.js';
|
|
3
|
+
/** A typed opening symbol wraps a selection before ordinary replacement runs.
|
|
4
|
+
* Shift is allowed because several symbols require it on common keyboards.
|
|
5
|
+
* Returning the original state consumes unsupported multi-line wrapping safely.
|
|
6
|
+
*/
|
|
7
|
+
export declare function wrapSelectionShortcut(state: MathState, range: MathRange | undefined, event: {
|
|
8
|
+
key: string;
|
|
9
|
+
ctrlKey?: boolean;
|
|
10
|
+
metaKey?: boolean;
|
|
11
|
+
altKey?: boolean;
|
|
12
|
+
isComposing?: boolean;
|
|
13
|
+
}): MathState | undefined;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { isLiteralText } from './model.js';
|
|
2
|
+
import { wrapRange } from './range.js';
|
|
3
|
+
const wrappers = {
|
|
4
|
+
'(': 'parentheses',
|
|
5
|
+
'[': 'brackets',
|
|
6
|
+
'{': 'braces',
|
|
7
|
+
'|': 'absolute',
|
|
8
|
+
'/': 'fraction',
|
|
9
|
+
'^': 'superscript',
|
|
10
|
+
_: 'subscript',
|
|
11
|
+
};
|
|
12
|
+
/** A typed opening symbol wraps a selection before ordinary replacement runs.
|
|
13
|
+
* Shift is allowed because several symbols require it on common keyboards.
|
|
14
|
+
* Returning the original state consumes unsupported multi-line wrapping safely.
|
|
15
|
+
*/
|
|
16
|
+
export function wrapSelectionShortcut(state, range, event) {
|
|
17
|
+
if (event.ctrlKey || event.metaKey || event.altKey || event.isComposing)
|
|
18
|
+
return;
|
|
19
|
+
const kind = wrappers[event.key];
|
|
20
|
+
if (!kind)
|
|
21
|
+
return;
|
|
22
|
+
const selection = range ??
|
|
23
|
+
(state.caret.start !== state.caret.end
|
|
24
|
+
? {
|
|
25
|
+
anchor: { id: state.caret.id, offset: state.caret.start },
|
|
26
|
+
focus: { id: state.caret.id, offset: state.caret.end },
|
|
27
|
+
}
|
|
28
|
+
: undefined);
|
|
29
|
+
if (!selection ||
|
|
30
|
+
(selection.anchor.id === selection.focus.id &&
|
|
31
|
+
selection.anchor.offset === selection.focus.offset) ||
|
|
32
|
+
isLiteralText(state.document, selection.anchor.id))
|
|
33
|
+
return;
|
|
34
|
+
return wrapRange(state, selection, kind);
|
|
35
|
+
}
|
package/dist/session.d.ts
CHANGED
package/dist/session.js
CHANGED
|
@@ -215,7 +215,7 @@ export function createMathSession(options = {}) {
|
|
|
215
215
|
return mode === 'inline' ? false : apply(splitLine(state));
|
|
216
216
|
if (range)
|
|
217
217
|
return (wrappingKinds.includes(command.kind) &&
|
|
218
|
-
apply(wrapRange(state, range, command.kind)));
|
|
218
|
+
apply(wrapRange(state, range, command.kind, command.fractionSlot)));
|
|
219
219
|
return apply(insertStructure(state, command.kind, ['fraction', 'binomial', 'superscript', 'subscript'].includes(command.kind)));
|
|
220
220
|
},
|
|
221
221
|
destroy() {
|
package/dist/symbols.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** One catalog powers discovery and LaTeX export. */
|
|
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"]];
|
|
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.prime", "prime 프라임 미분", "", "\\prime"], 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"]];
|
package/dist/symbols.js
CHANGED
|
@@ -70,6 +70,7 @@ export const mathSymbols = [
|
|
|
70
70
|
['⋯', 'symbol.centeredDots', 'cdots', '', '\\cdots'],
|
|
71
71
|
['⋮', 'symbol.verticalDots', 'vdots', '', '\\vdots'],
|
|
72
72
|
['⋱', 'symbol.diagonalDots', 'ddots', '', '\\ddots'],
|
|
73
|
+
['′', 'symbol.prime', 'prime 프라임 미분', '', '\\prime'],
|
|
73
74
|
['°', 'symbol.degree', 'degree degrees 각도', '', '{}^{\\circ}'],
|
|
74
75
|
['∠', 'symbol.angle', 'angle', '', '\\angle'],
|
|
75
76
|
['+', 'symbol.plus', 'plus sum', '+', '+'],
|