@file-viewer/renderer-eda 2.1.1 → 2.1.3
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/dist/eda.d.ts +1 -1
- package/dist/eda.js +183 -70
- package/dist/edaParser.d.ts +4 -1
- package/dist/edaParser.js +66 -23
- package/package.json +4 -4
package/dist/eda.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type FileRenderContext, type FileViewerRenderedInstance } from '@file-viewer/core';
|
|
2
2
|
export default function renderEda(buffer: ArrayBuffer, target: HTMLDivElement, type?: string, context?: FileRenderContext): Promise<FileViewerRenderedInstance>;
|
package/dist/eda.js
CHANGED
|
@@ -1,22 +1,131 @@
|
|
|
1
|
+
import { resolveFileViewerLocale, } from '@file-viewer/core';
|
|
1
2
|
import { createEdaLayoutWebglBatch, } from '@file-viewer/eda-layout';
|
|
2
3
|
import { parseEdaFile, } from './edaParser';
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
4
|
+
const EDA_UI_TEXT = {
|
|
5
|
+
'zh-CN': {
|
|
6
|
+
'role.root': '根',
|
|
7
|
+
'role.library': '库',
|
|
8
|
+
'role.symbol': '元件符号',
|
|
9
|
+
'role.footprint': '封装',
|
|
10
|
+
'role.padstack': 'Padstack',
|
|
11
|
+
'role.drawing': '图纸',
|
|
12
|
+
'role.metadata': '元数据',
|
|
13
|
+
'role.property': '属性',
|
|
14
|
+
'role.geometry': '几何',
|
|
15
|
+
'role.net': '网络',
|
|
16
|
+
'role.unknown': '未知',
|
|
17
|
+
'confidence.high': '高',
|
|
18
|
+
'confidence.medium': '中',
|
|
19
|
+
'confidence.low': '低',
|
|
20
|
+
'kind.storage': '目录',
|
|
21
|
+
'kind.text': '文本',
|
|
22
|
+
'kind.binary': '二进制',
|
|
23
|
+
'panel.layout': '版图预览',
|
|
24
|
+
'empty.noGeometry.title': '没有可绘制几何',
|
|
25
|
+
'empty.noGeometry.description': '已读取 {layout} 头部和 structure 信息,但未发现 boundary、path、text 或 reference 元素。',
|
|
26
|
+
'stats.textStreams': '文本流',
|
|
27
|
+
'stats.binaryStreams': '二进制流',
|
|
28
|
+
'stats.storageEntries': '目录',
|
|
29
|
+
'stats.properties': '属性',
|
|
30
|
+
'stats.symbols': '符号',
|
|
31
|
+
'stats.footprints': '封装',
|
|
32
|
+
'stats.confidence': '可信度',
|
|
33
|
+
'group.symbol': '元件符号',
|
|
34
|
+
'group.footprint': '封装图形',
|
|
35
|
+
'group.drawing': '图纸信息',
|
|
36
|
+
'state.loading': '正在解析 {type}...',
|
|
37
|
+
'state.errorTitle': 'EDA 预览提示',
|
|
38
|
+
'header.format': '格式',
|
|
39
|
+
'header.size': '大小',
|
|
40
|
+
'header.entries': '条目',
|
|
41
|
+
'summary.layoutReady': '{layout} 属于芯片版图工程文件。预览器已在浏览器端解析可识别几何,小图生成 SVG,大图自动切换 WebGL canvas,同时保留结构、字符串和诊断索引。',
|
|
42
|
+
'summary.layoutSafe': 'GDSII / OASIS 属于芯片版图工程文件。预览器优先索引结构、属性、可读字符串和二进制线索,并在纯前端安全退化。',
|
|
43
|
+
'summary.orcadSafe': 'OLB / DRA 属于 OrCAD / Allegro 生态的私有设计数据。预览器优先解析 CFB 结构、对象候选、属性和可读文本,并在纯前端安全退化。',
|
|
44
|
+
'search.placeholder': '筛选路径、角色、属性或文本',
|
|
45
|
+
'selection.title': '当前条目',
|
|
46
|
+
'selection.none': '未选择',
|
|
47
|
+
'selection.storageTitle': '目录条目',
|
|
48
|
+
'selection.storageDescription': '该节点用于组织下级流,没有可直接展示的文本或十六进制片段。',
|
|
49
|
+
'selection.localStrings': '当前条目字符串',
|
|
50
|
+
'panel.overview': '解析概览',
|
|
51
|
+
'panel.tree': '结构树',
|
|
52
|
+
'panel.objects': 'EDA 对象',
|
|
53
|
+
'panel.strings': '可读字符串',
|
|
54
|
+
'panel.diagnostics': '诊断',
|
|
55
|
+
'panel.nodeCount': '{count} 节点',
|
|
56
|
+
'panel.itemCount': '{count} 项',
|
|
57
|
+
'panel.entryCount': '{count} 条目',
|
|
58
|
+
'empty.noObjects.title': '没有明确对象候选',
|
|
59
|
+
'empty.noObjects.description': '仍可从结构树、属性和字符串索引中查看可读内容。',
|
|
60
|
+
'meta.renderer': '渲染器',
|
|
61
|
+
'meta.library': '库',
|
|
62
|
+
'meta.userUnit': '用户单位',
|
|
63
|
+
'meta.dbUnit': '数据库单位',
|
|
64
|
+
},
|
|
65
|
+
'en-US': {
|
|
66
|
+
'role.root': 'Root',
|
|
67
|
+
'role.library': 'Library',
|
|
68
|
+
'role.symbol': 'Symbol',
|
|
69
|
+
'role.footprint': 'Footprint',
|
|
70
|
+
'role.padstack': 'Padstack',
|
|
71
|
+
'role.drawing': 'Drawing',
|
|
72
|
+
'role.metadata': 'Metadata',
|
|
73
|
+
'role.property': 'Property',
|
|
74
|
+
'role.geometry': 'Geometry',
|
|
75
|
+
'role.net': 'Net',
|
|
76
|
+
'role.unknown': 'Unknown',
|
|
77
|
+
'confidence.high': 'High',
|
|
78
|
+
'confidence.medium': 'Medium',
|
|
79
|
+
'confidence.low': 'Low',
|
|
80
|
+
'kind.storage': 'Directory',
|
|
81
|
+
'kind.text': 'Text',
|
|
82
|
+
'kind.binary': 'Binary',
|
|
83
|
+
'panel.layout': 'Layout preview',
|
|
84
|
+
'empty.noGeometry.title': 'No drawable geometry',
|
|
85
|
+
'empty.noGeometry.description': '{layout} headers and structure metadata were read, but no boundary, path, text, or reference elements were found.',
|
|
86
|
+
'stats.textStreams': 'Text streams',
|
|
87
|
+
'stats.binaryStreams': 'Binary streams',
|
|
88
|
+
'stats.storageEntries': 'Directories',
|
|
89
|
+
'stats.properties': 'Properties',
|
|
90
|
+
'stats.symbols': 'Symbols',
|
|
91
|
+
'stats.footprints': 'Footprints',
|
|
92
|
+
'stats.confidence': 'Confidence',
|
|
93
|
+
'group.symbol': 'Component symbols',
|
|
94
|
+
'group.footprint': 'Footprint graphics',
|
|
95
|
+
'group.drawing': 'Drawing information',
|
|
96
|
+
'state.loading': 'Parsing {type}...',
|
|
97
|
+
'state.errorTitle': 'EDA preview notice',
|
|
98
|
+
'header.format': 'Format',
|
|
99
|
+
'header.size': 'Size',
|
|
100
|
+
'header.entries': 'Entries',
|
|
101
|
+
'summary.layoutReady': '{layout} is an IC layout engineering file. Recognizable geometry is parsed in the browser, small drawings use SVG, large drawings switch to WebGL canvas, and structure, strings, and diagnostics remain indexed.',
|
|
102
|
+
'summary.layoutSafe': 'GDSII / OASIS are IC layout engineering files. The viewer prioritizes structure, properties, readable strings, and binary clues, then degrades safely in the frontend.',
|
|
103
|
+
'summary.orcadSafe': 'OLB / DRA are private OrCAD / Allegro design assets. The viewer prioritizes CFB structure, object candidates, properties, and readable text with safe frontend degradation.',
|
|
104
|
+
'search.placeholder': 'Filter paths, roles, properties, or text',
|
|
105
|
+
'selection.title': 'Current entry',
|
|
106
|
+
'selection.none': 'Not selected',
|
|
107
|
+
'selection.storageTitle': 'Directory entry',
|
|
108
|
+
'selection.storageDescription': 'This node organizes child streams and has no directly displayable text or hex fragment.',
|
|
109
|
+
'selection.localStrings': 'Current entry strings',
|
|
110
|
+
'panel.overview': 'Parse overview',
|
|
111
|
+
'panel.tree': 'Structure tree',
|
|
112
|
+
'panel.objects': 'EDA objects',
|
|
113
|
+
'panel.strings': 'Readable strings',
|
|
114
|
+
'panel.diagnostics': 'Diagnostics',
|
|
115
|
+
'panel.nodeCount': '{count} nodes',
|
|
116
|
+
'panel.itemCount': '{count} items',
|
|
117
|
+
'panel.entryCount': '{count} entries',
|
|
118
|
+
'empty.noObjects.title': 'No clear object candidates',
|
|
119
|
+
'empty.noObjects.description': 'Readable content is still available from the structure tree, properties, and string index.',
|
|
120
|
+
'meta.renderer': 'Renderer',
|
|
121
|
+
'meta.library': 'Library',
|
|
122
|
+
'meta.userUnit': 'User unit',
|
|
123
|
+
'meta.dbUnit': 'DB unit',
|
|
124
|
+
},
|
|
15
125
|
};
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
low: '低',
|
|
126
|
+
const formatEdaUiText = (locale, key, params = {}) => {
|
|
127
|
+
const template = EDA_UI_TEXT[locale][key] || EDA_UI_TEXT['zh-CN'][key] || key;
|
|
128
|
+
return Object.entries(params).reduce((message, [name, value]) => message.replace(new RegExp(`\\{${name}\\}`, 'g'), String(value)), template);
|
|
20
129
|
};
|
|
21
130
|
const edaStyle = `
|
|
22
131
|
.eda-viewer{position:relative;height:100%;min-height:0;display:flex;flex-direction:column;background:#edf1f5;color:#172033;box-sizing:border-box}
|
|
@@ -122,9 +231,12 @@ const formatBytes = (value) => {
|
|
|
122
231
|
}
|
|
123
232
|
return `${(value / 1024).toFixed(value < 10 * 1024 ? 1 : 0)} KB`;
|
|
124
233
|
};
|
|
125
|
-
const roleLabel = (role) =>
|
|
126
|
-
|
|
127
|
-
|
|
234
|
+
const roleLabel = (role, locale) => {
|
|
235
|
+
return formatEdaUiText(locale, `role.${role}`) || role;
|
|
236
|
+
};
|
|
237
|
+
const confidenceLabel = (confidence, locale) => formatEdaUiText(locale, `confidence.${confidence}`);
|
|
238
|
+
const kindLabel = (kind, locale) => {
|
|
239
|
+
return formatEdaUiText(locale, `kind.${kind}`);
|
|
128
240
|
};
|
|
129
241
|
const normalizePath = (value) => value.replace(/^\/+/, '').toLowerCase();
|
|
130
242
|
const flattenTree = (nodes, depth = 0) => {
|
|
@@ -328,19 +440,19 @@ const createWebglLayoutPreview = (layout, width, height) => {
|
|
|
328
440
|
batch,
|
|
329
441
|
};
|
|
330
442
|
};
|
|
331
|
-
const createLayoutPreview = (layout) => {
|
|
443
|
+
const createLayoutPreview = (layout, locale) => {
|
|
332
444
|
const panel = createElement('section', 'eda-panel eda-layout-panel');
|
|
333
445
|
const layoutLabel = layout.format === 'oasis' ? 'OASIS' : 'GDSII';
|
|
334
|
-
appendPanelHead(panel, '
|
|
446
|
+
appendPanelHead(panel, formatEdaUiText(locale, 'panel.layout'), `${layoutLabel} · ${layout.structureCount || layout.structures.length} structures · ${layout.elements.length} elements`);
|
|
335
447
|
const meta = createElement('div', 'eda-layout-meta');
|
|
336
448
|
[
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
449
|
+
`${formatEdaUiText(locale, 'meta.library')}: ${layout.libraryName || '-'}`,
|
|
450
|
+
`${formatEdaUiText(locale, 'meta.userUnit')}: ${formatOptionalNumber(layout.userUnit)}`,
|
|
451
|
+
`${formatEdaUiText(locale, 'meta.dbUnit')}: ${formatOptionalNumber(layout.databaseUnit)}`,
|
|
340
452
|
].forEach(item => meta.append(createElement('span', undefined, item)));
|
|
341
453
|
panel.append(meta);
|
|
342
454
|
if (!layout.bounds || !layout.elements.length) {
|
|
343
|
-
panel.append(createEmpty('
|
|
455
|
+
panel.append(createEmpty(formatEdaUiText(locale, 'empty.noGeometry.title'), formatEdaUiText(locale, 'empty.noGeometry.description', { layout: layoutLabel })));
|
|
344
456
|
return panel;
|
|
345
457
|
}
|
|
346
458
|
const bounds = layout.bounds;
|
|
@@ -367,7 +479,7 @@ const createLayoutPreview = (layout) => {
|
|
|
367
479
|
? createWebglLayoutPreview(layout, svgWidth, svgHeight)
|
|
368
480
|
: null;
|
|
369
481
|
if (webglPreview) {
|
|
370
|
-
meta.append(createElement('span', undefined,
|
|
482
|
+
meta.append(createElement('span', undefined, `${formatEdaUiText(locale, 'meta.renderer')}: WebGL · ${webglPreview.batch.elementCount} elements`));
|
|
371
483
|
webglPreview.batch.warnings.forEach(item => {
|
|
372
484
|
const warning = createElement('div', 'eda-warning');
|
|
373
485
|
warning.append(createElement('p', undefined, item));
|
|
@@ -377,7 +489,7 @@ const createLayoutPreview = (layout) => {
|
|
|
377
489
|
panel.append(canvas);
|
|
378
490
|
return panel;
|
|
379
491
|
}
|
|
380
|
-
meta.append(createElement('span', undefined, '
|
|
492
|
+
meta.append(createElement('span', undefined, `${formatEdaUiText(locale, 'meta.renderer')}: SVG`));
|
|
381
493
|
const svg = createSvgElement('svg', {
|
|
382
494
|
class: 'eda-layout-svg',
|
|
383
495
|
width: svgWidth,
|
|
@@ -439,25 +551,25 @@ const createLayoutPreview = (layout) => {
|
|
|
439
551
|
panel.append(canvas);
|
|
440
552
|
return panel;
|
|
441
553
|
};
|
|
442
|
-
const buildStatsCards = (parsed) => {
|
|
554
|
+
const buildStatsCards = (parsed, locale) => {
|
|
443
555
|
const stats = parsed.stats;
|
|
444
556
|
return [
|
|
445
|
-
{ label: '
|
|
446
|
-
{ label: '
|
|
447
|
-
{ label: '
|
|
448
|
-
{ label: '
|
|
449
|
-
{ label: '
|
|
450
|
-
{ label: '
|
|
557
|
+
{ label: formatEdaUiText(locale, 'stats.textStreams'), value: stats.textStreams },
|
|
558
|
+
{ label: formatEdaUiText(locale, 'stats.binaryStreams'), value: stats.binaryStreams },
|
|
559
|
+
{ label: formatEdaUiText(locale, 'stats.storageEntries'), value: stats.storageEntries },
|
|
560
|
+
{ label: formatEdaUiText(locale, 'stats.properties'), value: stats.propertyCount },
|
|
561
|
+
{ label: formatEdaUiText(locale, 'stats.symbols'), value: stats.symbolCount },
|
|
562
|
+
{ label: formatEdaUiText(locale, 'stats.footprints'), value: stats.footprintCount },
|
|
451
563
|
{ label: 'Padstack', value: stats.padstackCount },
|
|
452
|
-
{ label: '
|
|
564
|
+
{ label: formatEdaUiText(locale, 'stats.confidence'), value: confidenceLabel(stats.confidence, locale) },
|
|
453
565
|
];
|
|
454
566
|
};
|
|
455
|
-
const buildEntityGroups = (entities) => {
|
|
567
|
+
const buildEntityGroups = (entities, locale) => {
|
|
456
568
|
const groups = [
|
|
457
|
-
{ role: 'symbol', label: '
|
|
458
|
-
{ role: 'footprint', label: '
|
|
569
|
+
{ role: 'symbol', label: formatEdaUiText(locale, 'group.symbol'), items: [] },
|
|
570
|
+
{ role: 'footprint', label: formatEdaUiText(locale, 'group.footprint'), items: [] },
|
|
459
571
|
{ role: 'padstack', label: 'Padstack', items: [] },
|
|
460
|
-
{ role: 'drawing', label: '
|
|
572
|
+
{ role: 'drawing', label: formatEdaUiText(locale, 'group.drawing'), items: [] },
|
|
461
573
|
];
|
|
462
574
|
groups.forEach(group => {
|
|
463
575
|
group.items = entities.filter(entity => entity.role === group.role);
|
|
@@ -480,6 +592,7 @@ const createEmpty = (title, description) => {
|
|
|
480
592
|
};
|
|
481
593
|
export default async function renderEda(buffer, target, type = 'olb', context) {
|
|
482
594
|
const normalizedType = ['dra', 'gds', 'oas', 'oasis'].includes(type) ? type : 'olb';
|
|
595
|
+
const locale = resolveFileViewerLocale(context?.options) === 'en-US' ? 'en-US' : 'zh-CN';
|
|
483
596
|
const filename = context?.filename || `preview.${normalizedType}`;
|
|
484
597
|
const root = createElement('section', 'eda-viewer');
|
|
485
598
|
const style = createStyle();
|
|
@@ -493,13 +606,13 @@ export default async function renderEda(buffer, target, type = 'olb', context) {
|
|
|
493
606
|
};
|
|
494
607
|
const showLoading = () => {
|
|
495
608
|
const state = createElement('div', 'eda-state');
|
|
496
|
-
state.append(createElement('span'), createElement('strong', undefined,
|
|
609
|
+
state.append(createElement('span'), createElement('strong', undefined, formatEdaUiText(locale, 'state.loading', { type: normalizedType.toUpperCase() })));
|
|
497
610
|
root.append(state);
|
|
498
611
|
return state;
|
|
499
612
|
};
|
|
500
613
|
const showError = (message) => {
|
|
501
614
|
const error = createElement('div', 'eda-error');
|
|
502
|
-
error.append(createElement('strong', undefined,
|
|
615
|
+
error.append(createElement('strong', undefined, formatEdaUiText(locale, 'state.errorTitle')), createElement('p', undefined, message));
|
|
503
616
|
root.append(error);
|
|
504
617
|
};
|
|
505
618
|
const renderParsed = (parsed) => {
|
|
@@ -508,27 +621,27 @@ export default async function renderEda(buffer, target, type = 'olb', context) {
|
|
|
508
621
|
|| parsed.streams.find(stream => stream.kind === 'text')
|
|
509
622
|
|| parsed.streams[0]
|
|
510
623
|
|| null;
|
|
511
|
-
const statsCards = buildStatsCards(parsed);
|
|
624
|
+
const statsCards = buildStatsCards(parsed, locale);
|
|
512
625
|
const treeRows = flattenTree(parsed.tree);
|
|
513
|
-
const entityGroups = buildEntityGroups(parsed.entities);
|
|
626
|
+
const entityGroups = buildEntityGroups(parsed.entities, locale);
|
|
514
627
|
root.replaceChildren();
|
|
515
628
|
const header = createElement('header', 'eda-header');
|
|
516
629
|
const headerTitle = document.createElement('div');
|
|
517
630
|
headerTitle.append(createElement('span', undefined, parsed.parser === 'cfb' ? 'CFB STRUCTURE VIEWER' : 'BINARY STRUCTURE VIEWER'), createElement('h2', undefined, filename));
|
|
518
631
|
const headerStats = document.createElement('dl');
|
|
519
|
-
appendDefinition(headerStats, '
|
|
520
|
-
appendDefinition(headerStats, '
|
|
521
|
-
appendDefinition(headerStats, '
|
|
522
|
-
appendDefinition(headerStats, '
|
|
632
|
+
appendDefinition(headerStats, formatEdaUiText(locale, 'header.format'), parsed.type.toUpperCase());
|
|
633
|
+
appendDefinition(headerStats, formatEdaUiText(locale, 'header.size'), formatBytes(parsed.byteLength));
|
|
634
|
+
appendDefinition(headerStats, formatEdaUiText(locale, 'header.entries'), String(parsed.streamCount));
|
|
635
|
+
appendDefinition(headerStats, formatEdaUiText(locale, 'stats.confidence'), confidenceLabel(parsed.stats.confidence, locale));
|
|
523
636
|
header.append(headerTitle, headerStats);
|
|
524
637
|
const body = createElement('div', 'eda-body');
|
|
525
638
|
const sidebar = createElement('aside', 'eda-sidebar');
|
|
526
639
|
const summary = createElement('div', 'eda-summary');
|
|
527
640
|
summary.append(createElement('strong', undefined, parsed.title), createElement('p', undefined, parsed.type === 'gds' || parsed.type === 'oas' || parsed.type === 'oasis'
|
|
528
641
|
? parsed.layout
|
|
529
|
-
?
|
|
530
|
-
:
|
|
531
|
-
:
|
|
642
|
+
? formatEdaUiText(locale, 'summary.layoutReady', { layout: parsed.layout.format === 'oasis' ? 'OASIS' : 'GDSII' })
|
|
643
|
+
: formatEdaUiText(locale, 'summary.layoutSafe')
|
|
644
|
+
: formatEdaUiText(locale, 'summary.orcadSafe')));
|
|
532
645
|
sidebar.append(summary);
|
|
533
646
|
appendStatGrid(sidebar, statsCards.slice(0, 4), 'eda-mini-grid');
|
|
534
647
|
if (parsed.warnings.length) {
|
|
@@ -538,15 +651,15 @@ export default async function renderEda(buffer, target, type = 'olb', context) {
|
|
|
538
651
|
}
|
|
539
652
|
const search = createElement('input', 'eda-search');
|
|
540
653
|
search.type = 'search';
|
|
541
|
-
search.placeholder = '
|
|
654
|
+
search.placeholder = formatEdaUiText(locale, 'search.placeholder');
|
|
542
655
|
sidebar.append(search);
|
|
543
656
|
const streamList = createElement('div', 'eda-stream-list');
|
|
544
657
|
const preview = createElement('main', 'eda-preview');
|
|
545
658
|
let streamButtons = [];
|
|
546
659
|
const currentPanel = createElement('section', 'eda-panel');
|
|
547
660
|
const selectedHead = createElement('div', 'eda-panel-head');
|
|
548
|
-
const selectedTitle = createElement('span', undefined, '
|
|
549
|
-
const selectedPath = createElement('strong', undefined, '
|
|
661
|
+
const selectedTitle = createElement('span', undefined, formatEdaUiText(locale, 'selection.title'));
|
|
662
|
+
const selectedPath = createElement('strong', undefined, formatEdaUiText(locale, 'selection.none'));
|
|
550
663
|
selectedHead.append(selectedTitle, selectedPath);
|
|
551
664
|
const selectedMeta = createElement('div', 'eda-selected-meta');
|
|
552
665
|
const selectedProperties = createElement('div', 'eda-property-grid');
|
|
@@ -557,16 +670,16 @@ export default async function renderEda(buffer, target, type = 'olb', context) {
|
|
|
557
670
|
streamButtons.forEach(({ path, button }) => {
|
|
558
671
|
button.classList.toggle('active', normalizePath(path) === normalizePath(selectedStream?.path || ''));
|
|
559
672
|
});
|
|
560
|
-
selectedPath.textContent = selectedStream?.path || '
|
|
673
|
+
selectedPath.textContent = selectedStream?.path || formatEdaUiText(locale, 'selection.none');
|
|
561
674
|
selectedMeta.replaceChildren();
|
|
562
675
|
selectedProperties.replaceChildren();
|
|
563
676
|
selectedPreviewContainer.replaceChildren();
|
|
564
677
|
localStrings.replaceChildren();
|
|
565
678
|
if (!selectedStream) {
|
|
566
|
-
selectedPreviewContainer.append(createEmpty('
|
|
679
|
+
selectedPreviewContainer.append(createEmpty(formatEdaUiText(locale, 'selection.storageTitle'), formatEdaUiText(locale, 'selection.storageDescription')));
|
|
567
680
|
return;
|
|
568
681
|
}
|
|
569
|
-
selectedMeta.append(createElement('span', undefined, roleLabel(selectedStream.role)), createElement('span', undefined, kindLabel(selectedStream.kind)), createElement('span', undefined, formatBytes(selectedStream.size)));
|
|
682
|
+
selectedMeta.append(createElement('span', undefined, roleLabel(selectedStream.role, locale)), createElement('span', undefined, kindLabel(selectedStream.kind, locale)), createElement('span', undefined, formatBytes(selectedStream.size)));
|
|
570
683
|
selectedStream.properties.forEach(property => {
|
|
571
684
|
const item = document.createElement('div');
|
|
572
685
|
item.append(createElement('span', undefined, property.key), createElement('strong', undefined, property.value));
|
|
@@ -577,10 +690,10 @@ export default async function renderEda(buffer, target, type = 'olb', context) {
|
|
|
577
690
|
selectedPreviewContainer.append(createElement('pre', undefined, previewText));
|
|
578
691
|
}
|
|
579
692
|
else {
|
|
580
|
-
selectedPreviewContainer.append(createEmpty('
|
|
693
|
+
selectedPreviewContainer.append(createEmpty(formatEdaUiText(locale, 'selection.storageTitle'), formatEdaUiText(locale, 'selection.storageDescription')));
|
|
581
694
|
}
|
|
582
695
|
if (selectedStream.strings.length) {
|
|
583
|
-
localStrings.append(createElement('strong', undefined, '
|
|
696
|
+
localStrings.append(createElement('strong', undefined, formatEdaUiText(locale, 'selection.localStrings')));
|
|
584
697
|
selectedStream.strings.forEach(item => localStrings.append(createElement('span', undefined, item)));
|
|
585
698
|
}
|
|
586
699
|
};
|
|
@@ -620,9 +733,9 @@ export default async function renderEda(buffer, target, type = 'olb', context) {
|
|
|
620
733
|
parsed.streams.filter(stream => matchesFilter(stream, keyword)).forEach(stream => {
|
|
621
734
|
const button = createElement('button', 'eda-stream');
|
|
622
735
|
button.type = 'button';
|
|
623
|
-
const role = createElement('span', undefined, roleLabel(stream.role));
|
|
736
|
+
const role = createElement('span', undefined, roleLabel(stream.role, locale));
|
|
624
737
|
role.dataset.role = stream.role;
|
|
625
|
-
button.append(role, createElement('strong', undefined, stream.name || stream.path), createElement('em', undefined, stream.path), createElement('small', undefined, `${kindLabel(stream.kind)} · ${formatBytes(stream.size)}`));
|
|
738
|
+
button.append(role, createElement('strong', undefined, stream.name || stream.path), createElement('em', undefined, stream.path), createElement('small', undefined, `${kindLabel(stream.kind, locale)} · ${formatBytes(stream.size)}`));
|
|
626
739
|
listen(button, 'click', () => selectStream(stream));
|
|
627
740
|
streamButtons.push({ path: stream.path, button });
|
|
628
741
|
streamList.append(button);
|
|
@@ -632,24 +745,24 @@ export default async function renderEda(buffer, target, type = 'olb', context) {
|
|
|
632
745
|
listen(search, 'input', renderStreams);
|
|
633
746
|
sidebar.append(streamList);
|
|
634
747
|
const overview = createElement('section', 'eda-panel eda-panel--compact');
|
|
635
|
-
appendPanelHead(overview, '
|
|
748
|
+
appendPanelHead(overview, formatEdaUiText(locale, 'panel.overview'), `${parsed.parser.toUpperCase()} · ${formatBytes(parsed.totalStreamBytes)}`);
|
|
636
749
|
appendStatGrid(overview, statsCards, 'eda-stat-grid');
|
|
637
750
|
const topology = createElement('section', 'eda-topology');
|
|
638
751
|
const treePanel = createElement('div', 'eda-panel');
|
|
639
|
-
appendPanelHead(treePanel, '
|
|
752
|
+
appendPanelHead(treePanel, formatEdaUiText(locale, 'panel.tree'), formatEdaUiText(locale, 'panel.nodeCount', { count: treeRows.length }));
|
|
640
753
|
const tree = createElement('div', 'eda-tree');
|
|
641
754
|
treeRows.forEach(row => {
|
|
642
755
|
const button = createElement('button');
|
|
643
756
|
button.type = 'button';
|
|
644
757
|
const twist = createElement('span', undefined, row.children.length ? '▸' : '•');
|
|
645
758
|
twist.style.paddingLeft = `${row.depth * 14}px`;
|
|
646
|
-
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)));
|
|
759
|
+
button.append(twist, createElement('strong', undefined, row.name), createElement('em', undefined, roleLabel(row.role, locale)), createElement('small', undefined, row.size ? formatBytes(row.size) : kindLabel(row.kind, locale)));
|
|
647
760
|
listen(button, 'click', () => selectTreeRow(row));
|
|
648
761
|
tree.append(button);
|
|
649
762
|
});
|
|
650
763
|
treePanel.append(tree);
|
|
651
764
|
const entityPanel = createElement('div', 'eda-panel');
|
|
652
|
-
appendPanelHead(entityPanel, '
|
|
765
|
+
appendPanelHead(entityPanel, formatEdaUiText(locale, 'panel.objects'), formatEdaUiText(locale, 'panel.itemCount', { count: parsed.entities.length }));
|
|
653
766
|
if (entityGroups.length) {
|
|
654
767
|
const entityRoot = createElement('div', 'eda-entities');
|
|
655
768
|
entityGroups.forEach(group => {
|
|
@@ -658,7 +771,7 @@ export default async function renderEda(buffer, target, type = 'olb', context) {
|
|
|
658
771
|
group.items.forEach(entity => {
|
|
659
772
|
const button = createElement('button');
|
|
660
773
|
button.type = 'button';
|
|
661
|
-
button.append(createElement('strong', undefined, entity.name), createElement('span', undefined, `${formatBytes(entity.byteLength)} · ${entity.streamCount}
|
|
774
|
+
button.append(createElement('strong', undefined, entity.name), createElement('span', undefined, `${formatBytes(entity.byteLength)} · ${formatEdaUiText(locale, 'panel.entryCount', { count: entity.streamCount })}`));
|
|
662
775
|
if (entity.description) {
|
|
663
776
|
button.append(createElement('p', undefined, entity.description));
|
|
664
777
|
}
|
|
@@ -683,17 +796,17 @@ export default async function renderEda(buffer, target, type = 'olb', context) {
|
|
|
683
796
|
entityPanel.append(entityRoot);
|
|
684
797
|
}
|
|
685
798
|
else {
|
|
686
|
-
entityPanel.append(createEmpty('
|
|
799
|
+
entityPanel.append(createEmpty(formatEdaUiText(locale, 'empty.noObjects.title'), formatEdaUiText(locale, 'empty.noObjects.description')));
|
|
687
800
|
}
|
|
688
801
|
topology.append(treePanel, entityPanel);
|
|
689
802
|
const bottom = createElement('section', 'eda-bottom');
|
|
690
803
|
const stringsPanel = createElement('div', 'eda-panel');
|
|
691
|
-
appendPanelHead(stringsPanel, '
|
|
804
|
+
appendPanelHead(stringsPanel, formatEdaUiText(locale, 'panel.strings'), formatEdaUiText(locale, 'panel.itemCount', { count: parsed.strings.length }));
|
|
692
805
|
const stringGrid = createElement('div', 'eda-string-grid');
|
|
693
806
|
parsed.strings.forEach(item => stringGrid.append(createElement('span', undefined, item)));
|
|
694
807
|
stringsPanel.append(stringGrid);
|
|
695
808
|
const diagnosticsPanel = createElement('div', 'eda-panel');
|
|
696
|
-
appendPanelHead(diagnosticsPanel, '
|
|
809
|
+
appendPanelHead(diagnosticsPanel, formatEdaUiText(locale, 'panel.diagnostics'), formatEdaUiText(locale, 'panel.itemCount', { count: parsed.diagnostics.length }));
|
|
697
810
|
const diagnostics = createElement('div', 'eda-diagnostics');
|
|
698
811
|
parsed.diagnostics.forEach(diagnostic => {
|
|
699
812
|
const item = createElement('p');
|
|
@@ -704,7 +817,7 @@ export default async function renderEda(buffer, target, type = 'olb', context) {
|
|
|
704
817
|
diagnosticsPanel.append(diagnostics, localStrings);
|
|
705
818
|
bottom.append(stringsPanel, diagnosticsPanel);
|
|
706
819
|
if (parsed.layout) {
|
|
707
|
-
preview.append(createLayoutPreview(parsed.layout));
|
|
820
|
+
preview.append(createLayoutPreview(parsed.layout, locale));
|
|
708
821
|
}
|
|
709
822
|
preview.append(overview, topology, currentPanel, bottom);
|
|
710
823
|
body.append(sidebar, preview);
|
|
@@ -713,7 +826,7 @@ export default async function renderEda(buffer, target, type = 'olb', context) {
|
|
|
713
826
|
};
|
|
714
827
|
const loading = showLoading();
|
|
715
828
|
try {
|
|
716
|
-
const parsed = await parseEdaFile(buffer, normalizedType);
|
|
829
|
+
const parsed = await parseEdaFile(buffer, normalizedType, { locale });
|
|
717
830
|
renderParsed(parsed);
|
|
718
831
|
}
|
|
719
832
|
catch (nextError) {
|
package/dist/edaParser.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type EdaLayoutPreview } from '@file-viewer/eda-layout';
|
|
2
|
+
export type EdaParserLocale = 'zh-CN' | 'en-US';
|
|
2
3
|
export type { EdaLayoutElement, EdaLayoutPreview, } from '@file-viewer/eda-layout';
|
|
3
4
|
export type EdaFileType = 'olb' | 'dra' | 'gds' | 'oas' | 'oasis';
|
|
4
5
|
export type EdaParserMode = 'cfb' | 'binary';
|
|
@@ -77,4 +78,6 @@ export interface EdaParseResult {
|
|
|
77
78
|
stats: EdaStats;
|
|
78
79
|
layout?: EdaLayoutPreview;
|
|
79
80
|
}
|
|
80
|
-
export declare const parseEdaFile: (buffer: ArrayBuffer, type?: string
|
|
81
|
+
export declare const parseEdaFile: (buffer: ArrayBuffer, type?: string, options?: {
|
|
82
|
+
locale?: EdaParserLocale;
|
|
83
|
+
}) => Promise<EdaParseResult>;
|
package/dist/edaParser.js
CHANGED
|
@@ -3,6 +3,40 @@ import { cleanupOrcadText as cleanupText, collectOrcadStrings as collectStrings,
|
|
|
3
3
|
const MAX_STREAMS = 200;
|
|
4
4
|
const MAX_STREAM_STRINGS = 24;
|
|
5
5
|
const MAX_PROPERTIES = 420;
|
|
6
|
+
const EDA_PARSER_TEXT = {
|
|
7
|
+
'zh-CN': {
|
|
8
|
+
oasisFixture: '已识别为 OASIS 文本结构夹具,并在浏览器端解析几何预览和结构索引;真实 SEMI 二进制 OASIS 仍走安全索引与后续独立内核路线。',
|
|
9
|
+
gdsLayout: '已识别为标准 GDSII 二进制版图记录,并在浏览器端解析几何预览和结构索引。',
|
|
10
|
+
cfbContainer: '已识别为 Microsoft Compound File / OLE2 复合文档容器,并在浏览器端解析目录与流。',
|
|
11
|
+
binaryIndex: '未识别为 CFB 容器,已使用二进制字符串索引模式展示可读信息。',
|
|
12
|
+
coverage: '已索引 {streams} 个条目、{strings} 个可读字符串、{entities} 个 EDA 结构候选。',
|
|
13
|
+
layout: '已解析 {layout}: {structures} 个 structure、{elements} 个几何/引用/文本元素,可在版图预览面板中拖动查看。',
|
|
14
|
+
noSymbol: '未发现明确的元件符号候选,文件可能使用了私有二进制编码或需要专业工具导出 ASCII/XML 后再检查。',
|
|
15
|
+
noFootprint: '未发现明确的封装、图形或 padstack 候选,文件可能使用了私有二进制数据库编码。',
|
|
16
|
+
noGds: '未发现明确的 GDSII 版图结构候选。文件可能不是标准 GDSII 二进制或使用了专有封装。',
|
|
17
|
+
noOasis: '未发现明确的 OASIS 版图结构候选。OASIS 完整几何浏览通常需要专业版图库或独立 WASM/TS 内核,当前前端包会安全展示头部、字符串、属性和二进制结构线索。',
|
|
18
|
+
maxStreams: '仅展示前 {count} 个 CFB 项,完整文件仍可下载后在专业 EDA 工具中打开。',
|
|
19
|
+
binaryFallback: '该文件不是标准 CFB 容器,已退化为安全的二进制字符串索引预览。',
|
|
20
|
+
},
|
|
21
|
+
'en-US': {
|
|
22
|
+
oasisFixture: 'Detected an OASIS text fixture and parsed geometry preview plus structure indexes in the browser. Full SEMI binary OASIS still follows the safe index and dedicated-kernel path.',
|
|
23
|
+
gdsLayout: 'Detected standard GDSII binary layout records and parsed geometry preview plus structure indexes in the browser.',
|
|
24
|
+
cfbContainer: 'Detected a Microsoft Compound File / OLE2 container and parsed its directory and streams in the browser.',
|
|
25
|
+
binaryIndex: 'This file is not recognized as a CFB container, so readable information is shown through a safe binary string index.',
|
|
26
|
+
coverage: 'Indexed {streams} entries, {strings} readable strings, and {entities} EDA structure candidates.',
|
|
27
|
+
layout: 'Parsed {layout}: {structures} structures and {elements} geometry/reference/text elements. Drag the layout preview panel to inspect it.',
|
|
28
|
+
noSymbol: 'No clear component-symbol candidates were found. The file may use private binary encoding or need ASCII/XML export from a professional tool.',
|
|
29
|
+
noFootprint: 'No clear footprint, drawing, or padstack candidates were found. The file may use private binary database encoding.',
|
|
30
|
+
noGds: 'No clear GDSII layout structure candidates were found. The file may not be standard GDSII binary or may use a proprietary wrapper.',
|
|
31
|
+
noOasis: 'No clear OASIS layout structure candidates were found. Full OASIS geometry browsing usually needs a professional layout library or dedicated WASM/TS kernel; this frontend package safely exposes headers, strings, properties, and binary clues.',
|
|
32
|
+
maxStreams: 'Only the first {count} CFB entries are shown. Download the full file and open it in a professional EDA tool for complete inspection.',
|
|
33
|
+
binaryFallback: 'This file is not a standard CFB container, so it falls back to a safe binary string index preview.',
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
const getEdaParserText = (locale, key, params = {}) => {
|
|
37
|
+
const template = EDA_PARSER_TEXT[locale]?.[key] || EDA_PARSER_TEXT['zh-CN'][key] || key;
|
|
38
|
+
return Object.entries(params).reduce((message, [name, value]) => message.replace(new RegExp(`\\{${name}\\}`, 'g'), String(value)), template);
|
|
39
|
+
};
|
|
6
40
|
const toBytes = (buffer) => new Uint8Array(buffer);
|
|
7
41
|
const normalizeBytes = (value) => {
|
|
8
42
|
return value instanceof Uint8Array ? value : new Uint8Array(value);
|
|
@@ -352,7 +386,7 @@ const buildStats = (streams, entities, strings, parser, layout) => {
|
|
|
352
386
|
}
|
|
353
387
|
return stats;
|
|
354
388
|
};
|
|
355
|
-
const buildDiagnostics = (type, parser, streams, entities, strings, warnings, layout) => {
|
|
389
|
+
const buildDiagnostics = (type, parser, streams, entities, strings, warnings, layout, locale) => {
|
|
356
390
|
const diagnostics = warnings.map((message, index) => ({
|
|
357
391
|
level: 'warning',
|
|
358
392
|
code: `warning-${index + 1}`,
|
|
@@ -363,22 +397,30 @@ const buildDiagnostics = (type, parser, streams, entities, strings, warnings, la
|
|
|
363
397
|
code: 'parser',
|
|
364
398
|
message: layout
|
|
365
399
|
? layout.format === 'oasis'
|
|
366
|
-
?
|
|
367
|
-
:
|
|
400
|
+
? getEdaParserText(locale, 'oasisFixture')
|
|
401
|
+
: getEdaParserText(locale, 'gdsLayout')
|
|
368
402
|
: parser === 'cfb'
|
|
369
|
-
?
|
|
370
|
-
:
|
|
403
|
+
? getEdaParserText(locale, 'cfbContainer')
|
|
404
|
+
: getEdaParserText(locale, 'binaryIndex')
|
|
371
405
|
});
|
|
372
406
|
diagnostics.push({
|
|
373
407
|
level: 'info',
|
|
374
408
|
code: 'coverage',
|
|
375
|
-
message:
|
|
409
|
+
message: getEdaParserText(locale, 'coverage', {
|
|
410
|
+
streams: streams.length,
|
|
411
|
+
strings: strings.length,
|
|
412
|
+
entities: entities.length,
|
|
413
|
+
})
|
|
376
414
|
});
|
|
377
415
|
if (layout) {
|
|
378
416
|
diagnostics.push({
|
|
379
417
|
level: 'info',
|
|
380
418
|
code: `${layout.format}-layout`,
|
|
381
|
-
message:
|
|
419
|
+
message: getEdaParserText(locale, 'layout', {
|
|
420
|
+
layout: layout.format === 'oasis' ? 'OASIS fixture' : 'GDSII layout',
|
|
421
|
+
structures: layout.structureCount,
|
|
422
|
+
elements: layout.elements.length,
|
|
423
|
+
})
|
|
382
424
|
});
|
|
383
425
|
}
|
|
384
426
|
const needsSymbol = type === 'olb' && !entities.some(entity => entity.role === 'symbol');
|
|
@@ -389,21 +431,21 @@ const buildDiagnostics = (type, parser, streams, entities, strings, warnings, la
|
|
|
389
431
|
level: 'warning',
|
|
390
432
|
code: 'domain-candidates',
|
|
391
433
|
message: type === 'olb'
|
|
392
|
-
?
|
|
434
|
+
? getEdaParserText(locale, 'noSymbol')
|
|
393
435
|
: type === 'dra'
|
|
394
|
-
?
|
|
436
|
+
? getEdaParserText(locale, 'noFootprint')
|
|
395
437
|
: type === 'gds'
|
|
396
|
-
?
|
|
397
|
-
:
|
|
438
|
+
? getEdaParserText(locale, 'noGds')
|
|
439
|
+
: getEdaParserText(locale, 'noOasis')
|
|
398
440
|
});
|
|
399
441
|
}
|
|
400
442
|
return diagnostics;
|
|
401
443
|
};
|
|
402
|
-
const assembleResult = (buffer, type, parser, streamCount, streams, strings, warnings, layout) => {
|
|
444
|
+
const assembleResult = (buffer, type, parser, streamCount, streams, strings, warnings, layout, locale) => {
|
|
403
445
|
const totalStreamBytes = streams.reduce((sum, stream) => sum + stream.size, 0);
|
|
404
446
|
const entities = collectEntities(streams, type);
|
|
405
447
|
const metadata = collectMetadata(streams);
|
|
406
|
-
const diagnostics = buildDiagnostics(type, parser, streams, entities, strings, warnings, layout);
|
|
448
|
+
const diagnostics = buildDiagnostics(type, parser, streams, entities, strings, warnings, layout, locale);
|
|
407
449
|
return {
|
|
408
450
|
type,
|
|
409
451
|
parser,
|
|
@@ -426,7 +468,7 @@ const assembleResult = (buffer, type, parser, streamCount, streams, strings, war
|
|
|
426
468
|
layout
|
|
427
469
|
};
|
|
428
470
|
};
|
|
429
|
-
const parseCfbContainer = async (buffer, type) => {
|
|
471
|
+
const parseCfbContainer = async (buffer, type, locale) => {
|
|
430
472
|
const CFB = await import('cfb');
|
|
431
473
|
const container = CFB.parse(toBytes(buffer), { type: 'array' });
|
|
432
474
|
const streamEntries = container.FileIndex
|
|
@@ -443,11 +485,11 @@ const parseCfbContainer = async (buffer, type) => {
|
|
|
443
485
|
return buildStreamView(type, path, entry.name, entry.size || content.byteLength || 0, 'binary', content);
|
|
444
486
|
});
|
|
445
487
|
const warnings = streamEntries.length >= MAX_STREAMS
|
|
446
|
-
? [
|
|
488
|
+
? [getEdaParserText(locale, 'maxStreams', { count: MAX_STREAMS })]
|
|
447
489
|
: [];
|
|
448
|
-
return assembleResult(buffer, type, 'cfb', container.FileIndex.length, streams, collectStrings(byteChunks), warnings);
|
|
490
|
+
return assembleResult(buffer, type, 'cfb', container.FileIndex.length, streams, collectStrings(byteChunks), warnings, undefined, locale);
|
|
449
491
|
};
|
|
450
|
-
const parseBinaryFallback = (buffer, type) => {
|
|
492
|
+
const parseBinaryFallback = (buffer, type, locale) => {
|
|
451
493
|
const bytes = toBytes(buffer);
|
|
452
494
|
const stream = buildStreamView(type, `${type}.${type}`, `${type}.${type}`, buffer.byteLength, 'binary', bytes);
|
|
453
495
|
const layout = type === 'gds'
|
|
@@ -460,10 +502,11 @@ const parseBinaryFallback = (buffer, type) => {
|
|
|
460
502
|
? layout.warnings
|
|
461
503
|
: oasis
|
|
462
504
|
? oasis.warnings
|
|
463
|
-
: [
|
|
464
|
-
return assembleResult(buffer, type, 'binary', 1, [stream], collectStrings([bytes]), warnings, layout);
|
|
505
|
+
: [getEdaParserText(locale, 'binaryFallback')];
|
|
506
|
+
return assembleResult(buffer, type, 'binary', 1, [stream], collectStrings([bytes]), warnings, layout, locale);
|
|
465
507
|
};
|
|
466
|
-
export const parseEdaFile = async (buffer, type = 'olb') => {
|
|
508
|
+
export const parseEdaFile = async (buffer, type = 'olb', options = {}) => {
|
|
509
|
+
const locale = options.locale || 'zh-CN';
|
|
467
510
|
const normalizedType = type === 'dra'
|
|
468
511
|
? 'dra'
|
|
469
512
|
: type === 'gds' || type === 'oas' || type === 'oasis'
|
|
@@ -471,13 +514,13 @@ export const parseEdaFile = async (buffer, type = 'olb') => {
|
|
|
471
514
|
: 'olb';
|
|
472
515
|
const bytes = toBytes(buffer);
|
|
473
516
|
if (!isOrcadCompoundFile(bytes)) {
|
|
474
|
-
return parseBinaryFallback(buffer, normalizedType);
|
|
517
|
+
return parseBinaryFallback(buffer, normalizedType, locale);
|
|
475
518
|
}
|
|
476
519
|
try {
|
|
477
|
-
return await parseCfbContainer(buffer, normalizedType);
|
|
520
|
+
return await parseCfbContainer(buffer, normalizedType, locale);
|
|
478
521
|
}
|
|
479
522
|
catch (error) {
|
|
480
|
-
const fallback = parseBinaryFallback(buffer, normalizedType);
|
|
523
|
+
const fallback = parseBinaryFallback(buffer, normalizedType, locale);
|
|
481
524
|
fallback.warnings.unshift(error instanceof Error ? error.message : String(error));
|
|
482
525
|
fallback.diagnostics.unshift({
|
|
483
526
|
level: 'warning',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@file-viewer/renderer-eda",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Standalone EDA renderer plugin for Flyfish File Viewer with OLB, DRA, GDSII, and OASIS structure preview.",
|
|
@@ -57,9 +57,9 @@
|
|
|
57
57
|
"LICENSE"
|
|
58
58
|
],
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@file-viewer/core": "^2.1.
|
|
61
|
-
"@file-viewer/eda-layout": "^2.1.
|
|
62
|
-
"@file-viewer/eda-orcad": "^2.1.
|
|
60
|
+
"@file-viewer/core": "^2.1.3",
|
|
61
|
+
"@file-viewer/eda-layout": "^2.1.3",
|
|
62
|
+
"@file-viewer/eda-orcad": "^2.1.3",
|
|
63
63
|
"cfb": "^1.2.2"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|