@lvce-editor/output-view 2.10.1 → 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/dist/outputViewWorkerMain.js +174 -46
- package/package.json +1 -1
|
@@ -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
|
};
|
|
@@ -1256,6 +1265,35 @@ const filterItems = (items, filterValue) => {
|
|
|
1256
1265
|
return items.filter(parts => getTextFromParts(parts).toLowerCase().includes(normalizedFilterValue));
|
|
1257
1266
|
};
|
|
1258
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;
|
|
1295
|
+
};
|
|
1296
|
+
|
|
1259
1297
|
const isFileNotFoundError = error => {
|
|
1260
1298
|
return error?.message?.includes('File not found') ?? false;
|
|
1261
1299
|
};
|
|
@@ -1266,10 +1304,75 @@ const getLinkMatch = text => {
|
|
|
1266
1304
|
return match ? match[0] : null;
|
|
1267
1305
|
};
|
|
1268
1306
|
|
|
1269
|
-
const
|
|
1270
|
-
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
|
+
};
|
|
1271
1370
|
|
|
1272
1371
|
const parseLine = line => {
|
|
1372
|
+
const structuredLine = parseStructuredLogLine(line);
|
|
1373
|
+
if (structuredLine) {
|
|
1374
|
+
return structuredLine;
|
|
1375
|
+
}
|
|
1273
1376
|
const parts = [];
|
|
1274
1377
|
let rest = line;
|
|
1275
1378
|
while (rest.length > 0) {
|
|
@@ -1309,7 +1412,7 @@ const loadLines = async uri => {
|
|
|
1309
1412
|
try {
|
|
1310
1413
|
// TODO use log stream, updating the output when the file is changed
|
|
1311
1414
|
const content = await readFile(uri);
|
|
1312
|
-
const lines = content.split('\n').map(parseLine);
|
|
1415
|
+
const lines = aggregateLines(content.split('\n').map(parseLine));
|
|
1313
1416
|
return {
|
|
1314
1417
|
code: 0,
|
|
1315
1418
|
error: '',
|
|
@@ -1550,8 +1653,8 @@ const getKeyBindings = () => {
|
|
|
1550
1653
|
}];
|
|
1551
1654
|
};
|
|
1552
1655
|
|
|
1553
|
-
const Filter$
|
|
1554
|
-
const Output
|
|
1656
|
+
const Filter$1 = 'filter';
|
|
1657
|
+
const Output = 'output';
|
|
1555
1658
|
const MainProcess = 'MainProcess';
|
|
1556
1659
|
const SharedProcess = 'SharedProcess';
|
|
1557
1660
|
const Window = 'Window';
|
|
@@ -1762,7 +1865,7 @@ const i18nString = (key, placeholders = emptyObject) => {
|
|
|
1762
1865
|
};
|
|
1763
1866
|
|
|
1764
1867
|
const ClearOutput = 'clear output';
|
|
1765
|
-
const Filter
|
|
1868
|
+
const Filter = 'Filter';
|
|
1766
1869
|
const LogFileNotFound$1 = 'The log file was not found.';
|
|
1767
1870
|
const Settings = 'Settings';
|
|
1768
1871
|
const TurnOffAutoScroll = 'Turn auto scrolling off';
|
|
@@ -1780,7 +1883,7 @@ const logFileNotFound = () => {
|
|
|
1780
1883
|
return i18nString(LogFileNotFound$1);
|
|
1781
1884
|
};
|
|
1782
1885
|
const filter = () => {
|
|
1783
|
-
return i18nString(Filter
|
|
1886
|
+
return i18nString(Filter);
|
|
1784
1887
|
};
|
|
1785
1888
|
|
|
1786
1889
|
const loadButtons = () => {
|
|
@@ -1972,47 +2075,69 @@ const refresh = async state => {
|
|
|
1972
2075
|
};
|
|
1973
2076
|
|
|
1974
2077
|
const renderFilterValue = (oldState, newState) => {
|
|
1975
|
-
return ['Viewlet.setValueByName', Filter$
|
|
2078
|
+
return ['Viewlet.setValueByName', Filter$1, newState.filterValue];
|
|
1976
2079
|
};
|
|
1977
2080
|
|
|
1978
|
-
const
|
|
1979
|
-
const
|
|
1980
|
-
const InputBox = 'InputBox';
|
|
1981
|
-
const MaskIcon = 'MaskIcon';
|
|
1982
|
-
const FilterInput = 'FilterInput';
|
|
1983
|
-
const OutputContent = 'OutputContent';
|
|
1984
|
-
const Actions = 'Actions';
|
|
1985
|
-
const Message = 'Message';
|
|
1986
|
-
const Viewlet = 'Viewlet';
|
|
1987
|
-
const Output = 'Output';
|
|
1988
|
-
const Option = 'Option';
|
|
1989
|
-
const Select = 'Select';
|
|
1990
|
-
const Error$1 = 'Error';
|
|
1991
|
-
const Line = 'Line';
|
|
1992
|
-
|
|
1993
|
-
const parentNode = {
|
|
2081
|
+
const noNodes = [];
|
|
2082
|
+
const repeatCountNode = {
|
|
1994
2083
|
childCount: 1,
|
|
1995
|
-
className:
|
|
1996
|
-
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
|
+
}
|
|
1997
2126
|
};
|
|
1998
2127
|
const getLineDom = parts => {
|
|
1999
2128
|
const children = [];
|
|
2129
|
+
let childCount = 0;
|
|
2000
2130
|
for (const part of parts) {
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
children.push({
|
|
2005
|
-
childCount: 1,
|
|
2006
|
-
href: part.value,
|
|
2007
|
-
rel: 'noopener noreferrer',
|
|
2008
|
-
target: '_blank',
|
|
2009
|
-
type: A
|
|
2010
|
-
}, text(part.value));
|
|
2011
|
-
}
|
|
2131
|
+
const partDom = getLinePartDom(part);
|
|
2132
|
+
children.push(...partDom.nodes);
|
|
2133
|
+
childCount += partDom.childCount;
|
|
2012
2134
|
}
|
|
2135
|
+
const level = getLevel(parts);
|
|
2136
|
+
const className = level ? mergeClassNames(Line, level) : Line;
|
|
2013
2137
|
const lineNode = {
|
|
2014
|
-
|
|
2015
|
-
|
|
2138
|
+
childCount,
|
|
2139
|
+
className,
|
|
2140
|
+
type: Div
|
|
2016
2141
|
};
|
|
2017
2142
|
return [lineNode, ...children];
|
|
2018
2143
|
};
|
|
@@ -2063,7 +2188,7 @@ const getErrorDom = (errorCode, error) => {
|
|
|
2063
2188
|
const getOutputVirtualDom = (lines, errorCode, error) => {
|
|
2064
2189
|
return [{
|
|
2065
2190
|
childCount: 1,
|
|
2066
|
-
className: mergeClassNames(Viewlet, Output),
|
|
2191
|
+
className: mergeClassNames(Viewlet, Output$1),
|
|
2067
2192
|
type: Div
|
|
2068
2193
|
}, ...getContentDom(lines, error), ...getErrorDom(errorCode, error)];
|
|
2069
2194
|
};
|
|
@@ -2075,7 +2200,7 @@ const renderItems = (oldState, newState) => {
|
|
|
2075
2200
|
|
|
2076
2201
|
const renderSelectedItem = (oldState, newState) => {
|
|
2077
2202
|
const value = newState.selectedOption;
|
|
2078
|
-
const name = Output
|
|
2203
|
+
const name = Output;
|
|
2079
2204
|
return ['Viewlet.setValueByName', name, value];
|
|
2080
2205
|
};
|
|
2081
2206
|
|
|
@@ -2144,7 +2269,7 @@ const getActionButtonsVirtualDom = buttons => {
|
|
|
2144
2269
|
|
|
2145
2270
|
const filterNode = {
|
|
2146
2271
|
childCount: 1,
|
|
2147
|
-
className: Filter,
|
|
2272
|
+
className: Filter$2,
|
|
2148
2273
|
type: Div
|
|
2149
2274
|
};
|
|
2150
2275
|
const getFilterVirtualDom = () => {
|
|
@@ -2152,7 +2277,7 @@ const getFilterVirtualDom = () => {
|
|
|
2152
2277
|
return [filterNode, {
|
|
2153
2278
|
childCount: 0,
|
|
2154
2279
|
className: mergeClassNames(InputBox, FilterInput),
|
|
2155
|
-
name: Filter$
|
|
2280
|
+
name: Filter$1,
|
|
2156
2281
|
onInput: HandleFilterInput,
|
|
2157
2282
|
placeholder,
|
|
2158
2283
|
type: Input
|
|
@@ -2176,7 +2301,7 @@ const getSelectVirtualDom = options => {
|
|
|
2176
2301
|
return [{
|
|
2177
2302
|
childCount: options.length,
|
|
2178
2303
|
className: Select,
|
|
2179
|
-
name: Output
|
|
2304
|
+
name: Output,
|
|
2180
2305
|
onChange: HandleSelect,
|
|
2181
2306
|
type: Select$1
|
|
2182
2307
|
}, ...options.flatMap(getOptionVirtualDom)];
|
|
@@ -2241,7 +2366,10 @@ const resize = (state, dimensions) => {
|
|
|
2241
2366
|
};
|
|
2242
2367
|
|
|
2243
2368
|
const serializeLinePart = part => {
|
|
2244
|
-
|
|
2369
|
+
if (part.type === LogLevel || part.type === RepeatCount) {
|
|
2370
|
+
return '';
|
|
2371
|
+
}
|
|
2372
|
+
return part.type === Link ? part.label || part.value : part.value;
|
|
2245
2373
|
};
|
|
2246
2374
|
const serializeLineParts = parts => {
|
|
2247
2375
|
return parts.map(serializeLinePart).join('');
|