@lvce-editor/output-view 2.10.0 → 2.11.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 +0 -4
- package/dist/outputViewWorkerMain.js +176 -47
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -991,6 +991,7 @@ const ToolBar = 'toolbar';
|
|
|
991
991
|
const Button = 1;
|
|
992
992
|
const Div = 4;
|
|
993
993
|
const Input = 6;
|
|
994
|
+
const Span = 8;
|
|
994
995
|
const Text$1 = 12;
|
|
995
996
|
const A = 53;
|
|
996
997
|
const Select$1 = 63;
|
|
@@ -1241,10 +1242,18 @@ const terminate = () => {
|
|
|
1241
1242
|
globalThis.close();
|
|
1242
1243
|
};
|
|
1243
1244
|
|
|
1245
|
+
const Text = 1;
|
|
1246
|
+
const Link = 2;
|
|
1247
|
+
const LogLevel = 3;
|
|
1248
|
+
const RepeatCount = 4;
|
|
1249
|
+
|
|
1244
1250
|
const getTextFromParts = parts => {
|
|
1245
1251
|
let result = '';
|
|
1246
1252
|
for (const part of parts) {
|
|
1247
|
-
|
|
1253
|
+
if (part.type === RepeatCount) {
|
|
1254
|
+
continue;
|
|
1255
|
+
}
|
|
1256
|
+
result += part.type === Link ? part.label || part.value : part.value;
|
|
1248
1257
|
}
|
|
1249
1258
|
return result;
|
|
1250
1259
|
};
|
|
@@ -1252,7 +1261,37 @@ const filterItems = (items, filterValue) => {
|
|
|
1252
1261
|
if (!filterValue) {
|
|
1253
1262
|
return items;
|
|
1254
1263
|
}
|
|
1255
|
-
|
|
1264
|
+
const normalizedFilterValue = filterValue.toLowerCase();
|
|
1265
|
+
return items.filter(parts => getTextFromParts(parts).toLowerCase().includes(normalizedFilterValue));
|
|
1266
|
+
};
|
|
1267
|
+
|
|
1268
|
+
const getAggregationKey = line => {
|
|
1269
|
+
return JSON.stringify(line.filter(part => part.type !== RepeatCount));
|
|
1270
|
+
};
|
|
1271
|
+
const withRepeatCount = (line, count) => {
|
|
1272
|
+
const parts = line.filter(part => part.type !== RepeatCount);
|
|
1273
|
+
return [{
|
|
1274
|
+
type: RepeatCount,
|
|
1275
|
+
value: String(count)
|
|
1276
|
+
}, ...parts];
|
|
1277
|
+
};
|
|
1278
|
+
const aggregateLines = lines => {
|
|
1279
|
+
const result = [];
|
|
1280
|
+
let previousKey = '';
|
|
1281
|
+
let repeatCount = 0;
|
|
1282
|
+
for (const line of lines) {
|
|
1283
|
+
const key = getAggregationKey(line);
|
|
1284
|
+
if (result.length > 0 && key === previousKey) {
|
|
1285
|
+
repeatCount++;
|
|
1286
|
+
const previousIndex = result.length - 1;
|
|
1287
|
+
result[previousIndex] = withRepeatCount(result.at(-1), repeatCount);
|
|
1288
|
+
continue;
|
|
1289
|
+
}
|
|
1290
|
+
result.push(line);
|
|
1291
|
+
previousKey = key;
|
|
1292
|
+
repeatCount = 1;
|
|
1293
|
+
}
|
|
1294
|
+
return result;
|
|
1256
1295
|
};
|
|
1257
1296
|
|
|
1258
1297
|
const isFileNotFoundError = error => {
|
|
@@ -1265,10 +1304,75 @@ const getLinkMatch = text => {
|
|
|
1265
1304
|
return match ? match[0] : null;
|
|
1266
1305
|
};
|
|
1267
1306
|
|
|
1268
|
-
const
|
|
1269
|
-
const
|
|
1307
|
+
const Filter$2 = 'Filter';
|
|
1308
|
+
const IconButton = 'IconButton';
|
|
1309
|
+
const InputBox = 'InputBox';
|
|
1310
|
+
const MaskIcon = 'MaskIcon';
|
|
1311
|
+
const FilterInput = 'FilterInput';
|
|
1312
|
+
const OutputContent = 'OutputContent';
|
|
1313
|
+
const Actions = 'Actions';
|
|
1314
|
+
const Message = 'Message';
|
|
1315
|
+
const Viewlet = 'Viewlet';
|
|
1316
|
+
const Output$1 = 'Output';
|
|
1317
|
+
const Option = 'Option';
|
|
1318
|
+
const Select = 'Select';
|
|
1319
|
+
const Error$1 = 'Error';
|
|
1320
|
+
const Line = 'Line';
|
|
1321
|
+
const OutputRepeatCount = 'OutputRepeatCount';
|
|
1322
|
+
const OutputSourceLink = 'OutputSourceLink';
|
|
1323
|
+
|
|
1324
|
+
const isStructuredLogEntry = value => {
|
|
1325
|
+
return value?.category === 'Window' && typeof value.level === 'string' && typeof value.line === 'number' && typeof value.message === 'string' && typeof value.source === 'string' && typeof value.timestamp === 'string';
|
|
1326
|
+
};
|
|
1327
|
+
const getSourceLabel = (source, line) => {
|
|
1328
|
+
const withoutQueryOrFragment = source.split(/[?#]/, 1)[0];
|
|
1329
|
+
const slashIndex = withoutQueryOrFragment.lastIndexOf('/');
|
|
1330
|
+
const name = slashIndex === -1 ? withoutQueryOrFragment : withoutQueryOrFragment.slice(slashIndex + 1);
|
|
1331
|
+
return line > 0 ? `${name}:${line}` : name;
|
|
1332
|
+
};
|
|
1333
|
+
const normalizeLevel = level => {
|
|
1334
|
+
return level === 'warn' ? 'warning' : level;
|
|
1335
|
+
};
|
|
1336
|
+
const parseStructuredLogLine = line => {
|
|
1337
|
+
if (!line.startsWith('{')) {
|
|
1338
|
+
return undefined;
|
|
1339
|
+
}
|
|
1340
|
+
let parsed;
|
|
1341
|
+
try {
|
|
1342
|
+
parsed = JSON.parse(line);
|
|
1343
|
+
} catch {
|
|
1344
|
+
return undefined;
|
|
1345
|
+
}
|
|
1346
|
+
if (!isStructuredLogEntry(parsed)) {
|
|
1347
|
+
return undefined;
|
|
1348
|
+
}
|
|
1349
|
+
const parts = [{
|
|
1350
|
+
type: LogLevel,
|
|
1351
|
+
value: normalizeLevel(parsed.level)
|
|
1352
|
+
}, {
|
|
1353
|
+
type: Text,
|
|
1354
|
+
value: parsed.message
|
|
1355
|
+
}];
|
|
1356
|
+
if (!parsed.source) {
|
|
1357
|
+
return parts;
|
|
1358
|
+
}
|
|
1359
|
+
const href = parsed.line > 0 ? `${parsed.source}:${parsed.line}` : parsed.source;
|
|
1360
|
+
return [...parts, {
|
|
1361
|
+
type: Text,
|
|
1362
|
+
value: ' '
|
|
1363
|
+
}, {
|
|
1364
|
+
className: OutputSourceLink,
|
|
1365
|
+
label: getSourceLabel(parsed.source, parsed.line),
|
|
1366
|
+
type: Link,
|
|
1367
|
+
value: href
|
|
1368
|
+
}];
|
|
1369
|
+
};
|
|
1270
1370
|
|
|
1271
1371
|
const parseLine = line => {
|
|
1372
|
+
const structuredLine = parseStructuredLogLine(line);
|
|
1373
|
+
if (structuredLine) {
|
|
1374
|
+
return structuredLine;
|
|
1375
|
+
}
|
|
1272
1376
|
const parts = [];
|
|
1273
1377
|
let rest = line;
|
|
1274
1378
|
while (rest.length > 0) {
|
|
@@ -1308,7 +1412,7 @@ const loadLines = async uri => {
|
|
|
1308
1412
|
try {
|
|
1309
1413
|
// TODO use log stream, updating the output when the file is changed
|
|
1310
1414
|
const content = await readFile(uri);
|
|
1311
|
-
const lines = content.split('\n').map(parseLine);
|
|
1415
|
+
const lines = aggregateLines(content.split('\n').map(parseLine));
|
|
1312
1416
|
return {
|
|
1313
1417
|
code: 0,
|
|
1314
1418
|
error: '',
|
|
@@ -1549,8 +1653,8 @@ const getKeyBindings = () => {
|
|
|
1549
1653
|
}];
|
|
1550
1654
|
};
|
|
1551
1655
|
|
|
1552
|
-
const Filter$
|
|
1553
|
-
const Output
|
|
1656
|
+
const Filter$1 = 'filter';
|
|
1657
|
+
const Output = 'output';
|
|
1554
1658
|
const MainProcess = 'MainProcess';
|
|
1555
1659
|
const SharedProcess = 'SharedProcess';
|
|
1556
1660
|
const Window = 'Window';
|
|
@@ -1761,7 +1865,7 @@ const i18nString = (key, placeholders = emptyObject) => {
|
|
|
1761
1865
|
};
|
|
1762
1866
|
|
|
1763
1867
|
const ClearOutput = 'clear output';
|
|
1764
|
-
const Filter
|
|
1868
|
+
const Filter = 'Filter';
|
|
1765
1869
|
const LogFileNotFound$1 = 'The log file was not found.';
|
|
1766
1870
|
const Settings = 'Settings';
|
|
1767
1871
|
const TurnOffAutoScroll = 'Turn auto scrolling off';
|
|
@@ -1779,7 +1883,7 @@ const logFileNotFound = () => {
|
|
|
1779
1883
|
return i18nString(LogFileNotFound$1);
|
|
1780
1884
|
};
|
|
1781
1885
|
const filter = () => {
|
|
1782
|
-
return i18nString(Filter
|
|
1886
|
+
return i18nString(Filter);
|
|
1783
1887
|
};
|
|
1784
1888
|
|
|
1785
1889
|
const loadButtons = () => {
|
|
@@ -1971,47 +2075,69 @@ const refresh = async state => {
|
|
|
1971
2075
|
};
|
|
1972
2076
|
|
|
1973
2077
|
const renderFilterValue = (oldState, newState) => {
|
|
1974
|
-
return ['Viewlet.setValueByName', Filter$
|
|
2078
|
+
return ['Viewlet.setValueByName', Filter$1, newState.filterValue];
|
|
1975
2079
|
};
|
|
1976
2080
|
|
|
1977
|
-
const
|
|
1978
|
-
const
|
|
1979
|
-
const InputBox = 'InputBox';
|
|
1980
|
-
const MaskIcon = 'MaskIcon';
|
|
1981
|
-
const FilterInput = 'FilterInput';
|
|
1982
|
-
const OutputContent = 'OutputContent';
|
|
1983
|
-
const Actions = 'Actions';
|
|
1984
|
-
const Message = 'Message';
|
|
1985
|
-
const Viewlet = 'Viewlet';
|
|
1986
|
-
const Output = 'Output';
|
|
1987
|
-
const Option = 'Option';
|
|
1988
|
-
const Select = 'Select';
|
|
1989
|
-
const Error$1 = 'Error';
|
|
1990
|
-
const Line = 'Line';
|
|
1991
|
-
|
|
1992
|
-
const parentNode = {
|
|
2081
|
+
const noNodes = [];
|
|
2082
|
+
const repeatCountNode = {
|
|
1993
2083
|
childCount: 1,
|
|
1994
|
-
className:
|
|
1995
|
-
type:
|
|
2084
|
+
className: OutputRepeatCount,
|
|
2085
|
+
type: Span
|
|
2086
|
+
};
|
|
2087
|
+
const spaceNode = text(' ');
|
|
2088
|
+
const getLevel = parts => {
|
|
2089
|
+
return parts.find(part => part.type === LogLevel)?.value || '';
|
|
2090
|
+
};
|
|
2091
|
+
const getLinePartDom = part => {
|
|
2092
|
+
switch (part.type) {
|
|
2093
|
+
case Link:
|
|
2094
|
+
{
|
|
2095
|
+
const linkNode = {
|
|
2096
|
+
childCount: 1,
|
|
2097
|
+
href: part.value,
|
|
2098
|
+
rel: 'noopener noreferrer',
|
|
2099
|
+
target: '_blank',
|
|
2100
|
+
type: A,
|
|
2101
|
+
...(part.className && {
|
|
2102
|
+
className: part.className
|
|
2103
|
+
})
|
|
2104
|
+
};
|
|
2105
|
+
return {
|
|
2106
|
+
childCount: 1,
|
|
2107
|
+
nodes: [linkNode, text(part.label || part.value)]
|
|
2108
|
+
};
|
|
2109
|
+
}
|
|
2110
|
+
case RepeatCount:
|
|
2111
|
+
return {
|
|
2112
|
+
childCount: 2,
|
|
2113
|
+
nodes: [repeatCountNode, text(part.value), spaceNode]
|
|
2114
|
+
};
|
|
2115
|
+
case Text:
|
|
2116
|
+
return {
|
|
2117
|
+
childCount: 1,
|
|
2118
|
+
nodes: [text(part.value)]
|
|
2119
|
+
};
|
|
2120
|
+
default:
|
|
2121
|
+
return {
|
|
2122
|
+
childCount: 0,
|
|
2123
|
+
nodes: noNodes
|
|
2124
|
+
};
|
|
2125
|
+
}
|
|
1996
2126
|
};
|
|
1997
2127
|
const getLineDom = parts => {
|
|
1998
2128
|
const children = [];
|
|
2129
|
+
let childCount = 0;
|
|
1999
2130
|
for (const part of parts) {
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
children.push({
|
|
2004
|
-
childCount: 1,
|
|
2005
|
-
href: part.value,
|
|
2006
|
-
rel: 'noopener noreferrer',
|
|
2007
|
-
target: '_blank',
|
|
2008
|
-
type: A
|
|
2009
|
-
}, text(part.value));
|
|
2010
|
-
}
|
|
2131
|
+
const partDom = getLinePartDom(part);
|
|
2132
|
+
children.push(...partDom.nodes);
|
|
2133
|
+
childCount += partDom.childCount;
|
|
2011
2134
|
}
|
|
2135
|
+
const level = getLevel(parts);
|
|
2136
|
+
const className = level ? mergeClassNames(Line, level) : Line;
|
|
2012
2137
|
const lineNode = {
|
|
2013
|
-
|
|
2014
|
-
|
|
2138
|
+
childCount,
|
|
2139
|
+
className,
|
|
2140
|
+
type: Div
|
|
2015
2141
|
};
|
|
2016
2142
|
return [lineNode, ...children];
|
|
2017
2143
|
};
|
|
@@ -2062,7 +2188,7 @@ const getErrorDom = (errorCode, error) => {
|
|
|
2062
2188
|
const getOutputVirtualDom = (lines, errorCode, error) => {
|
|
2063
2189
|
return [{
|
|
2064
2190
|
childCount: 1,
|
|
2065
|
-
className: mergeClassNames(Viewlet, Output),
|
|
2191
|
+
className: mergeClassNames(Viewlet, Output$1),
|
|
2066
2192
|
type: Div
|
|
2067
2193
|
}, ...getContentDom(lines, error), ...getErrorDom(errorCode, error)];
|
|
2068
2194
|
};
|
|
@@ -2074,7 +2200,7 @@ const renderItems = (oldState, newState) => {
|
|
|
2074
2200
|
|
|
2075
2201
|
const renderSelectedItem = (oldState, newState) => {
|
|
2076
2202
|
const value = newState.selectedOption;
|
|
2077
|
-
const name = Output
|
|
2203
|
+
const name = Output;
|
|
2078
2204
|
return ['Viewlet.setValueByName', name, value];
|
|
2079
2205
|
};
|
|
2080
2206
|
|
|
@@ -2143,7 +2269,7 @@ const getActionButtonsVirtualDom = buttons => {
|
|
|
2143
2269
|
|
|
2144
2270
|
const filterNode = {
|
|
2145
2271
|
childCount: 1,
|
|
2146
|
-
className: Filter,
|
|
2272
|
+
className: Filter$2,
|
|
2147
2273
|
type: Div
|
|
2148
2274
|
};
|
|
2149
2275
|
const getFilterVirtualDom = () => {
|
|
@@ -2151,7 +2277,7 @@ const getFilterVirtualDom = () => {
|
|
|
2151
2277
|
return [filterNode, {
|
|
2152
2278
|
childCount: 0,
|
|
2153
2279
|
className: mergeClassNames(InputBox, FilterInput),
|
|
2154
|
-
name: Filter$
|
|
2280
|
+
name: Filter$1,
|
|
2155
2281
|
onInput: HandleFilterInput,
|
|
2156
2282
|
placeholder,
|
|
2157
2283
|
type: Input
|
|
@@ -2175,7 +2301,7 @@ const getSelectVirtualDom = options => {
|
|
|
2175
2301
|
return [{
|
|
2176
2302
|
childCount: options.length,
|
|
2177
2303
|
className: Select,
|
|
2178
|
-
name: Output
|
|
2304
|
+
name: Output,
|
|
2179
2305
|
onChange: HandleSelect,
|
|
2180
2306
|
type: Select$1
|
|
2181
2307
|
}, ...options.flatMap(getOptionVirtualDom)];
|
|
@@ -2240,7 +2366,10 @@ const resize = (state, dimensions) => {
|
|
|
2240
2366
|
};
|
|
2241
2367
|
|
|
2242
2368
|
const serializeLinePart = part => {
|
|
2243
|
-
|
|
2369
|
+
if (part.type === LogLevel || part.type === RepeatCount) {
|
|
2370
|
+
return '';
|
|
2371
|
+
}
|
|
2372
|
+
return part.type === Link ? part.label || part.value : part.value;
|
|
2244
2373
|
};
|
|
2245
2374
|
const serializeLineParts = parts => {
|
|
2246
2375
|
return parts.map(serializeLinePart).join('');
|