@tfw.in/structura-lib 0.2.0 → 0.2.2
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 +72 -323
- package/dist/cjs/EditableContent.js +46 -18
- package/dist/cjs/HtmlViewer.js +238 -85
- 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 +49 -76
- package/dist/cjs/Table.js +75 -8
- package/dist/cjs/TableCell.js +34 -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 +51 -19
- package/dist/esm/HtmlViewer.js +287 -103
- 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 +57 -80
- package/dist/esm/Table.js +85 -8
- package/dist/esm/TableCell.js +34 -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 +8 -1
- package/dist/esm/types/HtmlViewer.d.ts +9 -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 +13 -8
- package/dist/esm/types/Table.d.ts +4 -1
- package/dist/esm/types/TableCell.d.ts +7 -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 +90 -10
- 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
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { slicedToArray as _slicedToArray } from './_virtual/_rollupPluginBabelHelpers.js';
|
|
2
2
|
import { jsx } from 'react/jsx-runtime';
|
|
3
|
-
import { useState, useRef, useEffect } from 'react';
|
|
3
|
+
import { useState, useRef, useEffect, useMemo } from 'react';
|
|
4
|
+
import SemanticTagRenderer from './SemanticTagRenderer.js';
|
|
5
|
+
import { hasSemanticTags } from './SemanticTagParser.js';
|
|
6
|
+
import { renderMathInHtml } from './MathRenderer.js';
|
|
4
7
|
|
|
5
8
|
// Helper function to extract text content while preserving structure
|
|
6
9
|
var extractTextPreservingStructure = function extractTextPreservingStructure(html) {
|
|
@@ -23,7 +26,17 @@ function EditableContent(_ref) {
|
|
|
23
26
|
onContentChange = _ref.onContentChange,
|
|
24
27
|
_ref$isHeading = _ref.isHeading,
|
|
25
28
|
isHeading = _ref$isHeading === void 0 ? false : _ref$isHeading,
|
|
26
|
-
|
|
29
|
+
_ref$isEditMode = _ref.isEditMode,
|
|
30
|
+
isEditMode = _ref$isEditMode === void 0 ? false : _ref$isEditMode,
|
|
31
|
+
_ref$isJsonMode = _ref.isJsonMode,
|
|
32
|
+
isJsonMode = _ref$isJsonMode === void 0 ? false : _ref$isJsonMode,
|
|
33
|
+
onNodeClick = _ref.onNodeClick,
|
|
34
|
+
onJsonClick = _ref.onJsonClick,
|
|
35
|
+
_ref$enableSemanticTa = _ref.enableSemanticTags,
|
|
36
|
+
enableSemanticTags = _ref$enableSemanticTa === void 0 ? true : _ref$enableSemanticTa,
|
|
37
|
+
onSemanticTagClick = _ref.onSemanticTagClick,
|
|
38
|
+
_ref$enableMathRender = _ref.enableMathRendering,
|
|
39
|
+
enableMathRendering = _ref$enableMathRender === void 0 ? true : _ref$enableMathRender;
|
|
27
40
|
var _useState = useState(false),
|
|
28
41
|
_useState2 = _slicedToArray(_useState, 2),
|
|
29
42
|
isEditing = _useState2[0],
|
|
@@ -64,24 +77,22 @@ function EditableContent(_ref) {
|
|
|
64
77
|
var getHeadingStyles = function getHeadingStyles(level) {
|
|
65
78
|
switch (level) {
|
|
66
79
|
case 1:
|
|
67
|
-
return "text-2xl font-bold";
|
|
68
|
-
case 2:
|
|
69
80
|
return "text-xl font-bold";
|
|
70
|
-
case
|
|
81
|
+
case 2:
|
|
71
82
|
return "text-lg font-bold";
|
|
72
|
-
case
|
|
83
|
+
case 3:
|
|
73
84
|
return "text-base font-bold";
|
|
74
|
-
case
|
|
85
|
+
case 4:
|
|
75
86
|
return "text-sm font-bold";
|
|
76
|
-
case
|
|
87
|
+
case 5:
|
|
77
88
|
return "text-xs font-bold";
|
|
89
|
+
case 6:
|
|
90
|
+
return "text-xs font-semibold";
|
|
78
91
|
default:
|
|
79
|
-
return "text-
|
|
92
|
+
return "text-sm";
|
|
80
93
|
}
|
|
81
94
|
};
|
|
82
|
-
var
|
|
83
|
-
// Stop propagation to prevent parent click handlers from firing
|
|
84
|
-
e.stopPropagation();
|
|
95
|
+
var startEditing = function startEditing() {
|
|
85
96
|
if (onContentChange) {
|
|
86
97
|
// Extract text content for textarea while preserving structure
|
|
87
98
|
setTextAreaContent(extractTextPreservingStructure(editedContent));
|
|
@@ -120,6 +131,18 @@ function EditableContent(_ref) {
|
|
|
120
131
|
e.stopPropagation();
|
|
121
132
|
return;
|
|
122
133
|
}
|
|
134
|
+
// In JSON mode, show JSON on click
|
|
135
|
+
if (isJsonMode && onJsonClick) {
|
|
136
|
+
e.stopPropagation();
|
|
137
|
+
onJsonClick();
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
// In edit mode, single click activates editing
|
|
141
|
+
if (isEditMode && onContentChange) {
|
|
142
|
+
e.stopPropagation();
|
|
143
|
+
startEditing();
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
123
146
|
// If there's an onNodeClick handler, call it
|
|
124
147
|
if (onNodeClick) {
|
|
125
148
|
e.stopPropagation(); // Prevent click from reaching parent containers
|
|
@@ -133,27 +156,36 @@ function EditableContent(_ref) {
|
|
|
133
156
|
handleBlur();
|
|
134
157
|
}
|
|
135
158
|
};
|
|
159
|
+
// Render math expressions in content (conditionally)
|
|
160
|
+
var renderedContent = useMemo(function () {
|
|
161
|
+
return enableMathRendering ? renderMathInHtml(editedContent) : editedContent;
|
|
162
|
+
}, [editedContent, enableMathRendering]);
|
|
136
163
|
return jsx("div", {
|
|
137
|
-
className: "w-full ".concat(isEdited ? "bg-yellow-100" : "", " ").concat(onNodeClick && !isEditing ? "cursor-pointer" : ""),
|
|
164
|
+
className: "w-full ".concat(isEdited ? "bg-yellow-100" : "", " ").concat(isJsonMode ? "cursor-pointer hover:bg-purple-50 border border-transparent hover:border-purple-300 rounded" : "", " ").concat(isEditMode && !isEditing ? "cursor-pointer hover:bg-blue-50 border border-transparent hover:border-blue-300 rounded" : "", " ").concat(onNodeClick && !isEditing && !isEditMode && !isJsonMode ? "cursor-pointer" : ""),
|
|
138
165
|
onClick: handleClick,
|
|
139
|
-
onDoubleClick: handleDoubleClick,
|
|
140
166
|
children: isEditing ? jsx("textarea", {
|
|
141
167
|
value: textAreaContent,
|
|
142
168
|
onChange: handleChange,
|
|
143
169
|
onBlur: handleBlur,
|
|
144
170
|
onKeyDown: handleKeyDown,
|
|
145
171
|
autoFocus: true,
|
|
146
|
-
className: "w-full p-1 border border-blue-400 rounded focus:outline-none focus:ring-2 focus:ring-blue-500
|
|
172
|
+
className: "w-full p-1 border border-blue-400 rounded focus:outline-none focus:ring-2 focus:ring-blue-500",
|
|
147
173
|
onClick: function onClick(e) {
|
|
148
174
|
return e.stopPropagation();
|
|
149
175
|
},
|
|
150
176
|
rows: 3
|
|
151
177
|
}) : jsx("div", {
|
|
152
178
|
ref: contentRef,
|
|
153
|
-
className: "prose max-w-none ".concat(isHeading ? getHeadingStyles(headingLevel) : ""),
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
179
|
+
className: "prose prose-sm max-w-none ".concat(isHeading ? getHeadingStyles(headingLevel) : "text-sm"),
|
|
180
|
+
children: enableSemanticTags && hasSemanticTags(editedContent) ? jsx(SemanticTagRenderer, {
|
|
181
|
+
content: editedContent,
|
|
182
|
+
showTooltips: true,
|
|
183
|
+
onTagClick: onSemanticTagClick
|
|
184
|
+
}) : jsx("span", {
|
|
185
|
+
dangerouslySetInnerHTML: {
|
|
186
|
+
__html: renderedContent
|
|
187
|
+
}
|
|
188
|
+
})
|
|
157
189
|
})
|
|
158
190
|
});
|
|
159
191
|
}
|
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,127 @@ 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,
|
|
251
|
+
_ref6$editMode = _ref6.editMode,
|
|
252
|
+
enableEditMode = _ref6$editMode === void 0 ? true : _ref6$editMode,
|
|
253
|
+
_ref6$jsonMode = _ref6.jsonMode,
|
|
254
|
+
enableJsonMode = _ref6$jsonMode === void 0 ? true : _ref6$jsonMode,
|
|
255
|
+
_ref6$mathRendering = _ref6.mathRendering,
|
|
256
|
+
enableMathRendering = _ref6$mathRendering === void 0 ? true : _ref6$mathRendering,
|
|
257
|
+
_ref6$semanticTags = _ref6.semanticTags,
|
|
258
|
+
enableSemanticTags = _ref6$semanticTags === void 0 ? true : _ref6$semanticTags,
|
|
259
|
+
_ref6$headerFooterBad = _ref6.headerFooterBadges,
|
|
260
|
+
enableHeaderFooterBadges = _ref6$headerFooterBad === void 0 ? true : _ref6$headerFooterBad,
|
|
261
|
+
_ref6$defaultViewMode = _ref6.defaultViewMode,
|
|
262
|
+
defaultViewMode = _ref6$defaultViewMode === void 0 ? 'read' : _ref6$defaultViewMode,
|
|
263
|
+
onContentChangeCallback = _ref6.onContentChange,
|
|
264
|
+
onExportCallback = _ref6.onExport;
|
|
153
265
|
var _useState = useState(jsonData),
|
|
154
266
|
_useState2 = _slicedToArray(_useState, 2),
|
|
155
267
|
editedData = _useState2[0],
|
|
@@ -166,15 +278,11 @@ function HtmlViewer(_ref5) {
|
|
|
166
278
|
_useState8 = _slicedToArray(_useState7, 2),
|
|
167
279
|
modalData = _useState8[0],
|
|
168
280
|
setModalData = _useState8[1];
|
|
169
|
-
var _useState9 = useState(
|
|
281
|
+
var _useState9 = useState(defaultViewMode),
|
|
170
282
|
_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({
|
|
283
|
+
viewMode = _useState0[0],
|
|
284
|
+
setViewMode = _useState0[1];
|
|
285
|
+
var _useState1 = useState({
|
|
178
286
|
totalChanges: 0,
|
|
179
287
|
totalCharactersEdited: 0,
|
|
180
288
|
totalWordsEdited: 0,
|
|
@@ -182,13 +290,25 @@ function HtmlViewer(_ref5) {
|
|
|
182
290
|
changeHistory: [],
|
|
183
291
|
blockTypeStats: {}
|
|
184
292
|
}),
|
|
293
|
+
_useState10 = _slicedToArray(_useState1, 2),
|
|
294
|
+
accuracyMetrics = _useState10[0],
|
|
295
|
+
setAccuracyMetrics = _useState10[1];
|
|
296
|
+
var _useState11 = useState(false),
|
|
185
297
|
_useState12 = _slicedToArray(_useState11, 2),
|
|
186
|
-
|
|
187
|
-
|
|
298
|
+
isAnalyticsOpen = _useState12[0],
|
|
299
|
+
setIsAnalyticsOpen = _useState12[1];
|
|
188
300
|
var _useState13 = useState(false),
|
|
189
301
|
_useState14 = _slicedToArray(_useState13, 2),
|
|
190
|
-
|
|
191
|
-
|
|
302
|
+
isTagModalOpen = _useState14[0],
|
|
303
|
+
setIsTagModalOpen = _useState14[1];
|
|
304
|
+
var _useState15 = useState(null),
|
|
305
|
+
_useState16 = _slicedToArray(_useState15, 2),
|
|
306
|
+
selectedTag = _useState16[0],
|
|
307
|
+
setSelectedTag = _useState16[1];
|
|
308
|
+
var _useState17 = useState(enableSemanticTags),
|
|
309
|
+
_useState18 = _slicedToArray(_useState17, 2),
|
|
310
|
+
showSemanticTags = _useState18[0],
|
|
311
|
+
setShowSemanticTags = _useState18[1];
|
|
192
312
|
useEffect(function () {
|
|
193
313
|
// Reset state when jsonData changes
|
|
194
314
|
// console.log("HtmlViewer received new jsonData");
|
|
@@ -207,6 +327,10 @@ function HtmlViewer(_ref5) {
|
|
|
207
327
|
setModalData(node);
|
|
208
328
|
setIsModalOpen(true);
|
|
209
329
|
};
|
|
330
|
+
var handleSemanticTagClick = function handleSemanticTagClick(tag) {
|
|
331
|
+
setSelectedTag(tag);
|
|
332
|
+
setIsTagModalOpen(true);
|
|
333
|
+
};
|
|
210
334
|
var updateAccuracyMetrics = useCallback(function (nodeId, blockType, originalContent, newContent) {
|
|
211
335
|
var differences = calculateDifferences(originalContent, newContent);
|
|
212
336
|
var change = {
|
|
@@ -247,12 +371,13 @@ function HtmlViewer(_ref5) {
|
|
|
247
371
|
}, [jsonData]);
|
|
248
372
|
var handleContentChange = useCallback(function (nodeId, newContent) {
|
|
249
373
|
setHasChanges(true);
|
|
374
|
+
var originalContent = "";
|
|
250
375
|
setEditedData(function (prevData) {
|
|
251
376
|
var newData = JSON.parse(JSON.stringify(prevData));
|
|
252
377
|
var _updateNode = function updateNode(node) {
|
|
253
378
|
if (!node) return false;
|
|
254
379
|
if (node.id === nodeId) {
|
|
255
|
-
|
|
380
|
+
originalContent = node.html || "";
|
|
256
381
|
var blockType = node.block_type || "unknown";
|
|
257
382
|
// Update accuracy metrics before changing content
|
|
258
383
|
updateAccuracyMetrics(nodeId, blockType, originalContent, newContent);
|
|
@@ -278,9 +403,17 @@ function HtmlViewer(_ref5) {
|
|
|
278
403
|
_updateNode(newData);
|
|
279
404
|
return newData;
|
|
280
405
|
});
|
|
281
|
-
|
|
406
|
+
// Call external callback if provided
|
|
407
|
+
if (onContentChangeCallback) {
|
|
408
|
+
onContentChangeCallback(nodeId, originalContent, newContent);
|
|
409
|
+
}
|
|
410
|
+
}, [updateAccuracyMetrics, onContentChangeCallback]);
|
|
282
411
|
var handleDownload = function handleDownload() {
|
|
283
412
|
if (!editedData) return;
|
|
413
|
+
// Call external callback if provided
|
|
414
|
+
if (onExportCallback) {
|
|
415
|
+
onExportCallback(editedData);
|
|
416
|
+
}
|
|
284
417
|
var jsonString = JSON.stringify(editedData, null, 2);
|
|
285
418
|
var blob = new Blob([jsonString], {
|
|
286
419
|
type: "application/json"
|
|
@@ -296,10 +429,7 @@ function HtmlViewer(_ref5) {
|
|
|
296
429
|
};
|
|
297
430
|
// Function to get the appropriate HTML content based on settings
|
|
298
431
|
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 || '');
|
|
432
|
+
return cleanHtml(node.html || "");
|
|
303
433
|
};
|
|
304
434
|
var mergedTablesMap = useMemo(function () {
|
|
305
435
|
var map = new Map();
|
|
@@ -450,10 +580,13 @@ function HtmlViewer(_ref5) {
|
|
|
450
580
|
var hasChildren = node.children && node.children.length > 0;
|
|
451
581
|
var isTable = ((_a = node.block_type) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === "table";
|
|
452
582
|
var isTableOfContents = node.block_type === "TableOfContents";
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
583
|
+
node.block_type === "Text";
|
|
584
|
+
node.block_type === "Handwriting";
|
|
585
|
+
node.block_type === "SectionHeader";
|
|
456
586
|
var isPage = node.block_type === "Page";
|
|
587
|
+
var isFigure = node.block_type === "Figure" || node.block_type === "Picture";
|
|
588
|
+
var isPageHeader = node.block_type === "PageHeader";
|
|
589
|
+
var isPageFooter = node.block_type === "PageFooter";
|
|
457
590
|
// Get the appropriate HTML content
|
|
458
591
|
var htmlContent = getHtmlContent(node);
|
|
459
592
|
var isHeading = htmlContent && (htmlContent.startsWith("<h1") || htmlContent.startsWith("<h2") || htmlContent.startsWith("<h3") || htmlContent.startsWith("<h4"));
|
|
@@ -474,50 +607,84 @@ function HtmlViewer(_ref5) {
|
|
|
474
607
|
onNodeClick(node.id);
|
|
475
608
|
}
|
|
476
609
|
};
|
|
477
|
-
return
|
|
610
|
+
return jsx("div", {
|
|
478
611
|
id: node.id,
|
|
479
|
-
className: "
|
|
612
|
+
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
613
|
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, {
|
|
614
|
+
children: isTable || isTableOfContents ? jsx(Table, {
|
|
492
615
|
node: node,
|
|
493
616
|
selectedBboxId: selectedBboxId,
|
|
494
617
|
onJsonClick: handleJsonClick,
|
|
495
618
|
onContentChange: handleContentChange,
|
|
496
619
|
mergedTables: node.merged_table_id ? (mergedTablesMap.get(node.merged_table_id) || []).slice(1) : [],
|
|
497
620
|
hasLlmHtml: !!node.llm_table_html,
|
|
498
|
-
showJsonIcons:
|
|
499
|
-
onNodeClick: onNodeClick
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
return
|
|
507
|
-
} : undefined
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
621
|
+
showJsonIcons: false,
|
|
622
|
+
onNodeClick: onNodeClick,
|
|
623
|
+
isEditMode: viewMode === 'edit',
|
|
624
|
+
isJsonMode: viewMode === 'json',
|
|
625
|
+
enableMathRendering: enableMathRendering
|
|
626
|
+
}) : isFigure && node.images ? jsx("div", {
|
|
627
|
+
className: "my-2 ".concat(viewMode === 'json' ? 'cursor-pointer hover:opacity-80' : ''),
|
|
628
|
+
onClick: viewMode === 'json' ? function () {
|
|
629
|
+
return handleJsonClick(node);
|
|
630
|
+
} : undefined,
|
|
631
|
+
children: Object.entries(node.images).map(function (_ref7) {
|
|
632
|
+
var _ref8 = _slicedToArray(_ref7, 2),
|
|
633
|
+
key = _ref8[0],
|
|
634
|
+
imageData = _ref8[1];
|
|
635
|
+
return jsx("img", {
|
|
636
|
+
src: typeof imageData === 'string' && imageData.startsWith('data:') ? imageData : "data:image/png;base64,".concat(imageData),
|
|
637
|
+
alt: "Figure ".concat(node.id),
|
|
638
|
+
className: "max-w-full h-auto rounded border border-gray-200"
|
|
639
|
+
}, key);
|
|
640
|
+
})
|
|
641
|
+
}) : (isPageHeader || isPageFooter) && enableHeaderFooterBadges ? jsxs("div", {
|
|
642
|
+
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' : ''),
|
|
643
|
+
onClick: viewMode === 'json' ? function () {
|
|
644
|
+
return handleJsonClick(node);
|
|
645
|
+
} : undefined,
|
|
646
|
+
children: [jsx("span", {
|
|
647
|
+
className: "font-semibold uppercase tracking-wide ".concat(isPageHeader ? 'text-amber-600' : 'text-slate-500'),
|
|
648
|
+
children: isPageHeader ? '⬆ Header' : '⬇ Footer'
|
|
649
|
+
}), htmlContent && jsx("span", {
|
|
650
|
+
className: "text-gray-600",
|
|
511
651
|
dangerouslySetInnerHTML: {
|
|
512
652
|
__html: htmlContent
|
|
513
653
|
}
|
|
654
|
+
}), node.images && Object.entries(node.images).map(function (_ref9) {
|
|
655
|
+
var _ref0 = _slicedToArray(_ref9, 2),
|
|
656
|
+
key = _ref0[0],
|
|
657
|
+
imageData = _ref0[1];
|
|
658
|
+
return jsx("img", {
|
|
659
|
+
src: typeof imageData === 'string' && imageData.startsWith('data:') ? imageData : "data:image/png;base64,".concat(imageData),
|
|
660
|
+
alt: "".concat(isPageHeader ? 'Header' : 'Footer', " image"),
|
|
661
|
+
className: "h-6 w-auto"
|
|
662
|
+
}, key);
|
|
663
|
+
})]
|
|
664
|
+
}) : jsxs(Fragment, {
|
|
665
|
+
children: [jsx(EditableContent, {
|
|
666
|
+
id: node.id,
|
|
667
|
+
content: htmlContent,
|
|
668
|
+
onContentChange: handleContentChange,
|
|
669
|
+
isHeading: !!isHeading,
|
|
670
|
+
isEditMode: viewMode === 'edit',
|
|
671
|
+
isJsonMode: viewMode === 'json',
|
|
672
|
+
onJsonClick: function onJsonClick() {
|
|
673
|
+
return handleJsonClick(node);
|
|
674
|
+
},
|
|
675
|
+
onNodeClick: onNodeClick && !isPage ? function () {
|
|
676
|
+
return onNodeClick(node.id);
|
|
677
|
+
} : undefined,
|
|
678
|
+
enableSemanticTags: showSemanticTags,
|
|
679
|
+
onSemanticTagClick: handleSemanticTagClick,
|
|
680
|
+
enableMathRendering: enableMathRendering
|
|
514
681
|
}), hasChildren && jsx("div", {
|
|
515
|
-
className: "ml-
|
|
682
|
+
className: "ml-2 mt-1 border-l border-gray-200 pl-2 max-w-full overflow-hidden",
|
|
516
683
|
children: node.children.map(function (child) {
|
|
517
684
|
return _renderHtmlContent(child);
|
|
518
685
|
})
|
|
519
686
|
})]
|
|
520
|
-
})
|
|
687
|
+
})
|
|
521
688
|
}, node.id);
|
|
522
689
|
};
|
|
523
690
|
var getAllNodes = function getAllNodes(data) {
|
|
@@ -535,69 +702,80 @@ function HtmlViewer(_ref5) {
|
|
|
535
702
|
});
|
|
536
703
|
};
|
|
537
704
|
var allNodes = getAllNodes(editedData);
|
|
538
|
-
// Update the header section
|
|
705
|
+
// Update the header section with toggle buttons
|
|
539
706
|
var renderHeader = function renderHeader() {
|
|
540
707
|
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
|
-
children: [onSave && jsxs("button", {
|
|
546
|
-
onClick: function onClick() {
|
|
547
|
-
return onSave(editedData);
|
|
548
|
-
},
|
|
549
|
-
className: "inline-flex items-center gap-2 px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2",
|
|
550
|
-
title: "Save Changes",
|
|
551
|
-
children: [jsx(FaFileDownloadIcon, {
|
|
552
|
-
size: 18
|
|
553
|
-
}), "Save"]
|
|
554
|
-
}), jsxs("button", {
|
|
555
|
-
onClick: handleDownload,
|
|
556
|
-
className: "inline-flex items-center gap-2 px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2",
|
|
557
|
-
title: "Download Updated JSON",
|
|
558
|
-
children: [jsx(FaFileDownloadIcon, {
|
|
559
|
-
size: 18
|
|
560
|
-
}), "Download"]
|
|
561
|
-
})]
|
|
562
|
-
})
|
|
563
|
-
}), jsxs("div", {
|
|
564
|
-
className: "flex gap-2 items-center",
|
|
565
|
-
children: [jsx("button", {
|
|
566
|
-
onClick: function onClick() {
|
|
567
|
-
return setIsAnalyticsOpen(true);
|
|
568
|
-
},
|
|
569
|
-
className: "inline-flex items-center gap-2 px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2",
|
|
570
|
-
title: "View Analytics",
|
|
571
|
-
children: jsx(FaChartBarIcon, {
|
|
572
|
-
size: 18
|
|
573
|
-
})
|
|
574
|
-
}), jsxs("div", {
|
|
708
|
+
className: "sticky top-0 z-20 bg-white border-b border-gray-200 p-3 flex justify-between items-center flex-shrink-0",
|
|
709
|
+
children: [jsxs("div", {
|
|
710
|
+
className: "flex gap-1",
|
|
711
|
+
children: [(enableJsonMode || enableEditMode) && jsxs("div", {
|
|
575
712
|
className: "flex bg-gray-100 rounded-lg p-1",
|
|
576
|
-
children: [
|
|
713
|
+
children: [enableJsonMode && jsxs("button", {
|
|
577
714
|
onClick: function onClick() {
|
|
578
|
-
|
|
579
|
-
setActiveFormat("Show JSON");
|
|
715
|
+
return setViewMode(viewMode === 'json' ? 'read' : 'json');
|
|
580
716
|
},
|
|
581
|
-
className: "
|
|
582
|
-
|
|
583
|
-
|
|
717
|
+
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"),
|
|
718
|
+
title: "JSON Mode - Click any element to view its JSON",
|
|
719
|
+
children: [jsx(VscJsonIcon, {
|
|
720
|
+
size: 16
|
|
721
|
+
}), jsx("span", {
|
|
722
|
+
className: "text-sm font-medium",
|
|
723
|
+
children: "JSON"
|
|
724
|
+
})]
|
|
725
|
+
}), enableEditMode && jsxs("button", {
|
|
584
726
|
onClick: function onClick() {
|
|
585
|
-
|
|
586
|
-
setActiveFormat("Hide JSON");
|
|
727
|
+
return setViewMode(viewMode === 'edit' ? 'read' : 'edit');
|
|
587
728
|
},
|
|
588
|
-
className: "
|
|
589
|
-
|
|
729
|
+
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"),
|
|
730
|
+
title: "Edit Mode - Click any element to edit it",
|
|
731
|
+
children: [jsx(FaEditIcon, {
|
|
732
|
+
size: 16
|
|
733
|
+
}), jsx("span", {
|
|
734
|
+
className: "text-sm font-medium",
|
|
735
|
+
children: "Edit"
|
|
736
|
+
})]
|
|
737
|
+
})]
|
|
738
|
+
}), enableSemanticTags && jsxs("button", {
|
|
739
|
+
onClick: function onClick() {
|
|
740
|
+
return setShowSemanticTags(!showSemanticTags);
|
|
741
|
+
},
|
|
742
|
+
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"),
|
|
743
|
+
title: showSemanticTags ? "Hide Semantic Tags" : "Show Semantic Tags",
|
|
744
|
+
children: [jsx(FaTagsIcon, {
|
|
745
|
+
size: 16
|
|
746
|
+
}), jsx("span", {
|
|
747
|
+
className: "text-sm font-medium",
|
|
748
|
+
children: "Tags"
|
|
749
|
+
})]
|
|
750
|
+
}), hasChanges && jsxs("button", {
|
|
751
|
+
onClick: handleDownload,
|
|
752
|
+
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",
|
|
753
|
+
title: "Download Updated JSON",
|
|
754
|
+
children: [jsx(FaFileDownloadIcon, {
|
|
755
|
+
size: 16
|
|
756
|
+
}), jsx("span", {
|
|
757
|
+
className: "text-sm font-medium",
|
|
758
|
+
children: "Save"
|
|
590
759
|
})]
|
|
591
760
|
})]
|
|
761
|
+
}), jsx("button", {
|
|
762
|
+
onClick: function onClick() {
|
|
763
|
+
return setIsAnalyticsOpen(true);
|
|
764
|
+
},
|
|
765
|
+
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",
|
|
766
|
+
title: "View Analytics",
|
|
767
|
+
children: jsx(FaChartBarIcon, {
|
|
768
|
+
size: 16
|
|
769
|
+
})
|
|
592
770
|
})]
|
|
593
771
|
});
|
|
594
772
|
};
|
|
595
773
|
return jsxs("div", {
|
|
596
774
|
className: "w-full h-full max-w-full flex flex-col overflow-hidden",
|
|
597
775
|
children: [renderHeader(), jsx("div", {
|
|
598
|
-
className: "flex-1 overflow-auto min-h-0 max-w-full",
|
|
776
|
+
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
777
|
children: jsx("div", {
|
|
600
|
-
className: "p-
|
|
778
|
+
className: "p-2 max-w-full",
|
|
601
779
|
children: allNodes.map(function (node) {
|
|
602
780
|
return jsx("div", {
|
|
603
781
|
className: "w-full max-w-full overflow-hidden break-words",
|
|
@@ -617,6 +795,12 @@ function HtmlViewer(_ref5) {
|
|
|
617
795
|
return setIsModalOpen(false);
|
|
618
796
|
},
|
|
619
797
|
data: modalData
|
|
798
|
+
}), jsx(TagModal, {
|
|
799
|
+
isOpen: isTagModalOpen,
|
|
800
|
+
onClose: function onClose() {
|
|
801
|
+
return setIsTagModalOpen(false);
|
|
802
|
+
},
|
|
803
|
+
tag: selectedTag
|
|
620
804
|
})]
|
|
621
805
|
});
|
|
622
806
|
}
|