@drghaliasri/butex 5.4.6 → 5.5.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/README.md +3 -2
- package/dist/document.js +2 -1
- package/dist/document.js.map +1 -1
- package/dist/document.mjs +2 -1
- package/dist/document.mjs.map +1 -1
- package/dist/document2.d.mts +20 -2
- package/dist/document2.d.ts +20 -2
- package/dist/document2.js +184 -22
- package/dist/document2.js.map +1 -1
- package/dist/document2.mjs +183 -22
- package/dist/document2.mjs.map +1 -1
- package/dist/index.d.mts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.global.js +137 -37
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +137 -37
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +137 -37
- package/dist/index.mjs.map +1 -1
- package/dist/react-document.js +171 -39
- package/dist/react-document.js.map +1 -1
- package/dist/react-document.mjs +171 -39
- package/dist/react-document.mjs.map +1 -1
- package/dist/react-document2.d.mts +23 -3
- package/dist/react-document2.d.ts +23 -3
- package/dist/react-document2.js +690 -95
- package/dist/react-document2.js.map +1 -1
- package/dist/react-document2.mjs +736 -141
- package/dist/react-document2.mjs.map +1 -1
- package/dist/react.d.mts +1 -0
- package/dist/react.d.ts +1 -0
- package/dist/react.js +171 -39
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +171 -39
- package/dist/react.mjs.map +1 -1
- package/package.json +1 -1
package/dist/react-document2.mjs
CHANGED
|
@@ -1133,7 +1133,7 @@ function parseReferences(json) {
|
|
|
1133
1133
|
}
|
|
1134
1134
|
return references;
|
|
1135
1135
|
}
|
|
1136
|
-
function createInlineField2(value = "", mathObjects = [], options = {}, path = "$", diagnostics = []) {
|
|
1136
|
+
function createInlineField2(value = "", mathObjects = [], options = {}, path = "$", diagnostics = [], formats = []) {
|
|
1137
1137
|
const mode = options.mode ?? "english";
|
|
1138
1138
|
const spans = detectInlineSpans2(value);
|
|
1139
1139
|
const mathSpans = spans.filter((span) => span.kind === "math");
|
|
@@ -1145,7 +1145,7 @@ function createInlineField2(value = "", mathObjects = [], options = {}, path = "
|
|
|
1145
1145
|
}
|
|
1146
1146
|
for (const span of spans) {
|
|
1147
1147
|
if (span.start > index) {
|
|
1148
|
-
tokens
|
|
1148
|
+
pushFormattedTextTokens(tokens, value.slice(index, span.start), index, formats);
|
|
1149
1149
|
}
|
|
1150
1150
|
if (span.kind === "cite") {
|
|
1151
1151
|
tokens.push({
|
|
@@ -1201,9 +1201,81 @@ function createInlineField2(value = "", mathObjects = [], options = {}, path = "
|
|
|
1201
1201
|
index = span.end;
|
|
1202
1202
|
}
|
|
1203
1203
|
if (index < value.length || tokens.length === 0) {
|
|
1204
|
-
tokens
|
|
1204
|
+
pushFormattedTextTokens(tokens, value.slice(index), index, formats);
|
|
1205
|
+
}
|
|
1206
|
+
return { id: document2Id("field"), tokens: compactTextTokens(tokens) };
|
|
1207
|
+
}
|
|
1208
|
+
function styleFromFormat(format) {
|
|
1209
|
+
const style = {};
|
|
1210
|
+
if (format.bold === true) {
|
|
1211
|
+
style.bold = true;
|
|
1212
|
+
}
|
|
1213
|
+
if (format.italic === true) {
|
|
1214
|
+
style.italic = true;
|
|
1215
|
+
}
|
|
1216
|
+
if (format.underline === true) {
|
|
1217
|
+
style.underline = true;
|
|
1218
|
+
}
|
|
1219
|
+
return style.bold || style.italic || style.underline ? style : null;
|
|
1220
|
+
}
|
|
1221
|
+
function mergeTextStyle(base, added) {
|
|
1222
|
+
return {
|
|
1223
|
+
...base?.bold ? { bold: true } : {},
|
|
1224
|
+
...base?.italic ? { italic: true } : {},
|
|
1225
|
+
...base?.underline ? { underline: true } : {},
|
|
1226
|
+
...added.bold ? { bold: true } : {},
|
|
1227
|
+
...added.italic ? { italic: true } : {},
|
|
1228
|
+
...added.underline ? { underline: true } : {}
|
|
1229
|
+
};
|
|
1230
|
+
}
|
|
1231
|
+
function textStylesEqual(a, b) {
|
|
1232
|
+
return Boolean(a?.bold) === Boolean(b?.bold) && Boolean(a?.italic) === Boolean(b?.italic) && Boolean(a?.underline) === Boolean(b?.underline);
|
|
1233
|
+
}
|
|
1234
|
+
function compactTextTokens(tokens) {
|
|
1235
|
+
const compacted = [];
|
|
1236
|
+
for (const token of tokens) {
|
|
1237
|
+
const previous = compacted[compacted.length - 1];
|
|
1238
|
+
if (previous?.kind === "text" && token.kind === "text" && textStylesEqual(previous.style, token.style)) {
|
|
1239
|
+
previous.text += token.text;
|
|
1240
|
+
} else {
|
|
1241
|
+
compacted.push(token);
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
return compacted;
|
|
1245
|
+
}
|
|
1246
|
+
function styleKey(style) {
|
|
1247
|
+
return `${style?.bold ? "b" : ""}${style?.italic ? "i" : ""}${style?.underline ? "u" : ""}`;
|
|
1248
|
+
}
|
|
1249
|
+
function pushFormattedTextTokens(tokens, text, sourceStart, formats) {
|
|
1250
|
+
if (text.length === 0) {
|
|
1251
|
+
tokens.push({ id: document2Id("text"), kind: "text", text });
|
|
1252
|
+
return;
|
|
1253
|
+
}
|
|
1254
|
+
const styles = Array.from({ length: text.length });
|
|
1255
|
+
for (const format of formats) {
|
|
1256
|
+
const style = styleFromFormat(format);
|
|
1257
|
+
if (!style || !Number.isFinite(format.start) || !Number.isFinite(format.end)) {
|
|
1258
|
+
continue;
|
|
1259
|
+
}
|
|
1260
|
+
const start = Math.max(0, Math.min(text.length, Math.trunc(format.start) - sourceStart));
|
|
1261
|
+
const end = Math.max(0, Math.min(text.length, Math.trunc(format.end) - sourceStart));
|
|
1262
|
+
if (end <= start) {
|
|
1263
|
+
continue;
|
|
1264
|
+
}
|
|
1265
|
+
for (let index = start; index < end; index += 1) {
|
|
1266
|
+
styles[index] = mergeTextStyle(styles[index], style);
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
let chunkStart = 0;
|
|
1270
|
+
for (let index = 1; index <= text.length; index += 1) {
|
|
1271
|
+
if (index < text.length && styleKey(styles[index]) === styleKey(styles[chunkStart])) {
|
|
1272
|
+
continue;
|
|
1273
|
+
}
|
|
1274
|
+
const chunk = text.slice(chunkStart, index);
|
|
1275
|
+
const style = styles[chunkStart];
|
|
1276
|
+
tokens.push({ id: document2Id("text"), kind: "text", text: chunk, ...style ? { style } : {} });
|
|
1277
|
+
chunkStart = index;
|
|
1205
1278
|
}
|
|
1206
|
-
return { id: document2Id("field"), tokens };
|
|
1207
1279
|
}
|
|
1208
1280
|
function closingForList(command) {
|
|
1209
1281
|
return command === "\\begin{itemize}" ? "\\end{itemize}" : "\\end{enumerate}";
|
|
@@ -1214,7 +1286,7 @@ function parseTextBlock(json, options, path, diagnostics) {
|
|
|
1214
1286
|
id: document2Id("block"),
|
|
1215
1287
|
kind: "textBlock",
|
|
1216
1288
|
command: json.command,
|
|
1217
|
-
field: createInlineField2(value, json.math_objects ?? [], options, `${path}.value`, diagnostics),
|
|
1289
|
+
field: createInlineField2(value, json.math_objects ?? [], options, `${path}.value`, diagnostics, json.command === "\\paragraph" ? json.formats ?? [] : []),
|
|
1218
1290
|
...json.centered === true ? { centered: true } : {}
|
|
1219
1291
|
};
|
|
1220
1292
|
}
|
|
@@ -1223,7 +1295,7 @@ function parseListItem(json, options, path, diagnostics) {
|
|
|
1223
1295
|
const blocksJson = Array.isArray(json.blocks) ? json.blocks : [];
|
|
1224
1296
|
return {
|
|
1225
1297
|
id: document2Id("item"),
|
|
1226
|
-
field: createInlineField2(value, json.math_objects ?? [], options, `${path}.value`, diagnostics),
|
|
1298
|
+
field: createInlineField2(value, json.math_objects ?? [], options, `${path}.value`, diagnostics, json.formats ?? []),
|
|
1227
1299
|
blocks: blocksJson.map((block, index) => parseBlock(asBlockJson(block), options, `${path}.blocks[${String(index)}]`, diagnostics))
|
|
1228
1300
|
};
|
|
1229
1301
|
}
|
|
@@ -1256,7 +1328,8 @@ function parseTableBlock(json, options, path, diagnostics) {
|
|
|
1256
1328
|
const spanCount = detectMathSpans2(value).length;
|
|
1257
1329
|
const cellMathObjects = mathObjects.slice(mathObjectIndex, mathObjectIndex + spanCount);
|
|
1258
1330
|
mathObjectIndex += spanCount;
|
|
1259
|
-
|
|
1331
|
+
const cellFormats = json.cell_formats?.[rowIndex]?.[columnIndex] ?? [];
|
|
1332
|
+
return createInlineField2(value, cellMathObjects, options, `${path}.rows[${String(rowIndex)}][${String(columnIndex)}]`, diagnostics, cellFormats);
|
|
1260
1333
|
});
|
|
1261
1334
|
});
|
|
1262
1335
|
if (mathObjects.length > 0 && mathObjects.length !== mathObjectIndex) {
|
|
@@ -6327,7 +6400,8 @@ ${BUTEX_FONT_FACE_CSS}
|
|
|
6327
6400
|
transition: box-shadow 0.15s ease, border-color 0.15s ease;
|
|
6328
6401
|
}
|
|
6329
6402
|
|
|
6330
|
-
.surface:focus
|
|
6403
|
+
.surface:focus,
|
|
6404
|
+
.surface.surface--typing-focus {
|
|
6331
6405
|
border-color: var(--butex-focus-border, rgba(13, 148, 136, 0.45));
|
|
6332
6406
|
box-shadow: 0 0 0 3px var(--butex-focus-shadow, rgba(13, 148, 136, 0.12));
|
|
6333
6407
|
}
|
|
@@ -6529,7 +6603,7 @@ function injectBuTeXEditorStyles(doc) {
|
|
|
6529
6603
|
|
|
6530
6604
|
// src/editor/runtime.ts
|
|
6531
6605
|
function createEditorRuntime(options) {
|
|
6532
|
-
const { surfaceEl } = options;
|
|
6606
|
+
const { surfaceEl, inputEl } = options;
|
|
6533
6607
|
const buttonElements = options.buttonElements ?? {};
|
|
6534
6608
|
const outsidePointerIgnoreSelectors = options.outsidePointerIgnoreSelectors ?? [];
|
|
6535
6609
|
let session = options.initialSession ?? createStarterSession();
|
|
@@ -6543,6 +6617,23 @@ function createEditorRuntime(options) {
|
|
|
6543
6617
|
let dragSelecting = false;
|
|
6544
6618
|
let dragChainId = null;
|
|
6545
6619
|
let dragChanged = false;
|
|
6620
|
+
let composingInput = false;
|
|
6621
|
+
let pendingCompositionText = null;
|
|
6622
|
+
function resetInputElement() {
|
|
6623
|
+
if (!inputEl) {
|
|
6624
|
+
return;
|
|
6625
|
+
}
|
|
6626
|
+
inputEl.value = "";
|
|
6627
|
+
}
|
|
6628
|
+
function focusInput() {
|
|
6629
|
+
if (!inputEl) {
|
|
6630
|
+
surfaceEl.focus();
|
|
6631
|
+
return;
|
|
6632
|
+
}
|
|
6633
|
+
inputEl.focus({ preventScroll: true });
|
|
6634
|
+
const end = inputEl.value.length;
|
|
6635
|
+
inputEl.setSelectionRange(end, end);
|
|
6636
|
+
}
|
|
6546
6637
|
function notifySessionChange() {
|
|
6547
6638
|
options.onSessionChange?.(session);
|
|
6548
6639
|
}
|
|
@@ -6807,7 +6898,7 @@ function createEditorRuntime(options) {
|
|
|
6807
6898
|
event.preventDefault();
|
|
6808
6899
|
event.stopPropagation();
|
|
6809
6900
|
startDragSelection(chainId, index);
|
|
6810
|
-
|
|
6901
|
+
focusInput();
|
|
6811
6902
|
});
|
|
6812
6903
|
slot.addEventListener("click", (event) => {
|
|
6813
6904
|
if (dragChanged) {
|
|
@@ -6817,7 +6908,7 @@ function createEditorRuntime(options) {
|
|
|
6817
6908
|
return;
|
|
6818
6909
|
}
|
|
6819
6910
|
applyTransient((prev) => setCaret(prev, chainId, index));
|
|
6820
|
-
|
|
6911
|
+
focusInput();
|
|
6821
6912
|
});
|
|
6822
6913
|
if (session.caret.chainId === chainId && session.caret.index === index) {
|
|
6823
6914
|
const caret = document.createElement("span");
|
|
@@ -6849,7 +6940,7 @@ function createEditorRuntime(options) {
|
|
|
6849
6940
|
event.preventDefault();
|
|
6850
6941
|
event.stopPropagation();
|
|
6851
6942
|
startDragSelection(chainId, indexInChain);
|
|
6852
|
-
|
|
6943
|
+
focusInput();
|
|
6853
6944
|
});
|
|
6854
6945
|
nodeEl.addEventListener("click", (event) => {
|
|
6855
6946
|
if (dragChanged) {
|
|
@@ -6860,7 +6951,7 @@ function createEditorRuntime(options) {
|
|
|
6860
6951
|
}
|
|
6861
6952
|
event.stopPropagation();
|
|
6862
6953
|
applyTransient((prev) => selectNode(prev, node.id));
|
|
6863
|
-
|
|
6954
|
+
focusInput();
|
|
6864
6955
|
});
|
|
6865
6956
|
const body = document.createElement("span");
|
|
6866
6957
|
body.className = "node-body";
|
|
@@ -6895,7 +6986,7 @@ function createEditorRuntime(options) {
|
|
|
6895
6986
|
const activeTree = session[activeTreeKey(session.activeSide)];
|
|
6896
6987
|
surfaceEl.appendChild(buildChain(activeTree));
|
|
6897
6988
|
if (initialKeyboardFocusPending) {
|
|
6898
|
-
requestAnimationFrame(
|
|
6989
|
+
requestAnimationFrame(focusInput);
|
|
6899
6990
|
initialKeyboardFocusPending = false;
|
|
6900
6991
|
}
|
|
6901
6992
|
notifySessionChange();
|
|
@@ -6933,7 +7024,7 @@ function createEditorRuntime(options) {
|
|
|
6933
7024
|
}
|
|
6934
7025
|
session = restored;
|
|
6935
7026
|
render();
|
|
6936
|
-
|
|
7027
|
+
focusInput();
|
|
6937
7028
|
}
|
|
6938
7029
|
function performRedo() {
|
|
6939
7030
|
const restored = restoreRedo(undoRedo, session);
|
|
@@ -6942,9 +7033,12 @@ function createEditorRuntime(options) {
|
|
|
6942
7033
|
}
|
|
6943
7034
|
session = restored;
|
|
6944
7035
|
render();
|
|
6945
|
-
|
|
7036
|
+
focusInput();
|
|
6946
7037
|
}
|
|
6947
7038
|
function onKeyDown(event) {
|
|
7039
|
+
if (event.isComposing || event.key === "Process" || event.keyCode === 229) {
|
|
7040
|
+
return;
|
|
7041
|
+
}
|
|
6948
7042
|
const shortcutMod = event.ctrlKey || event.metaKey;
|
|
6949
7043
|
const keyLower = typeof event.key === "string" ? event.key.toLowerCase() : "";
|
|
6950
7044
|
if (shortcutMod && !event.altKey && keyLower === "z") {
|
|
@@ -7043,6 +7137,70 @@ function createEditorRuntime(options) {
|
|
|
7043
7137
|
applyStructural((prev) => insertChar(prev, char));
|
|
7044
7138
|
}
|
|
7045
7139
|
}
|
|
7140
|
+
function onBeforeInput(event) {
|
|
7141
|
+
if (composingInput || event.isComposing) {
|
|
7142
|
+
return;
|
|
7143
|
+
}
|
|
7144
|
+
if (event.inputType === "deleteContentBackward") {
|
|
7145
|
+
event.preventDefault();
|
|
7146
|
+
applyStructural((prev) => deleteBackward(prev));
|
|
7147
|
+
resetInputElement();
|
|
7148
|
+
return;
|
|
7149
|
+
}
|
|
7150
|
+
if (event.inputType === "deleteContentForward") {
|
|
7151
|
+
event.preventDefault();
|
|
7152
|
+
applyStructural((prev) => deleteForward(prev));
|
|
7153
|
+
resetInputElement();
|
|
7154
|
+
}
|
|
7155
|
+
}
|
|
7156
|
+
function onInput(event) {
|
|
7157
|
+
if (!inputEl || composingInput) {
|
|
7158
|
+
return;
|
|
7159
|
+
}
|
|
7160
|
+
const inputEvent = event;
|
|
7161
|
+
const text = inputEvent.data ?? inputEl.value;
|
|
7162
|
+
resetInputElement();
|
|
7163
|
+
if (pendingCompositionText !== null && (inputEvent.inputType === "insertFromComposition" || text === pendingCompositionText)) {
|
|
7164
|
+
pendingCompositionText = null;
|
|
7165
|
+
return;
|
|
7166
|
+
}
|
|
7167
|
+
pendingCompositionText = null;
|
|
7168
|
+
if (inputEvent.inputType === "deleteContentBackward") {
|
|
7169
|
+
applyStructural((prev) => deleteBackward(prev));
|
|
7170
|
+
return;
|
|
7171
|
+
}
|
|
7172
|
+
if (inputEvent.inputType === "deleteContentForward") {
|
|
7173
|
+
applyStructural((prev) => deleteForward(prev));
|
|
7174
|
+
return;
|
|
7175
|
+
}
|
|
7176
|
+
if (text) {
|
|
7177
|
+
applyStructural((prev) => pasteText(prev, text));
|
|
7178
|
+
}
|
|
7179
|
+
}
|
|
7180
|
+
function onCompositionStart() {
|
|
7181
|
+
composingInput = true;
|
|
7182
|
+
}
|
|
7183
|
+
function onCompositionEnd(event) {
|
|
7184
|
+
if (!inputEl) {
|
|
7185
|
+
return;
|
|
7186
|
+
}
|
|
7187
|
+
composingInput = false;
|
|
7188
|
+
const text = event.data || inputEl.value;
|
|
7189
|
+
resetInputElement();
|
|
7190
|
+
if (text) {
|
|
7191
|
+
applyStructural((prev) => pasteText(prev, text));
|
|
7192
|
+
}
|
|
7193
|
+
pendingCompositionText = text || null;
|
|
7194
|
+
window.setTimeout(() => {
|
|
7195
|
+
pendingCompositionText = null;
|
|
7196
|
+
}, 0);
|
|
7197
|
+
}
|
|
7198
|
+
function onInputFocus() {
|
|
7199
|
+
surfaceEl.classList.add("surface--typing-focus");
|
|
7200
|
+
}
|
|
7201
|
+
function onInputBlur() {
|
|
7202
|
+
surfaceEl.classList.remove("surface--typing-focus");
|
|
7203
|
+
}
|
|
7046
7204
|
function isShortcutOnlyEvent(event) {
|
|
7047
7205
|
if (!(event.ctrlKey || event.metaKey) || event.altKey) {
|
|
7048
7206
|
return false;
|
|
@@ -7092,7 +7250,7 @@ function createEditorRuntime(options) {
|
|
|
7092
7250
|
}
|
|
7093
7251
|
event.preventDefault();
|
|
7094
7252
|
startDragSelection(resolved.chainId, resolved.slotIndex);
|
|
7095
|
-
|
|
7253
|
+
focusInput();
|
|
7096
7254
|
}
|
|
7097
7255
|
function onSurfaceClick(event) {
|
|
7098
7256
|
if (dragChanged) {
|
|
@@ -7109,7 +7267,7 @@ function createEditorRuntime(options) {
|
|
|
7109
7267
|
} else {
|
|
7110
7268
|
clearSelectionAndNodeHighlights();
|
|
7111
7269
|
}
|
|
7112
|
-
|
|
7270
|
+
focusInput();
|
|
7113
7271
|
}
|
|
7114
7272
|
function onDocumentPointerDown(event) {
|
|
7115
7273
|
const target = event.target;
|
|
@@ -7125,6 +7283,13 @@ function createEditorRuntime(options) {
|
|
|
7125
7283
|
clearSelectionAndNodeHighlights();
|
|
7126
7284
|
}
|
|
7127
7285
|
surfaceEl.addEventListener("keydown", onKeyDown);
|
|
7286
|
+
inputEl?.addEventListener("keydown", onKeyDown);
|
|
7287
|
+
inputEl?.addEventListener("beforeinput", onBeforeInput);
|
|
7288
|
+
inputEl?.addEventListener("input", onInput);
|
|
7289
|
+
inputEl?.addEventListener("compositionstart", onCompositionStart);
|
|
7290
|
+
inputEl?.addEventListener("compositionend", onCompositionEnd);
|
|
7291
|
+
inputEl?.addEventListener("focus", onInputFocus);
|
|
7292
|
+
inputEl?.addEventListener("blur", onInputBlur);
|
|
7128
7293
|
document.addEventListener("keydown", onDocumentKeyDown);
|
|
7129
7294
|
document.addEventListener("mouseup", endDragSelection);
|
|
7130
7295
|
document.addEventListener("mouseleave", endDragSelection);
|
|
@@ -7136,6 +7301,13 @@ function createEditorRuntime(options) {
|
|
|
7136
7301
|
render,
|
|
7137
7302
|
destroy: () => {
|
|
7138
7303
|
surfaceEl.removeEventListener("keydown", onKeyDown);
|
|
7304
|
+
inputEl?.removeEventListener("keydown", onKeyDown);
|
|
7305
|
+
inputEl?.removeEventListener("beforeinput", onBeforeInput);
|
|
7306
|
+
inputEl?.removeEventListener("input", onInput);
|
|
7307
|
+
inputEl?.removeEventListener("compositionstart", onCompositionStart);
|
|
7308
|
+
inputEl?.removeEventListener("compositionend", onCompositionEnd);
|
|
7309
|
+
inputEl?.removeEventListener("focus", onInputFocus);
|
|
7310
|
+
inputEl?.removeEventListener("blur", onInputBlur);
|
|
7139
7311
|
document.removeEventListener("keydown", onDocumentKeyDown);
|
|
7140
7312
|
document.removeEventListener("mouseup", endDragSelection);
|
|
7141
7313
|
document.removeEventListener("mouseleave", endDragSelection);
|
|
@@ -7156,6 +7328,7 @@ function createEditorRuntime(options) {
|
|
|
7156
7328
|
uiLocale = locale;
|
|
7157
7329
|
render();
|
|
7158
7330
|
},
|
|
7331
|
+
focusInput,
|
|
7159
7332
|
performUndo,
|
|
7160
7333
|
performRedo,
|
|
7161
7334
|
performCopy,
|
|
@@ -7163,27 +7336,27 @@ function createEditorRuntime(options) {
|
|
|
7163
7336
|
performPaste,
|
|
7164
7337
|
toggleSide: () => {
|
|
7165
7338
|
applyTransient((prev) => switchSide(prev));
|
|
7166
|
-
|
|
7339
|
+
focusInput();
|
|
7167
7340
|
},
|
|
7168
7341
|
toggleSplitLeafTyping: () => {
|
|
7169
7342
|
applyStructural((prev) => setSplitLeafTyping(prev, !prev.splitLeafTyping));
|
|
7170
|
-
|
|
7343
|
+
focusInput();
|
|
7171
7344
|
},
|
|
7172
7345
|
toggleArabicReverseNumberTyping: () => {
|
|
7173
7346
|
applyStructural((prev) => setArabicReverseNumberTyping(prev, !prev.arabicReverseNumberTyping));
|
|
7174
|
-
|
|
7347
|
+
focusInput();
|
|
7175
7348
|
},
|
|
7176
7349
|
toggleTakweenCharacterFont: () => {
|
|
7177
7350
|
applyTransient((prev) => toggleTakweenCharacterFont(prev));
|
|
7178
|
-
|
|
7351
|
+
focusInput();
|
|
7179
7352
|
},
|
|
7180
7353
|
setCurrentCharacterFont: (fontId) => {
|
|
7181
7354
|
applyTransient((prev) => setCurrentCharacterFont(prev, fontId));
|
|
7182
|
-
|
|
7355
|
+
focusInput();
|
|
7183
7356
|
},
|
|
7184
7357
|
setCurrentDigitForm: (digitForm) => {
|
|
7185
7358
|
applyStructural((prev) => setCurrentDigitForm(prev, digitForm));
|
|
7186
|
-
|
|
7359
|
+
focusInput();
|
|
7187
7360
|
},
|
|
7188
7361
|
insertDelimiterByKind: (kind) => {
|
|
7189
7362
|
if (kind === "paren") {
|
|
@@ -7193,79 +7366,79 @@ function createEditorRuntime(options) {
|
|
|
7193
7366
|
} else {
|
|
7194
7367
|
applyStructural((prev) => insertDelimiterPair(prev, "\\left\\{", "\\right\\}"));
|
|
7195
7368
|
}
|
|
7196
|
-
|
|
7369
|
+
focusInput();
|
|
7197
7370
|
},
|
|
7198
7371
|
insertFraction: () => {
|
|
7199
7372
|
applyStructural((prev) => insertFraction(prev));
|
|
7200
|
-
|
|
7373
|
+
focusInput();
|
|
7201
7374
|
},
|
|
7202
7375
|
insertFirstDerivative: () => {
|
|
7203
7376
|
applyStructural((prev) => insertFirstDerivative(prev));
|
|
7204
|
-
|
|
7377
|
+
focusInput();
|
|
7205
7378
|
},
|
|
7206
7379
|
insertSecondDerivative: () => {
|
|
7207
7380
|
applyStructural((prev) => insertSecondDerivative(prev));
|
|
7208
|
-
|
|
7381
|
+
focusInput();
|
|
7209
7382
|
},
|
|
7210
7383
|
insertMatrixEnv: (style, rows, columns) => {
|
|
7211
7384
|
applyStructural((prev) => insertMatrixEnv(prev, style, rows, columns));
|
|
7212
|
-
|
|
7385
|
+
focusInput();
|
|
7213
7386
|
},
|
|
7214
7387
|
insertArrayEnv: (rows, columns) => {
|
|
7215
7388
|
applyStructural((prev) => insertArrayEnv(prev, rows, columns));
|
|
7216
|
-
|
|
7389
|
+
focusInput();
|
|
7217
7390
|
},
|
|
7218
7391
|
insertAlignedEnv: (rows, columns) => {
|
|
7219
7392
|
applyStructural((prev) => insertAlignedEnv(prev, rows, columns));
|
|
7220
|
-
|
|
7393
|
+
focusInput();
|
|
7221
7394
|
},
|
|
7222
7395
|
insertSqrt: () => {
|
|
7223
7396
|
applyStructural((prev) => insertSqrt(prev));
|
|
7224
|
-
|
|
7397
|
+
focusInput();
|
|
7225
7398
|
},
|
|
7226
7399
|
insertOverset: () => {
|
|
7227
7400
|
applyStructural((prev) => insertOverset(prev));
|
|
7228
|
-
|
|
7401
|
+
focusInput();
|
|
7229
7402
|
},
|
|
7230
7403
|
insertUnderset: () => {
|
|
7231
7404
|
applyStructural((prev) => insertUnderset(prev));
|
|
7232
|
-
|
|
7405
|
+
focusInput();
|
|
7233
7406
|
},
|
|
7234
7407
|
insertLimitsSeriesTemplate: (commandId) => {
|
|
7235
7408
|
applyStructural((prev) => insertLimitsSeriesTemplate(prev, commandId));
|
|
7236
|
-
|
|
7409
|
+
focusInput();
|
|
7237
7410
|
},
|
|
7238
7411
|
insertAccentPair: () => {
|
|
7239
7412
|
applyStructural((prev) => insertAccentPair(prev));
|
|
7240
|
-
|
|
7413
|
+
focusInput();
|
|
7241
7414
|
},
|
|
7242
7415
|
insertAccent: (accentId) => {
|
|
7243
7416
|
applyStructural((prev) => insertAccent(prev, accentId));
|
|
7244
|
-
|
|
7417
|
+
focusInput();
|
|
7245
7418
|
},
|
|
7246
7419
|
insertAtomicCommand: (commandId) => {
|
|
7247
7420
|
applyStructural((prev) => insertAtomicCommand(prev, commandId));
|
|
7248
|
-
|
|
7421
|
+
focusInput();
|
|
7249
7422
|
},
|
|
7250
7423
|
insertAtomicOperatorCommand: (commandId) => {
|
|
7251
7424
|
applyStructural((prev) => insertAtomicOperatorCommand(prev, commandId));
|
|
7252
|
-
|
|
7425
|
+
focusInput();
|
|
7253
7426
|
},
|
|
7254
7427
|
addSup: () => {
|
|
7255
7428
|
applyStructural((prev) => addSup(prev));
|
|
7256
|
-
|
|
7429
|
+
focusInput();
|
|
7257
7430
|
},
|
|
7258
7431
|
addSub: () => {
|
|
7259
7432
|
applyStructural((prev) => addSub(prev));
|
|
7260
|
-
|
|
7433
|
+
focusInput();
|
|
7261
7434
|
},
|
|
7262
7435
|
removeSup: () => {
|
|
7263
7436
|
applyStructural((prev) => removeSup(prev));
|
|
7264
|
-
|
|
7437
|
+
focusInput();
|
|
7265
7438
|
},
|
|
7266
7439
|
removeSub: () => {
|
|
7267
7440
|
applyStructural((prev) => removeSub(prev));
|
|
7268
|
-
|
|
7441
|
+
focusInput();
|
|
7269
7442
|
},
|
|
7270
7443
|
setMatrixEnvStyle: (style) => {
|
|
7271
7444
|
applyStructural((prev) => setMatrixEnvStyle(prev, style));
|
|
@@ -7287,7 +7460,7 @@ function createEditorRuntime(options) {
|
|
|
7287
7460
|
},
|
|
7288
7461
|
deleteStructure: () => {
|
|
7289
7462
|
applyStructural((prev) => deleteStructure(prev));
|
|
7290
|
-
|
|
7463
|
+
focusInput();
|
|
7291
7464
|
}
|
|
7292
7465
|
};
|
|
7293
7466
|
render();
|
|
@@ -8081,6 +8254,79 @@ function normalizeFieldTokens(tokens) {
|
|
|
8081
8254
|
}
|
|
8082
8255
|
return tokens;
|
|
8083
8256
|
}
|
|
8257
|
+
function textStylesEqual2(a, b) {
|
|
8258
|
+
return Boolean(a?.bold) === Boolean(b?.bold) && Boolean(a?.italic) === Boolean(b?.italic) && Boolean(a?.underline) === Boolean(b?.underline);
|
|
8259
|
+
}
|
|
8260
|
+
function compactAdjacentTextTokens(tokens) {
|
|
8261
|
+
const compacted = [];
|
|
8262
|
+
for (const token of tokens) {
|
|
8263
|
+
const previous = compacted[compacted.length - 1];
|
|
8264
|
+
if (previous?.kind === "text" && token.kind === "text" && textStylesEqual2(previous.style, token.style)) {
|
|
8265
|
+
previous.text += token.text;
|
|
8266
|
+
} else {
|
|
8267
|
+
compacted.push(token);
|
|
8268
|
+
}
|
|
8269
|
+
}
|
|
8270
|
+
return normalizeFieldTokens(compacted);
|
|
8271
|
+
}
|
|
8272
|
+
function withoutEmptyStyle(style) {
|
|
8273
|
+
const next = {};
|
|
8274
|
+
if (style.bold) {
|
|
8275
|
+
next.bold = true;
|
|
8276
|
+
}
|
|
8277
|
+
if (style.italic) {
|
|
8278
|
+
next.italic = true;
|
|
8279
|
+
}
|
|
8280
|
+
if (style.underline) {
|
|
8281
|
+
next.underline = true;
|
|
8282
|
+
}
|
|
8283
|
+
return next.bold || next.italic || next.underline ? next : void 0;
|
|
8284
|
+
}
|
|
8285
|
+
function textTokenPart(text, style, id = document2Id("text")) {
|
|
8286
|
+
return { id, kind: "text", text, ...style ? { style } : {} };
|
|
8287
|
+
}
|
|
8288
|
+
function toggleTextTokenStyle(document2, fieldId, tokenId, selectionStart, selectionEnd, styleName) {
|
|
8289
|
+
if (selectionEnd <= selectionStart) {
|
|
8290
|
+
return document2;
|
|
8291
|
+
}
|
|
8292
|
+
const next = cloneDocument(document2);
|
|
8293
|
+
visitFields(next.blocks, (field) => {
|
|
8294
|
+
if (field.id !== fieldId) {
|
|
8295
|
+
return false;
|
|
8296
|
+
}
|
|
8297
|
+
const tokenIndex = field.tokens.findIndex((entry) => entry.id === tokenId && entry.kind === "text");
|
|
8298
|
+
if (tokenIndex < 0) {
|
|
8299
|
+
return true;
|
|
8300
|
+
}
|
|
8301
|
+
const token = field.tokens[tokenIndex];
|
|
8302
|
+
const start = Math.max(0, Math.min(token.text.length, selectionStart));
|
|
8303
|
+
const end = Math.max(0, Math.min(token.text.length, selectionEnd));
|
|
8304
|
+
if (end <= start) {
|
|
8305
|
+
return true;
|
|
8306
|
+
}
|
|
8307
|
+
const selectedStyle = token.style ?? {};
|
|
8308
|
+
const enabled = selectedStyle[styleName] === true;
|
|
8309
|
+
const nextStyle = withoutEmptyStyle({ ...selectedStyle, [styleName]: enabled ? void 0 : true });
|
|
8310
|
+
const parts = [];
|
|
8311
|
+
const before = token.text.slice(0, start);
|
|
8312
|
+
const selected = token.text.slice(start, end);
|
|
8313
|
+
const after = token.text.slice(end);
|
|
8314
|
+
if (before.length > 0) {
|
|
8315
|
+
parts.push(textTokenPart(before, token.style, token.id));
|
|
8316
|
+
}
|
|
8317
|
+
parts.push(textTokenPart(selected, nextStyle, before.length > 0 ? document2Id("text") : token.id));
|
|
8318
|
+
if (after.length > 0) {
|
|
8319
|
+
parts.push(textTokenPart(after, token.style));
|
|
8320
|
+
}
|
|
8321
|
+
field.tokens = compactAdjacentTextTokens([
|
|
8322
|
+
...field.tokens.slice(0, tokenIndex),
|
|
8323
|
+
...parts,
|
|
8324
|
+
...field.tokens.slice(tokenIndex + 1)
|
|
8325
|
+
]);
|
|
8326
|
+
return true;
|
|
8327
|
+
});
|
|
8328
|
+
return next;
|
|
8329
|
+
}
|
|
8084
8330
|
function stitchTextAroundRemovedToken(tokens, index) {
|
|
8085
8331
|
const before = tokens[index - 1];
|
|
8086
8332
|
const after = tokens[index + 1];
|
|
@@ -8108,8 +8354,8 @@ function removeMathTokenById(document2, tokenId) {
|
|
|
8108
8354
|
function splitTextTokenAt(token, offset) {
|
|
8109
8355
|
const safeOffset = Math.max(0, Math.min(offset, token.text.length));
|
|
8110
8356
|
return [
|
|
8111
|
-
{ id: token.id, kind: "text", text: token.text.slice(0, safeOffset) },
|
|
8112
|
-
{ id: document2Id("text"), kind: "text", text: token.text.slice(safeOffset) }
|
|
8357
|
+
{ id: token.id, kind: "text", text: token.text.slice(0, safeOffset), ...token.style ? { style: token.style } : {} },
|
|
8358
|
+
{ id: document2Id("text"), kind: "text", text: token.text.slice(safeOffset), ...token.style ? { style: token.style } : {} }
|
|
8113
8359
|
];
|
|
8114
8360
|
}
|
|
8115
8361
|
function insertMathTokenAtCaret(document2, fieldId, textTokenId, caretOffset, session, opening = "$", closing = "$", side = "arabic") {
|
|
@@ -8612,7 +8858,7 @@ function arabicXeLatexPreamblePkg(twocolumn = false) {
|
|
|
8612
8858
|
\usepackage{bidi}
|
|
8613
8859
|
\usepackage{multirow}
|
|
8614
8860
|
\usepackage{booktabs}
|
|
8615
|
-
\usepackage{graphicx} % For \
|
|
8861
|
+
\usepackage{graphicx} % For \reflectbox
|
|
8616
8862
|
\usepackage{xcolor}
|
|
8617
8863
|
\usepackage{tikz}
|
|
8618
8864
|
\usepackage{tcolorbox} % For tcolorbox environment
|
|
@@ -8681,10 +8927,8 @@ function arabicXeLatexPreambleCmd() {
|
|
|
8681
8927
|
\newcommand{\horzbar}{\rule[.5ex]{2.5ex}{0.5pt}}
|
|
8682
8928
|
|
|
8683
8929
|
|
|
8684
|
-
\newcommand{\
|
|
8685
|
-
|
|
8686
|
-
\newcommand{\arabsqrt}[2]{\butexreflect{\(\sqrt[\butexreflect{\(#1\)}]{\butexreflect{\(#2\)}}\)}}
|
|
8687
|
-
\newcommand{\arabvec}[1]{\butexreflect{$\vec{\butexreflect{$#1$}}$}}
|
|
8930
|
+
\newcommand{\arabsqrt}[2]{\reflectbox{\(\sqrt[\reflectbox{\(#1\)}]{\reflectbox{\(#2\)}}\)}}
|
|
8931
|
+
\newcommand{\arabvec}[1]{\reflectbox{$\vec{\reflectbox{$#1$}}$}}
|
|
8688
8932
|
|
|
8689
8933
|
\newcommand{\arabexp}[1]{{}^{#1}\!\raisebox{-4.5pt}{\text{\diwani{ه}}}}
|
|
8690
8934
|
\newcommand{\arablog}[2]{\left(\text{#2}\right)\!\prescript{}{\text{#1}}{\text{\diwani{لو}}}}
|
|
@@ -8732,9 +8976,9 @@ function arabicXeLatexPreambleCmd() {
|
|
|
8732
8976
|
\newcommand{\araboddde}[2][-5pt]{\stackrel{\raisebox{#1}{$\vcenter{\hbox{$\cdot\!\cdot\!\cdot$}}$}}{\text{#2}}}
|
|
8733
8977
|
\newcommand{\arabpde}[1]{\prescript{}{#1\!\!}{\nabla}} % arabic partial differential equation (PDE)
|
|
8734
8978
|
|
|
8735
|
-
\newcommand{\arabprime}[0]{\
|
|
8736
|
-
\newcommand{\arabpprime}[0]{\
|
|
8737
|
-
\newcommand{\arabppprime}[0]{\
|
|
8979
|
+
\newcommand{\arabprime}[0]{\reflectbox{$\prime$}\!} % arabic prime notation
|
|
8980
|
+
\newcommand{\arabpprime}[0]{\reflectbox{$\prime$}\reflectbox{$\prime$}\!} % arabic prime notation
|
|
8981
|
+
\newcommand{\arabppprime}[0]{\reflectbox{$\prime$}\reflectbox{$\prime$}\reflectbox{$\prime$}\!} % arabic prime notation
|
|
8738
8982
|
|
|
8739
8983
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
8740
8984
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
@@ -8754,7 +8998,7 @@ function arabicXeLatexPreambleCmd() {
|
|
|
8754
8998
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
8755
8999
|
|
|
8756
9000
|
|
|
8757
|
-
\newcommand{\arsqrt}[2][]{\
|
|
9001
|
+
\newcommand{\arsqrt}[2][]{\reflectbox{\(\sqrt[\reflectbox{\(#1\)}]{\reflectbox{\(#2\)}}\)}}
|
|
8758
9002
|
\newcommand{\arexp}[0]{\!\raisebox{-4.5pt}{\text{\diwani{ه}}}}
|
|
8759
9003
|
\newcommand{\arlog}[0]{\!\!\text{\diwani{لو}}}
|
|
8760
9004
|
\newcommand{\arln}[0]{\!\!\prescript{}{\text{\diwani{ه}}}{\text{\diwani{لو}}}}
|
|
@@ -8817,9 +9061,22 @@ function mathBodyLatex(token) {
|
|
|
8817
9061
|
const rendered = renderMathNodeLatex(token.math);
|
|
8818
9062
|
return stripDisplayMathDelimiters(rendered);
|
|
8819
9063
|
}
|
|
9064
|
+
function styledTextLatex(text, style) {
|
|
9065
|
+
let output = text;
|
|
9066
|
+
if (style?.bold) {
|
|
9067
|
+
output = `\\textbf{${output}}`;
|
|
9068
|
+
}
|
|
9069
|
+
if (style?.italic) {
|
|
9070
|
+
output = `\\textit{${output}}`;
|
|
9071
|
+
}
|
|
9072
|
+
if (style?.underline) {
|
|
9073
|
+
output = `\\underline{${output}}`;
|
|
9074
|
+
}
|
|
9075
|
+
return output;
|
|
9076
|
+
}
|
|
8820
9077
|
function tokenLatex(token) {
|
|
8821
9078
|
if (token.kind === "text") {
|
|
8822
|
-
return token.text;
|
|
9079
|
+
return styledTextLatex(token.text, token.style);
|
|
8823
9080
|
}
|
|
8824
9081
|
if (token.kind === "cite") {
|
|
8825
9082
|
return citeTokenLatex(token.keys);
|
|
@@ -8843,7 +9100,9 @@ function inlineFieldLatex(field) {
|
|
|
8843
9100
|
return field.tokens.map((token) => tokenLatex(token)).join("");
|
|
8844
9101
|
}
|
|
8845
9102
|
function textBlockLatex(block) {
|
|
8846
|
-
const
|
|
9103
|
+
const content = inlineFieldLatex(block.field);
|
|
9104
|
+
const body = block.command === "\\paragraph" ? `\\par
|
|
9105
|
+
${content}` : `${block.command}{${content}}`;
|
|
8847
9106
|
if (block.command === "\\paragraph" && block.centered) {
|
|
8848
9107
|
return `\\begin{center}
|
|
8849
9108
|
${body}
|
|
@@ -9095,7 +9354,7 @@ function mathTex(token, equationSide) {
|
|
|
9095
9354
|
function previewInlines(field, islands, output, equationSide, document2, previewOptions) {
|
|
9096
9355
|
return field.tokens.map((token) => {
|
|
9097
9356
|
if (token.kind === "text") {
|
|
9098
|
-
return { kind: "text", text: token.text };
|
|
9357
|
+
return { kind: "text", text: token.text, ...token.style ? { style: token.style } : {} };
|
|
9099
9358
|
}
|
|
9100
9359
|
if (token.kind === "cite") {
|
|
9101
9360
|
return {
|
|
@@ -9271,6 +9530,10 @@ var DOCUMENT2_MESSAGES = {
|
|
|
9271
9530
|
redo: "\u0625\u0639\u0627\u062F\u0629",
|
|
9272
9531
|
structure: "\u0647\u064A\u0643\u0644",
|
|
9273
9532
|
content: "\u0645\u062D\u062A\u0648\u0649",
|
|
9533
|
+
textFormatting: "\u062A\u0646\u0633\u064A\u0642 \u0627\u0644\u0646\u0635",
|
|
9534
|
+
bold: "\u063A\u0627\u0645\u0642",
|
|
9535
|
+
italic: "\u0645\u0627\u0626\u0644",
|
|
9536
|
+
underline: "\u062A\u062D\u062A\u0647 \u062E\u0637",
|
|
9274
9537
|
equations: "\u0645\u0639\u0627\u062F\u0644\u0627\u062A",
|
|
9275
9538
|
citations: "\u0627\u0642\u062A\u0628\u0627\u0633\u0627\u062A \u0648\u0645\u0631\u0627\u062C\u0639",
|
|
9276
9539
|
lists: "\u0642\u0648\u0627\u0626\u0645",
|
|
@@ -9410,6 +9673,10 @@ var DOCUMENT2_MESSAGES = {
|
|
|
9410
9673
|
redo: "Redo",
|
|
9411
9674
|
structure: "Structure",
|
|
9412
9675
|
content: "Content",
|
|
9676
|
+
textFormatting: "Text formatting",
|
|
9677
|
+
bold: "Bold",
|
|
9678
|
+
italic: "Italic",
|
|
9679
|
+
underline: "Underline",
|
|
9413
9680
|
equations: "Equations",
|
|
9414
9681
|
citations: "Citations and references",
|
|
9415
9682
|
lists: "Lists",
|
|
@@ -9753,7 +10020,7 @@ function focusArticleMetaPanel(panel) {
|
|
|
9753
10020
|
}
|
|
9754
10021
|
|
|
9755
10022
|
// src/react-document2/ButexDocumentEditor2.tsx
|
|
9756
|
-
import { useCallback as useCallback2, useEffect as
|
|
10023
|
+
import { useCallback as useCallback2, useEffect as useEffect9, useMemo as useMemo2, useRef as useRef8, useState as useState12 } from "react";
|
|
9757
10024
|
|
|
9758
10025
|
// src/react-document2/BlockEditor.tsx
|
|
9759
10026
|
import { useState as useState3 } from "react";
|
|
@@ -10448,7 +10715,9 @@ function rememberCaret(element, blockId, fieldId, tokenId, onFieldFocus) {
|
|
|
10448
10715
|
if (!blockId || !onFieldFocus) {
|
|
10449
10716
|
return;
|
|
10450
10717
|
}
|
|
10451
|
-
|
|
10718
|
+
const selectionStart = element.selectionStart ?? element.value.length;
|
|
10719
|
+
const selectionEnd = element.selectionEnd ?? selectionStart;
|
|
10720
|
+
onFieldFocus(blockId, fieldId, tokenId, selectionEnd, selectionStart, selectionEnd);
|
|
10452
10721
|
}
|
|
10453
10722
|
function fitTextareaHeight(element) {
|
|
10454
10723
|
if (!element) {
|
|
@@ -10582,6 +10851,9 @@ function InlineField({
|
|
|
10582
10851
|
{
|
|
10583
10852
|
className: "butex-document2-widget__inline-text",
|
|
10584
10853
|
value: token.text,
|
|
10854
|
+
"data-bold": token.style?.bold === true ? "true" : void 0,
|
|
10855
|
+
"data-italic": token.style?.italic === true ? "true" : void 0,
|
|
10856
|
+
"data-underline": token.style?.underline === true ? "true" : void 0,
|
|
10585
10857
|
dir: documentDirection,
|
|
10586
10858
|
"aria-label": messages.text,
|
|
10587
10859
|
rows: 1,
|
|
@@ -11300,7 +11572,7 @@ function CitePickerPopover({
|
|
|
11300
11572
|
}
|
|
11301
11573
|
|
|
11302
11574
|
// src/react-document2/DocumentInsertToolbar.tsx
|
|
11303
|
-
import { useState as useState6 } from "react";
|
|
11575
|
+
import { useEffect as useEffect5, useRef as useRef5, useState as useState6 } from "react";
|
|
11304
11576
|
|
|
11305
11577
|
// src/react-document2/TableInsertPopover.tsx
|
|
11306
11578
|
import { useEffect as useEffect4, useRef as useRef4, useState as useState5 } from "react";
|
|
@@ -11378,8 +11650,11 @@ function DocumentInsertToolbar({
|
|
|
11378
11650
|
selectionCount = 0,
|
|
11379
11651
|
canMoveSelectionUp = false,
|
|
11380
11652
|
canMoveSelectionDown = false,
|
|
11653
|
+
canFormatText = false,
|
|
11654
|
+
activeTextStyles = {},
|
|
11381
11655
|
onUndo,
|
|
11382
11656
|
onRedo,
|
|
11657
|
+
onToggleTextStyle,
|
|
11383
11658
|
onMoveSelectionUp,
|
|
11384
11659
|
onMoveSelectionDown,
|
|
11385
11660
|
onDeleteSelection,
|
|
@@ -11403,6 +11678,56 @@ function DocumentInsertToolbar({
|
|
|
11403
11678
|
}) {
|
|
11404
11679
|
const messages = document2Messages(uiLocale);
|
|
11405
11680
|
const [digitMenuOpen, setDigitMenuOpen] = useState6(false);
|
|
11681
|
+
const [referencesMenuOpen, setReferencesMenuOpen] = useState6(false);
|
|
11682
|
+
const referencesMenuRef = useRef5(null);
|
|
11683
|
+
const referencesTriggerRef = useRef5(null);
|
|
11684
|
+
useEffect5(() => {
|
|
11685
|
+
if (!referencesMenuOpen) {
|
|
11686
|
+
return;
|
|
11687
|
+
}
|
|
11688
|
+
referencesMenuRef.current?.querySelector('[role="menuitem"]')?.focus();
|
|
11689
|
+
const closeOnOutsideClick = (event) => {
|
|
11690
|
+
if (!referencesMenuRef.current?.contains(event.target)) {
|
|
11691
|
+
setReferencesMenuOpen(false);
|
|
11692
|
+
}
|
|
11693
|
+
};
|
|
11694
|
+
const closeOnEscape = (event) => {
|
|
11695
|
+
if (event.key === "Escape") {
|
|
11696
|
+
setReferencesMenuOpen(false);
|
|
11697
|
+
referencesTriggerRef.current?.focus();
|
|
11698
|
+
}
|
|
11699
|
+
};
|
|
11700
|
+
document.addEventListener("mousedown", closeOnOutsideClick);
|
|
11701
|
+
document.addEventListener("keydown", closeOnEscape);
|
|
11702
|
+
return () => {
|
|
11703
|
+
document.removeEventListener("mousedown", closeOnOutsideClick);
|
|
11704
|
+
document.removeEventListener("keydown", closeOnEscape);
|
|
11705
|
+
};
|
|
11706
|
+
}, [referencesMenuOpen]);
|
|
11707
|
+
function runReferenceAction(action) {
|
|
11708
|
+
setReferencesMenuOpen(false);
|
|
11709
|
+
action();
|
|
11710
|
+
}
|
|
11711
|
+
function moveReferenceMenuFocus(event) {
|
|
11712
|
+
if (!["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key)) {
|
|
11713
|
+
return;
|
|
11714
|
+
}
|
|
11715
|
+
const items = Array.from(event.currentTarget.querySelectorAll('[role="menuitem"]'));
|
|
11716
|
+
if (items.length === 0) {
|
|
11717
|
+
return;
|
|
11718
|
+
}
|
|
11719
|
+
event.preventDefault();
|
|
11720
|
+
const currentIndex = items.indexOf(document.activeElement);
|
|
11721
|
+
if (event.key === "Home") {
|
|
11722
|
+
items[0]?.focus();
|
|
11723
|
+
} else if (event.key === "End") {
|
|
11724
|
+
items[items.length - 1]?.focus();
|
|
11725
|
+
} else {
|
|
11726
|
+
const change = event.key === "ArrowDown" ? 1 : -1;
|
|
11727
|
+
const nextIndex = (currentIndex + change + items.length) % items.length;
|
|
11728
|
+
items[nextIndex]?.focus();
|
|
11729
|
+
}
|
|
11730
|
+
}
|
|
11406
11731
|
function digitTitle(id) {
|
|
11407
11732
|
if (id === "arabicIndic") {
|
|
11408
11733
|
return messages.arabicIndicDigits;
|
|
@@ -11460,6 +11785,50 @@ function DocumentInsertToolbar({
|
|
|
11460
11785
|
messages.selectedBlockCount
|
|
11461
11786
|
] }) : null
|
|
11462
11787
|
] }),
|
|
11788
|
+
/* @__PURE__ */ jsxs8("div", { className: "butex-document2-widget__toolbar-group", role: "group", "aria-label": messages.textFormatting, children: [
|
|
11789
|
+
/* @__PURE__ */ jsx10(
|
|
11790
|
+
"button",
|
|
11791
|
+
{
|
|
11792
|
+
type: "button",
|
|
11793
|
+
className: "butex-document2-widget__icon-btn butex-document2-widget__format-btn",
|
|
11794
|
+
title: messages.bold,
|
|
11795
|
+
"aria-label": messages.bold,
|
|
11796
|
+
"aria-pressed": activeTextStyles.bold === true,
|
|
11797
|
+
disabled: !canFormatText,
|
|
11798
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
11799
|
+
onClick: () => onToggleTextStyle?.("bold"),
|
|
11800
|
+
children: /* @__PURE__ */ jsx10("span", { className: "butex-document2-widget__format-icon butex-document2-widget__format-icon--bold", "aria-hidden": "true", children: "\u0646\u0635" })
|
|
11801
|
+
}
|
|
11802
|
+
),
|
|
11803
|
+
/* @__PURE__ */ jsx10(
|
|
11804
|
+
"button",
|
|
11805
|
+
{
|
|
11806
|
+
type: "button",
|
|
11807
|
+
className: "butex-document2-widget__icon-btn butex-document2-widget__format-btn",
|
|
11808
|
+
title: messages.italic,
|
|
11809
|
+
"aria-label": messages.italic,
|
|
11810
|
+
"aria-pressed": activeTextStyles.italic === true,
|
|
11811
|
+
disabled: !canFormatText,
|
|
11812
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
11813
|
+
onClick: () => onToggleTextStyle?.("italic"),
|
|
11814
|
+
children: /* @__PURE__ */ jsx10("span", { className: "butex-document2-widget__format-icon butex-document2-widget__format-icon--italic", "aria-hidden": "true", children: "\u0646\u0635" })
|
|
11815
|
+
}
|
|
11816
|
+
),
|
|
11817
|
+
/* @__PURE__ */ jsx10(
|
|
11818
|
+
"button",
|
|
11819
|
+
{
|
|
11820
|
+
type: "button",
|
|
11821
|
+
className: "butex-document2-widget__icon-btn butex-document2-widget__format-btn",
|
|
11822
|
+
title: messages.underline,
|
|
11823
|
+
"aria-label": messages.underline,
|
|
11824
|
+
"aria-pressed": activeTextStyles.underline === true,
|
|
11825
|
+
disabled: !canFormatText,
|
|
11826
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
11827
|
+
onClick: () => onToggleTextStyle?.("underline"),
|
|
11828
|
+
children: /* @__PURE__ */ jsx10("span", { className: "butex-document2-widget__format-icon butex-document2-widget__format-icon--underline", "aria-hidden": "true", children: "\u0646\u0635" })
|
|
11829
|
+
}
|
|
11830
|
+
)
|
|
11831
|
+
] }),
|
|
11463
11832
|
/* @__PURE__ */ jsxs8("div", { className: "butex-document2-widget__toolbar-group", role: "group", "aria-label": messages.structure, children: [
|
|
11464
11833
|
/* @__PURE__ */ jsx10(
|
|
11465
11834
|
"button",
|
|
@@ -11511,35 +11880,57 @@ function DocumentInsertToolbar({
|
|
|
11511
11880
|
)) }) : null
|
|
11512
11881
|
] })
|
|
11513
11882
|
] }),
|
|
11514
|
-
/* @__PURE__ */
|
|
11515
|
-
/* @__PURE__ */
|
|
11516
|
-
|
|
11517
|
-
|
|
11518
|
-
|
|
11519
|
-
"
|
|
11520
|
-
|
|
11521
|
-
|
|
11522
|
-
|
|
11523
|
-
|
|
11524
|
-
|
|
11525
|
-
|
|
11526
|
-
|
|
11527
|
-
|
|
11528
|
-
|
|
11529
|
-
|
|
11530
|
-
|
|
11531
|
-
|
|
11532
|
-
|
|
11533
|
-
|
|
11534
|
-
|
|
11535
|
-
|
|
11536
|
-
|
|
11537
|
-
|
|
11538
|
-
|
|
11539
|
-
|
|
11540
|
-
|
|
11541
|
-
|
|
11542
|
-
|
|
11883
|
+
/* @__PURE__ */ jsx10("div", { className: "butex-document2-widget__toolbar-group", role: "group", "aria-label": messages.citations, children: /* @__PURE__ */ jsxs8("div", { className: "butex-document2-widget__references-menu", ref: referencesMenuRef, children: [
|
|
11884
|
+
/* @__PURE__ */ jsxs8(
|
|
11885
|
+
"button",
|
|
11886
|
+
{
|
|
11887
|
+
ref: referencesTriggerRef,
|
|
11888
|
+
type: "button",
|
|
11889
|
+
className: "butex-document2-widget__icon-btn butex-document2-widget__references-trigger",
|
|
11890
|
+
title: messages.citations,
|
|
11891
|
+
"aria-label": messages.citations,
|
|
11892
|
+
"aria-haspopup": "menu",
|
|
11893
|
+
"aria-expanded": referencesMenuOpen,
|
|
11894
|
+
onClick: () => setReferencesMenuOpen((open) => !open),
|
|
11895
|
+
children: [
|
|
11896
|
+
/* @__PURE__ */ jsx10("span", { className: "butex-document2-widget__icon-bibliography", "aria-hidden": "true", children: /* @__PURE__ */ jsx10("svg", { viewBox: "0 0 16 16", width: "14", height: "14", focusable: "false", children: /* @__PURE__ */ jsx10("path", { fill: "currentColor", d: "M2 2.2h4.2c.7 0 1.3.3 1.8.8.5-.5 1.1-.8 1.8-.8H14v10.6H9.8c-.6 0-1.1.3-1.4.8h-.8c-.3-.5-.8-.8-1.4-.8H2V2.2zm1.2 1.2v8.2h3c.4 0 .8.1 1.2.3V4.6c-.2-.7-.6-1.2-1.2-1.2h-3zm9.6 0h-3c-.6 0-1 .5-1.2 1.2v7.3c.4-.2.8-.3 1.2-.3h3V3.4z" }) }) }),
|
|
11897
|
+
/* @__PURE__ */ jsx10("span", { children: messages.citations }),
|
|
11898
|
+
/* @__PURE__ */ jsx10("span", { className: "butex-document2-widget__menu-chevron", "aria-hidden": "true", children: "\u2304" })
|
|
11899
|
+
]
|
|
11900
|
+
}
|
|
11901
|
+
),
|
|
11902
|
+
referencesMenuOpen ? /* @__PURE__ */ jsxs8(
|
|
11903
|
+
"div",
|
|
11904
|
+
{
|
|
11905
|
+
className: "butex-document2-widget__references-menu-options",
|
|
11906
|
+
role: "menu",
|
|
11907
|
+
"aria-label": messages.citations,
|
|
11908
|
+
onKeyDown: moveReferenceMenuFocus,
|
|
11909
|
+
children: [
|
|
11910
|
+
/* @__PURE__ */ jsxs8("button", { type: "button", role: "menuitem", title: messages.insertCitation, onClick: () => runReferenceAction(onInsertCitation), children: [
|
|
11911
|
+
/* @__PURE__ */ jsx10("span", { "aria-hidden": "true", children: "[]" }),
|
|
11912
|
+
/* @__PURE__ */ jsx10("span", { children: messages.insertCitation })
|
|
11913
|
+
] }),
|
|
11914
|
+
/* @__PURE__ */ jsxs8("button", { type: "button", role: "menuitem", title: messages.insertInternalRef, onClick: () => runReferenceAction(onInsertInternalRef), children: [
|
|
11915
|
+
/* @__PURE__ */ jsx10("span", { "aria-hidden": "true", children: "\xA7" }),
|
|
11916
|
+
/* @__PURE__ */ jsx10("span", { children: messages.insertInternalRef })
|
|
11917
|
+
] }),
|
|
11918
|
+
/* @__PURE__ */ jsxs8("button", { type: "button", role: "menuitem", title: messages.insertBibliography, onClick: () => runReferenceAction(onInsertBibliography), children: [
|
|
11919
|
+
/* @__PURE__ */ jsx10("span", { className: "butex-document2-widget__icon-bibliography", "aria-hidden": "true", children: /* @__PURE__ */ jsx10("svg", { viewBox: "0 0 16 16", width: "14", height: "14", focusable: "false", children: /* @__PURE__ */ jsx10("path", { fill: "currentColor", d: "M2.2 2.4h7.2c.9 0 1.6.7 1.6 1.6v9.2c0 .5-.6.8-1 .5l-2.2-1.6H2.2c-.9 0-1.6-.7-1.6-1.6V4c0-.9.7-1.6 1.6-1.6zm0 1.2c-.2 0-.4.2-.4.4v6.5c0 .2.2.4.4.4h6.1l1.5 1.1V4c0-.2-.2-.4-.4-.4H2.2zM3.4 5.2h5.2v1H3.4zm0 2.1h4.2v1H3.4zm0 2.1h3.4v1H3.4zM11.4 4.1h2.2c.8 0 1.4.6 1.4 1.4v7.1c0 .4-.5.7-.8.4l-1.7-1.3h-1.1V4.1zm1.2 1.2v5.4l.7.5V5.5c0-.1-.1-.2-.2-.2h-.5z" }) }) }),
|
|
11920
|
+
/* @__PURE__ */ jsx10("span", { children: messages.insertBibliography })
|
|
11921
|
+
] }),
|
|
11922
|
+
/* @__PURE__ */ jsxs8("button", { type: "button", role: "menuitem", title: messages.manageReferences, onClick: () => runReferenceAction(onManageReferences), children: [
|
|
11923
|
+
/* @__PURE__ */ jsx10("span", { "aria-hidden": "true", children: "\u2630" }),
|
|
11924
|
+
/* @__PURE__ */ jsx10("span", { children: messages.manageReferences })
|
|
11925
|
+
] }),
|
|
11926
|
+
/* @__PURE__ */ jsxs8("button", { type: "button", role: "menuitem", title: messages.manageLabels, onClick: () => runReferenceAction(onManageLabels), children: [
|
|
11927
|
+
/* @__PURE__ */ jsx10("span", { "aria-hidden": "true", children: "\u2317" }),
|
|
11928
|
+
/* @__PURE__ */ jsx10("span", { children: messages.manageLabels })
|
|
11929
|
+
] })
|
|
11930
|
+
]
|
|
11931
|
+
}
|
|
11932
|
+
) : null
|
|
11933
|
+
] }) }),
|
|
11543
11934
|
/* @__PURE__ */ jsxs8("div", { className: "butex-document2-widget__toolbar-group", role: "group", "aria-label": messages.lists, children: [
|
|
11544
11935
|
/* @__PURE__ */ jsx10("button", { type: "button", className: "butex-document2-widget__icon-btn", title: messages.bulletedList, "aria-label": messages.bulletedList, onClick: onAddList, children: "\u2022\u2261" }),
|
|
11545
11936
|
/* @__PURE__ */ jsx10("button", { type: "button", className: "butex-document2-widget__icon-btn", title: messages.numberedList, "aria-label": messages.numberedList, onClick: onAddEnumerate, children: "1." })
|
|
@@ -11554,7 +11945,17 @@ import { Fragment, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
|
11554
11945
|
function PreviewInlines({ inlines, output }) {
|
|
11555
11946
|
return /* @__PURE__ */ jsx11(Fragment, { children: inlines.map((inline, index) => {
|
|
11556
11947
|
if (inline.kind === "text") {
|
|
11557
|
-
|
|
11948
|
+
let content = /* @__PURE__ */ jsx11("span", { children: inline.text });
|
|
11949
|
+
if (inline.style?.bold) {
|
|
11950
|
+
content = /* @__PURE__ */ jsx11("strong", { children: content });
|
|
11951
|
+
}
|
|
11952
|
+
if (inline.style?.italic) {
|
|
11953
|
+
content = /* @__PURE__ */ jsx11("em", { children: content });
|
|
11954
|
+
}
|
|
11955
|
+
if (inline.style?.underline) {
|
|
11956
|
+
content = /* @__PURE__ */ jsx11("span", { className: "butex-document2-widget__preview-underline", children: content });
|
|
11957
|
+
}
|
|
11958
|
+
return /* @__PURE__ */ jsx11("span", { children: content }, index);
|
|
11558
11959
|
}
|
|
11559
11960
|
if (inline.kind === "cite") {
|
|
11560
11961
|
return /* @__PURE__ */ jsx11("span", { className: "butex-document2-widget__preview-cite", children: inline.label }, inline.id);
|
|
@@ -11703,15 +12104,15 @@ function DocumentPreview({
|
|
|
11703
12104
|
}
|
|
11704
12105
|
|
|
11705
12106
|
// src/react-document2/EquationDrawer.tsx
|
|
11706
|
-
import { useEffect as
|
|
12107
|
+
import { useEffect as useEffect7, useRef as useRef7, useState as useState8 } from "react";
|
|
11707
12108
|
|
|
11708
12109
|
// src/react/ButexEditor.tsx
|
|
11709
12110
|
import {
|
|
11710
12111
|
forwardRef,
|
|
11711
12112
|
useCallback,
|
|
11712
|
-
useEffect as
|
|
12113
|
+
useEffect as useEffect6,
|
|
11713
12114
|
useImperativeHandle,
|
|
11714
|
-
useRef as
|
|
12115
|
+
useRef as useRef6,
|
|
11715
12116
|
useState as useState7
|
|
11716
12117
|
} from "react";
|
|
11717
12118
|
|
|
@@ -11787,6 +12188,22 @@ var WIDGET_CHROME_CSS = `
|
|
|
11787
12188
|
padding: 10px 12px;
|
|
11788
12189
|
}
|
|
11789
12190
|
|
|
12191
|
+
.butex-widget .butex-editor-input-bridge {
|
|
12192
|
+
border: 0;
|
|
12193
|
+
font-size: 16px;
|
|
12194
|
+
height: 1px;
|
|
12195
|
+
margin: 0;
|
|
12196
|
+
max-height: 1px;
|
|
12197
|
+
min-height: 1px;
|
|
12198
|
+
opacity: 0;
|
|
12199
|
+
overflow: hidden;
|
|
12200
|
+
padding: 0;
|
|
12201
|
+
pointer-events: none;
|
|
12202
|
+
position: absolute;
|
|
12203
|
+
resize: none;
|
|
12204
|
+
width: 1px;
|
|
12205
|
+
}
|
|
12206
|
+
|
|
11790
12207
|
.butex-widget .toolbar {
|
|
11791
12208
|
display: flex;
|
|
11792
12209
|
flex-wrap: wrap;
|
|
@@ -12786,28 +13203,29 @@ ${latex || messages.empty}`;
|
|
|
12786
13203
|
var ButexEditor = forwardRef(
|
|
12787
13204
|
function ButexEditor2({ className, debug = false, defaultSide, uiLocale = "ar", initialSession, onSessionChange }, ref) {
|
|
12788
13205
|
const messages = equationEditorMessages(uiLocale);
|
|
12789
|
-
const wrapperRef =
|
|
12790
|
-
const surfaceRef =
|
|
12791
|
-
const
|
|
12792
|
-
const
|
|
12793
|
-
const
|
|
12794
|
-
const
|
|
12795
|
-
const
|
|
12796
|
-
const
|
|
12797
|
-
const
|
|
12798
|
-
const
|
|
12799
|
-
const
|
|
12800
|
-
const
|
|
12801
|
-
const
|
|
12802
|
-
const
|
|
12803
|
-
const
|
|
12804
|
-
const
|
|
13206
|
+
const wrapperRef = useRef6(null);
|
|
13207
|
+
const surfaceRef = useRef6(null);
|
|
13208
|
+
const inputRef = useRef6(null);
|
|
13209
|
+
const mathOutputRef = useRef6(null);
|
|
13210
|
+
const renderErrorRef = useRef6(null);
|
|
13211
|
+
const latexLinesRef = useRef6(null);
|
|
13212
|
+
const passivePreviewRef = useRef6(null);
|
|
13213
|
+
const debugLogRef = useRef6(null);
|
|
13214
|
+
const undoBtnRef = useRef6(null);
|
|
13215
|
+
const redoBtnRef = useRef6(null);
|
|
13216
|
+
const copyBtnRef = useRef6(null);
|
|
13217
|
+
const cutBtnRef = useRef6(null);
|
|
13218
|
+
const splitTypingBtnRef = useRef6(null);
|
|
13219
|
+
const characterFontBtnRef = useRef6(null);
|
|
13220
|
+
const digitFormBtnRef = useRef6(null);
|
|
13221
|
+
const runtimeRef = useRef6(null);
|
|
13222
|
+
const debugRef = useRef6(debug);
|
|
12805
13223
|
debugRef.current = debug;
|
|
12806
|
-
const uiLocaleRef =
|
|
13224
|
+
const uiLocaleRef = useRef6(uiLocale);
|
|
12807
13225
|
uiLocaleRef.current = uiLocale;
|
|
12808
|
-
const onSessionChangeRef =
|
|
13226
|
+
const onSessionChangeRef = useRef6(onSessionChange);
|
|
12809
13227
|
onSessionChangeRef.current = onSessionChange;
|
|
12810
|
-
const debugBodyHiddenRef =
|
|
13228
|
+
const debugBodyHiddenRef = useRef6(false);
|
|
12811
13229
|
const [debugBodyHidden, setDebugBodyHidden] = useState7(false);
|
|
12812
13230
|
debugBodyHiddenRef.current = debugBodyHidden;
|
|
12813
13231
|
const [digitMenuOpen, setDigitMenuOpen] = useState7(false);
|
|
@@ -12888,9 +13306,9 @@ ${arabic || currentMessages.empty}`;
|
|
|
12888
13306
|
}
|
|
12889
13307
|
}
|
|
12890
13308
|
}, []);
|
|
12891
|
-
const updatePreviewRef =
|
|
13309
|
+
const updatePreviewRef = useRef6(updatePreview);
|
|
12892
13310
|
updatePreviewRef.current = updatePreview;
|
|
12893
|
-
|
|
13311
|
+
useEffect6(() => {
|
|
12894
13312
|
injectWidgetChromeCss();
|
|
12895
13313
|
injectBuTeXEditorStyles(typeof document !== "undefined" ? document : void 0);
|
|
12896
13314
|
const surfaceEl = surfaceRef.current;
|
|
@@ -12899,6 +13317,7 @@ ${arabic || currentMessages.empty}`;
|
|
|
12899
13317
|
}
|
|
12900
13318
|
const runtime = createEditorRuntime({
|
|
12901
13319
|
surfaceEl,
|
|
13320
|
+
inputEl: inputRef.current,
|
|
12902
13321
|
initialSession,
|
|
12903
13322
|
defaultSide,
|
|
12904
13323
|
uiLocale,
|
|
@@ -12940,13 +13359,13 @@ ${arabic || currentMessages.empty}`;
|
|
|
12940
13359
|
} else {
|
|
12941
13360
|
runtime.render();
|
|
12942
13361
|
}
|
|
12943
|
-
|
|
13362
|
+
runtime.focusInput();
|
|
12944
13363
|
return () => {
|
|
12945
13364
|
runtime.destroy();
|
|
12946
13365
|
runtimeRef.current = null;
|
|
12947
13366
|
};
|
|
12948
13367
|
}, []);
|
|
12949
|
-
|
|
13368
|
+
useEffect6(() => {
|
|
12950
13369
|
runtimeRef.current?.setUiLocale(uiLocale);
|
|
12951
13370
|
const session = runtimeRef.current?.getSession();
|
|
12952
13371
|
if (session) {
|
|
@@ -12954,7 +13373,7 @@ ${arabic || currentMessages.empty}`;
|
|
|
12954
13373
|
}
|
|
12955
13374
|
}, [uiLocale]);
|
|
12956
13375
|
function focusSurface() {
|
|
12957
|
-
|
|
13376
|
+
runtimeRef.current?.focusInput();
|
|
12958
13377
|
}
|
|
12959
13378
|
function insertSelectedEnvironment(rows, columns) {
|
|
12960
13379
|
if (envPaletteMode === "array") {
|
|
@@ -14032,6 +14451,20 @@ ${arabic || currentMessages.empty}`;
|
|
|
14032
14451
|
"aria-label": messages.equationEditor
|
|
14033
14452
|
}
|
|
14034
14453
|
),
|
|
14454
|
+
/* @__PURE__ */ jsx12(
|
|
14455
|
+
"textarea",
|
|
14456
|
+
{
|
|
14457
|
+
ref: inputRef,
|
|
14458
|
+
className: "butex-editor-input-bridge",
|
|
14459
|
+
"aria-label": messages.equationEditor,
|
|
14460
|
+
autoCapitalize: "none",
|
|
14461
|
+
autoComplete: "off",
|
|
14462
|
+
autoCorrect: "off",
|
|
14463
|
+
inputMode: "text",
|
|
14464
|
+
spellCheck: false,
|
|
14465
|
+
tabIndex: -1
|
|
14466
|
+
}
|
|
14467
|
+
),
|
|
14035
14468
|
/* @__PURE__ */ jsx12("div", { ref: renderErrorRef, className: "error", hidden: true })
|
|
14036
14469
|
] }),
|
|
14037
14470
|
/* @__PURE__ */ jsx12("section", { className: "panel panel-preview", "aria-label": messages.renderPreview, children: /* @__PURE__ */ jsx12("div", { ref: mathOutputRef, className: "preview-box" }) }),
|
|
@@ -14122,7 +14555,7 @@ function EquationDrawer({
|
|
|
14122
14555
|
onDelete
|
|
14123
14556
|
}) {
|
|
14124
14557
|
const messages = document2Messages(uiLocale);
|
|
14125
|
-
const latestSession =
|
|
14558
|
+
const latestSession = useRef7(session);
|
|
14126
14559
|
const [labelOverride, setLabelOverride] = useState8(null);
|
|
14127
14560
|
const displayedLabel = labelOverride ?? label;
|
|
14128
14561
|
const labelError = labelEnabled && mathMode === "display" ? document2KeyError(displayedLabel, {
|
|
@@ -14130,10 +14563,10 @@ function EquationDrawer({
|
|
|
14130
14563
|
labels,
|
|
14131
14564
|
excludeOwnerId: ownerId || void 0
|
|
14132
14565
|
}) : null;
|
|
14133
|
-
|
|
14566
|
+
useEffect7(() => {
|
|
14134
14567
|
setLabelOverride(null);
|
|
14135
14568
|
}, [ownerId, label]);
|
|
14136
|
-
|
|
14569
|
+
useEffect7(() => {
|
|
14137
14570
|
const onKeyDown = (event) => {
|
|
14138
14571
|
if (event.key === "Escape") {
|
|
14139
14572
|
onClose();
|
|
@@ -14675,7 +15108,7 @@ function ReferencesPanel({
|
|
|
14675
15108
|
}
|
|
14676
15109
|
|
|
14677
15110
|
// src/react-document2/RefPickerPopover.tsx
|
|
14678
|
-
import { useEffect as
|
|
15111
|
+
import { useEffect as useEffect8, useState as useState11 } from "react";
|
|
14679
15112
|
import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
14680
15113
|
function RefPickerPopover({
|
|
14681
15114
|
open,
|
|
@@ -14692,7 +15125,7 @@ function RefPickerPopover({
|
|
|
14692
15125
|
const documentDirection = uiLocale === "ar" ? "rtl" : "ltr";
|
|
14693
15126
|
const [selected, setSelected] = useState11(initialKeys);
|
|
14694
15127
|
const [refCommand, setRefCommand] = useState11(initialRefCommand);
|
|
14695
|
-
|
|
15128
|
+
useEffect8(() => {
|
|
14696
15129
|
if (open) {
|
|
14697
15130
|
setSelected(initialKeys);
|
|
14698
15131
|
setRefCommand(initialRefCommand);
|
|
@@ -14757,7 +15190,7 @@ function RefPickerPopover({
|
|
|
14757
15190
|
|
|
14758
15191
|
// src/react-document2/editorFocus.ts
|
|
14759
15192
|
function createEmptyDocument2EditorFocus() {
|
|
14760
|
-
return { blockId: null, fieldId: null, textTokenId: null, caretOffset: 0 };
|
|
15193
|
+
return { blockId: null, fieldId: null, textTokenId: null, caretOffset: 0, selectionStart: 0, selectionEnd: 0 };
|
|
14761
15194
|
}
|
|
14762
15195
|
function findBlockIdForField(blocks, fieldId) {
|
|
14763
15196
|
for (const block of blocks) {
|
|
@@ -14965,6 +15398,89 @@ var DOCUMENT2_WIDGET_CSS = `
|
|
|
14965
15398
|
display: block;
|
|
14966
15399
|
}
|
|
14967
15400
|
|
|
15401
|
+
.butex-document2-widget__format-btn {
|
|
15402
|
+
font-family: "Amiri", "Noto Serif Arabic", Georgia, serif;
|
|
15403
|
+
min-width: 36px;
|
|
15404
|
+
}
|
|
15405
|
+
|
|
15406
|
+
.butex-document2-widget__format-icon {
|
|
15407
|
+
direction: rtl;
|
|
15408
|
+
display: inline-block;
|
|
15409
|
+
font-size: 0.84rem;
|
|
15410
|
+
font-weight: 500;
|
|
15411
|
+
}
|
|
15412
|
+
|
|
15413
|
+
.butex-document2-widget__format-icon--bold {
|
|
15414
|
+
font-weight: 900;
|
|
15415
|
+
}
|
|
15416
|
+
|
|
15417
|
+
.butex-document2-widget__format-icon--italic {
|
|
15418
|
+
font-style: italic;
|
|
15419
|
+
transform: skewX(-7deg);
|
|
15420
|
+
}
|
|
15421
|
+
|
|
15422
|
+
.butex-document2-widget__format-icon--underline {
|
|
15423
|
+
text-decoration: underline;
|
|
15424
|
+
text-underline-offset: 0.12em;
|
|
15425
|
+
}
|
|
15426
|
+
|
|
15427
|
+
.butex-document2-widget__format-underline,
|
|
15428
|
+
.butex-document2-widget__preview-underline {
|
|
15429
|
+
text-decoration: underline;
|
|
15430
|
+
text-underline-offset: 0.12em;
|
|
15431
|
+
}
|
|
15432
|
+
|
|
15433
|
+
.butex-document2-widget__references-menu {
|
|
15434
|
+
position: relative;
|
|
15435
|
+
}
|
|
15436
|
+
|
|
15437
|
+
.butex-document2-widget__references-trigger {
|
|
15438
|
+
gap: 5px;
|
|
15439
|
+
white-space: nowrap;
|
|
15440
|
+
}
|
|
15441
|
+
|
|
15442
|
+
.butex-document2-widget__menu-chevron {
|
|
15443
|
+
color: var(--butex-document2-muted);
|
|
15444
|
+
font-size: 0.8rem;
|
|
15445
|
+
}
|
|
15446
|
+
|
|
15447
|
+
.butex-document2-widget__references-menu-options {
|
|
15448
|
+
background: var(--butex-document2-panel);
|
|
15449
|
+
border: 1px solid var(--butex-document2-border);
|
|
15450
|
+
border-radius: 8px;
|
|
15451
|
+
box-shadow: 0 8px 24px color-mix(in srgb, var(--butex-document2-fg) 16%, transparent);
|
|
15452
|
+
display: grid;
|
|
15453
|
+
gap: 2px;
|
|
15454
|
+
inset-inline-start: 0;
|
|
15455
|
+
margin-top: 4px;
|
|
15456
|
+
min-width: max-content;
|
|
15457
|
+
padding: 4px;
|
|
15458
|
+
position: absolute;
|
|
15459
|
+
top: 100%;
|
|
15460
|
+
z-index: 30;
|
|
15461
|
+
}
|
|
15462
|
+
|
|
15463
|
+
.butex-document2-widget__references-menu-options button {
|
|
15464
|
+
align-items: center;
|
|
15465
|
+
background: transparent;
|
|
15466
|
+
border: 0;
|
|
15467
|
+
border-radius: 6px;
|
|
15468
|
+
color: var(--butex-document2-fg);
|
|
15469
|
+
cursor: pointer;
|
|
15470
|
+
display: grid;
|
|
15471
|
+
font: inherit;
|
|
15472
|
+
gap: 8px;
|
|
15473
|
+
grid-template-columns: 18px 1fr;
|
|
15474
|
+
padding: 7px 9px;
|
|
15475
|
+
text-align: start;
|
|
15476
|
+
}
|
|
15477
|
+
|
|
15478
|
+
.butex-document2-widget__references-menu-options button:hover,
|
|
15479
|
+
.butex-document2-widget__references-menu-options button:focus-visible {
|
|
15480
|
+
background: var(--butex-document2-accent-bg);
|
|
15481
|
+
outline: none;
|
|
15482
|
+
}
|
|
15483
|
+
|
|
14968
15484
|
.butex-document2-widget__float-meta {
|
|
14969
15485
|
display: grid;
|
|
14970
15486
|
gap: 8px;
|
|
@@ -15408,6 +15924,19 @@ var DOCUMENT2_WIDGET_CSS = `
|
|
|
15408
15924
|
border-color: color-mix(in srgb, var(--butex-document2-text-token-border) 55%, var(--butex-document2-accent));
|
|
15409
15925
|
}
|
|
15410
15926
|
|
|
15927
|
+
.butex-document2-widget__inline-text[data-bold="true"] {
|
|
15928
|
+
font-weight: 700;
|
|
15929
|
+
}
|
|
15930
|
+
|
|
15931
|
+
.butex-document2-widget__inline-text[data-italic="true"] {
|
|
15932
|
+
font-style: italic;
|
|
15933
|
+
}
|
|
15934
|
+
|
|
15935
|
+
.butex-document2-widget__inline-text[data-underline="true"] {
|
|
15936
|
+
text-decoration: underline;
|
|
15937
|
+
text-underline-offset: 0.12em;
|
|
15938
|
+
}
|
|
15939
|
+
|
|
15411
15940
|
.butex-document2-widget__inline-field input {
|
|
15412
15941
|
min-width: 12ch;
|
|
15413
15942
|
}
|
|
@@ -16425,6 +16954,50 @@ function topLevelBlockIdForField(document2, fieldId) {
|
|
|
16425
16954
|
function topLevelBlockIdForToken(document2, tokenId) {
|
|
16426
16955
|
return document2.blocks.find((block) => blockHasToken(block, tokenId))?.id ?? null;
|
|
16427
16956
|
}
|
|
16957
|
+
function findFormatTextToken(document2, focus) {
|
|
16958
|
+
if (!focus.fieldId || !focus.textTokenId || focus.selectionEnd <= focus.selectionStart) {
|
|
16959
|
+
return null;
|
|
16960
|
+
}
|
|
16961
|
+
function textTokenFromField(field) {
|
|
16962
|
+
if (field.id !== focus.fieldId) {
|
|
16963
|
+
return null;
|
|
16964
|
+
}
|
|
16965
|
+
const token = field.tokens.find((entry) => entry.id === focus.textTokenId && entry.kind === "text");
|
|
16966
|
+
return token ?? null;
|
|
16967
|
+
}
|
|
16968
|
+
function visit(blocks) {
|
|
16969
|
+
for (const block of blocks) {
|
|
16970
|
+
if (block.kind === "textBlock") {
|
|
16971
|
+
const token = block.command === "\\paragraph" ? textTokenFromField(block.field) : null;
|
|
16972
|
+
if (token) {
|
|
16973
|
+
return token;
|
|
16974
|
+
}
|
|
16975
|
+
} else if (block.kind === "list") {
|
|
16976
|
+
for (const item of block.items) {
|
|
16977
|
+
const itemToken = textTokenFromField(item.field);
|
|
16978
|
+
if (itemToken) {
|
|
16979
|
+
return itemToken;
|
|
16980
|
+
}
|
|
16981
|
+
const nestedToken = visit(item.blocks);
|
|
16982
|
+
if (nestedToken) {
|
|
16983
|
+
return nestedToken;
|
|
16984
|
+
}
|
|
16985
|
+
}
|
|
16986
|
+
} else if (block.kind === "table") {
|
|
16987
|
+
for (const row of block.rows) {
|
|
16988
|
+
for (const cell of row) {
|
|
16989
|
+
const token = textTokenFromField(cell);
|
|
16990
|
+
if (token) {
|
|
16991
|
+
return token;
|
|
16992
|
+
}
|
|
16993
|
+
}
|
|
16994
|
+
}
|
|
16995
|
+
}
|
|
16996
|
+
}
|
|
16997
|
+
return null;
|
|
16998
|
+
}
|
|
16999
|
+
return visit(document2.blocks);
|
|
17000
|
+
}
|
|
16428
17001
|
function formatDocument2Diagnostic(d, messages) {
|
|
16429
17002
|
if (d.message === "math_objects order mismatch") {
|
|
16430
17003
|
return `${messages.importOrderMismatch} ${messages.path}: ${d.path}`;
|
|
@@ -16510,13 +17083,13 @@ function ButexDocumentEditor2({
|
|
|
16510
17083
|
const [blockSelectionState, setBlockSelectionState] = useState12(emptyBlockSelection);
|
|
16511
17084
|
const [historyTick, setHistoryTick] = useState12(0);
|
|
16512
17085
|
const digitForm = digitFormProp ?? digitFormState ?? (documentDirection === "rtl" ? "arabicIndic" : "western");
|
|
16513
|
-
const historyRef =
|
|
16514
|
-
const documentRef =
|
|
16515
|
-
const textSnapshotArmedRef =
|
|
16516
|
-
const textDebounceRef =
|
|
16517
|
-
const widgetRef =
|
|
16518
|
-
const articleMetaPanelRef =
|
|
16519
|
-
const pendingFocusRef =
|
|
17086
|
+
const historyRef = useRef8(createDocument2History());
|
|
17087
|
+
const documentRef = useRef8(documentNode);
|
|
17088
|
+
const textSnapshotArmedRef = useRef8(false);
|
|
17089
|
+
const textDebounceRef = useRef8(null);
|
|
17090
|
+
const widgetRef = useRef8(null);
|
|
17091
|
+
const articleMetaPanelRef = useRef8(null);
|
|
17092
|
+
const pendingFocusRef = useRef8(null);
|
|
16520
17093
|
documentRef.current = documentNode;
|
|
16521
17094
|
const latex = document2Latex(documentNode);
|
|
16522
17095
|
const documentLabels = useMemo2(() => collectDocument2Labels(documentNode), [documentNode]);
|
|
@@ -16543,6 +17116,9 @@ function ButexDocumentEditor2({
|
|
|
16543
17116
|
const selectionCount = blockSelection ? blockSelection.to - blockSelection.from + 1 : 0;
|
|
16544
17117
|
const canMoveSelectionUp = Boolean(blockSelection && blockSelection.from > 0);
|
|
16545
17118
|
const canMoveSelectionDown = Boolean(blockSelection && blockSelection.to < documentNode.blocks.length - 1);
|
|
17119
|
+
const formatTextToken = useMemo2(() => findFormatTextToken(documentNode, editorFocus), [documentNode, editorFocus]);
|
|
17120
|
+
const canFormatText = formatTextToken !== null;
|
|
17121
|
+
const activeTextStyles = formatTextToken?.style ?? {};
|
|
16546
17122
|
function clearBlockSelection() {
|
|
16547
17123
|
setBlockSelectionState(emptyBlockSelection());
|
|
16548
17124
|
}
|
|
@@ -16580,15 +17156,15 @@ function ButexDocumentEditor2({
|
|
|
16580
17156
|
applyDocument(removeDocument2BlockRange(documentRef.current, selection.from, selection.to), "immediate");
|
|
16581
17157
|
clearBlockSelection();
|
|
16582
17158
|
}
|
|
16583
|
-
|
|
17159
|
+
useEffect9(() => {
|
|
16584
17160
|
injectBuTeXDocument2Styles();
|
|
16585
17161
|
}, []);
|
|
16586
|
-
|
|
17162
|
+
useEffect9(() => {
|
|
16587
17163
|
if (!editableEquations || previewOnly) {
|
|
16588
17164
|
setSelectedMath(null);
|
|
16589
17165
|
}
|
|
16590
17166
|
}, [editableEquations, previewOnly]);
|
|
16591
|
-
|
|
17167
|
+
useEffect9(() => {
|
|
16592
17168
|
const next = resolveInitialDocument2(initialDocument, uiLocale, documentMeta);
|
|
16593
17169
|
setDocumentNode(next.document);
|
|
16594
17170
|
setError(next.error);
|
|
@@ -16597,13 +17173,13 @@ function ButexDocumentEditor2({
|
|
|
16597
17173
|
historyRef.current = createDocument2History();
|
|
16598
17174
|
setHistoryTick((tick) => tick + 1);
|
|
16599
17175
|
}, [initialDocument, documentMeta, uiLocale]);
|
|
16600
|
-
|
|
17176
|
+
useEffect9(() => {
|
|
16601
17177
|
onDocumentChange?.(documentNode);
|
|
16602
17178
|
}, [documentNode, onDocumentChange]);
|
|
16603
|
-
|
|
17179
|
+
useEffect9(() => {
|
|
16604
17180
|
onLatexChange?.(latex);
|
|
16605
17181
|
}, [latex, onLatexChange]);
|
|
16606
|
-
|
|
17182
|
+
useEffect9(() => {
|
|
16607
17183
|
const pending = pendingFocusRef.current;
|
|
16608
17184
|
const root = widgetRef.current;
|
|
16609
17185
|
if (!pending || !root) {
|
|
@@ -16719,7 +17295,7 @@ function ButexDocumentEditor2({
|
|
|
16719
17295
|
function openAllBlocks() {
|
|
16720
17296
|
setCollapsedBlockIds(/* @__PURE__ */ new Set());
|
|
16721
17297
|
}
|
|
16722
|
-
|
|
17298
|
+
useEffect9(() => {
|
|
16723
17299
|
const root = widgetRef.current;
|
|
16724
17300
|
if (!root) {
|
|
16725
17301
|
return;
|
|
@@ -16743,15 +17319,15 @@ function ButexDocumentEditor2({
|
|
|
16743
17319
|
root.addEventListener("keydown", onKeyDown);
|
|
16744
17320
|
return () => root.removeEventListener("keydown", onKeyDown);
|
|
16745
17321
|
}, [editorOpen]);
|
|
16746
|
-
function rememberFieldFocus(blockId, fieldId, textTokenId, caretOffset) {
|
|
17322
|
+
function rememberFieldFocus(blockId, fieldId, textTokenId, caretOffset, selectionStart, selectionEnd) {
|
|
16747
17323
|
openBlock(blockId);
|
|
16748
17324
|
clearBlockSelection();
|
|
16749
|
-
setEditorFocus({ blockId, fieldId, textTokenId, caretOffset });
|
|
17325
|
+
setEditorFocus({ blockId, fieldId, textTokenId, caretOffset, selectionStart, selectionEnd });
|
|
16750
17326
|
}
|
|
16751
17327
|
function rememberMathFocus(blockId, fieldId) {
|
|
16752
17328
|
openBlock(blockId);
|
|
16753
17329
|
clearBlockSelection();
|
|
16754
|
-
setEditorFocus({ blockId, fieldId, textTokenId: null, caretOffset: 0 });
|
|
17330
|
+
setEditorFocus({ blockId, fieldId, textTokenId: null, caretOffset: 0, selectionStart: 0, selectionEnd: 0 });
|
|
16755
17331
|
}
|
|
16756
17332
|
function rememberBlockFocus(blockId) {
|
|
16757
17333
|
openBlock(blockId);
|
|
@@ -17014,6 +17590,22 @@ function ButexDocumentEditor2({
|
|
|
17014
17590
|
function deleteRefToken(tokenId) {
|
|
17015
17591
|
applyDocument(removeRefTokenById(documentRef.current, tokenId), "immediate");
|
|
17016
17592
|
}
|
|
17593
|
+
function toggleInlineTextStyle(styleName) {
|
|
17594
|
+
if (!canFormatText || !editorFocus.fieldId || !editorFocus.textTokenId) {
|
|
17595
|
+
return;
|
|
17596
|
+
}
|
|
17597
|
+
applyDocument(
|
|
17598
|
+
toggleTextTokenStyle(
|
|
17599
|
+
documentRef.current,
|
|
17600
|
+
editorFocus.fieldId,
|
|
17601
|
+
editorFocus.textTokenId,
|
|
17602
|
+
editorFocus.selectionStart,
|
|
17603
|
+
editorFocus.selectionEnd,
|
|
17604
|
+
styleName
|
|
17605
|
+
),
|
|
17606
|
+
"immediate"
|
|
17607
|
+
);
|
|
17608
|
+
}
|
|
17017
17609
|
const showEditorPanel = !previewOnly && editorOpen;
|
|
17018
17610
|
const showPreviewPanel = previewOnly || previewOpen;
|
|
17019
17611
|
return /* @__PURE__ */ jsx17(
|
|
@@ -17036,8 +17628,11 @@ function ButexDocumentEditor2({
|
|
|
17036
17628
|
selectionCount,
|
|
17037
17629
|
canMoveSelectionUp,
|
|
17038
17630
|
canMoveSelectionDown,
|
|
17631
|
+
canFormatText,
|
|
17632
|
+
activeTextStyles,
|
|
17039
17633
|
onUndo: undoDocument,
|
|
17040
17634
|
onRedo: redoDocument,
|
|
17635
|
+
onToggleTextStyle: toggleInlineTextStyle,
|
|
17041
17636
|
onMoveSelectionUp: () => moveSelectedBlocks(-1),
|
|
17042
17637
|
onMoveSelectionDown: () => moveSelectedBlocks(1),
|
|
17043
17638
|
onDeleteSelection: deleteSelectedBlocks,
|