omni-viewer-core 0.5.0 → 0.6.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.md +1 -1
- package/dist/i18n/catalog.en.js +13 -0
- package/dist/i18n/catalog.ja.js +13 -1
- package/dist/i18n/catalog.ko.js +13 -0
- package/dist/i18n/catalog.zh-cn.js +10 -0
- package/dist/parsers/safetensors/index.d.ts +34 -0
- package/dist/parsers/safetensors/index.js +233 -0
- package/dist/parsers/toml/model.d.ts +10 -0
- package/dist/parsers/toml/parse.js +104 -34
- package/dist/registry/index.d.ts +1 -0
- package/dist/registry/index.js +5 -1
- package/dist/styles/pdf.css +177 -0
- package/dist/styles/safetensors.css +3 -0
- package/dist/styles/toml.css +1 -1
- package/dist/styles/yaml.css +1 -1
- package/dist/viewers/pdf/controller.d.ts +8 -0
- package/dist/viewers/pdf/controller.js +4 -0
- package/dist/viewers/pdf/editing.d.ts +11 -0
- package/dist/viewers/pdf/editing.js +19 -16
- package/dist/viewers/pdf/index.d.ts +3 -2
- package/dist/viewers/pdf/index.js +195 -23
- package/dist/viewers/pdf/styles.d.ts +1 -1
- package/dist/viewers/pdf/styles.js +177 -0
- package/dist/viewers/safetensors/index.d.ts +19 -0
- package/dist/viewers/safetensors/index.js +170 -0
- package/dist/viewers/safetensors/styles.d.ts +1 -0
- package/dist/viewers/safetensors/styles.js +4 -0
- package/dist/viewers/structured-styles.d.ts +1 -1
- package/dist/viewers/structured-styles.js +1 -1
- package/dist/viewers/structured.d.ts +15 -0
- package/dist/viewers/structured.js +196 -47
- package/dist/viewers/toml/controller.d.ts +27 -1
- package/dist/viewers/toml/controller.js +64 -10
- package/package.json +9 -1
|
@@ -2,11 +2,14 @@ import { tomlPath } from './model.js';
|
|
|
2
2
|
export function parseTomlText(text, limits = {}) {
|
|
3
3
|
const settings = typeof limits === 'number' ? { maxDepth: limits } : limits;
|
|
4
4
|
const maxDepth = settings.maxDepth ?? 100, maxNodes = settings.maxNodes ?? 100_000, maxTables = settings.maxTables ?? 50_000, maxArrayLength = settings.maxArrayLength ?? 100_000;
|
|
5
|
-
const root = { kind: 'table', key: '$', path: '', raw: '', line: 1, children: [] };
|
|
5
|
+
const root = { kind: 'table', key: '$', path: '', raw: '', line: 1, range: { start: 0, end: text.length }, children: [] };
|
|
6
6
|
const diagnostics = [];
|
|
7
7
|
let current = root, nodeCount = 1, tableCount = 1, stopped = false;
|
|
8
8
|
const tables = new Map([['', root]]);
|
|
9
|
-
|
|
9
|
+
// Offsets stay relative to the untouched `text` so ranges address the same
|
|
10
|
+
// string a host renders. A leading BOM is dropped by `trim()` instead.
|
|
11
|
+
const lines = logicalTomlLines(text);
|
|
12
|
+
const lineAt = lineIndexer(text);
|
|
10
13
|
const error = (code, line) => diagnostics.push({ severity: 'error', code, messageKey: `diag.${code}`, location: `line:${line}` });
|
|
11
14
|
const unquote = (value) => {
|
|
12
15
|
if (value.startsWith('"""') && value.endsWith('"""')) {
|
|
@@ -34,11 +37,15 @@ export function parseTomlText(text, limits = {}) {
|
|
|
34
37
|
return value.slice(1, -1);
|
|
35
38
|
return value;
|
|
36
39
|
};
|
|
37
|
-
|
|
40
|
+
/** Split on top-level commas, reporting where each trimmed part starts so
|
|
41
|
+
* inline-table and array members can carry their own range. */
|
|
42
|
+
const split = (value, base) => {
|
|
38
43
|
const out = [];
|
|
39
44
|
let start = 0;
|
|
40
45
|
let quote = '';
|
|
41
46
|
let depth = 0;
|
|
47
|
+
const push = (from, to) => { const part = value.slice(from, to); const lead = part.length - part.trimStart().length; const trimmed = part.trim(); if (trimmed)
|
|
48
|
+
out.push({ text: trimmed, at: base + from + lead }); };
|
|
42
49
|
for (let i = 0; i < value.length; i++) {
|
|
43
50
|
const c = value[i];
|
|
44
51
|
if (quote) {
|
|
@@ -52,16 +59,18 @@ export function parseTomlText(text, limits = {}) {
|
|
|
52
59
|
else if (c === ']' || c === '}')
|
|
53
60
|
depth--;
|
|
54
61
|
else if (c === ',' && depth === 0) {
|
|
55
|
-
|
|
62
|
+
push(start, i);
|
|
56
63
|
start = i + 1;
|
|
57
64
|
}
|
|
58
65
|
}
|
|
59
|
-
|
|
60
|
-
return out
|
|
66
|
+
push(start, value.length);
|
|
67
|
+
return out;
|
|
61
68
|
};
|
|
62
69
|
const keyParts = (key) => splitKey(key).map(unquote);
|
|
63
|
-
const makeValue = (key, path, rawValue, line, depth) => {
|
|
70
|
+
const makeValue = (key, path, rawValue, line, depth, start) => {
|
|
64
71
|
const raw = rawValue.trim();
|
|
72
|
+
const from = start + (rawValue.length - rawValue.trimStart().length);
|
|
73
|
+
const range = { start: from, end: from + raw.length };
|
|
65
74
|
let kind = 'string';
|
|
66
75
|
let value = unquote(raw);
|
|
67
76
|
if (/^(true|false)$/.test(raw)) {
|
|
@@ -76,34 +85,37 @@ export function parseTomlText(text, limits = {}) {
|
|
|
76
85
|
kind = 'datetime';
|
|
77
86
|
else if (raw.startsWith('[') && raw.endsWith(']')) {
|
|
78
87
|
kind = 'array';
|
|
79
|
-
const values = split(raw.slice(1, -1));
|
|
88
|
+
const values = split(raw.slice(1, -1), from + 1);
|
|
80
89
|
if (values.length > maxArrayLength) {
|
|
81
90
|
error('toml.array-limit', line);
|
|
82
91
|
values.length = maxArrayLength;
|
|
83
92
|
}
|
|
84
|
-
const children = values.map((
|
|
93
|
+
const children = values.map((entry, i) => makeValue(String(i), `${path}[${i}]`, entry.text, lineAt(entry.at), depth + 1, entry.at));
|
|
85
94
|
nodeCount += children.length;
|
|
86
|
-
return { kind, key, path, raw, line, children };
|
|
95
|
+
return { kind, key, path, raw, line, range, children };
|
|
87
96
|
}
|
|
88
97
|
else if (raw.startsWith('{') && raw.endsWith('}')) {
|
|
89
98
|
kind = 'table';
|
|
90
99
|
const children = [];
|
|
91
|
-
for (const pair of split(raw.slice(1, -1))) {
|
|
92
|
-
const eq = indexOfEquals(pair);
|
|
100
|
+
for (const pair of split(raw.slice(1, -1), from + 1)) {
|
|
101
|
+
const eq = indexOfEquals(pair.text);
|
|
93
102
|
if (eq < 0) {
|
|
94
|
-
error('toml.invalid-inline-table',
|
|
103
|
+
error('toml.invalid-inline-table', lineAt(pair.at));
|
|
95
104
|
continue;
|
|
96
105
|
}
|
|
97
|
-
const childKey = unquote(pair.slice(0, eq).trim());
|
|
98
|
-
|
|
106
|
+
const childKey = unquote(pair.text.slice(0, eq).trim());
|
|
107
|
+
const child = makeValue(childKey, tomlPath(path, childKey), pair.text.slice(eq + 1), lineAt(pair.at), depth + 1, pair.at + eq + 1);
|
|
108
|
+
child.range = { start: pair.at, end: pair.at + pair.text.length };
|
|
109
|
+
children.push(child);
|
|
99
110
|
}
|
|
100
|
-
return { kind, key, path, raw, line, children };
|
|
111
|
+
return { kind, key, path, raw, line, range, children };
|
|
101
112
|
}
|
|
102
113
|
if (depth > maxDepth)
|
|
103
114
|
error('toml.max-depth', line);
|
|
104
115
|
nodeCount++;
|
|
105
|
-
return { kind, key, path, value, raw, line };
|
|
116
|
+
return { kind, key, path, value, raw, line, range };
|
|
106
117
|
};
|
|
118
|
+
let pending = [];
|
|
107
119
|
for (const logical of lines) {
|
|
108
120
|
if (settings.signal?.aborted) {
|
|
109
121
|
error('aborted', logical.line);
|
|
@@ -116,9 +128,22 @@ export function parseTomlText(text, limits = {}) {
|
|
|
116
128
|
break;
|
|
117
129
|
}
|
|
118
130
|
const i = logical.line - 1;
|
|
119
|
-
const
|
|
120
|
-
|
|
131
|
+
const uncommented = stripComment(logical.text);
|
|
132
|
+
const trailing = commentBody(logical.text.slice(uncommented.length));
|
|
133
|
+
const source = uncommented.trim();
|
|
134
|
+
// Comment runs stay attached to the next declaration; a blank line ends
|
|
135
|
+
// the run so a file-header comment never leaks onto unrelated keys.
|
|
136
|
+
if (!source) {
|
|
137
|
+
if (trailing === undefined)
|
|
138
|
+
pending = [];
|
|
139
|
+
else
|
|
140
|
+
pending.push(trailing);
|
|
121
141
|
continue;
|
|
142
|
+
}
|
|
143
|
+
const comment = [...pending, ...(trailing === undefined ? [] : [trailing])].join('\n') || undefined;
|
|
144
|
+
pending = [];
|
|
145
|
+
const base = logical.offset + (logical.text.length - logical.text.trimStart().length);
|
|
146
|
+
const declaration = { start: base, end: base + source.length };
|
|
122
147
|
const arrayTable = source.match(/^\[\[(.+)\]\]$/);
|
|
123
148
|
const table = source.match(/^\[(.+)\]$/);
|
|
124
149
|
if (arrayTable || table) {
|
|
@@ -134,12 +159,12 @@ export function parseTomlText(text, limits = {}) {
|
|
|
134
159
|
const parent = tables.get(parentPath) ?? root;
|
|
135
160
|
let collection = parent.children.find(node => node.key === parts.at(-1) && node.kind === 'array');
|
|
136
161
|
if (!collection) {
|
|
137
|
-
collection = { kind: 'array', key: parts.at(-1), path, raw: '', line: i + 1, children: [] };
|
|
162
|
+
collection = { kind: 'array', key: parts.at(-1), path, raw: '', line: i + 1, range: declaration, children: [] };
|
|
138
163
|
parent.children.push(collection);
|
|
139
164
|
nodeCount++;
|
|
140
165
|
}
|
|
141
166
|
const index = collection.children.length;
|
|
142
|
-
const node = { kind: 'table', key: String(index), path: `${path}[${index}]`, raw: '', line: i + 1, children: [] };
|
|
167
|
+
const node = { kind: 'table', key: String(index), path: `${path}[${index}]`, raw: '', line: i + 1, range: declaration, ...(comment ? { comment } : {}), children: [] };
|
|
143
168
|
collection.children.push(node);
|
|
144
169
|
tables.set(path, node);
|
|
145
170
|
current = node;
|
|
@@ -149,7 +174,7 @@ export function parseTomlText(text, limits = {}) {
|
|
|
149
174
|
else {
|
|
150
175
|
let node = tables.get(path);
|
|
151
176
|
if (!node) {
|
|
152
|
-
node = { kind: 'table', key: parts.at(-1), path, raw: '', line: i + 1, children: [] };
|
|
177
|
+
node = { kind: 'table', key: parts.at(-1), path, raw: '', line: i + 1, range: declaration, ...(comment ? { comment } : {}), children: [] };
|
|
153
178
|
(tables.get(parts.slice(0, -1).join('.')) ?? root).children.push(node);
|
|
154
179
|
tables.set(path, node);
|
|
155
180
|
nodeCount++;
|
|
@@ -175,7 +200,7 @@ export function parseTomlText(text, limits = {}) {
|
|
|
175
200
|
for (const part of parts.slice(0, -1)) {
|
|
176
201
|
let nested = parent.children.find(n => n.key === part && n.kind === 'table');
|
|
177
202
|
if (!nested) {
|
|
178
|
-
nested = { kind: 'table', key: part, path: tomlPath(parent.path, part), raw: '', line: i + 1, children: [] };
|
|
203
|
+
nested = { kind: 'table', key: part, path: tomlPath(parent.path, part), raw: '', line: i + 1, range: declaration, children: [] };
|
|
179
204
|
parent.children.push(nested);
|
|
180
205
|
}
|
|
181
206
|
parent = nested;
|
|
@@ -183,25 +208,45 @@ export function parseTomlText(text, limits = {}) {
|
|
|
183
208
|
const key = parts.at(-1);
|
|
184
209
|
if (parent.children.some(n => n.key === key))
|
|
185
210
|
error('toml.duplicate-key', i + 1);
|
|
186
|
-
else
|
|
187
|
-
|
|
211
|
+
else {
|
|
212
|
+
const node = makeValue(key, tomlPath(parent.path, key), source.slice(eq + 1), i + 1, 0, base + eq + 1);
|
|
213
|
+
// The declaration reads better than the bare value when a host turns
|
|
214
|
+
// the range into a selection, so widen it to cover `key = value`.
|
|
215
|
+
node.range = declaration;
|
|
216
|
+
if (comment)
|
|
217
|
+
node.comment = comment;
|
|
218
|
+
parent.children.push(node);
|
|
219
|
+
}
|
|
188
220
|
}
|
|
189
221
|
return { document: { text, root }, diagnostics };
|
|
190
222
|
}
|
|
191
223
|
/** Group physical lines while a multiline string or a composite array/table
|
|
192
224
|
* remains open. This preserves the declaration line for diagnostics. */
|
|
193
225
|
function logicalTomlLines(text) {
|
|
194
|
-
const physical =
|
|
226
|
+
const physical = [];
|
|
227
|
+
{
|
|
228
|
+
const separator = /\r\n|\n|\r/g;
|
|
229
|
+
let last = 0;
|
|
230
|
+
let match;
|
|
231
|
+
while ((match = separator.exec(text))) {
|
|
232
|
+
physical.push({ text: text.slice(last, match.index), offset: last });
|
|
233
|
+
last = match.index + match[0].length;
|
|
234
|
+
}
|
|
235
|
+
physical.push({ text: text.slice(last), offset: last });
|
|
236
|
+
}
|
|
195
237
|
const out = [];
|
|
196
|
-
let
|
|
238
|
+
let open = false;
|
|
197
239
|
let start = 1;
|
|
240
|
+
let offset = 0;
|
|
198
241
|
let triple = '';
|
|
199
242
|
let depth = 0;
|
|
200
243
|
for (let i = 0; i < physical.length; i++) {
|
|
201
|
-
const line = physical[i]
|
|
202
|
-
if (!
|
|
244
|
+
const { text: line, offset: at } = physical[i];
|
|
245
|
+
if (!open) {
|
|
246
|
+
open = true;
|
|
203
247
|
start = i + 1;
|
|
204
|
-
|
|
248
|
+
offset = at;
|
|
249
|
+
}
|
|
205
250
|
for (let p = 0; p < line.length; p++) {
|
|
206
251
|
if (line.startsWith('"""', p) || line.startsWith("'''", p)) {
|
|
207
252
|
const token = line.slice(p, p + 3);
|
|
@@ -219,16 +264,41 @@ function logicalTomlLines(text) {
|
|
|
219
264
|
else if (c === ']' || c === '}')
|
|
220
265
|
depth--;
|
|
221
266
|
}
|
|
267
|
+
// Slicing the original text (rather than re-joining) keeps every offset
|
|
268
|
+
// inside a logical line usable as an index into `text`.
|
|
222
269
|
if (!triple && depth <= 0) {
|
|
223
|
-
out.push({ line: start, text:
|
|
224
|
-
|
|
270
|
+
out.push({ line: start, text: text.slice(offset, at + line.length), offset });
|
|
271
|
+
open = false;
|
|
225
272
|
depth = 0;
|
|
226
273
|
}
|
|
227
274
|
}
|
|
228
|
-
if (
|
|
229
|
-
out.push({ line: start, text:
|
|
275
|
+
if (open)
|
|
276
|
+
out.push({ line: start, text: text.slice(offset), offset });
|
|
230
277
|
return out;
|
|
231
278
|
}
|
|
279
|
+
/** 1-based line lookup for offsets, used by inline members that may sit on a
|
|
280
|
+
* different physical line than their declaration. */
|
|
281
|
+
function lineIndexer(text) {
|
|
282
|
+
const starts = [0];
|
|
283
|
+
for (let i = 0; i < text.length; i++) {
|
|
284
|
+
const c = text[i];
|
|
285
|
+
if (c === '\n')
|
|
286
|
+
starts.push(i + 1);
|
|
287
|
+
else if (c === '\r') {
|
|
288
|
+
if (text[i + 1] === '\n')
|
|
289
|
+
i++;
|
|
290
|
+
starts.push(i + 1);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return offset => { let low = 0, high = starts.length - 1; while (low < high) {
|
|
294
|
+
const mid = (low + high + 1) >> 1;
|
|
295
|
+
if (starts[mid] <= offset)
|
|
296
|
+
low = mid;
|
|
297
|
+
else
|
|
298
|
+
high = mid - 1;
|
|
299
|
+
} return low + 1; };
|
|
300
|
+
}
|
|
301
|
+
function commentBody(rest) { const text = rest.trimStart(); return text.startsWith('#') ? text.slice(1).trim() : undefined; }
|
|
232
302
|
function stripComment(line) { let q = ''; for (let i = 0; i < line.length; i++) {
|
|
233
303
|
const c = line[i];
|
|
234
304
|
if (q) {
|
package/dist/registry/index.d.ts
CHANGED
|
@@ -61,6 +61,7 @@ export declare const REQIF_VIEWER_DESCRIPTOR: ViewerDescriptor;
|
|
|
61
61
|
export declare const HDF5_MAGIC_PREFIX: readonly [137, 72, 68, 70, 13, 10, 26, 10];
|
|
62
62
|
export declare const HDF5_VIEWER_DESCRIPTOR: ViewerDescriptor;
|
|
63
63
|
export declare const MAT_VIEWER_DESCRIPTOR: ViewerDescriptor;
|
|
64
|
+
export declare const SAFETENSORS_VIEWER_DESCRIPTOR: ViewerDescriptor;
|
|
64
65
|
export declare const AUDIO_VIEWER_DESCRIPTOR: ViewerDescriptor;
|
|
65
66
|
export declare const VIDEO_VIEWER_DESCRIPTOR: ViewerDescriptor;
|
|
66
67
|
export declare const DBC_VIEWER_DESCRIPTOR: ViewerDescriptor;
|
package/dist/registry/index.js
CHANGED
|
@@ -72,7 +72,7 @@ export const PDF_VIEWER_DESCRIPTOR = {
|
|
|
72
72
|
priority: 20,
|
|
73
73
|
magicPrefix: [0x25, 0x50, 0x44, 0x46, 0x2d], // '%PDF-'
|
|
74
74
|
requiredServices: [],
|
|
75
|
-
optionalServices: ['save', 'writeback', 'filePick']
|
|
75
|
+
optionalServices: ['save', 'writeback', 'filePick', 'clipboard']
|
|
76
76
|
};
|
|
77
77
|
export const PARQUET_MAGIC_SIGNATURES = [[{ offset: 0, bytes: [0x50, 0x41, 0x52, 0x31] }]];
|
|
78
78
|
export const PARQUET_VIEWER_DESCRIPTOR = { id: 'parquet', displayNameKey: 'parquet.title', extensions: ['parquet'], priority: 20, magicSignatures: PARQUET_MAGIC_SIGNATURES, requiredServices: [], optionalServices: ['clipboard', 'save'] };
|
|
@@ -87,6 +87,9 @@ export const HDF5_MAGIC_PREFIX = [0x89, 0x48, 0x44, 0x46, 0x0d, 0x0a, 0x1a, 0x0a
|
|
|
87
87
|
// signature still enables extensionless content routing below.
|
|
88
88
|
export const HDF5_VIEWER_DESCRIPTOR = { id: 'hdf5', displayNameKey: 'hdf5.title', extensions: ['h5', 'hdf5', 'he5'], priority: 20, requiredServices: [], optionalServices: ['clipboard'] };
|
|
89
89
|
export const MAT_VIEWER_DESCRIPTOR = { id: 'mat', displayNameKey: 'mat.title', extensions: ['mat'], priority: 20, requiredServices: [], optionalServices: ['clipboard'] };
|
|
90
|
+
// Safetensors has no fixed leading magic (the file opens with an 8-byte header
|
|
91
|
+
// length), so it is admitted by extension and validated by the parser.
|
|
92
|
+
export const SAFETENSORS_VIEWER_DESCRIPTOR = { id: 'safetensors', displayNameKey: 'safetensors.title', extensions: ['safetensors'], priority: 20, requiredServices: [], optionalServices: ['clipboard'] };
|
|
90
93
|
export const AUDIO_VIEWER_DESCRIPTOR = { id: 'audio', displayNameKey: 'audio.title', extensions: ['mp3', 'wav', 'pcm', 'aiff', 'aif', 'aifc', 'amr', 'awb', 'ogg', 'flac', 'ac3', 'aac', 'm4a'], priority: 20, requiredServices: [], optionalServices: [] };
|
|
91
94
|
export const VIDEO_VIEWER_DESCRIPTOR = { id: 'video', displayNameKey: 'video.title', extensions: ['mp4', 'mts', 'm2ts', 'avi', 'mov', 'wmv', 'flv', 'webm', 'mkv'], priority: 20, requiredServices: [], optionalServices: [] };
|
|
92
95
|
export const DBC_VIEWER_DESCRIPTOR = { id: 'dbc', displayNameKey: 'dbc.title', extensions: ['dbc'], priority: 20, requiredServices: [], optionalServices: ['clipboard'] };
|
|
@@ -200,6 +203,7 @@ export const CORE_VIEWER_DESCRIPTORS = [
|
|
|
200
203
|
REQIF_VIEWER_DESCRIPTOR,
|
|
201
204
|
HDF5_VIEWER_DESCRIPTOR,
|
|
202
205
|
MAT_VIEWER_DESCRIPTOR,
|
|
206
|
+
SAFETENSORS_VIEWER_DESCRIPTOR,
|
|
203
207
|
PPT_VIEWER_DESCRIPTOR,
|
|
204
208
|
WORD_VIEWER_DESCRIPTOR,
|
|
205
209
|
HWP_VIEWER_DESCRIPTOR,
|
package/dist/styles/pdf.css
CHANGED
|
@@ -183,6 +183,17 @@
|
|
|
183
183
|
min-width: 56px;
|
|
184
184
|
text-align: center;
|
|
185
185
|
}
|
|
186
|
+
.omni-pdf__thumbs-toggle {
|
|
187
|
+
width: 30px;
|
|
188
|
+
height: 28px;
|
|
189
|
+
padding: 0;
|
|
190
|
+
margin-right: auto;
|
|
191
|
+
font-size: 16px;
|
|
192
|
+
line-height: 1;
|
|
193
|
+
}
|
|
194
|
+
.omni-pdf__thumbs-toggle.is-collapsed {
|
|
195
|
+
opacity: 0.6;
|
|
196
|
+
}
|
|
186
197
|
.omni-pdf__view-menu-wrap { position: relative; }
|
|
187
198
|
.omni-pdf__view-menu-btn {
|
|
188
199
|
width: 30px;
|
|
@@ -227,12 +238,19 @@
|
|
|
227
238
|
background: var(--omni-border, #3c3c3c);
|
|
228
239
|
}
|
|
229
240
|
.omni-pdf__body {
|
|
241
|
+
position: relative;
|
|
230
242
|
flex: 1;
|
|
231
243
|
min-height: 0;
|
|
232
244
|
display: grid;
|
|
233
245
|
grid-template-columns: 160px minmax(0, 1fr);
|
|
234
246
|
overflow: hidden;
|
|
235
247
|
}
|
|
248
|
+
.omni-pdf__body--thumbs-collapsed {
|
|
249
|
+
grid-template-columns: minmax(0, 1fr);
|
|
250
|
+
}
|
|
251
|
+
.omni-pdf__body--thumbs-collapsed .omni-pdf__thumbs {
|
|
252
|
+
display: none;
|
|
253
|
+
}
|
|
236
254
|
.omni-pdf__thumbs {
|
|
237
255
|
overflow: auto;
|
|
238
256
|
min-height: 0;
|
|
@@ -464,6 +482,161 @@
|
|
|
464
482
|
content: '';
|
|
465
483
|
background: var(--omni-hl-color, #ffeb3b);
|
|
466
484
|
}
|
|
485
|
+
/* Floating action bar shown above a selected text-markup annotation. */
|
|
486
|
+
.omni-pdf__markup-toolbar {
|
|
487
|
+
position: absolute;
|
|
488
|
+
z-index: 5;
|
|
489
|
+
display: flex;
|
|
490
|
+
align-items: center;
|
|
491
|
+
gap: 2px;
|
|
492
|
+
padding: 4px;
|
|
493
|
+
transform: translateY(calc(-100% - 8px));
|
|
494
|
+
background: var(--omni-bg-secondary, #252526);
|
|
495
|
+
border: 1px solid var(--omni-border, #3c3c3c);
|
|
496
|
+
border-radius: 10px;
|
|
497
|
+
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45);
|
|
498
|
+
cursor: default;
|
|
499
|
+
}
|
|
500
|
+
.omni-pdf button.omni-pdf__markup-tool {
|
|
501
|
+
display: inline-flex;
|
|
502
|
+
align-items: center;
|
|
503
|
+
justify-content: center;
|
|
504
|
+
width: 30px;
|
|
505
|
+
height: 30px;
|
|
506
|
+
padding: 0;
|
|
507
|
+
border: 0;
|
|
508
|
+
border-radius: 8px;
|
|
509
|
+
background: transparent;
|
|
510
|
+
color: var(--omni-fg, #e8e8e8);
|
|
511
|
+
font-size: 15px;
|
|
512
|
+
line-height: 1;
|
|
513
|
+
cursor: pointer;
|
|
514
|
+
}
|
|
515
|
+
.omni-pdf button.omni-pdf__markup-tool:hover:not(:disabled) { background: var(--omni-button-hover-bg, #45494e); }
|
|
516
|
+
.omni-pdf button.omni-pdf__markup-tool:disabled { opacity: 0.4; cursor: default; }
|
|
517
|
+
.omni-pdf__markup-color::before {
|
|
518
|
+
content: '';
|
|
519
|
+
width: 18px;
|
|
520
|
+
height: 18px;
|
|
521
|
+
border-radius: 5px;
|
|
522
|
+
background: var(--omni-hl-color, #ffeb3b);
|
|
523
|
+
border: 1px solid rgba(0, 0, 0, 0.25);
|
|
524
|
+
}
|
|
525
|
+
.omni-pdf__markup-color-wrap { position: relative; display: inline-flex; }
|
|
526
|
+
.omni-pdf__markup-palette {
|
|
527
|
+
position: absolute;
|
|
528
|
+
top: calc(100% + 6px);
|
|
529
|
+
left: 50%;
|
|
530
|
+
transform: translateX(-50%);
|
|
531
|
+
display: none;
|
|
532
|
+
grid-template-columns: repeat(3, auto);
|
|
533
|
+
gap: 6px;
|
|
534
|
+
padding: 8px;
|
|
535
|
+
background: var(--omni-bg-secondary, #252526);
|
|
536
|
+
border: 1px solid var(--omni-border, #3c3c3c);
|
|
537
|
+
border-radius: 8px;
|
|
538
|
+
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45);
|
|
539
|
+
z-index: 6;
|
|
540
|
+
}
|
|
541
|
+
.omni-pdf__markup-palette.is-open { display: grid; }
|
|
542
|
+
.omni-pdf button.omni-pdf__markup-swatch,
|
|
543
|
+
.omni-pdf button.omni-pdf__markup-swatch:hover:not(:disabled) {
|
|
544
|
+
width: 22px;
|
|
545
|
+
height: 22px;
|
|
546
|
+
padding: 0;
|
|
547
|
+
border-radius: 5px;
|
|
548
|
+
border: 1px solid rgba(255, 255, 255, 0.25);
|
|
549
|
+
background: var(--omni-hl-color, #ffeb3b);
|
|
550
|
+
cursor: pointer;
|
|
551
|
+
}
|
|
552
|
+
.omni-pdf button.omni-pdf__markup-swatch.is-current {
|
|
553
|
+
outline: 2px solid var(--omni-accent, #0e639c);
|
|
554
|
+
outline-offset: 1px;
|
|
555
|
+
}
|
|
556
|
+
/* Left overlay panel listing every text-markup annotation. */
|
|
557
|
+
.omni-pdf__markup-list {
|
|
558
|
+
position: absolute;
|
|
559
|
+
top: 0;
|
|
560
|
+
left: 0;
|
|
561
|
+
bottom: 0;
|
|
562
|
+
z-index: 6;
|
|
563
|
+
display: none;
|
|
564
|
+
flex-direction: column;
|
|
565
|
+
width: min(280px, 70%);
|
|
566
|
+
background: var(--omni-bg-secondary, #252526);
|
|
567
|
+
border-right: 1px solid var(--omni-border, #3c3c3c);
|
|
568
|
+
box-shadow: 2px 0 12px rgba(0, 0, 0, 0.35);
|
|
569
|
+
overflow-y: auto;
|
|
570
|
+
}
|
|
571
|
+
.omni-pdf__markup-list.is-open { display: flex; }
|
|
572
|
+
.omni-pdf__markup-list-head {
|
|
573
|
+
position: sticky;
|
|
574
|
+
top: 0;
|
|
575
|
+
display: flex;
|
|
576
|
+
align-items: center;
|
|
577
|
+
justify-content: space-between;
|
|
578
|
+
padding: 10px 12px;
|
|
579
|
+
background: var(--omni-bg-secondary, #252526);
|
|
580
|
+
border-bottom: 1px solid var(--omni-border, #3c3c3c);
|
|
581
|
+
}
|
|
582
|
+
.omni-pdf__markup-list-title { font-weight: 600; }
|
|
583
|
+
.omni-pdf button.omni-pdf__markup-list-close {
|
|
584
|
+
width: 26px;
|
|
585
|
+
height: 26px;
|
|
586
|
+
padding: 0;
|
|
587
|
+
border: 0;
|
|
588
|
+
border-radius: 6px;
|
|
589
|
+
background: transparent;
|
|
590
|
+
color: var(--omni-fg, #e8e8e8);
|
|
591
|
+
font-size: 18px;
|
|
592
|
+
line-height: 1;
|
|
593
|
+
cursor: pointer;
|
|
594
|
+
}
|
|
595
|
+
.omni-pdf button.omni-pdf__markup-list-close:hover:not(:disabled) { background: var(--omni-button-hover-bg, #45494e); }
|
|
596
|
+
.omni-pdf__markup-list-empty {
|
|
597
|
+
padding: 16px 12px;
|
|
598
|
+
color: var(--omni-fg-muted, #9d9d9d);
|
|
599
|
+
font-size: 13px;
|
|
600
|
+
}
|
|
601
|
+
.omni-pdf button.omni-pdf__markup-item {
|
|
602
|
+
display: flex;
|
|
603
|
+
align-items: center;
|
|
604
|
+
gap: 8px;
|
|
605
|
+
width: 100%;
|
|
606
|
+
padding: 10px 12px;
|
|
607
|
+
border: 0;
|
|
608
|
+
border-bottom: 1px solid var(--omni-border, #3c3c3c);
|
|
609
|
+
background: transparent;
|
|
610
|
+
color: var(--omni-fg, #e8e8e8);
|
|
611
|
+
text-align: left;
|
|
612
|
+
cursor: pointer;
|
|
613
|
+
}
|
|
614
|
+
.omni-pdf button.omni-pdf__markup-item:hover:not(:disabled) { background: var(--omni-button-hover-bg, #45494e); }
|
|
615
|
+
.omni-pdf button.omni-pdf__markup-item.is-selected {
|
|
616
|
+
background: var(--omni-button-hover-bg, #45494e);
|
|
617
|
+
box-shadow: inset 3px 0 0 var(--omni-accent, #0e639c);
|
|
618
|
+
}
|
|
619
|
+
.omni-pdf__markup-item-dot {
|
|
620
|
+
flex: none;
|
|
621
|
+
width: 14px;
|
|
622
|
+
height: 14px;
|
|
623
|
+
border-radius: 3px;
|
|
624
|
+
border: 1px solid rgba(255, 255, 255, 0.25);
|
|
625
|
+
background: var(--omni-hl-color, #ffeb3b);
|
|
626
|
+
}
|
|
627
|
+
.omni-pdf__markup-item-text {
|
|
628
|
+
flex: 1;
|
|
629
|
+
min-width: 0;
|
|
630
|
+
overflow: hidden;
|
|
631
|
+
text-overflow: ellipsis;
|
|
632
|
+
white-space: nowrap;
|
|
633
|
+
font-size: 13px;
|
|
634
|
+
}
|
|
635
|
+
.omni-pdf__markup-item-page {
|
|
636
|
+
flex: none;
|
|
637
|
+
color: var(--omni-fg-muted, #9d9d9d);
|
|
638
|
+
font-size: 12px;
|
|
639
|
+
}
|
|
467
640
|
.omni-pdf__text-editor {
|
|
468
641
|
position: absolute;
|
|
469
642
|
z-index: 3;
|
|
@@ -569,9 +742,13 @@
|
|
|
569
742
|
grid-template-columns: minmax(0, 1fr);
|
|
570
743
|
grid-template-rows: minmax(120px, 30vh) minmax(0, 1fr);
|
|
571
744
|
}
|
|
745
|
+
.omni-pdf__body--thumbs-collapsed {
|
|
746
|
+
grid-template-rows: minmax(0, 1fr);
|
|
747
|
+
}
|
|
572
748
|
.omni-pdf__thumbs {
|
|
573
749
|
border-right: 0;
|
|
574
750
|
border-bottom: 1px solid var(--omni-border, #3c3c3c);
|
|
575
751
|
}
|
|
576
752
|
.omni-pdf__pages { grid-row: 2; }
|
|
753
|
+
.omni-pdf__body--thumbs-collapsed .omni-pdf__pages { grid-row: 1; }
|
|
577
754
|
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
|
|
2
|
+
.omni-safetensors{height:100%;min-height:0;display:flex;flex-direction:column;background:var(--omni-bg,#fff);color:var(--omni-fg,#222);font:13px system-ui,sans-serif}.omni-safetensors__header{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;padding:18px 20px 12px;border-bottom:1px solid var(--omni-border,#ddd);background:var(--omni-panel-bg,#f7f7f7)}.omni-safetensors__eyebrow{color:var(--omni-muted,#666);font-size:12px;text-transform:uppercase}.omni-safetensors h1{margin:2px 0 4px;font-size:20px}.omni-safetensors__subtitle{color:var(--omni-muted,#666);font-size:12px}.omni-safetensors__summary{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:1px;background:var(--omni-border,#ddd);border-bottom:1px solid var(--omni-border,#ddd)}.omni-safetensors__summary-item{min-height:64px;padding:12px 14px;background:var(--omni-bg,#fff)}.omni-safetensors__summary-value{font-size:20px;font-weight:650}.omni-safetensors__summary-label{margin-top:4px;color:var(--omni-muted,#666);font-size:12px}.omni-safetensors__toolbar{display:flex;align-items:center;gap:8px;padding:10px 12px;border-bottom:1px solid var(--omni-border,#ddd);background:var(--omni-toolbar-bg,#f5f5f5)}.omni-safetensors__search{width:min(320px,36vw);min-width:180px;border:1px solid var(--omni-border,#ccc);background:var(--omni-input-bg,#fff);color:inherit;padding:7px 9px;border-radius:4px}.omni-safetensors__tabs{display:flex;flex-wrap:wrap;gap:4px;flex:1}.omni-safetensors button{border:1px solid var(--omni-border,#ccc);border-radius:4px;background:var(--omni-button-bg,#eee);color:inherit;cursor:pointer;padding:7px 10px}.omni-safetensors button:hover{background:var(--omni-hover,#e5e5e5)}.omni-safetensors button[aria-pressed=true]{background:var(--omni-accent,#0e639c);color:var(--omni-accent-fg,#fff)}.omni-safetensors button:disabled{opacity:.5;cursor:default}.omni-safetensors__warnings{padding:10px 14px;border-bottom:1px solid var(--omni-border,#ddd);background:var(--omni-warning-bg,#fff4ce);color:var(--omni-warning-fg,#5f4700)}.omni-safetensors__content{min-height:0;flex:1;overflow:auto}.omni-safetensors__panel-header{position:sticky;top:0;z-index:1;display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 14px;border-bottom:1px solid var(--omni-border,#ddd);background:var(--omni-bg,#fff)}.omni-safetensors__panel-header h2{margin:0;font-size:15px}.omni-safetensors__panel-header span{color:var(--omni-muted,#666);font-size:12px}.omni-safetensors__table-wrap{overflow:auto}.omni-safetensors table{width:100%;border-collapse:collapse}.omni-safetensors th,.omni-safetensors td{border-bottom:1px solid var(--omni-border,#ddd);padding:7px 9px;text-align:left;vertical-align:top;white-space:nowrap}.omni-safetensors th{background:var(--omni-header-bg,#f5f5f5);font-weight:650}.omni-safetensors td{max-width:520px;overflow:hidden;text-overflow:ellipsis}.omni-safetensors tr:hover td{background:var(--omni-hover,#f4f4f4)}.omni-safetensors pre{margin:0;padding:14px;font:13px/1.45 ui-monospace,SFMono-Regular,Consolas,monospace;white-space:pre-wrap}.omni-safetensors__empty{padding:24px;color:var(--omni-muted,#666)}
|
|
3
|
+
@media(max-width:720px){.omni-safetensors__header,.omni-safetensors__toolbar{align-items:stretch;flex-direction:column}.omni-safetensors__search{width:auto}}
|
package/dist/styles/toml.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
:host,.omni-viewer--toml,.omni-viewer--yaml{display:block;height:100%;color:var(--omni-fg,#ddd);background:var(--omni-bg,#1e1e1e);font:13px var(--omni-font,system-ui)}.omni-structured{height:100%;display:flex;flex-direction:column;box-sizing:border-box}.omni-structured__bar{display:flex;gap:5px;align-items:center;padding:6px;border-bottom:1px solid var(--omni-border,#444)}.omni-structured button,.omni-structured input,.omni-structured select{font:inherit;background:var(--omni-button-bg,#333);color:inherit;border:1px solid var(--omni-border,#555);border-radius:3px;padding:3px 7px}.omni-structured button:disabled{opacity:.5}.omni-structured__search{min-width:180px}.omni-structured__diagnostics{white-space:pre-wrap;color:var(--omni-error,#f48771);padding:6px;border-bottom:1px solid var(--omni-border,#444)}.omni-structured__workspace{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);grid-template-rows:minmax(0,1fr);gap:12px;flex:1;min-height:0;padding:12px}.omni-structured__pane{display:flex;flex-direction:column;min-width:0;min-height:0;border:1px solid var(--omni-border,#444);border-radius:8px;overflow:hidden;background:var(--omni-input-bg,#171717)}.omni-structured__pane-header{display:flex;justify-content:space-between;gap:12px;padding:10px 12px;border-bottom:1px solid var(--omni-border,#444)}.omni-structured__pane-header span{color:var(--omni-fg-muted,#999)}.omni-structured__editor,.omni-structured__tree{box-sizing:border-box;flex:1;min-height:0;padding:10px;background:transparent;color:inherit;font:inherit;font-family:var(--omni-font-mono,ui-monospace,monospace)}.omni-structured__editor{resize:none;border:0;outline:none;line-height:1.5;white-space:pre;overflow:auto}.omni-structured__source-surface{position:relative;flex:1;min-height:0;overflow:hidden}.omni-structured__source-highlight{position:absolute;inset:0;box-sizing:border-box;margin:0;padding:10px;overflow:auto;pointer-events:none;font:inherit;font-family:var(--omni-font-mono,ui-monospace,monospace);line-height:1.5;white-space:pre}.omni-structured__pane--highlighted-source .omni-structured__editor{position:relative;z-index:1;width:100%;height:100%;padding:10px;color:transparent;caret-color:var(--omni-fg,#ddd);-webkit-text-fill-color:transparent}.omni-structured__source-key{color:#9cdcfe}.omni-structured__source-value{color:#ce9178}.omni-structured__source-table{color:#c586c0}.omni-structured__source-comment{color:var(--omni-fg-muted,#999)}.omni-structured__tree{overflow:auto}.omni-structured__preview-body{position:relative;flex:1;min-height:200px}.omni-structured__preview-body>.omni-structured__tree,.omni-structured__preview-body>.omni-structured__json-preview,.omni-structured__preview-body>.omni-structured__raw-preview{position:absolute;inset:0}.omni-structured__node{display:flex;gap:6px;align-items:baseline;min-height:25px}.omni-structured__toggle{width:24px;padding:0!important;border:0!important;background:transparent!important}.omni-structured__key{color:var(--omni-accent,#5aa9e6)}.omni-structured__kind{color:var(--omni-fg-muted,#999)}.omni-structured__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.omni-structured__actions{margin-left:auto;display:flex;gap:4px;opacity:0}.omni-structured__node:hover .omni-structured__actions,.omni-structured__actions:focus-within{opacity:1}.omni-structured__raw-preview,.omni-structured__json-preview{flex:1;min-height:0;margin:0;padding:10px;overflow:auto;font-family:var(--omni-font-mono,ui-monospace,monospace);line-height:1.5}.omni-structured__flat-row .omni-structured__key{flex-shrink:0}@media(max-width:720px){.omni-structured__workspace{grid-template-columns:1fr;overflow:auto}.omni-structured__pane{min-height:320px}}
|
|
1
|
+
:host,.omni-viewer--toml,.omni-viewer--yaml{display:block;height:100%;color:var(--omni-fg,#ddd);background:var(--omni-bg,#1e1e1e);font:13px var(--omni-font,system-ui)}.omni-structured{height:100%;display:flex;flex-direction:column;box-sizing:border-box}.omni-structured__bar{display:flex;gap:5px;align-items:center;padding:6px;border-bottom:1px solid var(--omni-border,#444)}.omni-structured button,.omni-structured input,.omni-structured select{font:inherit;background:var(--omni-button-bg,#333);color:inherit;border:1px solid var(--omni-border,#555);border-radius:3px;padding:3px 7px}.omni-structured button:disabled{opacity:.5}.omni-structured__search{min-width:180px}.omni-structured__diagnostics{white-space:pre-wrap;color:var(--omni-error,#f48771);padding:6px;border-bottom:1px solid var(--omni-border,#444)}.omni-structured__workspace{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);grid-template-rows:minmax(0,1fr);gap:12px;flex:1;min-height:0;padding:12px}.omni-structured__pane{display:flex;flex-direction:column;min-width:0;min-height:0;border:1px solid var(--omni-border,#444);border-radius:8px;overflow:hidden;background:var(--omni-input-bg,#171717)}.omni-structured__pane-header{display:flex;justify-content:space-between;gap:12px;padding:10px 12px;border-bottom:1px solid var(--omni-border,#444)}.omni-structured__pane-header span{color:var(--omni-fg-muted,#999)}.omni-structured__editor,.omni-structured__tree{box-sizing:border-box;flex:1;min-height:0;padding:10px;background:transparent;color:inherit;font:inherit;font-family:var(--omni-font-mono,ui-monospace,monospace)}.omni-structured__editor{resize:none;border:0;outline:none;line-height:1.5;white-space:pre;overflow:auto}.omni-structured__source-surface{position:relative;flex:1;min-height:0;overflow:hidden}.omni-structured__source-highlight{position:absolute;inset:0;box-sizing:border-box;margin:0;padding:10px;overflow:auto;pointer-events:none;font:inherit;font-family:var(--omni-font-mono,ui-monospace,monospace);line-height:1.5;white-space:pre}.omni-structured__pane--highlighted-source .omni-structured__editor{position:relative;z-index:1;width:100%;height:100%;padding:10px;color:transparent;caret-color:var(--omni-fg,#ddd);-webkit-text-fill-color:transparent}.omni-structured__source-key{color:#9cdcfe}.omni-structured__source-value{color:#ce9178}.omni-structured__source-table{color:#c586c0}.omni-structured__source-comment{color:var(--omni-fg-muted,#999)}.omni-structured__tree{overflow:auto}.omni-structured__preview-body{position:relative;flex:1;min-height:200px}.omni-structured__preview-body>.omni-structured__tree,.omni-structured__preview-body>.omni-structured__json-preview,.omni-structured__preview-body>.omni-structured__raw-preview{position:absolute;inset:0}.omni-structured__node{display:flex;gap:6px;align-items:baseline;min-height:25px}.omni-structured__toggle{width:24px;padding:0!important;border:0!important;background:transparent!important}.omni-structured__key{color:var(--omni-accent,#5aa9e6)}.omni-structured__kind{color:var(--omni-fg-muted,#999)}.omni-structured__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.omni-structured__actions{margin-left:auto;display:flex;gap:4px;opacity:0}.omni-structured__node:hover .omni-structured__actions,.omni-structured__actions:focus-within{opacity:1}.omni-structured__raw-preview,.omni-structured__json-preview{flex:1;min-height:0;margin:0;padding:10px;overflow:auto;font-family:var(--omni-font-mono,ui-monospace,monospace);line-height:1.5}.omni-structured__flat-row .omni-structured__key{flex-shrink:0}.omni-structured__status{margin-left:auto;color:var(--omni-fg-muted,#999);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.omni-structured__node-comment{color:var(--omni-fg-muted,#999);font-style:italic;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.omni-structured__node--interactive{cursor:pointer;border-radius:3px}.omni-structured__node--interactive:hover{background:var(--omni-hover-bg,#2a2a2a)}.omni-structured__node--selected{background:var(--omni-selection-bg,#0a3a5e);outline:1px solid var(--omni-accent,#5aa9e6)}@media(max-width:720px){.omni-structured__workspace{grid-template-columns:1fr;overflow:auto}.omni-structured__pane{min-height:320px}}
|
package/dist/styles/yaml.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
:host,.omni-viewer--toml,.omni-viewer--yaml{display:block;height:100%;color:var(--omni-fg,#ddd);background:var(--omni-bg,#1e1e1e);font:13px var(--omni-font,system-ui)}.omni-structured{height:100%;display:flex;flex-direction:column;box-sizing:border-box}.omni-structured__bar{display:flex;gap:5px;align-items:center;padding:6px;border-bottom:1px solid var(--omni-border,#444)}.omni-structured button,.omni-structured input,.omni-structured select{font:inherit;background:var(--omni-button-bg,#333);color:inherit;border:1px solid var(--omni-border,#555);border-radius:3px;padding:3px 7px}.omni-structured button:disabled{opacity:.5}.omni-structured__search{min-width:180px}.omni-structured__diagnostics{white-space:pre-wrap;color:var(--omni-error,#f48771);padding:6px;border-bottom:1px solid var(--omni-border,#444)}.omni-structured__workspace{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);grid-template-rows:minmax(0,1fr);gap:12px;flex:1;min-height:0;padding:12px}.omni-structured__pane{display:flex;flex-direction:column;min-width:0;min-height:0;border:1px solid var(--omni-border,#444);border-radius:8px;overflow:hidden;background:var(--omni-input-bg,#171717)}.omni-structured__pane-header{display:flex;justify-content:space-between;gap:12px;padding:10px 12px;border-bottom:1px solid var(--omni-border,#444)}.omni-structured__pane-header span{color:var(--omni-fg-muted,#999)}.omni-structured__editor,.omni-structured__tree{box-sizing:border-box;flex:1;min-height:0;padding:10px;background:transparent;color:inherit;font:inherit;font-family:var(--omni-font-mono,ui-monospace,monospace)}.omni-structured__editor{resize:none;border:0;outline:none;line-height:1.5;white-space:pre;overflow:auto}.omni-structured__source-surface{position:relative;flex:1;min-height:0;overflow:hidden}.omni-structured__source-highlight{position:absolute;inset:0;box-sizing:border-box;margin:0;padding:10px;overflow:auto;pointer-events:none;font:inherit;font-family:var(--omni-font-mono,ui-monospace,monospace);line-height:1.5;white-space:pre}.omni-structured__pane--highlighted-source .omni-structured__editor{position:relative;z-index:1;width:100%;height:100%;padding:10px;color:transparent;caret-color:var(--omni-fg,#ddd);-webkit-text-fill-color:transparent}.omni-structured__source-key{color:#9cdcfe}.omni-structured__source-value{color:#ce9178}.omni-structured__source-table{color:#c586c0}.omni-structured__source-comment{color:var(--omni-fg-muted,#999)}.omni-structured__tree{overflow:auto}.omni-structured__preview-body{position:relative;flex:1;min-height:200px}.omni-structured__preview-body>.omni-structured__tree,.omni-structured__preview-body>.omni-structured__json-preview,.omni-structured__preview-body>.omni-structured__raw-preview{position:absolute;inset:0}.omni-structured__node{display:flex;gap:6px;align-items:baseline;min-height:25px}.omni-structured__toggle{width:24px;padding:0!important;border:0!important;background:transparent!important}.omni-structured__key{color:var(--omni-accent,#5aa9e6)}.omni-structured__kind{color:var(--omni-fg-muted,#999)}.omni-structured__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.omni-structured__actions{margin-left:auto;display:flex;gap:4px;opacity:0}.omni-structured__node:hover .omni-structured__actions,.omni-structured__actions:focus-within{opacity:1}.omni-structured__raw-preview,.omni-structured__json-preview{flex:1;min-height:0;margin:0;padding:10px;overflow:auto;font-family:var(--omni-font-mono,ui-monospace,monospace);line-height:1.5}.omni-structured__flat-row .omni-structured__key{flex-shrink:0}@media(max-width:720px){.omni-structured__workspace{grid-template-columns:1fr;overflow:auto}.omni-structured__pane{min-height:320px}}
|
|
1
|
+
:host,.omni-viewer--toml,.omni-viewer--yaml{display:block;height:100%;color:var(--omni-fg,#ddd);background:var(--omni-bg,#1e1e1e);font:13px var(--omni-font,system-ui)}.omni-structured{height:100%;display:flex;flex-direction:column;box-sizing:border-box}.omni-structured__bar{display:flex;gap:5px;align-items:center;padding:6px;border-bottom:1px solid var(--omni-border,#444)}.omni-structured button,.omni-structured input,.omni-structured select{font:inherit;background:var(--omni-button-bg,#333);color:inherit;border:1px solid var(--omni-border,#555);border-radius:3px;padding:3px 7px}.omni-structured button:disabled{opacity:.5}.omni-structured__search{min-width:180px}.omni-structured__diagnostics{white-space:pre-wrap;color:var(--omni-error,#f48771);padding:6px;border-bottom:1px solid var(--omni-border,#444)}.omni-structured__workspace{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);grid-template-rows:minmax(0,1fr);gap:12px;flex:1;min-height:0;padding:12px}.omni-structured__pane{display:flex;flex-direction:column;min-width:0;min-height:0;border:1px solid var(--omni-border,#444);border-radius:8px;overflow:hidden;background:var(--omni-input-bg,#171717)}.omni-structured__pane-header{display:flex;justify-content:space-between;gap:12px;padding:10px 12px;border-bottom:1px solid var(--omni-border,#444)}.omni-structured__pane-header span{color:var(--omni-fg-muted,#999)}.omni-structured__editor,.omni-structured__tree{box-sizing:border-box;flex:1;min-height:0;padding:10px;background:transparent;color:inherit;font:inherit;font-family:var(--omni-font-mono,ui-monospace,monospace)}.omni-structured__editor{resize:none;border:0;outline:none;line-height:1.5;white-space:pre;overflow:auto}.omni-structured__source-surface{position:relative;flex:1;min-height:0;overflow:hidden}.omni-structured__source-highlight{position:absolute;inset:0;box-sizing:border-box;margin:0;padding:10px;overflow:auto;pointer-events:none;font:inherit;font-family:var(--omni-font-mono,ui-monospace,monospace);line-height:1.5;white-space:pre}.omni-structured__pane--highlighted-source .omni-structured__editor{position:relative;z-index:1;width:100%;height:100%;padding:10px;color:transparent;caret-color:var(--omni-fg,#ddd);-webkit-text-fill-color:transparent}.omni-structured__source-key{color:#9cdcfe}.omni-structured__source-value{color:#ce9178}.omni-structured__source-table{color:#c586c0}.omni-structured__source-comment{color:var(--omni-fg-muted,#999)}.omni-structured__tree{overflow:auto}.omni-structured__preview-body{position:relative;flex:1;min-height:200px}.omni-structured__preview-body>.omni-structured__tree,.omni-structured__preview-body>.omni-structured__json-preview,.omni-structured__preview-body>.omni-structured__raw-preview{position:absolute;inset:0}.omni-structured__node{display:flex;gap:6px;align-items:baseline;min-height:25px}.omni-structured__toggle{width:24px;padding:0!important;border:0!important;background:transparent!important}.omni-structured__key{color:var(--omni-accent,#5aa9e6)}.omni-structured__kind{color:var(--omni-fg-muted,#999)}.omni-structured__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.omni-structured__actions{margin-left:auto;display:flex;gap:4px;opacity:0}.omni-structured__node:hover .omni-structured__actions,.omni-structured__actions:focus-within{opacity:1}.omni-structured__raw-preview,.omni-structured__json-preview{flex:1;min-height:0;margin:0;padding:10px;overflow:auto;font-family:var(--omni-font-mono,ui-monospace,monospace);line-height:1.5}.omni-structured__flat-row .omni-structured__key{flex-shrink:0}.omni-structured__status{margin-left:auto;color:var(--omni-fg-muted,#999);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.omni-structured__node-comment{color:var(--omni-fg-muted,#999);font-style:italic;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.omni-structured__node--interactive{cursor:pointer;border-radius:3px}.omni-structured__node--interactive:hover{background:var(--omni-hover-bg,#2a2a2a)}.omni-structured__node--selected{background:var(--omni-selection-bg,#0a3a5e);outline:1px solid var(--omni-accent,#5aa9e6)}@media(max-width:720px){.omni-structured__workspace{grid-template-columns:1fr;overflow:auto}.omni-structured__pane{min-height:320px}}
|
|
@@ -46,6 +46,8 @@ export interface PdfHighlightAnnotation {
|
|
|
46
46
|
/** A text selection can span several lines -> several rects. */
|
|
47
47
|
rects: PdfHighlightRect[];
|
|
48
48
|
color: string;
|
|
49
|
+
/** The plain text under the selection, kept for copy and the markup list. */
|
|
50
|
+
text?: string;
|
|
49
51
|
}
|
|
50
52
|
/** A text selection rendered as a horizontal strike through each line. */
|
|
51
53
|
export interface PdfStrikeoutAnnotation {
|
|
@@ -54,6 +56,7 @@ export interface PdfStrikeoutAnnotation {
|
|
|
54
56
|
page: number;
|
|
55
57
|
rects: PdfHighlightRect[];
|
|
56
58
|
color: string;
|
|
59
|
+
text?: string;
|
|
57
60
|
}
|
|
58
61
|
/** A text selection rendered as an underline beneath each line. */
|
|
59
62
|
export interface PdfUnderlineAnnotation {
|
|
@@ -62,6 +65,7 @@ export interface PdfUnderlineAnnotation {
|
|
|
62
65
|
page: number;
|
|
63
66
|
rects: PdfHighlightRect[];
|
|
64
67
|
color: string;
|
|
68
|
+
text?: string;
|
|
65
69
|
}
|
|
66
70
|
export type PdfAnnotation = PdfTextAnnotation | PdfSignatureAnnotation | PdfHighlightAnnotation | PdfStrikeoutAnnotation | PdfUnderlineAnnotation;
|
|
67
71
|
export type PdfAnnotationInput = Omit<PdfTextAnnotation, 'id'> | Omit<PdfSignatureAnnotation, 'id'> | Omit<PdfHighlightAnnotation, 'id'> | Omit<PdfStrikeoutAnnotation, 'id'> | Omit<PdfUnderlineAnnotation, 'id'>;
|
|
@@ -96,6 +100,10 @@ export type PdfAction = {
|
|
|
96
100
|
id: string;
|
|
97
101
|
x: number;
|
|
98
102
|
y: number;
|
|
103
|
+
} | {
|
|
104
|
+
type: 'set-annotation-color';
|
|
105
|
+
id: string;
|
|
106
|
+
color: string;
|
|
99
107
|
} | {
|
|
100
108
|
type: 'remove-annotation';
|
|
101
109
|
id: string;
|
|
@@ -138,6 +138,7 @@ export function createPdfController(pageCount, seed, options = {}) {
|
|
|
138
138
|
|| action.type === 'reset-pages'
|
|
139
139
|
|| action.type === 'add-annotation'
|
|
140
140
|
|| action.type === 'move-annotation'
|
|
141
|
+
|| action.type === 'set-annotation-color'
|
|
141
142
|
|| action.type === 'remove-annotation';
|
|
142
143
|
const before = tracksHistory ? snapshot() : undefined;
|
|
143
144
|
const beforeSignature = tracksHistory ? signature() : undefined;
|
|
@@ -187,6 +188,9 @@ export function createPdfController(pageCount, seed, options = {}) {
|
|
|
187
188
|
case 'move-annotation':
|
|
188
189
|
annotations = annotations.map((a) => a.id === action.id ? { ...a, x: action.x, y: action.y } : a);
|
|
189
190
|
break;
|
|
191
|
+
case 'set-annotation-color':
|
|
192
|
+
annotations = annotations.map((a) => a.id === action.id ? { ...a, color: action.color } : a);
|
|
193
|
+
break;
|
|
190
194
|
case 'remove-annotation':
|
|
191
195
|
annotations = annotations.filter((a) => a.id !== action.id);
|
|
192
196
|
if (selectedAnnotationId === action.id)
|
|
@@ -8,6 +8,17 @@ export interface ParsedLayer {
|
|
|
8
8
|
pageOrder: number[];
|
|
9
9
|
annotations: PdfAnnotation[];
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* PDF-space Y for a strike-through / underline drawn over a text rect.
|
|
13
|
+
* `rect.y` is the box top measured from the page top (top-left origin, as the
|
|
14
|
+
* DOM reports it); PDF space has a bottom-left origin, so we flip through the
|
|
15
|
+
* page height. Strikeout sits at the vertical middle; underline sits just above
|
|
16
|
+
* the bottom edge to mirror the on-screen `bottom: 8%` rendering.
|
|
17
|
+
*/
|
|
18
|
+
export declare function markupLineY(kind: 'strikeout' | 'underline', rect: {
|
|
19
|
+
y: number;
|
|
20
|
+
height: number;
|
|
21
|
+
}, pageHeight: number): number;
|
|
11
22
|
/** Persist reordered/deleted pages plus the text/signature overlays,
|
|
12
23
|
* flattened into the page content (portable, non-editable output). */
|
|
13
24
|
export declare function buildEditedPdf(pdfLib: PdfLibModule, source: Uint8Array, state: PdfViewState): Promise<Uint8Array>;
|