@tfw.in/structura-lib 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/PRODUCTION_ARCHITECTURE.md +511 -0
- package/README.md +379 -0
- package/SAVE_FUNCTIONALITY_COMPLETE.md +448 -0
- package/dist/cjs/EditableContent.js +150 -0
- package/dist/cjs/HtmlViewer.js +587 -0
- package/dist/cjs/PdfComponents.js +16 -0
- package/dist/cjs/PdfDocumentViewer.js +281 -0
- package/dist/cjs/Structura.js +806 -0
- package/dist/cjs/Table.js +164 -0
- package/dist/cjs/TableCell.js +115 -0
- package/dist/cjs/accuracyMetrics.js +39 -0
- package/dist/cjs/helpers/preprocessData.js +143 -0
- package/dist/cjs/index.js +7 -0
- package/dist/cjs/lib/polyfills.js +15 -0
- package/dist/cjs/lib/utils.js +10 -0
- package/dist/cjs/node_modules/react-icons/fa/index.esm.js +14 -0
- package/dist/cjs/node_modules/react-icons/lib/esm/iconBase.js +69 -0
- package/dist/cjs/node_modules/react-icons/lib/esm/iconContext.js +15 -0
- package/dist/cjs/polyfills.js +19 -0
- package/dist/cjs/route.js +102 -0
- package/dist/cjs/styles.css +7 -0
- package/dist/cjs/styles.css.map +1 -0
- package/dist/cjs/ui/badge.js +34 -0
- package/dist/cjs/ui/button.js +71 -0
- package/dist/cjs/ui/card.js +86 -0
- package/dist/cjs/ui/progress.js +45 -0
- package/dist/cjs/ui/scroll-area.js +62 -0
- package/dist/cjs/ui/tabs.js +60 -0
- package/dist/cjs/worker.js +36 -0
- package/dist/esm/EditableContent.js +161 -0
- package/dist/esm/HtmlViewer.js +640 -0
- package/dist/esm/PdfComponents.js +21 -0
- package/dist/esm/PdfDocumentViewer.js +294 -0
- package/dist/esm/Structura.js +951 -0
- package/dist/esm/Table.js +182 -0
- package/dist/esm/TableCell.js +122 -0
- package/dist/esm/_virtual/_rollupPluginBabelHelpers.js +305 -0
- package/dist/esm/accuracyMetrics.js +41 -0
- package/dist/esm/helpers/preprocessData.js +152 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/lib/polyfills.js +13 -0
- package/dist/esm/lib/utils.js +8 -0
- package/dist/esm/node_modules/react-icons/fa/index.esm.js +11 -0
- package/dist/esm/node_modules/react-icons/lib/esm/iconBase.js +66 -0
- package/dist/esm/node_modules/react-icons/lib/esm/iconContext.js +12 -0
- package/dist/esm/polyfills.js +17 -0
- package/dist/esm/route.js +154 -0
- package/dist/esm/styles.css +7 -0
- package/dist/esm/styles.css.map +1 -0
- package/dist/esm/types/EditableContent.d.ts +9 -0
- package/dist/esm/types/HtmlViewer.d.ts +10 -0
- package/dist/esm/types/PdfComponents.d.ts +35 -0
- package/dist/esm/types/PdfDocumentViewer.d.ts +22 -0
- package/dist/esm/types/Structura.d.ts +11 -0
- package/dist/esm/types/Table.d.ts +12 -0
- package/dist/esm/types/TableCell.d.ts +13 -0
- package/dist/esm/types/accuracy.d.ts +23 -0
- package/dist/esm/types/accuracyMetrics.d.ts +5 -0
- package/dist/esm/types/helpers/flattenJSON.d.ts +1 -0
- package/dist/esm/types/helpers/hardMerging.d.ts +2 -0
- package/dist/esm/types/helpers/index.d.ts +6 -0
- package/dist/esm/types/helpers/jsonToHtml.d.ts +40 -0
- package/dist/esm/types/helpers/preprocessData.d.ts +3 -0
- package/dist/esm/types/helpers/removeMetadata.d.ts +1 -0
- package/dist/esm/types/helpers/tableProcessor.d.ts +1 -0
- package/dist/esm/types/index.d.ts +3 -0
- package/dist/esm/types/lib/polyfills.d.ts +1 -0
- package/dist/esm/types/lib/utils.d.ts +2 -0
- package/dist/esm/types/polyfills.d.ts +1 -0
- package/dist/esm/types/route.d.ts +45 -0
- package/dist/esm/types/test-app/src/App.d.ts +4 -0
- package/dist/esm/types/test-app/src/main.d.ts +1 -0
- package/dist/esm/types/test-app/vite.config.d.ts +2 -0
- package/dist/esm/types/types.d.ts +23 -0
- package/dist/esm/types/ui/alert.d.ts +8 -0
- package/dist/esm/types/ui/badge.d.ts +9 -0
- package/dist/esm/types/ui/button.d.ts +11 -0
- package/dist/esm/types/ui/card.d.ts +8 -0
- package/dist/esm/types/ui/progress.d.ts +6 -0
- package/dist/esm/types/ui/scroll-area.d.ts +5 -0
- package/dist/esm/types/ui/skeleton.d.ts +2 -0
- package/dist/esm/types/ui/tabs.d.ts +7 -0
- package/dist/esm/types/worker.d.ts +1 -0
- package/dist/esm/ui/badge.js +31 -0
- package/dist/esm/ui/button.js +50 -0
- package/dist/esm/ui/card.js +67 -0
- package/dist/esm/ui/progress.js +26 -0
- package/dist/esm/ui/scroll-area.js +45 -0
- package/dist/esm/ui/tabs.js +39 -0
- package/dist/esm/worker.js +50 -0
- package/dist/index.d.ts +38 -0
- package/package.json +85 -0
- package/server/README.md +203 -0
- package/server/db.js +142 -0
- package/server/server.js +165 -0
package/README.md
ADDED
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
# Structura Library
|
|
2
|
+
|
|
3
|
+
A React component library for viewing and editing structured documents with PDF rendering and persistent storage.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 📄 **PDF Viewer** - Side-by-side PDF and structured content view
|
|
8
|
+
- ✏️ **Inline Editing** - Double-click to edit any text element
|
|
9
|
+
- 💾 **Persistent Storage** - Automatic save to SQLite database
|
|
10
|
+
- 🔄 **Version History** - Track all edits with timestamps
|
|
11
|
+
- 🎯 **Bidirectional Mapping** - Click highlighting between PDF and content
|
|
12
|
+
- 📦 **Production Ready** - Zero configuration, auto-initialization
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @tfw.in/structura-lib
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
### 1. Basic Usage
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
import { Structura } from '@tfw.in/structura-lib';
|
|
26
|
+
import '@tfw.in/structura-lib/dist/esm/styles.css';
|
|
27
|
+
|
|
28
|
+
function App() {
|
|
29
|
+
return (
|
|
30
|
+
<Structura
|
|
31
|
+
initialPdfPath="/document.pdf"
|
|
32
|
+
initialJsonData={jsonData}
|
|
33
|
+
props={{
|
|
34
|
+
APIKey: "your-api-key",
|
|
35
|
+
onSave: (editedData) => {
|
|
36
|
+
console.log('Document saved:', editedData);
|
|
37
|
+
}
|
|
38
|
+
}}
|
|
39
|
+
/>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### 2. With Backend Storage
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
import { Structura } from '@tfw.in/structura-lib';
|
|
48
|
+
import '@tfw.in/structura-lib/dist/esm/styles.css';
|
|
49
|
+
|
|
50
|
+
function App() {
|
|
51
|
+
const [jsonData, setJsonData] = useState(null);
|
|
52
|
+
|
|
53
|
+
const handleSave = async (editedData) => {
|
|
54
|
+
const response = await fetch('http://localhost:3002/api/save', {
|
|
55
|
+
method: 'POST',
|
|
56
|
+
headers: { 'Content-Type': 'application/json' },
|
|
57
|
+
body: JSON.stringify({
|
|
58
|
+
pdfName: 'document.pdf',
|
|
59
|
+
editedJson: editedData,
|
|
60
|
+
originalJson: jsonData // Only on first save
|
|
61
|
+
})
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const result = await response.json();
|
|
65
|
+
console.log('Saved:', result);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<Structura
|
|
70
|
+
initialPdfPath="/document.pdf"
|
|
71
|
+
initialJsonData={jsonData}
|
|
72
|
+
props={{
|
|
73
|
+
APIKey: "your-api-key",
|
|
74
|
+
onSave: handleSave
|
|
75
|
+
}}
|
|
76
|
+
/>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Props
|
|
82
|
+
|
|
83
|
+
### `Structura` Component
|
|
84
|
+
|
|
85
|
+
| Prop | Type | Required | Description |
|
|
86
|
+
|------|------|----------|-------------|
|
|
87
|
+
| `initialPdfPath` | `string \| null` | No | URL or path to PDF file |
|
|
88
|
+
| `initialJsonData` | `any \| null` | No | Pre-loaded JSON data (bypasses API call) |
|
|
89
|
+
| `props.APIKey` | `string` | Yes | Structura API key for processing |
|
|
90
|
+
| `props.baseUrl` | `string` | No | Custom API base URL |
|
|
91
|
+
| `props.onSave` | `(data: any) => void \| Promise<void>` | No | Callback when user saves edits |
|
|
92
|
+
|
|
93
|
+
## Backend Server (Optional)
|
|
94
|
+
|
|
95
|
+
The library includes an Express server for persistent storage.
|
|
96
|
+
|
|
97
|
+
### Start the Server
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
cd node_modules/@tfw.in/structura-lib
|
|
101
|
+
npm run server
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Server runs on `http://localhost:3002`
|
|
105
|
+
|
|
106
|
+
### API Endpoints
|
|
107
|
+
|
|
108
|
+
#### POST /api/save
|
|
109
|
+
Save edited document.
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
curl -X POST http://localhost:3002/api/save \
|
|
113
|
+
-H "Content-Type: application/json" \
|
|
114
|
+
-d '{
|
|
115
|
+
"pdfName": "document.pdf",
|
|
116
|
+
"editedJson": {...},
|
|
117
|
+
"originalJson": {...}
|
|
118
|
+
}'
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
#### GET /api/load/:pdfName
|
|
122
|
+
Load document with latest edit.
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
curl http://localhost:3002/api/load/document.pdf
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
#### GET /api/history/:pdfName
|
|
129
|
+
Get full edit history.
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
curl http://localhost:3002/api/history/document.pdf
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Usage Patterns
|
|
136
|
+
|
|
137
|
+
### Pattern 1: Database-First Loading
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
useEffect(() => {
|
|
141
|
+
const pdfName = 'document.pdf';
|
|
142
|
+
|
|
143
|
+
// Try database first
|
|
144
|
+
fetch(`http://localhost:3002/api/load/${pdfName}`)
|
|
145
|
+
.then(res => res.json())
|
|
146
|
+
.then(result => {
|
|
147
|
+
setJsonData(result.document.currentJson);
|
|
148
|
+
})
|
|
149
|
+
.catch(() => {
|
|
150
|
+
// Fallback to file
|
|
151
|
+
fetch('/data.json')
|
|
152
|
+
.then(res => res.json())
|
|
153
|
+
.then(data => setJsonData(data));
|
|
154
|
+
});
|
|
155
|
+
}, []);
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Pattern 2: Auto-Save on Edit
|
|
159
|
+
|
|
160
|
+
```tsx
|
|
161
|
+
const handleSave = async (editedData) => {
|
|
162
|
+
await fetch('http://localhost:3002/api/save', {
|
|
163
|
+
method: 'POST',
|
|
164
|
+
headers: { 'Content-Type': 'application/json' },
|
|
165
|
+
body: JSON.stringify({
|
|
166
|
+
pdfName: pdfUrl.split('/').pop(),
|
|
167
|
+
editedJson: editedData
|
|
168
|
+
})
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// Reload from database to verify
|
|
172
|
+
const response = await fetch(`http://localhost:3002/api/load/${pdfName}`);
|
|
173
|
+
const result = await response.json();
|
|
174
|
+
setJsonData(result.document.currentJson);
|
|
175
|
+
};
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Pattern 3: URL Parameters
|
|
179
|
+
|
|
180
|
+
```tsx
|
|
181
|
+
// Load from URL: ?pdf=/doc.pdf&json=/data.json
|
|
182
|
+
useEffect(() => {
|
|
183
|
+
const params = new URLSearchParams(window.location.search);
|
|
184
|
+
const pdf = params.get('pdf');
|
|
185
|
+
const json = params.get('json');
|
|
186
|
+
|
|
187
|
+
if (pdf && json) {
|
|
188
|
+
setPdfUrl(pdf);
|
|
189
|
+
fetch(json)
|
|
190
|
+
.then(res => res.json())
|
|
191
|
+
.then(data => setJsonData(data));
|
|
192
|
+
}
|
|
193
|
+
}, []);
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Features
|
|
197
|
+
|
|
198
|
+
### Inline Editing
|
|
199
|
+
|
|
200
|
+
Double-click any text to edit:
|
|
201
|
+
- Edits are tracked automatically
|
|
202
|
+
- Green **Save** button appears when changes are made
|
|
203
|
+
- Yellow highlight indicates edited content
|
|
204
|
+
|
|
205
|
+
### Version History
|
|
206
|
+
|
|
207
|
+
Every save creates a new version:
|
|
208
|
+
- Full edit history preserved
|
|
209
|
+
- Timestamps for each edit
|
|
210
|
+
- Can restore any previous version
|
|
211
|
+
|
|
212
|
+
### Bidirectional Mapping
|
|
213
|
+
|
|
214
|
+
Click elements to highlight corresponding content:
|
|
215
|
+
- PDF → HTML viewer
|
|
216
|
+
- HTML viewer → PDF location
|
|
217
|
+
- Smooth scrolling and highlighting
|
|
218
|
+
|
|
219
|
+
## Development
|
|
220
|
+
|
|
221
|
+
### Build the Library
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
npm run build
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Run Test App
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
cd test-app
|
|
231
|
+
npm install
|
|
232
|
+
npm run dev
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Open: `http://localhost:5175`
|
|
236
|
+
|
|
237
|
+
### Run with Backend
|
|
238
|
+
|
|
239
|
+
Terminal 1:
|
|
240
|
+
```bash
|
|
241
|
+
npm run server
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Terminal 2:
|
|
245
|
+
```bash
|
|
246
|
+
cd test-app
|
|
247
|
+
npm run dev
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## Database Schema
|
|
251
|
+
|
|
252
|
+
### documents table
|
|
253
|
+
```sql
|
|
254
|
+
CREATE TABLE documents (
|
|
255
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
256
|
+
pdf_name TEXT NOT NULL,
|
|
257
|
+
original_json TEXT NOT NULL,
|
|
258
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
259
|
+
);
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### edits table
|
|
263
|
+
```sql
|
|
264
|
+
CREATE TABLE edits (
|
|
265
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
266
|
+
document_id INTEGER NOT NULL,
|
|
267
|
+
edited_json TEXT NOT NULL,
|
|
268
|
+
edit_summary TEXT,
|
|
269
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
270
|
+
FOREIGN KEY (document_id) REFERENCES documents(id)
|
|
271
|
+
);
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## Architecture
|
|
275
|
+
|
|
276
|
+
```
|
|
277
|
+
┌──────────────────┐
|
|
278
|
+
│ React Component │
|
|
279
|
+
│ (Structura) │
|
|
280
|
+
└────────┬─────────┘
|
|
281
|
+
│
|
|
282
|
+
├─── PDF Viewer (Left)
|
|
283
|
+
│ - Render PDF pages
|
|
284
|
+
│ - Click to highlight
|
|
285
|
+
│
|
|
286
|
+
└─── HTML Viewer (Right)
|
|
287
|
+
- Structured content
|
|
288
|
+
- Inline editing
|
|
289
|
+
- Save button
|
|
290
|
+
│
|
|
291
|
+
▼
|
|
292
|
+
┌──────────────┐
|
|
293
|
+
│ Express API │
|
|
294
|
+
│ (port 3002) │
|
|
295
|
+
└──────┬───────┘
|
|
296
|
+
│
|
|
297
|
+
▼
|
|
298
|
+
┌──────────────┐
|
|
299
|
+
│ SQLite DB │
|
|
300
|
+
│ (edits.db) │
|
|
301
|
+
└──────────────┘
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
## Production Deployment
|
|
305
|
+
|
|
306
|
+
### Using PM2
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
npm install -g pm2
|
|
310
|
+
pm2 start server/server.js --name structura-server
|
|
311
|
+
pm2 save
|
|
312
|
+
pm2 startup
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### Docker
|
|
316
|
+
|
|
317
|
+
```dockerfile
|
|
318
|
+
FROM node:18
|
|
319
|
+
WORKDIR /app
|
|
320
|
+
COPY package*.json ./
|
|
321
|
+
RUN npm install --production
|
|
322
|
+
COPY . .
|
|
323
|
+
EXPOSE 3002
|
|
324
|
+
CMD ["node", "server/server.js"]
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Nginx
|
|
328
|
+
|
|
329
|
+
```nginx
|
|
330
|
+
location /api/ {
|
|
331
|
+
proxy_pass http://localhost:3002;
|
|
332
|
+
client_max_body_size 50M;
|
|
333
|
+
}
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
## Configuration
|
|
337
|
+
|
|
338
|
+
### Environment Variables
|
|
339
|
+
|
|
340
|
+
```bash
|
|
341
|
+
PORT=3002 # Server port
|
|
342
|
+
NODE_ENV=production # Environment
|
|
343
|
+
DATABASE_PATH=./edits.db # SQLite path
|
|
344
|
+
MAX_JSON_SIZE=50mb # Request limit
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
## Troubleshooting
|
|
348
|
+
|
|
349
|
+
### Save button not appearing
|
|
350
|
+
|
|
351
|
+
1. Check `onSave` prop is provided
|
|
352
|
+
2. Make an edit (double-click text)
|
|
353
|
+
3. Rebuild library: `npm run build`
|
|
354
|
+
|
|
355
|
+
### Database not persisting
|
|
356
|
+
|
|
357
|
+
1. Check server is running: `curl http://localhost:3002/health`
|
|
358
|
+
2. Check database file exists: `ls -la server/edits.db`
|
|
359
|
+
3. Check browser console for errors
|
|
360
|
+
|
|
361
|
+
### PDF not loading
|
|
362
|
+
|
|
363
|
+
1. Check CORS settings on PDF server
|
|
364
|
+
2. Verify PDF path is correct
|
|
365
|
+
3. Check browser console for errors
|
|
366
|
+
|
|
367
|
+
## License
|
|
368
|
+
|
|
369
|
+
MIT
|
|
370
|
+
|
|
371
|
+
## Author
|
|
372
|
+
|
|
373
|
+
TFW
|
|
374
|
+
|
|
375
|
+
## Support
|
|
376
|
+
|
|
377
|
+
For issues and questions:
|
|
378
|
+
- GitHub: https://github.com/ChakshuGautam/structura-lib
|
|
379
|
+
- Documentation: See `/server/README.md` for API details
|