@tfw.in/structura-lib 0.2.0 → 0.2.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 +9 -361
- package/dist/cjs/EditableContent.js +45 -18
- package/dist/cjs/HtmlViewer.js +217 -83
- package/dist/cjs/MathRenderer.js +88 -0
- package/dist/cjs/PdfDocumentViewer.js +1 -1
- package/dist/cjs/SemanticTagParser.js +189 -0
- package/dist/cjs/SemanticTagRenderer.js +135 -0
- package/dist/cjs/Structura.js +20 -66
- package/dist/cjs/Table.js +73 -8
- package/dist/cjs/TableCell.js +33 -10
- package/dist/cjs/index.js +12 -0
- package/dist/cjs/node_modules/react-icons/fa/index.esm.js +6 -0
- package/dist/cjs/styles.css +2 -4
- package/dist/cjs/styles.css.map +1 -1
- package/dist/esm/EditableContent.js +49 -19
- package/dist/esm/HtmlViewer.js +259 -100
- package/dist/esm/MathRenderer.js +85 -0
- package/dist/esm/PdfDocumentViewer.js +1 -1
- package/dist/esm/SemanticTagParser.js +187 -0
- package/dist/esm/SemanticTagRenderer.js +140 -0
- package/dist/esm/Structura.js +21 -69
- package/dist/esm/Table.js +82 -8
- package/dist/esm/TableCell.js +32 -6
- package/dist/esm/index.js +3 -0
- package/dist/esm/node_modules/react-icons/fa/index.esm.js +5 -1
- package/dist/esm/styles.css +2 -4
- package/dist/esm/styles.css.map +1 -1
- package/dist/esm/types/DocumentOutline.d.ts +7 -0
- package/dist/esm/types/EditableContent.d.ts +7 -1
- package/dist/esm/types/HtmlViewer.d.ts +1 -2
- package/dist/esm/types/MathRenderer.d.ts +25 -0
- package/dist/esm/types/SemanticTagParser.d.ts +33 -0
- package/dist/esm/types/SemanticTagRenderer.d.ts +17 -0
- package/dist/esm/types/Structura.d.ts +1 -2
- package/dist/esm/types/Table.d.ts +3 -1
- package/dist/esm/types/TableCell.d.ts +6 -1
- package/dist/esm/types/helpers/index.d.ts +0 -1
- package/dist/esm/types/index.d.ts +3 -0
- package/dist/esm/types/test-app/src/App.d.ts +1 -2
- package/dist/index.d.ts +78 -4
- package/package.json +9 -16
- package/PRODUCTION_ARCHITECTURE.md +0 -511
- package/SAVE_FUNCTIONALITY_COMPLETE.md +0 -448
- package/dist/cjs/ui/badge.js +0 -34
- package/dist/esm/types/helpers/jsonToHtml.d.ts +0 -40
- package/dist/esm/ui/badge.js +0 -31
- package/server/README.md +0 -203
- package/server/db.js +0 -142
- package/server/server.js +0 -165
package/dist/esm/HtmlViewer.js
CHANGED
|
@@ -2,10 +2,11 @@ import { slicedToArray as _slicedToArray, objectSpread2 as _objectSpread2, defin
|
|
|
2
2
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
3
|
import { useState, useEffect, useCallback, useMemo } from 'react';
|
|
4
4
|
import { VscJson } from 'react-icons/vsc';
|
|
5
|
-
import { FaFileDownload, FaChartBar } from './node_modules/react-icons/fa/index.esm.js';
|
|
5
|
+
import { FaEdit, FaTags, FaFileDownload, FaChartBar } from './node_modules/react-icons/fa/index.esm.js';
|
|
6
6
|
import Table from './Table.js';
|
|
7
7
|
import EditableContent from './EditableContent.js';
|
|
8
8
|
import { calculateDifferences } from './accuracyMetrics.js';
|
|
9
|
+
import { getTagTypeInfo } from './SemanticTagParser.js';
|
|
9
10
|
|
|
10
11
|
// Utility function to clean HTML content
|
|
11
12
|
var cleanHtml = function cleanHtml(html) {
|
|
@@ -140,16 +141,113 @@ function AnalyticsModal(_ref2) {
|
|
|
140
141
|
})
|
|
141
142
|
});
|
|
142
143
|
}
|
|
144
|
+
function TagModal(_ref5) {
|
|
145
|
+
var isOpen = _ref5.isOpen,
|
|
146
|
+
onClose = _ref5.onClose,
|
|
147
|
+
tag = _ref5.tag;
|
|
148
|
+
if (!isOpen || !tag) return null;
|
|
149
|
+
var typeInfo = getTagTypeInfo(tag.type);
|
|
150
|
+
return jsx("div", {
|
|
151
|
+
className: "fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50",
|
|
152
|
+
children: jsxs("div", {
|
|
153
|
+
className: "bg-white rounded-lg p-6 max-w-md w-full shadow-xl",
|
|
154
|
+
children: [jsxs("div", {
|
|
155
|
+
className: "flex justify-between items-center mb-4",
|
|
156
|
+
children: [jsxs("div", {
|
|
157
|
+
className: "flex items-center gap-2",
|
|
158
|
+
children: [jsx("span", {
|
|
159
|
+
className: "text-2xl",
|
|
160
|
+
children: typeInfo.icon
|
|
161
|
+
}), jsxs("h3", {
|
|
162
|
+
className: "text-lg font-semibold",
|
|
163
|
+
children: [typeInfo.label, " Tag"]
|
|
164
|
+
})]
|
|
165
|
+
}), jsx("button", {
|
|
166
|
+
onClick: onClose,
|
|
167
|
+
className: "text-gray-500 hover:text-gray-700",
|
|
168
|
+
children: "\u2715"
|
|
169
|
+
})]
|
|
170
|
+
}), jsx("div", {
|
|
171
|
+
className: "p-4 rounded-lg border ".concat(typeInfo.bgColor, " mb-4"),
|
|
172
|
+
children: jsxs("div", {
|
|
173
|
+
className: "text-2xl font-bold ".concat(typeInfo.color),
|
|
174
|
+
children: [tag.value, tag.attributes.uom && jsx("span", {
|
|
175
|
+
className: "text-lg ml-2 opacity-75",
|
|
176
|
+
children: tag.attributes.uom
|
|
177
|
+
})]
|
|
178
|
+
})
|
|
179
|
+
}), jsxs("div", {
|
|
180
|
+
className: "space-y-3",
|
|
181
|
+
children: [jsxs("div", {
|
|
182
|
+
className: "flex justify-between py-2 border-b",
|
|
183
|
+
children: [jsx("span", {
|
|
184
|
+
className: "text-gray-600",
|
|
185
|
+
children: "Type"
|
|
186
|
+
}), jsx("span", {
|
|
187
|
+
className: "font-medium ".concat(typeInfo.color),
|
|
188
|
+
children: tag.type
|
|
189
|
+
})]
|
|
190
|
+
}), tag.attributes.uom && jsxs("div", {
|
|
191
|
+
className: "flex justify-between py-2 border-b",
|
|
192
|
+
children: [jsx("span", {
|
|
193
|
+
className: "text-gray-600",
|
|
194
|
+
children: "Unit of Measure"
|
|
195
|
+
}), jsx("span", {
|
|
196
|
+
className: "font-medium",
|
|
197
|
+
children: tag.attributes.uom
|
|
198
|
+
})]
|
|
199
|
+
}), tag.attributes.id && jsxs("div", {
|
|
200
|
+
className: "py-2 border-b",
|
|
201
|
+
children: [jsx("span", {
|
|
202
|
+
className: "text-gray-600 block mb-1",
|
|
203
|
+
children: "Tag ID"
|
|
204
|
+
}), jsx("code", {
|
|
205
|
+
className: "text-xs bg-gray-100 p-2 rounded block break-all",
|
|
206
|
+
children: tag.attributes.id
|
|
207
|
+
})]
|
|
208
|
+
}), tag.attributes.format && jsxs("div", {
|
|
209
|
+
className: "flex justify-between py-2 border-b",
|
|
210
|
+
children: [jsx("span", {
|
|
211
|
+
className: "text-gray-600",
|
|
212
|
+
children: "Format"
|
|
213
|
+
}), jsx("span", {
|
|
214
|
+
className: "font-mono text-sm",
|
|
215
|
+
children: tag.attributes.format
|
|
216
|
+
})]
|
|
217
|
+
}), tag.attributes.filter && jsxs("div", {
|
|
218
|
+
className: "flex justify-between py-2 border-b",
|
|
219
|
+
children: [jsx("span", {
|
|
220
|
+
className: "text-gray-600",
|
|
221
|
+
children: "File Filter"
|
|
222
|
+
}), jsx("span", {
|
|
223
|
+
className: "font-mono text-sm",
|
|
224
|
+
children: tag.attributes.filter
|
|
225
|
+
})]
|
|
226
|
+
}), jsxs("div", {
|
|
227
|
+
className: "py-2",
|
|
228
|
+
children: [jsx("span", {
|
|
229
|
+
className: "text-gray-600 block mb-1",
|
|
230
|
+
children: "Raw Tag"
|
|
231
|
+
}), jsx("code", {
|
|
232
|
+
className: "text-xs bg-gray-100 p-2 rounded block break-all text-gray-700",
|
|
233
|
+
children: tag.rawMatch
|
|
234
|
+
})]
|
|
235
|
+
})]
|
|
236
|
+
})]
|
|
237
|
+
})
|
|
238
|
+
});
|
|
239
|
+
}
|
|
143
240
|
// Update icon usage in the JSX
|
|
144
241
|
var VscJsonIcon = VscJson;
|
|
145
242
|
var FaFileDownloadIcon = FaFileDownload;
|
|
146
243
|
var FaChartBarIcon = FaChartBar;
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
244
|
+
var FaEditIcon = FaEdit;
|
|
245
|
+
var FaTagsIcon = FaTags;
|
|
246
|
+
function HtmlViewer(_ref6) {
|
|
247
|
+
var jsonData = _ref6.jsonData,
|
|
248
|
+
selectedBboxId = _ref6.selectedBboxId,
|
|
249
|
+
isLoading = _ref6.isLoading,
|
|
250
|
+
onNodeClick = _ref6.onNodeClick;
|
|
153
251
|
var _useState = useState(jsonData),
|
|
154
252
|
_useState2 = _slicedToArray(_useState, 2),
|
|
155
253
|
editedData = _useState2[0],
|
|
@@ -166,15 +264,11 @@ function HtmlViewer(_ref5) {
|
|
|
166
264
|
_useState8 = _slicedToArray(_useState7, 2),
|
|
167
265
|
modalData = _useState8[0],
|
|
168
266
|
setModalData = _useState8[1];
|
|
169
|
-
var _useState9 = useState(
|
|
267
|
+
var _useState9 = useState('read'),
|
|
170
268
|
_useState0 = _slicedToArray(_useState9, 2),
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
var _useState1 = useState(
|
|
174
|
-
_useState10 = _slicedToArray(_useState1, 2),
|
|
175
|
-
activeFormat = _useState10[0],
|
|
176
|
-
setActiveFormat = _useState10[1];
|
|
177
|
-
var _useState11 = useState({
|
|
269
|
+
viewMode = _useState0[0],
|
|
270
|
+
setViewMode = _useState0[1];
|
|
271
|
+
var _useState1 = useState({
|
|
178
272
|
totalChanges: 0,
|
|
179
273
|
totalCharactersEdited: 0,
|
|
180
274
|
totalWordsEdited: 0,
|
|
@@ -182,13 +276,25 @@ function HtmlViewer(_ref5) {
|
|
|
182
276
|
changeHistory: [],
|
|
183
277
|
blockTypeStats: {}
|
|
184
278
|
}),
|
|
279
|
+
_useState10 = _slicedToArray(_useState1, 2),
|
|
280
|
+
accuracyMetrics = _useState10[0],
|
|
281
|
+
setAccuracyMetrics = _useState10[1];
|
|
282
|
+
var _useState11 = useState(false),
|
|
185
283
|
_useState12 = _slicedToArray(_useState11, 2),
|
|
186
|
-
|
|
187
|
-
|
|
284
|
+
isAnalyticsOpen = _useState12[0],
|
|
285
|
+
setIsAnalyticsOpen = _useState12[1];
|
|
188
286
|
var _useState13 = useState(false),
|
|
189
287
|
_useState14 = _slicedToArray(_useState13, 2),
|
|
190
|
-
|
|
191
|
-
|
|
288
|
+
isTagModalOpen = _useState14[0],
|
|
289
|
+
setIsTagModalOpen = _useState14[1];
|
|
290
|
+
var _useState15 = useState(null),
|
|
291
|
+
_useState16 = _slicedToArray(_useState15, 2),
|
|
292
|
+
selectedTag = _useState16[0],
|
|
293
|
+
setSelectedTag = _useState16[1];
|
|
294
|
+
var _useState17 = useState(true),
|
|
295
|
+
_useState18 = _slicedToArray(_useState17, 2),
|
|
296
|
+
showSemanticTags = _useState18[0],
|
|
297
|
+
setShowSemanticTags = _useState18[1];
|
|
192
298
|
useEffect(function () {
|
|
193
299
|
// Reset state when jsonData changes
|
|
194
300
|
// console.log("HtmlViewer received new jsonData");
|
|
@@ -207,6 +313,10 @@ function HtmlViewer(_ref5) {
|
|
|
207
313
|
setModalData(node);
|
|
208
314
|
setIsModalOpen(true);
|
|
209
315
|
};
|
|
316
|
+
var handleSemanticTagClick = function handleSemanticTagClick(tag) {
|
|
317
|
+
setSelectedTag(tag);
|
|
318
|
+
setIsTagModalOpen(true);
|
|
319
|
+
};
|
|
210
320
|
var updateAccuracyMetrics = useCallback(function (nodeId, blockType, originalContent, newContent) {
|
|
211
321
|
var differences = calculateDifferences(originalContent, newContent);
|
|
212
322
|
var change = {
|
|
@@ -296,10 +406,7 @@ function HtmlViewer(_ref5) {
|
|
|
296
406
|
};
|
|
297
407
|
// Function to get the appropriate HTML content based on settings
|
|
298
408
|
var getHtmlContent = function getHtmlContent(node) {
|
|
299
|
-
|
|
300
|
-
// This preserves the node structure and click interactivity
|
|
301
|
-
// getBlockHtml/jsonToHtml should only be used for full page rendering/export
|
|
302
|
-
return cleanHtml(node.html || '');
|
|
409
|
+
return cleanHtml(node.html || "");
|
|
303
410
|
};
|
|
304
411
|
var mergedTablesMap = useMemo(function () {
|
|
305
412
|
var map = new Map();
|
|
@@ -450,10 +557,13 @@ function HtmlViewer(_ref5) {
|
|
|
450
557
|
var hasChildren = node.children && node.children.length > 0;
|
|
451
558
|
var isTable = ((_a = node.block_type) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === "table";
|
|
452
559
|
var isTableOfContents = node.block_type === "TableOfContents";
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
560
|
+
node.block_type === "Text";
|
|
561
|
+
node.block_type === "Handwriting";
|
|
562
|
+
node.block_type === "SectionHeader";
|
|
456
563
|
var isPage = node.block_type === "Page";
|
|
564
|
+
var isFigure = node.block_type === "Figure" || node.block_type === "Picture";
|
|
565
|
+
var isPageHeader = node.block_type === "PageHeader";
|
|
566
|
+
var isPageFooter = node.block_type === "PageFooter";
|
|
457
567
|
// Get the appropriate HTML content
|
|
458
568
|
var htmlContent = getHtmlContent(node);
|
|
459
569
|
var isHeading = htmlContent && (htmlContent.startsWith("<h1") || htmlContent.startsWith("<h2") || htmlContent.startsWith("<h3") || htmlContent.startsWith("<h4"));
|
|
@@ -474,50 +584,82 @@ function HtmlViewer(_ref5) {
|
|
|
474
584
|
onNodeClick(node.id);
|
|
475
585
|
}
|
|
476
586
|
};
|
|
477
|
-
return
|
|
587
|
+
return jsx("div", {
|
|
478
588
|
id: node.id,
|
|
479
|
-
className: "
|
|
589
|
+
className: "px-1 py-0.5 rounded transition-colors relative group max-w-full overflow-hidden ".concat(isSelected ? "bg-blue-100 border-2 border-blue-500" : "", " ").concat(onNodeClick && !isPage ? "cursor-pointer hover:bg-gray-50" : ""),
|
|
480
590
|
onClick: isPage ? undefined : handleContentClick,
|
|
481
|
-
children:
|
|
482
|
-
onClick: function onClick(e) {
|
|
483
|
-
e.stopPropagation(); // Prevent triggering parent onClick
|
|
484
|
-
handleJsonClick(node);
|
|
485
|
-
},
|
|
486
|
-
className: "absolute right-2 top-2 z-10 ".concat(showJsonIcons ? "opacity-0 group-hover:opacity-100 transition-opacity" : "hidden", " text-gray-500 hover:text-gray-700"),
|
|
487
|
-
title: "View JSON",
|
|
488
|
-
children: jsx(VscJsonIcon, {
|
|
489
|
-
size: 18
|
|
490
|
-
})
|
|
491
|
-
}), isTable || isTableOfContents ? jsx(Table, {
|
|
591
|
+
children: isTable || isTableOfContents ? jsx(Table, {
|
|
492
592
|
node: node,
|
|
493
593
|
selectedBboxId: selectedBboxId,
|
|
494
594
|
onJsonClick: handleJsonClick,
|
|
495
595
|
onContentChange: handleContentChange,
|
|
496
596
|
mergedTables: node.merged_table_id ? (mergedTablesMap.get(node.merged_table_id) || []).slice(1) : [],
|
|
497
597
|
hasLlmHtml: !!node.llm_table_html,
|
|
498
|
-
showJsonIcons:
|
|
499
|
-
onNodeClick: onNodeClick
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
598
|
+
showJsonIcons: false,
|
|
599
|
+
onNodeClick: onNodeClick,
|
|
600
|
+
isEditMode: viewMode === 'edit',
|
|
601
|
+
isJsonMode: viewMode === 'json'
|
|
602
|
+
}) : isFigure && node.images ? jsx("div", {
|
|
603
|
+
className: "my-2 ".concat(viewMode === 'json' ? 'cursor-pointer hover:opacity-80' : ''),
|
|
604
|
+
onClick: viewMode === 'json' ? function () {
|
|
605
|
+
return handleJsonClick(node);
|
|
606
|
+
} : undefined,
|
|
607
|
+
children: Object.entries(node.images).map(function (_ref7) {
|
|
608
|
+
var _ref8 = _slicedToArray(_ref7, 2),
|
|
609
|
+
key = _ref8[0],
|
|
610
|
+
imageData = _ref8[1];
|
|
611
|
+
return jsx("img", {
|
|
612
|
+
src: typeof imageData === 'string' && imageData.startsWith('data:') ? imageData : "data:image/png;base64,".concat(imageData),
|
|
613
|
+
alt: "Figure ".concat(node.id),
|
|
614
|
+
className: "max-w-full h-auto rounded border border-gray-200"
|
|
615
|
+
}, key);
|
|
616
|
+
})
|
|
617
|
+
}) : isPageHeader || isPageFooter ? jsxs("div", {
|
|
618
|
+
className: "my-1 px-3 py-1.5 rounded-md border text-xs flex items-center gap-2\n\t\t\t\t\t\t\t".concat(isPageHeader ? 'bg-amber-50 border-amber-200 text-amber-800' : 'bg-slate-50 border-slate-200 text-slate-600', "\n\t\t\t\t\t\t\t").concat(viewMode === 'json' ? 'cursor-pointer hover:opacity-80' : ''),
|
|
619
|
+
onClick: viewMode === 'json' ? function () {
|
|
620
|
+
return handleJsonClick(node);
|
|
621
|
+
} : undefined,
|
|
622
|
+
children: [jsx("span", {
|
|
623
|
+
className: "font-semibold uppercase tracking-wide ".concat(isPageHeader ? 'text-amber-600' : 'text-slate-500'),
|
|
624
|
+
children: isPageHeader ? '⬆ Header' : '⬇ Footer'
|
|
625
|
+
}), htmlContent && jsx("span", {
|
|
626
|
+
className: "text-gray-600",
|
|
511
627
|
dangerouslySetInnerHTML: {
|
|
512
628
|
__html: htmlContent
|
|
513
629
|
}
|
|
630
|
+
}), node.images && Object.entries(node.images).map(function (_ref9) {
|
|
631
|
+
var _ref0 = _slicedToArray(_ref9, 2),
|
|
632
|
+
key = _ref0[0],
|
|
633
|
+
imageData = _ref0[1];
|
|
634
|
+
return jsx("img", {
|
|
635
|
+
src: typeof imageData === 'string' && imageData.startsWith('data:') ? imageData : "data:image/png;base64,".concat(imageData),
|
|
636
|
+
alt: "".concat(isPageHeader ? 'Header' : 'Footer', " image"),
|
|
637
|
+
className: "h-6 w-auto"
|
|
638
|
+
}, key);
|
|
639
|
+
})]
|
|
640
|
+
}) : jsxs(Fragment, {
|
|
641
|
+
children: [jsx(EditableContent, {
|
|
642
|
+
id: node.id,
|
|
643
|
+
content: htmlContent,
|
|
644
|
+
onContentChange: handleContentChange,
|
|
645
|
+
isHeading: !!isHeading,
|
|
646
|
+
isEditMode: viewMode === 'edit',
|
|
647
|
+
isJsonMode: viewMode === 'json',
|
|
648
|
+
onJsonClick: function onJsonClick() {
|
|
649
|
+
return handleJsonClick(node);
|
|
650
|
+
},
|
|
651
|
+
onNodeClick: onNodeClick && !isPage ? function () {
|
|
652
|
+
return onNodeClick(node.id);
|
|
653
|
+
} : undefined,
|
|
654
|
+
enableSemanticTags: showSemanticTags,
|
|
655
|
+
onSemanticTagClick: handleSemanticTagClick
|
|
514
656
|
}), hasChildren && jsx("div", {
|
|
515
|
-
className: "ml-
|
|
657
|
+
className: "ml-2 mt-1 border-l border-gray-200 pl-2 max-w-full overflow-hidden",
|
|
516
658
|
children: node.children.map(function (child) {
|
|
517
659
|
return _renderHtmlContent(child);
|
|
518
660
|
})
|
|
519
661
|
})]
|
|
520
|
-
})
|
|
662
|
+
})
|
|
521
663
|
}, node.id);
|
|
522
664
|
};
|
|
523
665
|
var getAllNodes = function getAllNodes(data) {
|
|
@@ -535,69 +677,80 @@ function HtmlViewer(_ref5) {
|
|
|
535
677
|
});
|
|
536
678
|
};
|
|
537
679
|
var allNodes = getAllNodes(editedData);
|
|
538
|
-
// Update the header section
|
|
680
|
+
// Update the header section with toggle buttons
|
|
539
681
|
var renderHeader = function renderHeader() {
|
|
540
682
|
return jsxs("div", {
|
|
541
|
-
className: "sticky top-0 z-20 bg-white border-b border-gray-200 p-
|
|
542
|
-
children: [
|
|
543
|
-
className: "flex gap-
|
|
544
|
-
children:
|
|
545
|
-
|
|
683
|
+
className: "sticky top-0 z-20 bg-white border-b border-gray-200 p-3 flex justify-between items-center flex-shrink-0",
|
|
684
|
+
children: [jsxs("div", {
|
|
685
|
+
className: "flex gap-1",
|
|
686
|
+
children: [jsxs("div", {
|
|
687
|
+
className: "flex bg-gray-100 rounded-lg p-1",
|
|
688
|
+
children: [jsxs("button", {
|
|
546
689
|
onClick: function onClick() {
|
|
547
|
-
return
|
|
690
|
+
return setViewMode(viewMode === 'json' ? 'read' : 'json');
|
|
548
691
|
},
|
|
549
|
-
className: "inline-flex items-center gap-2 px-
|
|
550
|
-
title: "
|
|
551
|
-
children: [jsx(
|
|
552
|
-
size:
|
|
553
|
-
}), "
|
|
692
|
+
className: "inline-flex items-center gap-2 px-3 py-1.5 rounded-md transition-colors ".concat(viewMode === 'json' ? "bg-blue-600 text-white shadow-sm" : "text-gray-600 hover:text-gray-900 hover:bg-gray-200"),
|
|
693
|
+
title: "JSON Mode - Click any element to view its JSON",
|
|
694
|
+
children: [jsx(VscJsonIcon, {
|
|
695
|
+
size: 16
|
|
696
|
+
}), jsx("span", {
|
|
697
|
+
className: "text-sm font-medium",
|
|
698
|
+
children: "JSON"
|
|
699
|
+
})]
|
|
554
700
|
}), jsxs("button", {
|
|
555
|
-
onClick:
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
701
|
+
onClick: function onClick() {
|
|
702
|
+
return setViewMode(viewMode === 'edit' ? 'read' : 'edit');
|
|
703
|
+
},
|
|
704
|
+
className: "inline-flex items-center gap-2 px-3 py-1.5 rounded-md transition-colors ".concat(viewMode === 'edit' ? "bg-green-600 text-white shadow-sm" : "text-gray-600 hover:text-gray-900 hover:bg-gray-200"),
|
|
705
|
+
title: "Edit Mode - Click any element to edit it",
|
|
706
|
+
children: [jsx(FaEditIcon, {
|
|
707
|
+
size: 16
|
|
708
|
+
}), jsx("span", {
|
|
709
|
+
className: "text-sm font-medium",
|
|
710
|
+
children: "Edit"
|
|
711
|
+
})]
|
|
561
712
|
})]
|
|
562
|
-
})
|
|
563
|
-
}), jsxs("div", {
|
|
564
|
-
className: "flex gap-2 items-center",
|
|
565
|
-
children: [jsx("button", {
|
|
713
|
+
}), jsxs("button", {
|
|
566
714
|
onClick: function onClick() {
|
|
567
|
-
return
|
|
715
|
+
return setShowSemanticTags(!showSemanticTags);
|
|
568
716
|
},
|
|
569
|
-
className: "inline-flex items-center gap-2 px-
|
|
570
|
-
title: "
|
|
571
|
-
children: jsx(
|
|
572
|
-
size:
|
|
573
|
-
})
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
}), jsx("
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
setActiveFormat("Hide JSON");
|
|
587
|
-
},
|
|
588
|
-
className: "py-1.5 px-3 text-sm font-medium rounded-md transition-colors whitespace-nowrap ".concat(activeFormat === "Hide JSON" ? "bg-white text-gray-900 shadow-sm" : "text-gray-600 hover:text-gray-900"),
|
|
589
|
-
children: "Hide JSON"
|
|
717
|
+
className: "inline-flex items-center gap-2 px-3 py-1.5 rounded-md transition-colors ml-2 ".concat(showSemanticTags ? "bg-amber-100 text-amber-700 border border-amber-300" : "bg-gray-100 text-gray-500 border border-gray-200"),
|
|
718
|
+
title: showSemanticTags ? "Hide Semantic Tags" : "Show Semantic Tags",
|
|
719
|
+
children: [jsx(FaTagsIcon, {
|
|
720
|
+
size: 16
|
|
721
|
+
}), jsx("span", {
|
|
722
|
+
className: "text-sm font-medium",
|
|
723
|
+
children: "Tags"
|
|
724
|
+
})]
|
|
725
|
+
}), hasChanges && jsxs("button", {
|
|
726
|
+
onClick: handleDownload,
|
|
727
|
+
className: "inline-flex items-center gap-2 px-3 py-1.5 bg-purple-600 text-white rounded-md hover:bg-purple-700 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2 ml-2",
|
|
728
|
+
title: "Download Updated JSON",
|
|
729
|
+
children: [jsx(FaFileDownloadIcon, {
|
|
730
|
+
size: 16
|
|
731
|
+
}), jsx("span", {
|
|
732
|
+
className: "text-sm font-medium",
|
|
733
|
+
children: "Save"
|
|
590
734
|
})]
|
|
591
735
|
})]
|
|
736
|
+
}), jsx("button", {
|
|
737
|
+
onClick: function onClick() {
|
|
738
|
+
return setIsAnalyticsOpen(true);
|
|
739
|
+
},
|
|
740
|
+
className: "inline-flex items-center gap-1 px-3 py-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-100 rounded-md",
|
|
741
|
+
title: "View Analytics",
|
|
742
|
+
children: jsx(FaChartBarIcon, {
|
|
743
|
+
size: 16
|
|
744
|
+
})
|
|
592
745
|
})]
|
|
593
746
|
});
|
|
594
747
|
};
|
|
595
748
|
return jsxs("div", {
|
|
596
749
|
className: "w-full h-full max-w-full flex flex-col overflow-hidden",
|
|
597
750
|
children: [renderHeader(), jsx("div", {
|
|
598
|
-
className: "flex-1 overflow-auto min-h-0 max-w-full",
|
|
751
|
+
className: "flex-1 overflow-auto min-h-0 max-w-full ".concat(viewMode === 'edit' ? 'bg-green-50/50' : viewMode === 'json' ? 'bg-blue-50/50' : ''),
|
|
599
752
|
children: jsx("div", {
|
|
600
|
-
className: "p-
|
|
753
|
+
className: "p-2 max-w-full",
|
|
601
754
|
children: allNodes.map(function (node) {
|
|
602
755
|
return jsx("div", {
|
|
603
756
|
className: "w-full max-w-full overflow-hidden break-words",
|
|
@@ -617,6 +770,12 @@ function HtmlViewer(_ref5) {
|
|
|
617
770
|
return setIsModalOpen(false);
|
|
618
771
|
},
|
|
619
772
|
data: modalData
|
|
773
|
+
}), jsx(TagModal, {
|
|
774
|
+
isOpen: isTagModalOpen,
|
|
775
|
+
onClose: function onClose() {
|
|
776
|
+
return setIsTagModalOpen(false);
|
|
777
|
+
},
|
|
778
|
+
tag: selectedTag
|
|
620
779
|
})]
|
|
621
780
|
});
|
|
622
781
|
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import katex from 'katex';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Renders LaTeX math expressions in HTML content using KaTeX.
|
|
7
|
+
* Supports both inline ($...$) and display ($$...$$) math.
|
|
8
|
+
*/
|
|
9
|
+
// Regex patterns for math delimiters
|
|
10
|
+
var DISPLAY_MATH_REGEX = /\$\$([\s\S]*?)\$\$/g;
|
|
11
|
+
var INLINE_MATH_REGEX = /\$([^\$\n]+?)\$/g;
|
|
12
|
+
/**
|
|
13
|
+
* Render a single LaTeX expression to HTML using KaTeX
|
|
14
|
+
*/
|
|
15
|
+
function renderLatex(latex, displayMode) {
|
|
16
|
+
try {
|
|
17
|
+
return katex.renderToString(latex, {
|
|
18
|
+
displayMode: displayMode,
|
|
19
|
+
throwOnError: false,
|
|
20
|
+
errorColor: "#cc0000",
|
|
21
|
+
strict: false,
|
|
22
|
+
trust: true,
|
|
23
|
+
macros: {
|
|
24
|
+
"\\leq": "\\le",
|
|
25
|
+
"\\geq": "\\ge"
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
} catch (error) {
|
|
29
|
+
console.warn("KaTeX render error:", error);
|
|
30
|
+
// Return the original with error styling
|
|
31
|
+
return "<span class=\"katex-error\" style=\"color: #cc0000;\">".concat(latex, "</span>");
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Process HTML content and render all math expressions
|
|
36
|
+
*/
|
|
37
|
+
function renderMathInHtml(html) {
|
|
38
|
+
if (!html) return "";
|
|
39
|
+
// First, handle display math ($$...$$)
|
|
40
|
+
var result = html.replace(DISPLAY_MATH_REGEX, function (match, latex) {
|
|
41
|
+
return renderLatex(latex.trim(), true);
|
|
42
|
+
});
|
|
43
|
+
// Then, handle inline math ($...$)
|
|
44
|
+
// The $...$ pattern with closing $ is always math, not currency
|
|
45
|
+
result = result.replace(INLINE_MATH_REGEX, function (match, latex) {
|
|
46
|
+
return renderLatex(latex.trim(), false);
|
|
47
|
+
});
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Check if content contains any math expressions
|
|
52
|
+
*/
|
|
53
|
+
function containsMath(html) {
|
|
54
|
+
if (!html) return false;
|
|
55
|
+
return DISPLAY_MATH_REGEX.test(html) || INLINE_MATH_REGEX.test(html);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* React component that renders HTML with math expressions
|
|
59
|
+
*/
|
|
60
|
+
function MathContent(_ref) {
|
|
61
|
+
var html = _ref.html,
|
|
62
|
+
_ref$className = _ref.className,
|
|
63
|
+
className = _ref$className === void 0 ? "" : _ref$className,
|
|
64
|
+
_ref$as = _ref.as,
|
|
65
|
+
Component = _ref$as === void 0 ? "span" : _ref$as;
|
|
66
|
+
var renderedHtml = useMemo(function () {
|
|
67
|
+
return renderMathInHtml(html);
|
|
68
|
+
}, [html]);
|
|
69
|
+
return jsx(Component, {
|
|
70
|
+
className: className,
|
|
71
|
+
dangerouslySetInnerHTML: {
|
|
72
|
+
__html: renderedHtml
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Hook to get rendered math HTML
|
|
78
|
+
*/
|
|
79
|
+
function useMathHtml(html) {
|
|
80
|
+
return useMemo(function () {
|
|
81
|
+
return renderMathInHtml(html);
|
|
82
|
+
}, [html]);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export { MathContent, containsMath, MathContent as default, renderMathInHtml, useMathHtml };
|
|
@@ -177,7 +177,7 @@ function PdfDocumentViewer(_ref2) {
|
|
|
177
177
|
var currentPath = "".concat(path, "/").concat(block.block_type, "[").concat(index, "](").concat(block.id, ")");
|
|
178
178
|
// Assuming block.polygon is number[][] (array of points)
|
|
179
179
|
var points = block.polygon;
|
|
180
|
-
if (points && Array.isArray(points) && points.length >= 2 && block.block_type !== "Page") {
|
|
180
|
+
if (points && Array.isArray(points) && points.length >= 2 && block.block_type !== "Page" && block.block_type !== "TableCell") {
|
|
181
181
|
// Calculate bbox from points
|
|
182
182
|
var x_coords = points.map(function (p) {
|
|
183
183
|
return p[0];
|