retold-facto 0.0.4

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.
Files changed (92) hide show
  1. package/.claude/launch.json +11 -0
  2. package/.dockerignore +8 -0
  3. package/.quackage.json +19 -0
  4. package/Dockerfile +26 -0
  5. package/bin/retold-facto.js +909 -0
  6. package/examples/facto-government-data.sqlite +0 -0
  7. package/examples/government-data-catalog.json +137 -0
  8. package/examples/government-data-loader.js +1432 -0
  9. package/package.json +91 -0
  10. package/scripts/facto-download.js +425 -0
  11. package/source/Retold-Facto.js +1042 -0
  12. package/source/services/Retold-Facto-BeaconProvider.js +511 -0
  13. package/source/services/Retold-Facto-CatalogManager.js +1252 -0
  14. package/source/services/Retold-Facto-DataLakeService.js +1642 -0
  15. package/source/services/Retold-Facto-DatasetManager.js +417 -0
  16. package/source/services/Retold-Facto-IngestEngine.js +1315 -0
  17. package/source/services/Retold-Facto-ProjectionEngine.js +3960 -0
  18. package/source/services/Retold-Facto-RecordManager.js +360 -0
  19. package/source/services/Retold-Facto-SchemaManager.js +1110 -0
  20. package/source/services/Retold-Facto-SourceFolderScanner.js +2243 -0
  21. package/source/services/Retold-Facto-SourceManager.js +730 -0
  22. package/source/services/Retold-Facto-StoreConnectionManager.js +441 -0
  23. package/source/services/Retold-Facto-ThroughputMonitor.js +478 -0
  24. package/source/services/web-app/codemirror-entry.js +7 -0
  25. package/source/services/web-app/pict-app/Pict-Application-Facto-Configuration.json +9 -0
  26. package/source/services/web-app/pict-app/Pict-Application-Facto.js +70 -0
  27. package/source/services/web-app/pict-app/Pict-Facto-Bundle.js +11 -0
  28. package/source/services/web-app/pict-app/providers/Pict-Provider-Facto-UI.js +66 -0
  29. package/source/services/web-app/pict-app/providers/Pict-Provider-Facto.js +69 -0
  30. package/source/services/web-app/pict-app/providers/facto-api/Facto-API-Catalog.js +93 -0
  31. package/source/services/web-app/pict-app/providers/facto-api/Facto-API-Connections.js +42 -0
  32. package/source/services/web-app/pict-app/providers/facto-api/Facto-API-Datasets.js +605 -0
  33. package/source/services/web-app/pict-app/providers/facto-api/Facto-API-Projections.js +188 -0
  34. package/source/services/web-app/pict-app/providers/facto-api/Facto-API-Scanner.js +80 -0
  35. package/source/services/web-app/pict-app/providers/facto-api/Facto-API-Schema.js +116 -0
  36. package/source/services/web-app/pict-app/providers/facto-api/Facto-API-Sources.js +104 -0
  37. package/source/services/web-app/pict-app/views/PictView-Facto-Catalog.js +526 -0
  38. package/source/services/web-app/pict-app/views/PictView-Facto-Datasets.js +173 -0
  39. package/source/services/web-app/pict-app/views/PictView-Facto-Ingest.js +259 -0
  40. package/source/services/web-app/pict-app/views/PictView-Facto-Layout.js +191 -0
  41. package/source/services/web-app/pict-app/views/PictView-Facto-Projections.js +231 -0
  42. package/source/services/web-app/pict-app/views/PictView-Facto-Records.js +326 -0
  43. package/source/services/web-app/pict-app/views/PictView-Facto-Scanner.js +624 -0
  44. package/source/services/web-app/pict-app/views/PictView-Facto-Sources.js +201 -0
  45. package/source/services/web-app/pict-app/views/PictView-Facto-Throughput.js +456 -0
  46. package/source/services/web-app/pict-app-full/Pict-Application-Facto-Full-Configuration.json +14 -0
  47. package/source/services/web-app/pict-app-full/Pict-Application-Facto-Full.js +391 -0
  48. package/source/services/web-app/pict-app-full/providers/PictRouter-Facto-Configuration.json +56 -0
  49. package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-BottomBar.js +68 -0
  50. package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-Connections.js +340 -0
  51. package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-Dashboard.js +149 -0
  52. package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-Dashboards.js +819 -0
  53. package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-Datasets.js +178 -0
  54. package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-IngestJobs.js +99 -0
  55. package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-Layout.js +62 -0
  56. package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-MappingEditor.js +158 -0
  57. package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-ProjectionDetail.js +1120 -0
  58. package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-Projections.js +172 -0
  59. package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-QueryPanel.js +119 -0
  60. package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-RecordViewer.js +663 -0
  61. package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-Records.js +648 -0
  62. package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-Scanner.js +1017 -0
  63. package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-SchemaDetail.js +1404 -0
  64. package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-SchemaDocEditor.js +1036 -0
  65. package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-SchemaEditor.js +636 -0
  66. package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-SchemaResearch.js +357 -0
  67. package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-SourceDetail.js +822 -0
  68. package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-SourceEditor.js +1036 -0
  69. package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-SourceResearch.js +487 -0
  70. package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-Sources.js +165 -0
  71. package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-Throughput.js +439 -0
  72. package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-TopBar.js +335 -0
  73. package/source/services/web-app/pict-app-full/views/projections/Facto-Projections-Constants.js +71 -0
  74. package/source/services/web-app/web/chart.min.js +20 -0
  75. package/source/services/web-app/web/codemirror-bundle.js +30099 -0
  76. package/source/services/web-app/web/css/facto-themes.css +467 -0
  77. package/source/services/web-app/web/css/facto.css +502 -0
  78. package/source/services/web-app/web/index.html +28 -0
  79. package/source/services/web-app/web/retold-facto.js +12138 -0
  80. package/source/services/web-app/web/retold-facto.js.map +1 -0
  81. package/source/services/web-app/web/retold-facto.min.js +2 -0
  82. package/source/services/web-app/web/retold-facto.min.js.map +1 -0
  83. package/source/services/web-app/web/simple/index.html +17 -0
  84. package/test/Facto_Browser_Integration_tests.js +798 -0
  85. package/test/RetoldFacto_tests.js +4117 -0
  86. package/test/fixtures/weather-readings.csv +17 -0
  87. package/test/fixtures/weather-stations.csv +9 -0
  88. package/test/model/MeadowModel-Extended.json +8497 -0
  89. package/test/model/MeadowModel-PICT.json +1 -0
  90. package/test/model/MeadowModel.json +1355 -0
  91. package/test/model/ddl/Facto.ddl +225 -0
  92. package/test/model/fable-configuration.json +14 -0
@@ -0,0 +1,502 @@
1
+ /* ================================================================
2
+ Retold Facto — Base Styles
3
+ ================================================================ */
4
+
5
+ /* Reset */
6
+ *,
7
+ *::before,
8
+ *::after {
9
+ margin: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ html {
15
+ font-size: 16px;
16
+ -webkit-font-smoothing: antialiased;
17
+ -moz-osx-font-smoothing: grayscale;
18
+ }
19
+
20
+ body {
21
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
22
+ background: var(--facto-bg-base);
23
+ color: var(--facto-text);
24
+ line-height: 1.6;
25
+ min-height: 100vh;
26
+ }
27
+
28
+ /* ================================================================
29
+ Layout
30
+ ================================================================ */
31
+
32
+ #Facto-Full-Application-Container {
33
+ display: flex;
34
+ flex-direction: column;
35
+ min-height: 100vh;
36
+ }
37
+
38
+ #Facto-Full-TopBar-Container {
39
+ flex-shrink: 0;
40
+ }
41
+
42
+ #Facto-Full-Content-Container {
43
+ flex: 1;
44
+ }
45
+
46
+ #Facto-Full-BottomBar-Container {
47
+ flex-shrink: 0;
48
+ }
49
+
50
+ /* ================================================================
51
+ Typography
52
+ ================================================================ */
53
+
54
+ h1, h2, h3, h4, h5, h6 {
55
+ color: var(--facto-text-heading);
56
+ font-weight: 600;
57
+ line-height: 1.3;
58
+ }
59
+
60
+ h1 { font-size: 1.75em; margin-bottom: 0.5em; }
61
+ h2 { font-size: 1.4em; margin-bottom: 0.4em; }
62
+ h3 { font-size: 1.15em; margin-bottom: 0.3em; }
63
+ h4 { font-size: 1em; margin-bottom: 0.25em; }
64
+
65
+ a {
66
+ color: var(--facto-link);
67
+ text-decoration: none;
68
+ cursor: pointer;
69
+ }
70
+
71
+ a:hover {
72
+ color: var(--facto-link-hover);
73
+ }
74
+
75
+ p {
76
+ margin-bottom: 0.75em;
77
+ }
78
+
79
+ code, pre {
80
+ font-family: 'SF Mono', 'Fira Code', 'Cascadia Code', Consolas, monospace;
81
+ font-size: 0.9em;
82
+ }
83
+
84
+ pre {
85
+ background: var(--facto-bg-code);
86
+ border: 1px solid var(--facto-border-subtle);
87
+ border-radius: 6px;
88
+ padding: 1em;
89
+ overflow-x: auto;
90
+ }
91
+
92
+ code {
93
+ background: var(--facto-bg-code);
94
+ padding: 0.15em 0.4em;
95
+ border-radius: 3px;
96
+ }
97
+
98
+ /* ================================================================
99
+ Buttons
100
+ ================================================================ */
101
+
102
+ button, .facto-btn {
103
+ display: inline-flex;
104
+ align-items: center;
105
+ gap: 0.4em;
106
+ padding: 0.5em 1em;
107
+ border: 1px solid transparent;
108
+ border-radius: 6px;
109
+ font-size: 0.9em;
110
+ font-weight: 500;
111
+ cursor: pointer;
112
+ transition: background 0.15s, border-color 0.15s, opacity 0.15s;
113
+ line-height: 1.4;
114
+ }
115
+
116
+ button:hover {
117
+ opacity: 0.9;
118
+ }
119
+
120
+ button:active {
121
+ opacity: 0.8;
122
+ }
123
+
124
+ button:disabled {
125
+ opacity: 0.5;
126
+ cursor: not-allowed;
127
+ }
128
+
129
+ .facto-btn-primary, button.primary {
130
+ background: var(--facto-btn-primary-bg);
131
+ color: var(--facto-btn-primary-text);
132
+ border-color: var(--facto-btn-primary-bg);
133
+ }
134
+
135
+ .facto-btn-secondary, button.secondary {
136
+ background: var(--facto-btn-secondary-bg);
137
+ color: var(--facto-btn-secondary-text);
138
+ border-color: var(--facto-border);
139
+ }
140
+
141
+ .facto-btn-success, button.success {
142
+ background: var(--facto-success);
143
+ color: #fff;
144
+ }
145
+
146
+ .facto-btn-danger, button.danger {
147
+ background: var(--facto-error);
148
+ color: #fff;
149
+ border-color: transparent;
150
+ }
151
+
152
+ .facto-btn-small {
153
+ padding: 0.3em 0.7em;
154
+ font-size: 0.8em;
155
+ }
156
+
157
+ /* ================================================================
158
+ Forms
159
+ ================================================================ */
160
+
161
+ input[type="text"],
162
+ input[type="number"],
163
+ input[type="url"],
164
+ input[type="email"],
165
+ input[type="search"],
166
+ textarea,
167
+ select {
168
+ width: 100%;
169
+ padding: 0.5em 0.75em;
170
+ background: var(--facto-bg-input);
171
+ color: var(--facto-text);
172
+ border: 1px solid var(--facto-border);
173
+ border-radius: 6px;
174
+ font-size: 0.9em;
175
+ font-family: inherit;
176
+ line-height: 1.5;
177
+ margin-bottom: 0.5em;
178
+ box-sizing: border-box;
179
+ transition: border-color 0.15s;
180
+ }
181
+
182
+ /* Ensure select elements match input height */
183
+ select:not([multiple]) {
184
+ -webkit-appearance: none;
185
+ appearance: none;
186
+ background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");
187
+ background-repeat: no-repeat;
188
+ background-position: right 0.5em center;
189
+ background-size: 1em;
190
+ padding-right: 2em;
191
+ }
192
+
193
+ input:focus,
194
+ textarea:focus,
195
+ select:focus {
196
+ outline: none;
197
+ border-color: var(--facto-border-focus);
198
+ }
199
+
200
+ label {
201
+ display: block;
202
+ font-size: 0.85em;
203
+ font-weight: 500;
204
+ color: var(--facto-text-secondary);
205
+ margin-bottom: 0.25em;
206
+ }
207
+
208
+ /* ================================================================
209
+ Tables
210
+ ================================================================ */
211
+
212
+ table {
213
+ width: 100%;
214
+ border-collapse: collapse;
215
+ font-size: 0.9em;
216
+ }
217
+
218
+ thead {
219
+ background: var(--facto-table-header-bg);
220
+ }
221
+
222
+ th {
223
+ text-align: left;
224
+ padding: 0.6em 0.75em;
225
+ font-weight: 600;
226
+ color: var(--facto-text-heading);
227
+ border-bottom: 2px solid var(--facto-border);
228
+ white-space: nowrap;
229
+ }
230
+
231
+ td {
232
+ padding: 0.5em 0.75em;
233
+ border-bottom: 1px solid var(--facto-border-subtle);
234
+ vertical-align: top;
235
+ }
236
+
237
+ tbody tr:nth-child(even) {
238
+ background: var(--facto-table-stripe);
239
+ }
240
+
241
+ tbody tr:hover {
242
+ background: var(--facto-table-row-hover);
243
+ }
244
+
245
+ /* ================================================================
246
+ Cards
247
+ ================================================================ */
248
+
249
+ .facto-card {
250
+ background: var(--facto-bg-surface);
251
+ border: 1px solid var(--facto-border-subtle);
252
+ border-radius: 8px;
253
+ padding: 1.25em;
254
+ transition: border-color 0.15s;
255
+ }
256
+
257
+ .facto-card:hover {
258
+ border-color: var(--facto-border);
259
+ }
260
+
261
+ .facto-card-grid {
262
+ display: grid;
263
+ grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
264
+ gap: 1em;
265
+ }
266
+
267
+ /* ================================================================
268
+ Status / Alerts
269
+ ================================================================ */
270
+
271
+ .facto-status {
272
+ padding: 0.6em 1em;
273
+ border-radius: 6px;
274
+ font-size: 0.9em;
275
+ margin-bottom: 0.75em;
276
+ }
277
+
278
+ .facto-status-ok {
279
+ background: color-mix(in srgb, var(--facto-success) 15%, transparent);
280
+ color: var(--facto-success);
281
+ border: 1px solid color-mix(in srgb, var(--facto-success) 30%, transparent);
282
+ }
283
+
284
+ .facto-status-error {
285
+ background: color-mix(in srgb, var(--facto-error) 15%, transparent);
286
+ color: var(--facto-error);
287
+ border: 1px solid color-mix(in srgb, var(--facto-error) 30%, transparent);
288
+ }
289
+
290
+ .facto-status-warn {
291
+ background: color-mix(in srgb, var(--facto-warning) 15%, transparent);
292
+ color: var(--facto-warning);
293
+ border: 1px solid color-mix(in srgb, var(--facto-warning) 30%, transparent);
294
+ }
295
+
296
+ .facto-status-info {
297
+ background: color-mix(in srgb, var(--facto-info) 15%, transparent);
298
+ color: var(--facto-info);
299
+ border: 1px solid color-mix(in srgb, var(--facto-info) 30%, transparent);
300
+ }
301
+
302
+ /* ================================================================
303
+ Badges
304
+ ================================================================ */
305
+
306
+ .facto-badge {
307
+ display: inline-block;
308
+ padding: 0.15em 0.5em;
309
+ border-radius: 4px;
310
+ font-size: 0.75em;
311
+ font-weight: 600;
312
+ text-transform: uppercase;
313
+ letter-spacing: 0.03em;
314
+ }
315
+
316
+ .facto-badge-primary { background: var(--facto-brand); color: #fff; }
317
+ .facto-badge-success { background: var(--facto-success); color: #fff; }
318
+ .facto-badge-warning { background: var(--facto-warning); color: #000; }
319
+ .facto-badge-error { background: var(--facto-error); color: #fff; }
320
+ .facto-badge-muted { background: var(--facto-bg-elevated); color: var(--facto-text-secondary); }
321
+
322
+ /* ================================================================
323
+ Inline form groups
324
+ ================================================================ */
325
+
326
+ .facto-inline-group {
327
+ display: flex;
328
+ gap: 1em;
329
+ margin-bottom: 0.75em;
330
+ }
331
+
332
+ .facto-inline-group > div {
333
+ flex: 1;
334
+ }
335
+
336
+ /* ================================================================
337
+ Content sections
338
+ ================================================================ */
339
+
340
+ .facto-content {
341
+ padding: 2em;
342
+ max-width: 1400px;
343
+ margin: 0 auto;
344
+ }
345
+
346
+ .facto-content-header {
347
+ margin-bottom: 1.5em;
348
+ padding-bottom: 1em;
349
+ border-bottom: 1px solid var(--facto-border-subtle);
350
+ }
351
+
352
+ .facto-content-header p {
353
+ color: var(--facto-text-secondary);
354
+ margin-bottom: 0;
355
+ }
356
+
357
+ .facto-section {
358
+ margin-bottom: 2em;
359
+ }
360
+
361
+ .facto-section-title {
362
+ font-size: 1em;
363
+ font-weight: 600;
364
+ color: var(--facto-text-heading);
365
+ margin-bottom: 0.75em;
366
+ padding-bottom: 0.4em;
367
+ border-bottom: 1px solid var(--facto-border-subtle);
368
+ }
369
+
370
+ /* ================================================================
371
+ Empty states
372
+ ================================================================ */
373
+
374
+ .facto-empty {
375
+ text-align: center;
376
+ padding: 3em 1em;
377
+ color: var(--facto-text-tertiary);
378
+ font-style: italic;
379
+ }
380
+
381
+ /* ================================================================
382
+ Scrollbar
383
+ ================================================================ */
384
+
385
+ ::-webkit-scrollbar {
386
+ width: 8px;
387
+ height: 8px;
388
+ }
389
+
390
+ ::-webkit-scrollbar-track {
391
+ background: var(--facto-scrollbar-track);
392
+ }
393
+
394
+ ::-webkit-scrollbar-thumb {
395
+ background: var(--facto-scrollbar-thumb);
396
+ border-radius: 4px;
397
+ }
398
+
399
+ ::-webkit-scrollbar-thumb:hover {
400
+ background: var(--facto-scrollbar-thumb-hover);
401
+ }
402
+
403
+ /* ================================================================
404
+ Row Actions Dropdown (hover hamburger menu)
405
+ ================================================================ */
406
+
407
+ .facto-row-actions {
408
+ position: relative;
409
+ display: inline-block;
410
+ }
411
+
412
+ .facto-row-actions-trigger {
413
+ display: none;
414
+ align-items: center;
415
+ justify-content: center;
416
+ width: 28px;
417
+ height: 28px;
418
+ padding: 0;
419
+ border: 1px solid var(--facto-border);
420
+ border-radius: 6px;
421
+ background: var(--facto-bg-surface);
422
+ color: var(--facto-text-secondary);
423
+ cursor: pointer;
424
+ font-size: 1em;
425
+ line-height: 1;
426
+ transition: background 0.15s, border-color 0.15s;
427
+ }
428
+
429
+ .facto-row-actions-trigger:hover {
430
+ background: var(--facto-bg-hover);
431
+ border-color: var(--facto-text-secondary);
432
+ }
433
+
434
+ tr:hover .facto-row-actions-trigger {
435
+ display: inline-flex;
436
+ }
437
+
438
+ .facto-row-actions-menu {
439
+ display: none;
440
+ position: absolute;
441
+ right: 0;
442
+ top: 100%;
443
+ z-index: 100;
444
+ min-width: 140px;
445
+ margin-top: 2px;
446
+ padding: 4px 0;
447
+ background: var(--facto-bg-surface);
448
+ border: 1px solid var(--facto-border);
449
+ border-radius: 6px;
450
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
451
+ }
452
+
453
+ .facto-row-actions.open .facto-row-actions-menu {
454
+ display: block;
455
+ }
456
+
457
+ .facto-row-actions-menu button {
458
+ display: block;
459
+ width: 100%;
460
+ padding: 6px 12px;
461
+ border: none;
462
+ border-radius: 0;
463
+ background: transparent;
464
+ color: var(--facto-text);
465
+ font-size: 0.82em;
466
+ font-weight: 500;
467
+ text-align: left;
468
+ cursor: pointer;
469
+ transition: background 0.1s;
470
+ }
471
+
472
+ .facto-row-actions-menu button:hover {
473
+ background: var(--facto-bg-hover);
474
+ opacity: 1;
475
+ }
476
+
477
+ .facto-row-actions-menu button.facto-action-success {
478
+ color: var(--facto-success);
479
+ }
480
+
481
+ .facto-row-actions-menu button.facto-action-primary {
482
+ color: var(--facto-brand);
483
+ }
484
+
485
+ /* ================================================================
486
+ Responsive
487
+ ================================================================ */
488
+
489
+ @media (max-width: 768px) {
490
+ .facto-content {
491
+ padding: 1em;
492
+ }
493
+
494
+ .facto-inline-group {
495
+ flex-direction: column;
496
+ gap: 0;
497
+ }
498
+
499
+ .facto-card-grid {
500
+ grid-template-columns: 1fr;
501
+ }
502
+ }
@@ -0,0 +1,28 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
6
+ <meta name="description" content="Retold Facto Data Warehouse">
7
+ <title>Retold Facto</title>
8
+ <link href="css/facto.css" rel="stylesheet">
9
+ <link href="css/facto-themes.css" rel="stylesheet">
10
+ <style id="PICT-CSS"></style>
11
+ <script>
12
+ (function(){
13
+ var t=localStorage.getItem('facto-theme');
14
+ if(t&&t!=='facto-dark')document.body.dataset.theme=t;
15
+ })();
16
+ </script>
17
+ </head>
18
+ <body>
19
+ <div id="Facto-Full-Application-Container"></div>
20
+ <script src="chart.min.js" type="text/javascript"></script>
21
+ <script src="codemirror-bundle.js" type="text/javascript"></script>
22
+ <script src="pict.min.js" type="text/javascript"></script>
23
+ <script src="retold-facto.js" type="text/javascript"></script>
24
+ <script type="text/javascript">
25
+ Pict.safeLoadPictApplication(FactoFullApplication, 2);
26
+ </script>
27
+ </body>
28
+ </html>