@lvce-editor/output-view 2.10.1 → 2.12.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 +179 -50
- 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
|
};
|
|
@@ -2060,12 +2185,13 @@ const getErrorDom = (errorCode, error) => {
|
|
|
2060
2185
|
return [errorNode, text(error)];
|
|
2061
2186
|
};
|
|
2062
2187
|
|
|
2188
|
+
const outputNode = {
|
|
2189
|
+
childCount: 1,
|
|
2190
|
+
className: mergeClassNames(Viewlet, Output$1),
|
|
2191
|
+
type: Div
|
|
2192
|
+
};
|
|
2063
2193
|
const getOutputVirtualDom = (lines, errorCode, error) => {
|
|
2064
|
-
return [
|
|
2065
|
-
childCount: 1,
|
|
2066
|
-
className: mergeClassNames(Viewlet, Output),
|
|
2067
|
-
type: Div
|
|
2068
|
-
}, ...getContentDom(lines, error), ...getErrorDom(errorCode, error)];
|
|
2194
|
+
return [outputNode, ...getContentDom(lines, error), ...getErrorDom(errorCode, error)];
|
|
2069
2195
|
};
|
|
2070
2196
|
|
|
2071
2197
|
const renderItems = (oldState, newState) => {
|
|
@@ -2075,7 +2201,7 @@ const renderItems = (oldState, newState) => {
|
|
|
2075
2201
|
|
|
2076
2202
|
const renderSelectedItem = (oldState, newState) => {
|
|
2077
2203
|
const value = newState.selectedOption;
|
|
2078
|
-
const name = Output
|
|
2204
|
+
const name = Output;
|
|
2079
2205
|
return ['Viewlet.setValueByName', name, value];
|
|
2080
2206
|
};
|
|
2081
2207
|
|
|
@@ -2144,7 +2270,7 @@ const getActionButtonsVirtualDom = buttons => {
|
|
|
2144
2270
|
|
|
2145
2271
|
const filterNode = {
|
|
2146
2272
|
childCount: 1,
|
|
2147
|
-
className: Filter,
|
|
2273
|
+
className: Filter$2,
|
|
2148
2274
|
type: Div
|
|
2149
2275
|
};
|
|
2150
2276
|
const getFilterVirtualDom = () => {
|
|
@@ -2152,7 +2278,7 @@ const getFilterVirtualDom = () => {
|
|
|
2152
2278
|
return [filterNode, {
|
|
2153
2279
|
childCount: 0,
|
|
2154
2280
|
className: mergeClassNames(InputBox, FilterInput),
|
|
2155
|
-
name: Filter$
|
|
2281
|
+
name: Filter$1,
|
|
2156
2282
|
onInput: HandleFilterInput,
|
|
2157
2283
|
placeholder,
|
|
2158
2284
|
type: Input
|
|
@@ -2176,7 +2302,7 @@ const getSelectVirtualDom = options => {
|
|
|
2176
2302
|
return [{
|
|
2177
2303
|
childCount: options.length,
|
|
2178
2304
|
className: Select,
|
|
2179
|
-
name: Output
|
|
2305
|
+
name: Output,
|
|
2180
2306
|
onChange: HandleSelect,
|
|
2181
2307
|
type: Select$1
|
|
2182
2308
|
}, ...options.flatMap(getOptionVirtualDom)];
|
|
@@ -2241,7 +2367,10 @@ const resize = (state, dimensions) => {
|
|
|
2241
2367
|
};
|
|
2242
2368
|
|
|
2243
2369
|
const serializeLinePart = part => {
|
|
2244
|
-
|
|
2370
|
+
if (part.type === LogLevel || part.type === RepeatCount) {
|
|
2371
|
+
return '';
|
|
2372
|
+
}
|
|
2373
|
+
return part.type === Link ? part.label || part.value : part.value;
|
|
2245
2374
|
};
|
|
2246
2375
|
const serializeLineParts = parts => {
|
|
2247
2376
|
return parts.map(serializeLinePart).join('');
|