@file-viewer/core 2.0.11 → 2.1.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/README.en.md +2 -2
- package/README.md +2 -2
- package/dist/config/options.d.ts +1 -1
- package/dist/config/options.js +1 -1
- package/dist/contracts/types.d.ts +71 -1
- package/dist/headless.d.ts +2 -2
- package/dist/headless.js +1 -1
- package/dist/index.d.ts +9 -6
- package/dist/index.js +105 -48
- package/dist/platform/assets.d.ts +3 -1
- package/dist/platform/assets.js +18 -2
- package/dist/registry/capabilities.d.ts +2 -2
- package/dist/registry/capabilities.js +2 -1
- package/dist/registry/formats.d.ts +20 -7
- package/dist/registry/formats.js +14 -5
- package/dist/registry/registry.d.ts +8 -1
- package/dist/registry/registry.js +29 -0
- package/dist/renderers/image.js +1 -10
- package/dist/renderers/index.d.ts +320 -2
- package/dist/renderers/index.js +27 -157
- package/dist/viewer/createViewer.js +86 -3
- package/package.json +17 -44
- package/dist/renderers/archive.d.ts +0 -2
- package/dist/renderers/archive.js +0 -547
- package/dist/renderers/archiveCache.d.ts +0 -10
- package/dist/renderers/archiveCache.js +0 -96
- package/dist/renderers/archiveFallback.d.ts +0 -7
- package/dist/renderers/archiveFallback.js +0 -166
- package/dist/renderers/archiveShared.d.ts +0 -23
- package/dist/renderers/archiveShared.js +0 -71
- package/dist/renderers/audio.d.ts +0 -8
- package/dist/renderers/audio.js +0 -219
- package/dist/renderers/cad.d.ts +0 -2
- package/dist/renderers/cad.js +0 -446
- package/dist/renderers/code.d.ts +0 -11
- package/dist/renderers/code.js +0 -233
- package/dist/renderers/data.d.ts +0 -7
- package/dist/renderers/data.js +0 -370
- package/dist/renderers/drawing.d.ts +0 -10
- package/dist/renderers/drawing.js +0 -882
- package/dist/renderers/eda.d.ts +0 -2
- package/dist/renderers/eda.js +0 -434
- package/dist/renderers/edaParser.d.ts +0 -77
- package/dist/renderers/edaParser.js +0 -569
- package/dist/renderers/email.d.ts +0 -2
- package/dist/renderers/email.js +0 -463
- package/dist/renderers/epub.d.ts +0 -2
- package/dist/renderers/epub.js +0 -331
- package/dist/renderers/geo.d.ts +0 -2
- package/dist/renderers/geo.js +0 -284
- package/dist/renderers/markdown.d.ts +0 -2
- package/dist/renderers/markdown.js +0 -83
- package/dist/renderers/model.d.ts +0 -2
- package/dist/renderers/model.js +0 -567
- package/dist/renderers/ofd.d.ts +0 -2
- package/dist/renderers/ofd.js +0 -256
- package/dist/renderers/openDocument.d.ts +0 -2
- package/dist/renderers/openDocument.js +0 -122
- package/dist/renderers/pdf.d.ts +0 -3
- package/dist/renderers/pdf.js +0 -1001
- package/dist/renderers/pdfStyles.d.ts +0 -1
- package/dist/renderers/pdfStyles.js +0 -1
- package/dist/renderers/pptx.d.ts +0 -2
- package/dist/renderers/pptx.js +0 -217
- package/dist/renderers/spreadsheet/state.d.ts +0 -80
- package/dist/renderers/spreadsheet/state.js +0 -96
- package/dist/renderers/spreadsheet/view.d.ts +0 -25
- package/dist/renderers/spreadsheet/view.js +0 -833
- package/dist/renderers/spreadsheet/worker/index.d.ts +0 -2
- package/dist/renderers/spreadsheet/worker/index.js +0 -1
- package/dist/renderers/spreadsheet/worker/sheetjs/SheetJsModel.d.ts +0 -73
- package/dist/renderers/spreadsheet/worker/sheetjs/SheetJsModel.js +0 -623
- package/dist/renderers/spreadsheet/worker/sheetjs/color.d.ts +0 -2
- package/dist/renderers/spreadsheet/worker/sheetjs/color.js +0 -73
- package/dist/renderers/spreadsheet/worker/sheetjs/index.d.ts +0 -1
- package/dist/renderers/spreadsheet/worker/sheetjs/index.js +0 -1
- package/dist/renderers/spreadsheet/worker/sheetjs/parser.d.ts +0 -18
- package/dist/renderers/spreadsheet/worker/sheetjs/parser.js +0 -106
- package/dist/renderers/spreadsheet/worker/sheetjs/sheet.worker.d.ts +0 -1
- package/dist/renderers/spreadsheet/worker/sheetjs/sheet.worker.js +0 -11
- package/dist/renderers/spreadsheet/worker/type.d.ts +0 -57
- package/dist/renderers/spreadsheet/worker/type.js +0 -1
- package/dist/renderers/spreadsheet.d.ts +0 -3
- package/dist/renderers/spreadsheet.js +0 -929
- package/dist/renderers/typst.d.ts +0 -8
- package/dist/renderers/typst.js +0 -547
- package/dist/renderers/umd/parser.d.ts +0 -30
- package/dist/renderers/umd/parser.js +0 -408
- package/dist/renderers/umd.d.ts +0 -2
- package/dist/renderers/umd.js +0 -297
- package/dist/renderers/video.d.ts +0 -8
- package/dist/renderers/video.js +0 -108
- package/dist/renderers/wordDoc.d.ts +0 -5
- package/dist/renderers/wordDoc.js +0 -284
- package/dist/renderers/wordDocx.d.ts +0 -5
- package/dist/renderers/wordDocx.js +0 -985
- package/dist/renderers/wordDocx.worker.d.ts +0 -1
- package/dist/renderers/wordDocx.worker.js +0 -96
- package/vendor/ofd/dltech/jbig2/arithmetic_decoder.js +0 -183
- package/vendor/ofd/dltech/jbig2/ccitt.js +0 -1070
- package/vendor/ofd/dltech/jbig2/compatibility.js +0 -12
- package/vendor/ofd/dltech/jbig2/core_utils.js +0 -180
- package/vendor/ofd/dltech/jbig2/is_node.js +0 -27
- package/vendor/ofd/dltech/jbig2/jbig2.js +0 -2589
- package/vendor/ofd/dltech/jbig2/jbig2_stream.js +0 -81
- package/vendor/ofd/dltech/jbig2/primitives.js +0 -387
- package/vendor/ofd/dltech/jbig2/stream.js +0 -1348
- package/vendor/ofd/dltech/jbig2/util.js +0 -972
- package/vendor/ofd/dltech/ofd/ofd.d.ts +0 -11
- package/vendor/ofd/dltech/ofd/ofd.js +0 -100
- package/vendor/ofd/dltech/ofd/ofd_parser.js +0 -395
- package/vendor/ofd/dltech/ofd/ofd_render.js +0 -473
- package/vendor/ofd/dltech/ofd/ofd_util.js +0 -350
- package/vendor/ofd/dltech/ofd/pipeline.js +0 -26
package/dist/renderers/eda.d.ts
DELETED
package/dist/renderers/eda.js
DELETED
|
@@ -1,434 +0,0 @@
|
|
|
1
|
-
import { parseEdaFile, } from './edaParser.js';
|
|
2
|
-
const roleLabels = {
|
|
3
|
-
root: '根',
|
|
4
|
-
library: '库',
|
|
5
|
-
symbol: '元件符号',
|
|
6
|
-
footprint: '封装',
|
|
7
|
-
padstack: 'Padstack',
|
|
8
|
-
drawing: '图纸',
|
|
9
|
-
metadata: '元数据',
|
|
10
|
-
property: '属性',
|
|
11
|
-
geometry: '几何',
|
|
12
|
-
net: '网络',
|
|
13
|
-
unknown: '未知',
|
|
14
|
-
};
|
|
15
|
-
const confidenceLabels = {
|
|
16
|
-
high: '高',
|
|
17
|
-
medium: '中',
|
|
18
|
-
low: '低',
|
|
19
|
-
};
|
|
20
|
-
const edaStyle = `
|
|
21
|
-
.eda-viewer{position:relative;height:100%;min-height:0;display:flex;flex-direction:column;background:#edf1f5;color:#172033;box-sizing:border-box}
|
|
22
|
-
.eda-viewer *{box-sizing:border-box}
|
|
23
|
-
.eda-header{min-height:84px;display:flex;align-items:center;justify-content:space-between;gap:18px;padding:18px 176px 18px 22px;border-bottom:1px solid rgba(23,32,51,.08);background:#fff}
|
|
24
|
-
.eda-header span,.eda-panel-head span{color:#0b7480;font-size:12px;font-weight:900;letter-spacing:0}
|
|
25
|
-
.eda-header h2{margin:4px 0 0;font-size:22px;line-height:1.2}
|
|
26
|
-
.eda-header dl{display:grid;grid-template-columns:repeat(4,minmax(70px,auto));gap:10px;margin:0}
|
|
27
|
-
.eda-header dt,.eda-header dd,.eda-entity-group dl,.eda-entity-group dt,.eda-entity-group dd{margin:0}
|
|
28
|
-
.eda-header dt{color:#718096;font-size:12px}
|
|
29
|
-
.eda-header dd{color:#172033;font-weight:900}
|
|
30
|
-
.eda-body{flex:1;min-height:0;display:grid;grid-template-columns:minmax(300px,32%) minmax(0,1fr)}
|
|
31
|
-
.eda-sidebar{min-height:0;display:flex;flex-direction:column;gap:12px;padding:16px;border-right:1px solid rgba(23,32,51,.08);background:rgba(255,255,255,.74)}
|
|
32
|
-
.eda-summary,.eda-warning,.eda-panel,.eda-error{border-radius:14px;background:#fff;box-shadow:inset 0 0 0 1px rgba(23,32,51,.06)}
|
|
33
|
-
.eda-summary,.eda-warning{padding:12px}
|
|
34
|
-
.eda-summary strong{display:block;color:#172033}
|
|
35
|
-
.eda-summary p,.eda-warning p,.eda-empty p,.eda-entity-group p{margin:6px 0 0;color:#64748b;line-height:1.55}
|
|
36
|
-
.eda-mini-grid,.eda-stat-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px}
|
|
37
|
-
.eda-mini-grid div,.eda-stat-grid div{min-width:0;padding:10px;border-radius:12px;background:#fff;box-shadow:inset 0 0 0 1px rgba(23,32,51,.06)}
|
|
38
|
-
.eda-mini-grid span,.eda-stat-grid span{display:block;color:#718096;font-size:12px}
|
|
39
|
-
.eda-mini-grid strong,.eda-stat-grid strong{display:block;margin-top:4px;overflow:hidden;color:#172033;font-size:18px;text-overflow:ellipsis;white-space:nowrap}
|
|
40
|
-
.eda-warning{background:#fff7e8;color:#8a4b00}
|
|
41
|
-
.eda-search{height:42px;padding:0 12px;border-radius:12px;border:1px solid rgba(23,32,51,.1);outline:none;background:#fff;font:inherit}
|
|
42
|
-
.eda-stream-list{flex:1;min-height:0;overflow:auto;display:flex;flex-direction:column;gap:8px}
|
|
43
|
-
.eda-stream{min-height:78px;display:grid;grid-template-columns:74px minmax(0,1fr);gap:8px 10px;align-items:center;padding:10px;border:1px solid rgba(23,32,51,.08);border-radius:13px;background:#fff;color:inherit;font:inherit;text-align:left;cursor:pointer}
|
|
44
|
-
.eda-stream:hover,.eda-stream.active,.eda-tree button:hover,.eda-tree button.active,.eda-entity-group button:hover{border-color:rgba(11,116,128,.3);box-shadow:0 10px 22px rgba(23,32,51,.08)}
|
|
45
|
-
.eda-stream span{grid-row:span 3;min-height:40px;display:inline-flex;align-items:center;justify-content:center;padding:0 8px;border-radius:10px;background:rgba(11,116,128,.12);color:#0b7480;font-size:11px;font-weight:900}
|
|
46
|
-
.eda-stream span[data-role='symbol']{background:rgba(34,134,90,.14);color:#1d7a52}
|
|
47
|
-
.eda-stream span[data-role='footprint'],.eda-stream span[data-role='padstack']{background:rgba(111,87,190,.14);color:#5c47a5}
|
|
48
|
-
.eda-stream strong,.eda-stream em,.eda-tree strong,.eda-tree em,.eda-tree small,.eda-entity-group strong,.eda-entity-group span,.eda-entity-group dd{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
49
|
-
.eda-stream em,.eda-stream small{color:#718096;font-size:12px;font-style:normal}
|
|
50
|
-
.eda-preview{min-width:0;min-height:0;overflow:auto;display:flex;flex-direction:column;gap:14px;padding:16px}
|
|
51
|
-
.eda-panel{min-height:0;overflow:hidden}
|
|
52
|
-
.eda-panel-head{min-height:54px;padding:12px 14px;border-bottom:1px solid rgba(23,32,51,.08)}
|
|
53
|
-
.eda-panel-head strong{display:block;margin-top:4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
54
|
-
.eda-panel--compact .eda-panel-head{min-height:auto}
|
|
55
|
-
.eda-stat-grid{padding:14px}
|
|
56
|
-
.eda-stat-grid div{background:#f6f9fb}
|
|
57
|
-
.eda-topology,.eda-bottom{min-height:300px;display:grid;grid-template-columns:minmax(0,.92fr) minmax(0,1.08fr);gap:14px}
|
|
58
|
-
.eda-topology>.eda-panel{min-height:360px;max-height:min(58vh,620px);display:flex;flex-direction:column}
|
|
59
|
-
.eda-tree,.eda-entities,.eda-diagnostics,.eda-string-grid{min-height:0;max-height:380px;overflow:auto;overscroll-behavior:contain}
|
|
60
|
-
.eda-tree{flex:1;max-height:none;padding:10px}
|
|
61
|
-
.eda-entities{flex:1;max-height:none;padding:12px}
|
|
62
|
-
.eda-tree button{width:100%;min-height:42px;display:grid;grid-template-columns:minmax(22px,auto) minmax(0,1fr) minmax(72px,auto) minmax(72px,auto);gap:8px;align-items:center;margin-bottom:6px;padding:8px;border:1px solid rgba(23,32,51,.06);border-radius:10px;background:#f8fafc;color:inherit;font:inherit;text-align:left;cursor:pointer}
|
|
63
|
-
.eda-tree span{color:#0b7480;font-weight:900}
|
|
64
|
-
.eda-tree em,.eda-tree small{color:#718096;font-size:12px;font-style:normal}
|
|
65
|
-
.eda-entity-group+.eda-entity-group{margin-top:16px}
|
|
66
|
-
.eda-entity-group h3{margin:0 0 8px;color:#172033;font-size:14px}
|
|
67
|
-
.eda-entity-group button{width:100%;display:block;margin-bottom:8px;padding:12px;border:1px solid rgba(23,32,51,.08);border-radius:12px;background:#f8fafc;color:inherit;font:inherit;text-align:left;cursor:pointer}
|
|
68
|
-
.eda-entity-group button>span{display:block;margin-top:4px;color:#718096;font-size:12px}
|
|
69
|
-
.eda-entity-group dl{display:grid;gap:6px;margin-top:10px}
|
|
70
|
-
.eda-entity-group dl div{min-width:0;display:grid;grid-template-columns:90px minmax(0,1fr);gap:8px;color:#475569;font-size:12px}
|
|
71
|
-
.eda-entity-group dt{color:#718096;font-weight:800}
|
|
72
|
-
.eda-selected-meta,.eda-property-grid,.eda-local-strings{display:flex;flex-wrap:wrap;gap:8px;padding:12px 14px 0}
|
|
73
|
-
.eda-selected-meta span,.eda-property-grid div,.eda-local-strings span{min-width:0;display:inline-flex;align-items:center;gap:6px;border-radius:999px;background:#eef6f7;color:#0b7480;font-size:12px;font-weight:800}
|
|
74
|
-
.eda-selected-meta span,.eda-local-strings span{padding:6px 10px}
|
|
75
|
-
.eda-property-grid div{max-width:100%;padding:6px 10px}
|
|
76
|
-
.eda-property-grid span{color:#64748b;font-weight:700}
|
|
77
|
-
.eda-property-grid strong{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
78
|
-
.eda-panel pre{min-height:220px;max-height:440px;margin:12px 0 0;overflow:auto;padding:16px;border-top:1px solid rgba(23,32,51,.08);background:#101725;color:#d9e7ff;font-size:13px;line-height:1.6;white-space:pre-wrap;word-break:break-word}
|
|
79
|
-
.eda-empty{min-height:180px;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:24px;text-align:center}
|
|
80
|
-
.eda-string-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));align-content:start;gap:8px;padding:14px}
|
|
81
|
-
.eda-string-grid span{min-width:0;padding:8px 10px;border-radius:10px;background:#f6f9fb;color:#334155;font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
82
|
-
.eda-diagnostics{padding:14px}
|
|
83
|
-
.eda-diagnostics p{margin:0 0 8px;padding:10px;border-radius:10px;background:#f6f9fb;color:#475569;line-height:1.5}
|
|
84
|
-
.eda-diagnostics p[data-level='warning']{background:#fff7e8;color:#8a4b00}
|
|
85
|
-
.eda-diagnostics span{display:inline-flex;margin-right:8px;color:#0b7480;font-size:11px;font-weight:900;text-transform:uppercase}
|
|
86
|
-
.eda-local-strings{padding-bottom:14px}
|
|
87
|
-
.eda-local-strings strong{width:100%;color:#172033;font-size:13px}
|
|
88
|
-
.eda-state{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;gap:12px;background:rgba(237,241,245,.9);z-index:2}
|
|
89
|
-
.eda-state span{width:32px;height:32px;border-radius:999px;border:3px solid rgba(11,116,128,.16);border-top-color:#0b7480;animation:eda-spin .9s linear infinite}
|
|
90
|
-
.eda-error{position:absolute;right:18px;bottom:18px;width:min(440px,calc(100% - 36px));padding:14px;background:#fff7e8;color:#8a4b00;z-index:3}
|
|
91
|
-
@keyframes eda-spin{to{transform:rotate(360deg)}}
|
|
92
|
-
.file-viewer[data-viewer-theme='dark'] .eda-viewer{background:#172033;color:#e5eef8}
|
|
93
|
-
.file-viewer[data-viewer-theme='dark'] .eda-header,.file-viewer[data-viewer-theme='dark'] .eda-summary,.file-viewer[data-viewer-theme='dark'] .eda-panel,.file-viewer[data-viewer-theme='dark'] .eda-sidebar{background:#fff;color:#172033}
|
|
94
|
-
@media (prefers-color-scheme:dark){.file-viewer[data-viewer-theme='system'] .eda-viewer{background:#172033;color:#e5eef8}.file-viewer[data-viewer-theme='system'] .eda-header,.file-viewer[data-viewer-theme='system'] .eda-summary,.file-viewer[data-viewer-theme='system'] .eda-panel,.file-viewer[data-viewer-theme='system'] .eda-sidebar{background:#fff;color:#172033}}
|
|
95
|
-
@media (max-width:980px){.eda-header,.eda-body,.eda-topology,.eda-bottom{grid-template-columns:1fr}.eda-header{align-items:flex-start;flex-direction:column;padding-right:22px}.eda-body{display:flex;flex-direction:column}.eda-sidebar{max-height:42vh;border-right:0;border-bottom:1px solid rgba(23,32,51,.08)}}
|
|
96
|
-
@media (max-width:640px){.eda-header dl,.eda-mini-grid,.eda-stat-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.eda-tree button{grid-template-columns:minmax(22px,auto) minmax(0,1fr)}.eda-tree em,.eda-tree small{display:none}}
|
|
97
|
-
`;
|
|
98
|
-
const formatBytes = (value) => {
|
|
99
|
-
if (!Number.isFinite(value) || value < 0) {
|
|
100
|
-
return '-';
|
|
101
|
-
}
|
|
102
|
-
if (value < 1024) {
|
|
103
|
-
return `${value} B`;
|
|
104
|
-
}
|
|
105
|
-
const mb = value / 1024 / 1024;
|
|
106
|
-
if (mb >= 1) {
|
|
107
|
-
return `${mb.toFixed(mb < 10 ? 1 : 0)} MB`;
|
|
108
|
-
}
|
|
109
|
-
return `${(value / 1024).toFixed(value < 10 * 1024 ? 1 : 0)} KB`;
|
|
110
|
-
};
|
|
111
|
-
const roleLabel = (role) => roleLabels[role] || role;
|
|
112
|
-
const kindLabel = (kind) => {
|
|
113
|
-
return kind === 'storage' ? '目录' : kind === 'text' ? '文本' : '二进制';
|
|
114
|
-
};
|
|
115
|
-
const normalizePath = (value) => value.replace(/^\/+/, '').toLowerCase();
|
|
116
|
-
const flattenTree = (nodes, depth = 0) => {
|
|
117
|
-
return nodes.flatMap(node => [
|
|
118
|
-
{ ...node, depth },
|
|
119
|
-
...flattenTree(node.children, depth + 1),
|
|
120
|
-
]);
|
|
121
|
-
};
|
|
122
|
-
const createStyle = () => {
|
|
123
|
-
const style = document.createElement('style');
|
|
124
|
-
style.textContent = edaStyle;
|
|
125
|
-
return style;
|
|
126
|
-
};
|
|
127
|
-
const createElement = (tagName, className, text) => {
|
|
128
|
-
const element = document.createElement(tagName);
|
|
129
|
-
if (className) {
|
|
130
|
-
element.className = className;
|
|
131
|
-
}
|
|
132
|
-
if (text !== undefined) {
|
|
133
|
-
element.textContent = text;
|
|
134
|
-
}
|
|
135
|
-
return element;
|
|
136
|
-
};
|
|
137
|
-
const appendDefinition = (list, label, value) => {
|
|
138
|
-
const item = document.createElement('div');
|
|
139
|
-
item.append(createElement('dt', undefined, label), createElement('dd', undefined, value));
|
|
140
|
-
list.append(item);
|
|
141
|
-
};
|
|
142
|
-
const appendPanelHead = (panel, title, value) => {
|
|
143
|
-
const head = createElement('div', 'eda-panel-head');
|
|
144
|
-
head.append(createElement('span', undefined, title), createElement('strong', undefined, value));
|
|
145
|
-
panel.append(head);
|
|
146
|
-
};
|
|
147
|
-
const buildStatsCards = (parsed) => {
|
|
148
|
-
const stats = parsed.stats;
|
|
149
|
-
return [
|
|
150
|
-
{ label: '文本流', value: stats.textStreams },
|
|
151
|
-
{ label: '二进制流', value: stats.binaryStreams },
|
|
152
|
-
{ label: '目录', value: stats.storageEntries },
|
|
153
|
-
{ label: '属性', value: stats.propertyCount },
|
|
154
|
-
{ label: '符号', value: stats.symbolCount },
|
|
155
|
-
{ label: '封装', value: stats.footprintCount },
|
|
156
|
-
{ label: 'Padstack', value: stats.padstackCount },
|
|
157
|
-
{ label: '可信度', value: confidenceLabels[stats.confidence] },
|
|
158
|
-
];
|
|
159
|
-
};
|
|
160
|
-
const buildEntityGroups = (entities) => {
|
|
161
|
-
const groups = [
|
|
162
|
-
{ role: 'symbol', label: '元件符号', items: [] },
|
|
163
|
-
{ role: 'footprint', label: '封装图形', items: [] },
|
|
164
|
-
{ role: 'padstack', label: 'Padstack', items: [] },
|
|
165
|
-
{ role: 'drawing', label: '图纸信息', items: [] },
|
|
166
|
-
];
|
|
167
|
-
groups.forEach(group => {
|
|
168
|
-
group.items = entities.filter(entity => entity.role === group.role);
|
|
169
|
-
});
|
|
170
|
-
return groups.filter(group => group.items.length);
|
|
171
|
-
};
|
|
172
|
-
const appendStatGrid = (target, items, className) => {
|
|
173
|
-
const grid = createElement('div', className);
|
|
174
|
-
items.forEach(item => {
|
|
175
|
-
const cell = document.createElement('div');
|
|
176
|
-
cell.append(createElement('span', undefined, item.label), createElement('strong', undefined, String(item.value)));
|
|
177
|
-
grid.append(cell);
|
|
178
|
-
});
|
|
179
|
-
target.append(grid);
|
|
180
|
-
};
|
|
181
|
-
const createEmpty = (title, description) => {
|
|
182
|
-
const empty = createElement('div', 'eda-empty');
|
|
183
|
-
empty.append(createElement('strong', undefined, title), createElement('p', undefined, description));
|
|
184
|
-
return empty;
|
|
185
|
-
};
|
|
186
|
-
export default async function renderEda(buffer, target, type = 'olb', context) {
|
|
187
|
-
const normalizedType = type === 'dra' ? 'dra' : 'olb';
|
|
188
|
-
const filename = (context === null || context === void 0 ? void 0 : context.filename) || `preview.${normalizedType}`;
|
|
189
|
-
const root = createElement('section', 'eda-viewer');
|
|
190
|
-
const style = createStyle();
|
|
191
|
-
const cleanups = [];
|
|
192
|
-
let selectedStream = null;
|
|
193
|
-
let parsedResult = null;
|
|
194
|
-
target.replaceChildren(style, root);
|
|
195
|
-
const listen = (element, event, listener) => {
|
|
196
|
-
element.addEventListener(event, listener);
|
|
197
|
-
cleanups.push(() => element.removeEventListener(event, listener));
|
|
198
|
-
};
|
|
199
|
-
const showLoading = () => {
|
|
200
|
-
const state = createElement('div', 'eda-state');
|
|
201
|
-
state.append(createElement('span'), createElement('strong', undefined, `正在解析 ${normalizedType.toUpperCase()}...`));
|
|
202
|
-
root.append(state);
|
|
203
|
-
return state;
|
|
204
|
-
};
|
|
205
|
-
const showError = (message) => {
|
|
206
|
-
const error = createElement('div', 'eda-error');
|
|
207
|
-
error.append(createElement('strong', undefined, 'EDA 预览提示'), createElement('p', undefined, message));
|
|
208
|
-
root.append(error);
|
|
209
|
-
};
|
|
210
|
-
const renderParsed = (parsed) => {
|
|
211
|
-
parsedResult = parsed;
|
|
212
|
-
selectedStream = parsed.streams.find(stream => stream.properties.length)
|
|
213
|
-
|| parsed.streams.find(stream => stream.kind === 'text')
|
|
214
|
-
|| parsed.streams[0]
|
|
215
|
-
|| null;
|
|
216
|
-
const statsCards = buildStatsCards(parsed);
|
|
217
|
-
const treeRows = flattenTree(parsed.tree);
|
|
218
|
-
const entityGroups = buildEntityGroups(parsed.entities);
|
|
219
|
-
root.replaceChildren();
|
|
220
|
-
const header = createElement('header', 'eda-header');
|
|
221
|
-
const headerTitle = document.createElement('div');
|
|
222
|
-
headerTitle.append(createElement('span', undefined, parsed.parser === 'cfb' ? 'CFB STRUCTURE VIEWER' : 'BINARY STRUCTURE VIEWER'), createElement('h2', undefined, filename));
|
|
223
|
-
const headerStats = document.createElement('dl');
|
|
224
|
-
appendDefinition(headerStats, '格式', parsed.type.toUpperCase());
|
|
225
|
-
appendDefinition(headerStats, '大小', formatBytes(parsed.byteLength));
|
|
226
|
-
appendDefinition(headerStats, '条目', String(parsed.streamCount));
|
|
227
|
-
appendDefinition(headerStats, '可信度', confidenceLabels[parsed.stats.confidence]);
|
|
228
|
-
header.append(headerTitle, headerStats);
|
|
229
|
-
const body = createElement('div', 'eda-body');
|
|
230
|
-
const sidebar = createElement('aside', 'eda-sidebar');
|
|
231
|
-
const summary = createElement('div', 'eda-summary');
|
|
232
|
-
summary.append(createElement('strong', undefined, parsed.title), createElement('p', undefined, 'OLB / DRA 属于 OrCAD / Allegro 生态的私有设计数据。预览器优先解析 CFB 结构、对象候选、属性和可读文本,并在纯前端安全退化。'));
|
|
233
|
-
sidebar.append(summary);
|
|
234
|
-
appendStatGrid(sidebar, statsCards.slice(0, 4), 'eda-mini-grid');
|
|
235
|
-
if (parsed.warnings.length) {
|
|
236
|
-
const warning = createElement('div', 'eda-warning');
|
|
237
|
-
parsed.warnings.forEach(item => warning.append(createElement('p', undefined, item)));
|
|
238
|
-
sidebar.append(warning);
|
|
239
|
-
}
|
|
240
|
-
const search = createElement('input', 'eda-search');
|
|
241
|
-
search.type = 'search';
|
|
242
|
-
search.placeholder = '筛选路径、角色、属性或文本';
|
|
243
|
-
sidebar.append(search);
|
|
244
|
-
const streamList = createElement('div', 'eda-stream-list');
|
|
245
|
-
const preview = createElement('main', 'eda-preview');
|
|
246
|
-
let streamButtons = [];
|
|
247
|
-
const currentPanel = createElement('section', 'eda-panel');
|
|
248
|
-
const selectedHead = createElement('div', 'eda-panel-head');
|
|
249
|
-
const selectedTitle = createElement('span', undefined, '当前条目');
|
|
250
|
-
const selectedPath = createElement('strong', undefined, '未选择');
|
|
251
|
-
selectedHead.append(selectedTitle, selectedPath);
|
|
252
|
-
const selectedMeta = createElement('div', 'eda-selected-meta');
|
|
253
|
-
const selectedProperties = createElement('div', 'eda-property-grid');
|
|
254
|
-
const selectedPreviewContainer = document.createElement('div');
|
|
255
|
-
currentPanel.append(selectedHead, selectedMeta, selectedProperties, selectedPreviewContainer);
|
|
256
|
-
const localStrings = createElement('div', 'eda-local-strings');
|
|
257
|
-
const syncSelection = () => {
|
|
258
|
-
streamButtons.forEach(({ path, button }) => {
|
|
259
|
-
button.classList.toggle('active', normalizePath(path) === normalizePath((selectedStream === null || selectedStream === void 0 ? void 0 : selectedStream.path) || ''));
|
|
260
|
-
});
|
|
261
|
-
selectedPath.textContent = (selectedStream === null || selectedStream === void 0 ? void 0 : selectedStream.path) || '未选择';
|
|
262
|
-
selectedMeta.replaceChildren();
|
|
263
|
-
selectedProperties.replaceChildren();
|
|
264
|
-
selectedPreviewContainer.replaceChildren();
|
|
265
|
-
localStrings.replaceChildren();
|
|
266
|
-
if (!selectedStream) {
|
|
267
|
-
selectedPreviewContainer.append(createEmpty('目录条目', '该节点用于组织下级流,没有可直接展示的文本或十六进制片段。'));
|
|
268
|
-
return;
|
|
269
|
-
}
|
|
270
|
-
selectedMeta.append(createElement('span', undefined, roleLabel(selectedStream.role)), createElement('span', undefined, kindLabel(selectedStream.kind)), createElement('span', undefined, formatBytes(selectedStream.size)));
|
|
271
|
-
selectedStream.properties.forEach(property => {
|
|
272
|
-
const item = document.createElement('div');
|
|
273
|
-
item.append(createElement('span', undefined, property.key), createElement('strong', undefined, property.value));
|
|
274
|
-
selectedProperties.append(item);
|
|
275
|
-
});
|
|
276
|
-
const previewText = selectedStream.sample || selectedStream.hex || '';
|
|
277
|
-
if (previewText) {
|
|
278
|
-
selectedPreviewContainer.append(createElement('pre', undefined, previewText));
|
|
279
|
-
}
|
|
280
|
-
else {
|
|
281
|
-
selectedPreviewContainer.append(createEmpty('目录条目', '该节点用于组织下级流,没有可直接展示的文本或十六进制片段。'));
|
|
282
|
-
}
|
|
283
|
-
if (selectedStream.strings.length) {
|
|
284
|
-
localStrings.append(createElement('strong', undefined, '当前条目字符串'));
|
|
285
|
-
selectedStream.strings.forEach(item => localStrings.append(createElement('span', undefined, item)));
|
|
286
|
-
}
|
|
287
|
-
};
|
|
288
|
-
const selectStream = (stream) => {
|
|
289
|
-
selectedStream = stream;
|
|
290
|
-
syncSelection();
|
|
291
|
-
};
|
|
292
|
-
const selectTreeRow = (row) => {
|
|
293
|
-
const rowPath = normalizePath(row.path);
|
|
294
|
-
const stream = parsed.streams.find(item => normalizePath(item.path) === rowPath);
|
|
295
|
-
if (stream) {
|
|
296
|
-
selectStream(stream);
|
|
297
|
-
}
|
|
298
|
-
};
|
|
299
|
-
const selectEntity = (entity) => {
|
|
300
|
-
const entityPath = normalizePath(entity.path);
|
|
301
|
-
const stream = parsed.streams.find(item => {
|
|
302
|
-
const streamPath = normalizePath(item.path);
|
|
303
|
-
return streamPath === entityPath || streamPath.startsWith(`${entityPath}/`);
|
|
304
|
-
});
|
|
305
|
-
if (stream) {
|
|
306
|
-
selectStream(stream);
|
|
307
|
-
}
|
|
308
|
-
};
|
|
309
|
-
const matchesFilter = (stream, keyword) => {
|
|
310
|
-
if (!keyword) {
|
|
311
|
-
return true;
|
|
312
|
-
}
|
|
313
|
-
const propertyText = stream.properties.map(property => `${property.key}=${property.value}`).join('\n');
|
|
314
|
-
const text = `${stream.path}\n${stream.name}\n${stream.kind}\n${stream.role}\n${stream.sample || ''}\n${stream.strings.join('\n')}\n${propertyText}`.toLowerCase();
|
|
315
|
-
return text.includes(keyword);
|
|
316
|
-
};
|
|
317
|
-
const renderStreams = () => {
|
|
318
|
-
const keyword = search.value.trim().toLowerCase();
|
|
319
|
-
streamList.replaceChildren();
|
|
320
|
-
streamButtons = [];
|
|
321
|
-
parsed.streams.filter(stream => matchesFilter(stream, keyword)).forEach(stream => {
|
|
322
|
-
const button = createElement('button', 'eda-stream');
|
|
323
|
-
button.type = 'button';
|
|
324
|
-
const role = createElement('span', undefined, roleLabel(stream.role));
|
|
325
|
-
role.dataset.role = stream.role;
|
|
326
|
-
button.append(role, createElement('strong', undefined, stream.name || stream.path), createElement('em', undefined, stream.path), createElement('small', undefined, `${kindLabel(stream.kind)} · ${formatBytes(stream.size)}`));
|
|
327
|
-
listen(button, 'click', () => selectStream(stream));
|
|
328
|
-
streamButtons.push({ path: stream.path, button });
|
|
329
|
-
streamList.append(button);
|
|
330
|
-
});
|
|
331
|
-
syncSelection();
|
|
332
|
-
};
|
|
333
|
-
listen(search, 'input', renderStreams);
|
|
334
|
-
sidebar.append(streamList);
|
|
335
|
-
const overview = createElement('section', 'eda-panel eda-panel--compact');
|
|
336
|
-
appendPanelHead(overview, '解析概览', `${parsed.parser.toUpperCase()} · ${formatBytes(parsed.totalStreamBytes)}`);
|
|
337
|
-
appendStatGrid(overview, statsCards, 'eda-stat-grid');
|
|
338
|
-
const topology = createElement('section', 'eda-topology');
|
|
339
|
-
const treePanel = createElement('div', 'eda-panel');
|
|
340
|
-
appendPanelHead(treePanel, '结构树', `${treeRows.length} 节点`);
|
|
341
|
-
const tree = createElement('div', 'eda-tree');
|
|
342
|
-
treeRows.forEach(row => {
|
|
343
|
-
const button = createElement('button');
|
|
344
|
-
button.type = 'button';
|
|
345
|
-
const twist = createElement('span', undefined, row.children.length ? '▸' : '•');
|
|
346
|
-
twist.style.paddingLeft = `${row.depth * 14}px`;
|
|
347
|
-
button.append(twist, createElement('strong', undefined, row.name), createElement('em', undefined, roleLabel(row.role)), createElement('small', undefined, row.size ? formatBytes(row.size) : kindLabel(row.kind)));
|
|
348
|
-
listen(button, 'click', () => selectTreeRow(row));
|
|
349
|
-
tree.append(button);
|
|
350
|
-
});
|
|
351
|
-
treePanel.append(tree);
|
|
352
|
-
const entityPanel = createElement('div', 'eda-panel');
|
|
353
|
-
appendPanelHead(entityPanel, 'EDA 对象', `${parsed.entities.length} 项`);
|
|
354
|
-
if (entityGroups.length) {
|
|
355
|
-
const entityRoot = createElement('div', 'eda-entities');
|
|
356
|
-
entityGroups.forEach(group => {
|
|
357
|
-
const groupRoot = createElement('div', 'eda-entity-group');
|
|
358
|
-
groupRoot.append(createElement('h3', undefined, group.label));
|
|
359
|
-
group.items.forEach(entity => {
|
|
360
|
-
const button = createElement('button');
|
|
361
|
-
button.type = 'button';
|
|
362
|
-
button.append(createElement('strong', undefined, entity.name), createElement('span', undefined, `${formatBytes(entity.byteLength)} · ${entity.streamCount} 条目`));
|
|
363
|
-
if (entity.description) {
|
|
364
|
-
button.append(createElement('p', undefined, entity.description));
|
|
365
|
-
}
|
|
366
|
-
const detail = document.createElement('dl');
|
|
367
|
-
const addDetail = (label, values) => {
|
|
368
|
-
const normalized = Array.isArray(values) ? values.join(', ') : values;
|
|
369
|
-
if (!normalized) {
|
|
370
|
-
return;
|
|
371
|
-
}
|
|
372
|
-
appendDefinition(detail, label, normalized);
|
|
373
|
-
};
|
|
374
|
-
addDetail('Footprint', entity.footprint);
|
|
375
|
-
addDetail('Pins', entity.pins);
|
|
376
|
-
addDetail('Layers', entity.layers);
|
|
377
|
-
addDetail('Keywords', entity.keywords);
|
|
378
|
-
button.append(detail);
|
|
379
|
-
listen(button, 'click', () => selectEntity(entity));
|
|
380
|
-
groupRoot.append(button);
|
|
381
|
-
});
|
|
382
|
-
entityRoot.append(groupRoot);
|
|
383
|
-
});
|
|
384
|
-
entityPanel.append(entityRoot);
|
|
385
|
-
}
|
|
386
|
-
else {
|
|
387
|
-
entityPanel.append(createEmpty('没有明确对象候选', '仍可从结构树、属性和字符串索引中查看可读内容。'));
|
|
388
|
-
}
|
|
389
|
-
topology.append(treePanel, entityPanel);
|
|
390
|
-
const bottom = createElement('section', 'eda-bottom');
|
|
391
|
-
const stringsPanel = createElement('div', 'eda-panel');
|
|
392
|
-
appendPanelHead(stringsPanel, '可读字符串', `${parsed.strings.length} 项`);
|
|
393
|
-
const stringGrid = createElement('div', 'eda-string-grid');
|
|
394
|
-
parsed.strings.forEach(item => stringGrid.append(createElement('span', undefined, item)));
|
|
395
|
-
stringsPanel.append(stringGrid);
|
|
396
|
-
const diagnosticsPanel = createElement('div', 'eda-panel');
|
|
397
|
-
appendPanelHead(diagnosticsPanel, '诊断', `${parsed.diagnostics.length} 条`);
|
|
398
|
-
const diagnostics = createElement('div', 'eda-diagnostics');
|
|
399
|
-
parsed.diagnostics.forEach(diagnostic => {
|
|
400
|
-
const item = createElement('p');
|
|
401
|
-
item.dataset.level = diagnostic.level;
|
|
402
|
-
item.append(createElement('span', undefined, diagnostic.level), document.createTextNode(diagnostic.message));
|
|
403
|
-
diagnostics.append(item);
|
|
404
|
-
});
|
|
405
|
-
diagnosticsPanel.append(diagnostics, localStrings);
|
|
406
|
-
bottom.append(stringsPanel, diagnosticsPanel);
|
|
407
|
-
preview.append(overview, topology, currentPanel, bottom);
|
|
408
|
-
body.append(sidebar, preview);
|
|
409
|
-
root.append(header, body);
|
|
410
|
-
renderStreams();
|
|
411
|
-
};
|
|
412
|
-
const loading = showLoading();
|
|
413
|
-
try {
|
|
414
|
-
const parsed = await parseEdaFile(buffer, normalizedType);
|
|
415
|
-
renderParsed(parsed);
|
|
416
|
-
}
|
|
417
|
-
catch (nextError) {
|
|
418
|
-
console.error(nextError);
|
|
419
|
-
root.replaceChildren();
|
|
420
|
-
showError(nextError instanceof Error ? nextError.message : String(nextError));
|
|
421
|
-
}
|
|
422
|
-
finally {
|
|
423
|
-
loading.remove();
|
|
424
|
-
}
|
|
425
|
-
return {
|
|
426
|
-
$el: root,
|
|
427
|
-
unmount() {
|
|
428
|
-
cleanups.splice(0).forEach(cleanup => cleanup());
|
|
429
|
-
parsedResult = null;
|
|
430
|
-
selectedStream = null;
|
|
431
|
-
target.replaceChildren();
|
|
432
|
-
},
|
|
433
|
-
};
|
|
434
|
-
}
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
export type EdaFileType = 'olb' | 'dra';
|
|
2
|
-
export type EdaParserMode = 'cfb' | 'binary';
|
|
3
|
-
export type EdaStreamKind = 'text' | 'binary' | 'storage';
|
|
4
|
-
export type EdaDomainRole = 'root' | 'library' | 'symbol' | 'footprint' | 'padstack' | 'drawing' | 'metadata' | 'property' | 'geometry' | 'net' | 'unknown';
|
|
5
|
-
export type EdaDiagnosticLevel = 'info' | 'warning';
|
|
6
|
-
export interface EdaProperty {
|
|
7
|
-
key: string;
|
|
8
|
-
value: string;
|
|
9
|
-
source: string;
|
|
10
|
-
}
|
|
11
|
-
export interface EdaStreamView {
|
|
12
|
-
path: string;
|
|
13
|
-
name: string;
|
|
14
|
-
size: number;
|
|
15
|
-
kind: EdaStreamKind;
|
|
16
|
-
role: EdaDomainRole;
|
|
17
|
-
sample?: string;
|
|
18
|
-
hex?: string;
|
|
19
|
-
strings: string[];
|
|
20
|
-
properties: EdaProperty[];
|
|
21
|
-
}
|
|
22
|
-
export interface EdaTreeNode {
|
|
23
|
-
id: string;
|
|
24
|
-
path: string;
|
|
25
|
-
name: string;
|
|
26
|
-
kind: EdaStreamKind;
|
|
27
|
-
role: EdaDomainRole;
|
|
28
|
-
size: number;
|
|
29
|
-
children: EdaTreeNode[];
|
|
30
|
-
}
|
|
31
|
-
export interface EdaEntity {
|
|
32
|
-
id: string;
|
|
33
|
-
name: string;
|
|
34
|
-
role: EdaDomainRole;
|
|
35
|
-
path: string;
|
|
36
|
-
streamCount: number;
|
|
37
|
-
byteLength: number;
|
|
38
|
-
properties: EdaProperty[];
|
|
39
|
-
pins: string[];
|
|
40
|
-
layers: string[];
|
|
41
|
-
keywords: string[];
|
|
42
|
-
description?: string;
|
|
43
|
-
footprint?: string;
|
|
44
|
-
}
|
|
45
|
-
export interface EdaStats {
|
|
46
|
-
textStreams: number;
|
|
47
|
-
binaryStreams: number;
|
|
48
|
-
storageEntries: number;
|
|
49
|
-
propertyCount: number;
|
|
50
|
-
stringCount: number;
|
|
51
|
-
symbolCount: number;
|
|
52
|
-
footprintCount: number;
|
|
53
|
-
padstackCount: number;
|
|
54
|
-
confidence: 'high' | 'medium' | 'low';
|
|
55
|
-
}
|
|
56
|
-
export interface EdaDiagnostic {
|
|
57
|
-
level: EdaDiagnosticLevel;
|
|
58
|
-
code: string;
|
|
59
|
-
message: string;
|
|
60
|
-
}
|
|
61
|
-
export interface EdaParseResult {
|
|
62
|
-
type: EdaFileType;
|
|
63
|
-
parser: EdaParserMode;
|
|
64
|
-
title: string;
|
|
65
|
-
byteLength: number;
|
|
66
|
-
streamCount: number;
|
|
67
|
-
totalStreamBytes: number;
|
|
68
|
-
streams: EdaStreamView[];
|
|
69
|
-
tree: EdaTreeNode[];
|
|
70
|
-
entities: EdaEntity[];
|
|
71
|
-
metadata: EdaProperty[];
|
|
72
|
-
strings: string[];
|
|
73
|
-
warnings: string[];
|
|
74
|
-
diagnostics: EdaDiagnostic[];
|
|
75
|
-
stats: EdaStats;
|
|
76
|
-
}
|
|
77
|
-
export declare const parseEdaFile: (buffer: ArrayBuffer, type?: string) => Promise<EdaParseResult>;
|