@lvce-editor/extension-detail-view 3.37.0 → 3.38.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.
@@ -1,1792 +1,2220 @@
1
- const normalizeLine = line => {
2
- if (line.startsWith('Error: ')) {
3
- return line.slice('Error: '.length);
4
- }
5
- if (line.startsWith('VError: ')) {
6
- return line.slice('VError: '.length);
1
+ const emptyObject = {};
2
+ const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
3
+ const i18nString = (key, placeholders = emptyObject) => {
4
+ if (placeholders === emptyObject) {
5
+ return key;
7
6
  }
8
- return line;
7
+ const replacer = (match, rest) => {
8
+ return placeholders[rest];
9
+ };
10
+ return key.replaceAll(RE_PLACEHOLDER, replacer);
9
11
  };
10
- const getCombinedMessage = (error, message) => {
11
- const stringifiedError = normalizeLine(`${error}`);
12
- if (message) {
13
- return `${message}: ${stringifiedError}`;
14
- }
15
- return stringifiedError;
12
+
13
+ const ActivationEvents$1 = 'Activation Events';
14
+ const Categories$1 = 'Categories';
15
+ const Changelog$2 = 'Changelog';
16
+ const Commands$1 = 'Commands';
17
+ const ContentSecurityPolicy = 'ContentSecurityPolicy';
18
+ const Copy = 'Copy';
19
+ const Details$1 = 'Details';
20
+ const Disable$1 = 'Disable';
21
+ const Elements = 'Elements';
22
+ const Features$2 = 'Features';
23
+ const FileMatch = 'File Match';
24
+ const Id = 'ID';
25
+ const Installation = 'Installation';
26
+ const JsonValidation$1 = 'Json Validation';
27
+ const Label = 'Label';
28
+ const Marketplace = 'Marketplace';
29
+ const None$1 = 'None';
30
+ const OpenImageInNewTab = 'Open Image in New Tab';
31
+ const OpenInNewTab = 'Open in New Tab';
32
+ const ProgrammingLanguages$1 = 'Programming Languages';
33
+ const Resources$1 = 'Resources';
34
+ const SaveImageAs = 'Save Image as';
35
+ const Schema = 'Schema';
36
+ const ScrollToTop$1 = 'Scroll to top';
37
+ const Selector = 'Selector';
38
+ const SetColorTheme$1 = 'Set Color Theme';
39
+ const Settings$1 = 'Settings';
40
+ const Theme$1 = 'Theme';
41
+ const Uninstall$1 = 'Uninstall';
42
+ const WebViews$1 = 'WebViews';
43
+
44
+ const installation = () => {
45
+ return i18nString(Installation);
16
46
  };
17
- const NewLine$2 = '\n';
18
- const getNewLineIndex$1 = (string, startIndex = undefined) => {
19
- return string.indexOf(NewLine$2, startIndex);
47
+ const marketplace = () => {
48
+ return i18nString(Marketplace);
20
49
  };
21
- const mergeStacks = (parent, child) => {
22
- if (!child) {
23
- return parent;
24
- }
25
- const parentNewLineIndex = getNewLineIndex$1(parent);
26
- const childNewLineIndex = getNewLineIndex$1(child);
27
- if (childNewLineIndex === -1) {
28
- return parent;
29
- }
30
- const parentFirstLine = parent.slice(0, parentNewLineIndex);
31
- const childRest = child.slice(childNewLineIndex);
32
- const childFirstLine = normalizeLine(child.slice(0, childNewLineIndex));
33
- if (parentFirstLine.includes(childFirstLine)) {
34
- return parentFirstLine + childRest;
35
- }
36
- return child;
50
+ const categories = () => {
51
+ return i18nString(Categories$1);
37
52
  };
38
- class VError extends Error {
39
- constructor(error, message) {
40
- const combinedMessage = getCombinedMessage(error, message);
41
- super(combinedMessage);
42
- this.name = 'VError';
43
- if (error instanceof Error) {
44
- this.stack = mergeStacks(this.stack, error.stack);
45
- }
46
- if (error.codeFrame) {
47
- // @ts-ignore
48
- this.codeFrame = error.codeFrame;
49
- }
50
- if (error.code) {
51
- // @ts-ignore
52
- this.code = error.code;
53
- }
54
- }
55
- }
56
-
57
- class AssertionError extends Error {
58
- constructor(message) {
59
- super(message);
60
- this.name = 'AssertionError';
61
- }
62
- }
63
- const Object$1 = 1;
64
- const Number$1 = 2;
65
- const Array$1 = 3;
66
- const String = 4;
67
- const Boolean$1 = 5;
68
- const Function = 6;
69
- const Null = 7;
70
- const Unknown = 8;
71
- const getType = value => {
72
- switch (typeof value) {
73
- case 'number':
74
- return Number$1;
75
- case 'function':
76
- return Function;
77
- case 'string':
78
- return String;
79
- case 'object':
80
- if (value === null) {
81
- return Null;
82
- }
83
- if (Array.isArray(value)) {
84
- return Array$1;
85
- }
86
- return Object$1;
87
- case 'boolean':
88
- return Boolean$1;
89
- default:
90
- return Unknown;
91
- }
53
+ const resources = () => {
54
+ return i18nString(Resources$1);
92
55
  };
93
- const string = value => {
94
- const type = getType(value);
95
- if (type !== String) {
96
- throw new AssertionError('expected value to be of type string');
97
- }
56
+ const copy = () => {
57
+ return i18nString(Copy);
98
58
  };
99
-
100
- const isMessagePort = value => {
101
- return value && value instanceof MessagePort;
59
+ const changelog = () => {
60
+ return i18nString(Changelog$2);
102
61
  };
103
- const isMessagePortMain = value => {
104
- return value && value.constructor && value.constructor.name === 'MessagePortMain';
62
+ const details = () => {
63
+ return i18nString(Details$1);
105
64
  };
106
- const isOffscreenCanvas = value => {
107
- return typeof OffscreenCanvas !== 'undefined' && value instanceof OffscreenCanvas;
65
+ const disable = () => {
66
+ return i18nString(Disable$1);
108
67
  };
109
- const isInstanceOf = (value, constructorName) => {
110
- return value?.constructor?.name === constructorName;
68
+ const features$1 = () => {
69
+ return i18nString(Features$2);
111
70
  };
112
- const isSocket = value => {
113
- return isInstanceOf(value, 'Socket');
71
+ const none = () => {
72
+ return i18nString(None$1);
114
73
  };
115
- const transferrables = [isMessagePort, isMessagePortMain, isOffscreenCanvas, isSocket];
116
- const isTransferrable = value => {
117
- for (const fn of transferrables) {
118
- if (fn(value)) {
119
- return true;
120
- }
121
- }
122
- return false;
74
+ const openInNewTab = () => {
75
+ return i18nString(OpenInNewTab);
123
76
  };
124
- const walkValue = (value, transferrables, isTransferrable) => {
125
- if (!value) {
126
- return;
127
- }
128
- if (isTransferrable(value)) {
129
- transferrables.push(value);
130
- return;
131
- }
132
- if (Array.isArray(value)) {
133
- for (const item of value) {
134
- walkValue(item, transferrables, isTransferrable);
135
- }
136
- return;
137
- }
138
- if (typeof value === 'object') {
139
- for (const property of Object.values(value)) {
140
- walkValue(property, transferrables, isTransferrable);
141
- }
142
- return;
143
- }
77
+ const label = () => {
78
+ return i18nString(Label);
144
79
  };
145
- const getTransferrables = value => {
146
- const transferrables = [];
147
- walkValue(value, transferrables, isTransferrable);
148
- return transferrables;
80
+ const openImageInNewTab = () => {
81
+ return i18nString(OpenImageInNewTab);
149
82
  };
150
- const attachEvents = that => {
151
- const handleMessage = (...args) => {
152
- const data = that.getData(...args);
153
- that.dispatchEvent(new MessageEvent('message', {
154
- data
155
- }));
156
- };
157
- that.onMessage(handleMessage);
158
- const handleClose = event => {
159
- that.dispatchEvent(new Event('close'));
160
- };
161
- that.onClose(handleClose);
83
+ const saveImageAs = () => {
84
+ return i18nString(SaveImageAs);
162
85
  };
163
- class Ipc extends EventTarget {
164
- constructor(rawIpc) {
165
- super();
166
- this._rawIpc = rawIpc;
167
- attachEvents(this);
168
- }
169
- }
170
- const E_INCOMPATIBLE_NATIVE_MODULE = 'E_INCOMPATIBLE_NATIVE_MODULE';
171
- const E_MODULES_NOT_SUPPORTED_IN_ELECTRON = 'E_MODULES_NOT_SUPPORTED_IN_ELECTRON';
172
- const ERR_MODULE_NOT_FOUND = 'ERR_MODULE_NOT_FOUND';
173
- const NewLine$1 = '\n';
174
- const joinLines$1 = lines => {
175
- return lines.join(NewLine$1);
86
+ const fileMatch = () => {
87
+ return i18nString(FileMatch);
176
88
  };
177
- const RE_AT = /^\s+at/;
178
- const RE_AT_PROMISE_INDEX = /^\s*at async Promise.all \(index \d+\)$/;
179
- const isNormalStackLine = line => {
180
- return RE_AT.test(line) && !RE_AT_PROMISE_INDEX.test(line);
89
+ const schema = () => {
90
+ return i18nString(Schema);
181
91
  };
182
- const getDetails = lines => {
183
- const index = lines.findIndex(isNormalStackLine);
184
- if (index === -1) {
185
- return {
186
- actualMessage: joinLines$1(lines),
187
- rest: []
188
- };
189
- }
190
- let lastIndex = index - 1;
191
- while (++lastIndex < lines.length) {
192
- if (!isNormalStackLine(lines[lastIndex])) {
193
- break;
194
- }
195
- }
196
- return {
197
- actualMessage: lines[index - 1],
198
- rest: lines.slice(index, lastIndex)
199
- };
92
+ const setColorTheme$3 = () => {
93
+ return i18nString(SetColorTheme$1);
200
94
  };
201
- const splitLines$1 = lines => {
202
- return lines.split(NewLine$1);
95
+ const theme = () => {
96
+ return i18nString(Theme$1);
203
97
  };
204
- const RE_MESSAGE_CODE_BLOCK_START = /^Error: The module '.*'$/;
205
- const RE_MESSAGE_CODE_BLOCK_END = /^\s* at/;
206
- const isMessageCodeBlockStartIndex = line => {
207
- return RE_MESSAGE_CODE_BLOCK_START.test(line);
98
+ const commands$1 = () => {
99
+ return i18nString(Commands$1);
208
100
  };
209
- const isMessageCodeBlockEndIndex = line => {
210
- return RE_MESSAGE_CODE_BLOCK_END.test(line);
101
+ const webViews = () => {
102
+ return i18nString(WebViews$1);
211
103
  };
212
- const getMessageCodeBlock = stderr => {
213
- const lines = splitLines$1(stderr);
214
- const startIndex = lines.findIndex(isMessageCodeBlockStartIndex);
215
- const endIndex = startIndex + lines.slice(startIndex).findIndex(isMessageCodeBlockEndIndex, startIndex);
216
- const relevantLines = lines.slice(startIndex, endIndex);
217
- const relevantMessage = relevantLines.join(' ').slice('Error: '.length);
218
- return relevantMessage;
104
+ const activationEvents = () => {
105
+ return i18nString(ActivationEvents$1);
219
106
  };
220
- const isModuleNotFoundMessage = line => {
221
- return line.includes('[ERR_MODULE_NOT_FOUND]');
107
+ const jsonValidation = () => {
108
+ return i18nString(JsonValidation$1);
222
109
  };
223
- const getModuleNotFoundError = stderr => {
224
- const lines = splitLines$1(stderr);
225
- const messageIndex = lines.findIndex(isModuleNotFoundMessage);
226
- const message = lines[messageIndex];
110
+ const programmingLanguages = () => {
111
+ return i18nString(ProgrammingLanguages$1);
112
+ };
113
+ const settings = () => {
114
+ return i18nString(Settings$1);
115
+ };
116
+ const id$1 = () => {
117
+ return i18nString(Id);
118
+ };
119
+ const selector = () => {
120
+ return i18nString(Selector);
121
+ };
122
+ const contentSecurityPolicy = () => {
123
+ return i18nString(ContentSecurityPolicy);
124
+ };
125
+ const elements = () => {
126
+ return i18nString(Elements);
127
+ };
128
+ const uninstall = () => {
129
+ return i18nString(Uninstall$1);
130
+ };
131
+ const scrollToTop = () => {
132
+ return i18nString(ScrollToTop$1);
133
+ };
134
+
135
+ const getActivationEventsDetails = async extension => {
136
+ const activationEvents = extension.activation || [];
227
137
  return {
228
- message,
229
- code: ERR_MODULE_NOT_FOUND
138
+ activationEvents
230
139
  };
231
140
  };
232
- const isModuleNotFoundError = stderr => {
233
- if (!stderr) {
234
- return false;
235
- }
236
- return stderr.includes('ERR_MODULE_NOT_FOUND');
237
- };
238
- const isModulesSyntaxError = stderr => {
239
- if (!stderr) {
141
+
142
+ const featureActivationEventsEnabled = extension => {
143
+ if (!extension || typeof extension !== 'object' || !('activation' in extension)) {
240
144
  return false;
241
145
  }
242
- return stderr.includes('SyntaxError: Cannot use import statement outside a module');
146
+ return Array.isArray(extension.activation);
243
147
  };
244
- const RE_NATIVE_MODULE_ERROR = /^innerError Error: Cannot find module '.*.node'/;
245
- const RE_NATIVE_MODULE_ERROR_2 = /was compiled against a different Node.js version/;
246
- const isUnhelpfulNativeModuleError = stderr => {
247
- return RE_NATIVE_MODULE_ERROR.test(stderr) && RE_NATIVE_MODULE_ERROR_2.test(stderr);
148
+
149
+ const Panel = 'panel';
150
+ const Tab$1 = 'tab';
151
+ const TabList = 'tablist';
152
+ const AriaRoles = {
153
+ __proto__: null,
154
+ Panel,
155
+ Tab: Tab$1,
156
+ TabList};
157
+ const mergeClassNames = (...classNames) => {
158
+ return classNames.filter(Boolean).join(' ');
248
159
  };
249
- const getNativeModuleErrorMessage = stderr => {
250
- const message = getMessageCodeBlock(stderr);
160
+ const Button$1 = 1;
161
+ const Div = 4;
162
+ const H1 = 5;
163
+ const Span = 8;
164
+ const Table$1 = 9;
165
+ const TBody = 10;
166
+ const Td = 11;
167
+ const Text$1 = 12;
168
+ const Th = 13;
169
+ const THead = 14;
170
+ const Tr = 15;
171
+ const Img = 17;
172
+ const H2 = 22;
173
+ const Dd = 43;
174
+ const Dl = 44;
175
+ const Li = 48;
176
+ const Pre = 51;
177
+ const A = 53;
178
+ const Ul = 60;
179
+ const Code$2 = 65;
180
+ const Dt = 67;
181
+ const VirtualDomElements = {
182
+ __proto__: null,
183
+ A,
184
+ Button: Button$1,
185
+ Code: Code$2,
186
+ Dd,
187
+ Div,
188
+ Dl,
189
+ Dt,
190
+ H1,
191
+ H2,
192
+ Img,
193
+ Li,
194
+ Pre,
195
+ Span,
196
+ TBody,
197
+ THead,
198
+ Table: Table$1,
199
+ Td,
200
+ Th,
201
+ Tr,
202
+ Ul};
203
+ const text = data => {
251
204
  return {
252
- message: `Incompatible native node module: ${message}`,
253
- code: E_INCOMPATIBLE_NATIVE_MODULE
205
+ type: Text$1,
206
+ text: data,
207
+ childCount: 0
254
208
  };
255
209
  };
256
- const getModuleSyntaxError = () => {
210
+
211
+ const AdditionalDetails = 'AdditionalDetails';
212
+ const AdditionalDetailsEntry = 'AdditionalDetailsEntry';
213
+ const AdditionalDetailsTitle = 'AdditionalDetailsTitle';
214
+ const Aside = 'Aside';
215
+ const Button = 'Button';
216
+ const ButtonPrimary = 'ButtonPrimary';
217
+ const Categories = 'Categories';
218
+ const Category = 'Category';
219
+ const Changelog$1 = 'Changelog';
220
+ const Code$1 = 'Code';
221
+ const DefaultMarkdown = 'DefaultMarkdown';
222
+ const DefinitionListItem = 'DefinitionListItem';
223
+ const DefinitionListItemHeading = 'DefinitionListItemHeading';
224
+ const DefinitionListItemValue = 'DefinitionListItemValue';
225
+ const ExtensionDetail = 'ExtensionDetail';
226
+ const ExtensionDetailDescription = 'ExtensionDetailDescription';
227
+ const ExtensionDetailHeader = 'ExtensionDetailHeader';
228
+ const ExtensionDetailHeaderActions = 'ExtensionDetailHeaderActions';
229
+ const ExtensionDetailHeaderDetails = 'ExtensionDetailHeaderDetails';
230
+ const ExtensionDetailIcon = 'ExtensionDetailIcon';
231
+ const ExtensionDetailName = 'ExtensionDetailName';
232
+ const ExtensionDetailNameBadge = 'ExtensionDetailNameBadge';
233
+ const ExtensionDetailPanel = 'ExtensionDetailPanel';
234
+ const ExtensionDetailTab = 'ExtensionDetailTab';
235
+ const ExtensionDetailTabs = 'ExtensionDetailTabs';
236
+ const ExtensionDetailTabSelected = 'ExtensionDetailTabSelected';
237
+ const Feature = 'Feature';
238
+ const FeatureContent = 'FeatureContent';
239
+ const Features$1 = 'Features';
240
+ const FeaturesList = 'FeaturesList';
241
+ const FeatureWebView = 'FeatureWebView';
242
+ const Large$1 = 'Large';
243
+ const Link = 'Link';
244
+ const MoreInfo = 'MoreInfo';
245
+ const MoreInfoEntry = 'MoreInfoEntry';
246
+ const MoreInfoEntryKey = 'MoreInfoEntryKey';
247
+ const MoreInfoEntryOdd = 'MoreInfoEntryOdd';
248
+ const MoreInfoEntryValue = 'MoreInfoEntryValue';
249
+ const Normal$1 = 'Normal';
250
+ const Resource = 'Resource';
251
+ const Resources = 'Resources';
252
+ const Sash = 'Sash';
253
+ const SashVertical = 'SashVertical';
254
+ const ScrollToTopButton = 'ScrollToTopButton';
255
+ const SettingsButton = 'SettingsButton';
256
+ const SettingsIcon = 'SettingsIcon';
257
+ const Small$1 = 'Small';
258
+ const Table = 'Table';
259
+ const TableCell = 'TableCell';
260
+ const TableHeading = 'TableHeading';
261
+ const Viewlet = 'Viewlet';
262
+
263
+ const getActivationEventVirtualDom = event => {
264
+ return [{
265
+ type: VirtualDomElements.Li,
266
+ childCount: 1
267
+ }, text(event)];
268
+ };
269
+
270
+ const getFeatureContentHeadingVirtualDom = heading => {
271
+ return [{
272
+ type: VirtualDomElements.H1,
273
+ childCount: 1
274
+ }, text(heading)];
275
+ };
276
+
277
+ const getFeatureActivationEventsVirtualDom = activationEvents$1 => {
278
+ const heading = activationEvents();
279
+ return [{
280
+ type: VirtualDomElements.Div,
281
+ className: FeatureContent,
282
+ childCount: 2
283
+ }, ...getFeatureContentHeadingVirtualDom(heading), {
284
+ type: VirtualDomElements.Ul,
285
+ childCount: activationEvents$1.length
286
+ }, ...activationEvents$1.flatMap(getActivationEventVirtualDom)];
287
+ };
288
+
289
+ const getActivationEventsVirtualDom = state => {
290
+ return getFeatureActivationEventsVirtualDom(state.activationEvents);
291
+ };
292
+
293
+ const Text = 1;
294
+ const Code = 2;
295
+
296
+ const getCommandTableEntry = command => {
297
+ // TODO watch out for command being null/undefined/number/string/array
298
+ const {
299
+ id,
300
+ label
301
+ } = command;
302
+ return [{
303
+ type: Code,
304
+ value: id
305
+ }, {
306
+ type: Text,
307
+ value: label
308
+ }];
309
+ };
310
+
311
+ const getCommandsDetails = async extension => {
312
+ const commands = extension.commands || [];
313
+ const rows = commands.map(getCommandTableEntry);
257
314
  return {
258
- message: `ES Modules are not supported in electron`,
259
- code: E_MODULES_NOT_SUPPORTED_IN_ELECTRON
315
+ commands: rows
260
316
  };
261
317
  };
262
- const getHelpfulChildProcessError = (stdout, stderr) => {
263
- if (isUnhelpfulNativeModuleError(stderr)) {
264
- return getNativeModuleErrorMessage(stderr);
265
- }
266
- if (isModulesSyntaxError(stderr)) {
267
- return getModuleSyntaxError();
268
- }
269
- if (isModuleNotFoundError(stderr)) {
270
- return getModuleNotFoundError(stderr);
318
+
319
+ const featureCommandsEnabled = extension => {
320
+ if (!extension || typeof extension !== 'object' || !('commands' in extension)) {
321
+ return false;
271
322
  }
272
- const lines = splitLines$1(stderr);
273
- const {
274
- actualMessage,
275
- rest
276
- } = getDetails(lines);
323
+ return Array.isArray(extension.commands);
324
+ };
325
+
326
+ const getCommandTableEntries = rows => {
327
+ const id = id$1();
328
+ const label$1 = label();
277
329
  return {
278
- message: actualMessage,
279
- code: '',
280
- stack: rest
330
+ headings: [id, label$1],
331
+ rows
281
332
  };
282
333
  };
283
- class IpcError extends VError {
284
- // @ts-ignore
285
- constructor(betterMessage, stdout = '', stderr = '') {
286
- if (stdout || stderr) {
287
- // @ts-ignore
288
- const {
289
- message,
290
- code,
291
- stack
292
- } = getHelpfulChildProcessError(stdout, stderr);
293
- const cause = new Error(message);
294
- // @ts-ignore
295
- cause.code = code;
296
- cause.stack = stack;
297
- super(cause, betterMessage);
298
- } else {
299
- super(betterMessage);
300
- }
301
- // @ts-ignore
302
- this.name = 'IpcError';
303
- // @ts-ignore
304
- this.stdout = stdout;
305
- // @ts-ignore
306
- this.stderr = stderr;
307
- }
308
- }
309
- const readyMessage = 'ready';
310
- const getData$2 = event => {
311
- return event.data;
334
+
335
+ const getTableHeadingVirtualDom = heading => {
336
+ return [{
337
+ type: VirtualDomElements.Th,
338
+ className: TableHeading,
339
+ childCount: 1
340
+ }, text(heading)];
312
341
  };
313
- const listen$7 = () => {
314
- // @ts-ignore
315
- if (typeof WorkerGlobalScope === 'undefined') {
316
- throw new TypeError('module is not in web worker scope');
317
- }
318
- return globalThis;
342
+
343
+ const getCellCodeVirtualDom = value => {
344
+ return [{
345
+ type: VirtualDomElements.Td,
346
+ className: TableCell,
347
+ childCount: 1
348
+ }, {
349
+ type: VirtualDomElements.Code,
350
+ childCount: 1
351
+ }, text(value)];
319
352
  };
320
- const signal$8 = global => {
321
- global.postMessage(readyMessage);
353
+
354
+ const getCellTextVirtualDom = value => {
355
+ return [{
356
+ type: VirtualDomElements.Td,
357
+ className: TableCell,
358
+ childCount: 1
359
+ }, text(value)];
322
360
  };
323
- class IpcChildWithModuleWorker extends Ipc {
324
- getData(event) {
325
- return getData$2(event);
326
- }
327
- send(message) {
328
- // @ts-ignore
329
- this._rawIpc.postMessage(message);
330
- }
331
- sendAndTransfer(message) {
332
- const transfer = getTransferrables(message);
333
- // @ts-ignore
334
- this._rawIpc.postMessage(message, transfer);
335
- }
336
- dispose() {
337
- // ignore
338
- }
339
- onClose(callback) {
340
- // ignore
341
- }
342
- onMessage(callback) {
343
- this._rawIpc.addEventListener('message', callback);
361
+
362
+ const getCellRenderer = type => {
363
+ switch (type) {
364
+ case Code:
365
+ return getCellCodeVirtualDom;
366
+ case Text:
367
+ return getCellTextVirtualDom;
368
+ default:
369
+ throw new Error(`unexpected cell type ${type}`);
344
370
  }
345
- }
346
- const wrap$f = global => {
347
- return new IpcChildWithModuleWorker(global);
348
371
  };
349
- const waitForFirstMessage = async port => {
372
+
373
+ const getCellVirtualDom = entry => {
350
374
  const {
351
- resolve,
352
- promise
353
- } = Promise.withResolvers();
354
- port.addEventListener('message', resolve, {
355
- once: true
356
- });
357
- const event = await promise;
358
- // @ts-ignore
359
- return event.data;
375
+ value,
376
+ type
377
+ } = entry;
378
+ const fn = getCellRenderer(type);
379
+ return fn(value);
360
380
  };
361
- const listen$6 = async () => {
362
- const parentIpcRaw = listen$7();
363
- signal$8(parentIpcRaw);
364
- const parentIpc = wrap$f(parentIpcRaw);
365
- const firstMessage = await waitForFirstMessage(parentIpc);
366
- if (firstMessage.method !== 'initialize') {
367
- throw new IpcError('unexpected first message');
368
- }
369
- const type = firstMessage.params[0];
370
- if (type === 'message-port') {
371
- parentIpc.send({
372
- jsonrpc: '2.0',
373
- id: firstMessage.id,
374
- result: null
375
- });
376
- parentIpc.dispose();
377
- const port = firstMessage.params[1];
378
- return port;
379
- }
380
- return globalThis;
381
+
382
+ const getTableRowVirtualDom = entries => {
383
+ return [{
384
+ type: VirtualDomElements.Tr,
385
+ childCount: entries.length
386
+ }, ...entries.flatMap(getCellVirtualDom)];
381
387
  };
382
- class IpcChildWithModuleWorkerAndMessagePort extends Ipc {
383
- getData(event) {
384
- return getData$2(event);
385
- }
386
- send(message) {
387
- this._rawIpc.postMessage(message);
388
- }
389
- sendAndTransfer(message) {
390
- const transfer = getTransferrables(message);
391
- this._rawIpc.postMessage(message, transfer);
392
- }
393
- dispose() {
394
- if (this._rawIpc.close) {
395
- this._rawIpc.close();
396
- }
388
+
389
+ const getTableVirtualDom = tableInfo => {
390
+ const {
391
+ headings,
392
+ rows
393
+ } = tableInfo;
394
+ return [{
395
+ type: VirtualDomElements.Table,
396
+ className: Table,
397
+ childCount: 2
398
+ }, {
399
+ type: VirtualDomElements.THead,
400
+ childCount: 1
401
+ }, {
402
+ type: VirtualDomElements.Tr,
403
+ childCount: headings.length
404
+ }, ...headings.flatMap(getTableHeadingVirtualDom), {
405
+ type: VirtualDomElements.TBody,
406
+ childCount: rows.length
407
+ }, ...rows.flatMap(getTableRowVirtualDom)];
408
+ };
409
+
410
+ // TODO have typed view-model
411
+ const getFeatureCommandsVirtualDom = commands => {
412
+ const heading = commands$1();
413
+ const tableInfo = getCommandTableEntries(commands);
414
+ return [{
415
+ type: VirtualDomElements.Div,
416
+ className: FeatureContent,
417
+ childCount: 2
418
+ }, ...getFeatureContentHeadingVirtualDom(heading), ...getTableVirtualDom(tableInfo)];
419
+ };
420
+
421
+ const getCommandsVirtualDom = state => {
422
+ return getFeatureCommandsVirtualDom(state.commands);
423
+ };
424
+
425
+ const getJsonValidationTableEntry = validation => {
426
+ const {
427
+ fileMatch,
428
+ schema
429
+ } = validation;
430
+ return [{
431
+ type: Code,
432
+ value: fileMatch
433
+ }, {
434
+ type: Code,
435
+ value: schema
436
+ }];
437
+ };
438
+
439
+ const getJsonValidationDetails = async extension => {
440
+ const validations = extension.jsonValidation || [];
441
+ const rows = validations.map(getJsonValidationTableEntry);
442
+ return {
443
+ jsonValidation: rows
444
+ };
445
+ };
446
+
447
+ const featureJsonValidationEnabled = extension => {
448
+ if (!extension || typeof extension !== 'object' || !('jsonValidation' in extension)) {
449
+ return false;
397
450
  }
398
- onClose(callback) {
399
- // ignore
451
+ return Array.isArray(extension.jsonValidation);
452
+ };
453
+
454
+ const getJsonValidationTableEntries = rows => {
455
+ return {
456
+ headings: [fileMatch(), schema()],
457
+ rows
458
+ };
459
+ };
460
+
461
+ const parentNode$1 = {
462
+ type: VirtualDomElements.Div,
463
+ className: FeatureContent,
464
+ childCount: 2
465
+ };
466
+ const getFeatureJsonValidationVirtualDom = jsonValidation$1 => {
467
+ const heading = jsonValidation();
468
+ const tableInfo = getJsonValidationTableEntries(jsonValidation$1);
469
+ return [parentNode$1, ...getFeatureContentHeadingVirtualDom(heading), ...getTableVirtualDom(tableInfo)];
470
+ };
471
+
472
+ const getJsonValidationVirtualDom = state => {
473
+ return getFeatureJsonValidationVirtualDom(state.jsonValidation);
474
+ };
475
+
476
+ const getProgrammingLanguagesDetails = async extension => {
477
+ // Programming languages feature doesn't need to store additional state
478
+ return {};
479
+ };
480
+
481
+ const featureProgrammingLanguagesEnabled = extension => {
482
+ if (!extension || typeof extension !== 'object' || !('programmingLanguages' in extension)) {
483
+ return false;
400
484
  }
401
- onMessage(callback) {
402
- this._rawIpc.addEventListener('message', callback);
403
- this._rawIpc.start();
485
+ const {
486
+ programmingLanguages
487
+ } = extension;
488
+ return Array.isArray(programmingLanguages);
489
+ };
490
+
491
+ const getFeatureProgrammingLanguagesVirtualDom = () => {
492
+ const heading = programmingLanguages();
493
+ // TODO
494
+ return [{
495
+ type: VirtualDomElements.Div,
496
+ className: FeatureContent,
497
+ childCount: 1
498
+ }, ...getFeatureContentHeadingVirtualDom(heading)];
499
+ };
500
+
501
+ const getProgrammingLanguagesVirtualDom = state => {
502
+ return getFeatureProgrammingLanguagesVirtualDom();
503
+ };
504
+
505
+ class FeatureNotFoundError extends Error {
506
+ constructor(featureName) {
507
+ super(`unknown feature: ${featureName}`);
508
+ this.name = 'FeatureNotFoundError';
404
509
  }
405
510
  }
406
- const wrap$e = port => {
407
- return new IpcChildWithModuleWorkerAndMessagePort(port);
511
+
512
+ const features = Object.create(null);
513
+ const register$1 = feature => {
514
+ features[feature.id] = feature;
408
515
  };
409
- const IpcChildWithModuleWorkerAndMessagePort$1 = {
410
- __proto__: null,
411
- listen: listen$6,
412
- wrap: wrap$e
516
+ const getFeatures = (selectedFeature, extension) => {
517
+ const allFeatures = Object.values(features);
518
+ const enabledFeatures = allFeatures.filter(item => item.isEnabled(extension));
519
+ const converted = enabledFeatures.map(item => {
520
+ return {
521
+ id: item.id,
522
+ label: item.getLabel(),
523
+ selected: item.id === selectedFeature
524
+ };
525
+ });
526
+ return converted;
413
527
  };
414
- const addListener = (emitter, type, callback) => {
415
- if ('addEventListener' in emitter) {
416
- emitter.addEventListener(type, callback);
417
- } else {
418
- emitter.on(type, callback);
528
+ const getFeatureDetailsHandler = featureName => {
529
+ const feature = features[featureName];
530
+ if (!feature) {
531
+ throw new FeatureNotFoundError(featureName);
419
532
  }
533
+ return feature.getDetails;
420
534
  };
421
- const removeListener = (emitter, type, callback) => {
422
- if ('removeEventListener' in emitter) {
423
- emitter.removeEventListener(type, callback);
424
- } else {
425
- emitter.off(type, callback);
535
+ const getFeatureVirtualDomHandler = featureName => {
536
+ const feature = features[featureName];
537
+ if (!feature) {
538
+ throw new FeatureNotFoundError(featureName);
426
539
  }
540
+ return feature.getVirtualDom;
427
541
  };
428
- const getFirstEvent = (eventEmitter, eventMap) => {
542
+
543
+ const getSettingsTableEntry = setting => {
429
544
  const {
430
- resolve,
431
- promise
432
- } = Promise.withResolvers();
433
- const listenerMap = Object.create(null);
434
- const cleanup = value => {
435
- for (const event of Object.keys(eventMap)) {
436
- removeListener(eventEmitter, event, listenerMap[event]);
437
- }
438
- resolve(value);
545
+ id,
546
+ label
547
+ } = setting;
548
+ // TODO watch out for null/undefined/number/string/array
549
+ return [{
550
+ type: Text,
551
+ value: id
552
+ }, {
553
+ type: Text,
554
+ value: label
555
+ }];
556
+ };
557
+
558
+ const getSettingsDetails = async extension => {
559
+ const settings = extension.settings || [];
560
+ const rows = settings.map(getSettingsTableEntry);
561
+ return {
562
+ settings: rows
439
563
  };
440
- for (const [event, type] of Object.entries(eventMap)) {
441
- const listener = event => {
442
- cleanup({
443
- type,
444
- event
445
- });
446
- };
447
- addListener(eventEmitter, event, listener);
448
- listenerMap[event] = listener;
449
- }
450
- return promise;
451
564
  };
452
- const Message$1 = 3;
453
- const create$5$1 = async ({
454
- messagePort,
455
- isMessagePortOpen
456
- }) => {
457
- if (!isMessagePort(messagePort)) {
458
- throw new IpcError('port must be of type MessagePort');
459
- }
460
- if (isMessagePortOpen) {
461
- return messagePort;
462
- }
463
- const eventPromise = getFirstEvent(messagePort, {
464
- message: Message$1
465
- });
466
- messagePort.start();
467
- const {
468
- type,
469
- event
470
- } = await eventPromise;
471
- if (type !== Message$1) {
472
- throw new IpcError('Failed to wait for ipc message');
473
- }
474
- if (event.data !== readyMessage) {
475
- throw new IpcError('unexpected first message');
565
+
566
+ const featureSettingsEnabled = extension => {
567
+ if (!extension || typeof extension !== 'object' || !('settings' in extension)) {
568
+ return false;
476
569
  }
477
- return messagePort;
570
+ return Array.isArray(extension.settings);
478
571
  };
479
- const signal$1 = messagePort => {
480
- messagePort.start();
572
+
573
+ const getSettingsTableEntries = rows => {
574
+ const textId = id$1();
575
+ const textLabel = label();
576
+ return {
577
+ headings: [textId, textLabel],
578
+ rows
579
+ };
481
580
  };
482
- class IpcParentWithMessagePort extends Ipc {
483
- getData = getData$2;
484
- send(message) {
485
- this._rawIpc.postMessage(message);
486
- }
487
- sendAndTransfer(message) {
488
- const transfer = getTransferrables(message);
489
- this._rawIpc.postMessage(message, transfer);
581
+
582
+ const getFeatureSettingsVirtualDom = rows => {
583
+ const heading = settings();
584
+ const tableInfo = getSettingsTableEntries(rows);
585
+ return [{
586
+ type: VirtualDomElements.Div,
587
+ className: FeatureContent,
588
+ childCount: 2
589
+ }, ...getFeatureContentHeadingVirtualDom(heading), ...getTableVirtualDom(tableInfo)];
590
+ };
591
+
592
+ const getSettingsVirtualDom = state => {
593
+ return getFeatureSettingsVirtualDom(state.settings);
594
+ };
595
+
596
+ class AssertionError extends Error {
597
+ constructor(message) {
598
+ super(message);
599
+ this.name = 'AssertionError';
490
600
  }
491
- dispose() {
492
- this._rawIpc.close();
601
+ }
602
+ const Object$1 = 1;
603
+ const Number$1 = 2;
604
+ const Array$1 = 3;
605
+ const String = 4;
606
+ const Boolean$1 = 5;
607
+ const Function = 6;
608
+ const Null = 7;
609
+ const Unknown = 8;
610
+ const getType = value => {
611
+ switch (typeof value) {
612
+ case 'number':
613
+ return Number$1;
614
+ case 'function':
615
+ return Function;
616
+ case 'string':
617
+ return String;
618
+ case 'object':
619
+ if (value === null) {
620
+ return Null;
621
+ }
622
+ if (Array.isArray(value)) {
623
+ return Array$1;
624
+ }
625
+ return Object$1;
626
+ case 'boolean':
627
+ return Boolean$1;
628
+ default:
629
+ return Unknown;
493
630
  }
494
- onMessage(callback) {
495
- this._rawIpc.addEventListener('message', callback);
631
+ };
632
+ const string = value => {
633
+ const type = getType(value);
634
+ if (type !== String) {
635
+ throw new AssertionError('expected value to be of type string');
496
636
  }
497
- onClose(callback) {}
498
- }
499
- const wrap$5 = messagePort => {
500
- return new IpcParentWithMessagePort(messagePort);
501
637
  };
502
- const IpcParentWithMessagePort$1 = {
503
- __proto__: null,
504
- create: create$5$1,
505
- signal: signal$1,
506
- wrap: wrap$5
638
+
639
+ const HandleClickCategory = 'handleClickCategory';
640
+ const HandleClickDisable = 'handleClickDisable';
641
+ const HandleClickScrollToTop = 'handleClickScrollToTop';
642
+ const HandleClickSetColorTheme = 'handleClickSetColorTheme';
643
+ const HandleClickSettings = 'handleClickSettings';
644
+ const HandleClickSize = 'handleClickSize';
645
+ const HandleClickUninstall = 'handleClickUninstall';
646
+ const HandleFeaturesClick = 'handleFeaturesClick';
647
+ const HandleIconError = 'handleIconError';
648
+ const HandleReadmeContextMenu = 'handleReadmeContextMenu';
649
+ const HandleReadmeWheel = 'handleReadmeWheel';
650
+ const HandleTabsClick = 'handleTabsClick';
651
+
652
+ const ActivationEvents = 'ActivationEvents';
653
+ const Changelog = 'Changelog';
654
+ const Commands = 'Commands';
655
+ const Details = 'Details';
656
+ const Disable = 'Disable';
657
+ const Features = 'Features';
658
+ const JsonValidation = 'JsonValidation';
659
+ const ProgrammingLanguages = 'ProgrammingLanguages';
660
+ const ScrollToTop = 'scrolltotop';
661
+ const SetColorTheme = 'SetColorTheme';
662
+ const Settings = 'Settings';
663
+ const Theme = 'Theme';
664
+ const Uninstall = 'Uninstall';
665
+ const WebViews = 'WebViews';
666
+
667
+ const getScrollToTopVirtualDom = scrollToTopButtonEnabled => {
668
+ return [{
669
+ type: VirtualDomElements.Button,
670
+ className: ScrollToTopButton,
671
+ childCount: 0,
672
+ onClick: HandleClickScrollToTop,
673
+ ariaLabel: scrollToTop(),
674
+ name: ScrollToTop
675
+ }];
507
676
  };
508
677
 
509
- const Two = '2.0';
510
- const create$4$1 = (method, params) => {
678
+ const rpcs = Object.create(null);
679
+ const set$g = (id, rpc) => {
680
+ rpcs[id] = rpc;
681
+ };
682
+ const get$2 = id => {
683
+ return rpcs[id];
684
+ };
685
+
686
+ /* eslint-disable @typescript-eslint/explicit-function-return-type */
687
+
688
+ const create$7 = rpcId => {
511
689
  return {
512
- jsonrpc: Two,
513
- method,
514
- params
690
+ // @ts-ignore
691
+ invoke(method, ...params) {
692
+ const rpc = get$2(rpcId);
693
+ // @ts-ignore
694
+ return rpc.invoke(method, ...params);
695
+ },
696
+ // @ts-ignore
697
+ invokeAndTransfer(method, ...params) {
698
+ const rpc = get$2(rpcId);
699
+ // @ts-ignore
700
+ return rpc.invokeAndTransfer(method, ...params);
701
+ },
702
+ set(rpc) {
703
+ set$g(rpcId, rpc);
704
+ },
705
+ async dispose() {
706
+ const rpc = get$2(rpcId);
707
+ await rpc.dispose();
708
+ }
515
709
  };
516
710
  };
517
- const callbacks = Object.create(null);
518
- const set$4 = (id, fn) => {
519
- callbacks[id] = fn;
711
+ const RendererWorker$1 = 1;
712
+ const MarkdownWorker$1 = 300;
713
+ const {
714
+ invoke: invoke$5,
715
+ set: set$5} = create$7(MarkdownWorker$1);
716
+ const getVirtualDom$1 = async html => {
717
+ // @ts-ignore
718
+ return invoke$5('Markdown.getVirtualDom', html);
520
719
  };
521
- const get$2 = id => {
522
- return callbacks[id];
720
+ const render$1 = async (markdown, options) => {
721
+ // @ts-ignore
722
+ return invoke$5('Markdown.render', markdown, options);
523
723
  };
524
- const remove = id => {
525
- delete callbacks[id];
724
+ const MarkdownWorker = {
725
+ __proto__: null,
726
+ getVirtualDom: getVirtualDom$1,
727
+ render: render$1,
728
+ set: set$5
526
729
  };
527
- let id$1 = 0;
528
- const create$3$1 = () => {
529
- return ++id$1;
730
+ const {
731
+ invoke: invoke$3,
732
+ invokeAndTransfer: invokeAndTransfer$3,
733
+ set: set$3$1} = create$7(RendererWorker$1);
734
+ const setColorTheme$2 = async id => {
735
+ // @ts-ignore
736
+ return invoke$3(/* ColorTheme.setColorTheme */'ColorTheme.setColorTheme', /* colorThemeId */id);
530
737
  };
531
- const registerPromise = () => {
532
- const id = create$3$1();
533
- const {
534
- resolve,
535
- promise
536
- } = Promise.withResolvers();
537
- set$4(id, resolve);
538
- return {
539
- id,
540
- promise
541
- };
738
+ const sendMessagePortToMarkdownWorker$2 = async (port, rpcId) => {
739
+ const command = 'Markdown.handleMessagePort';
740
+ // @ts-ignore
741
+ await invokeAndTransfer$3('SendMessagePortToExtensionHostWorker.sendMessagePortToMarkdownWorker', port, command, rpcId);
542
742
  };
543
- const create$2$1 = (method, params) => {
544
- const {
545
- id,
546
- promise
547
- } = registerPromise();
548
- const message = {
549
- jsonrpc: Two,
550
- method,
551
- params,
552
- id
553
- };
554
- return {
555
- message,
556
- promise
557
- };
558
- };
559
- class JsonRpcError extends Error {
560
- constructor(message) {
561
- super(message);
562
- this.name = 'JsonRpcError';
563
- }
564
- }
565
- const NewLine = '\n';
566
- const DomException = 'DOMException';
567
- const ReferenceError$1 = 'ReferenceError';
568
- const SyntaxError$1 = 'SyntaxError';
569
- const TypeError$1 = 'TypeError';
570
- const getErrorConstructor = (message, type) => {
571
- if (type) {
572
- switch (type) {
573
- case DomException:
574
- return DOMException;
575
- case TypeError$1:
576
- return TypeError;
577
- case SyntaxError$1:
578
- return SyntaxError;
579
- case ReferenceError$1:
580
- return ReferenceError;
581
- default:
582
- return Error;
583
- }
584
- }
585
- if (message.startsWith('TypeError: ')) {
586
- return TypeError;
587
- }
588
- if (message.startsWith('SyntaxError: ')) {
589
- return SyntaxError;
590
- }
591
- if (message.startsWith('ReferenceError: ')) {
592
- return ReferenceError;
593
- }
594
- return Error;
743
+ const readFile$2 = async uri => {
744
+ return invoke$3('FileSystem.readFile', uri);
595
745
  };
596
- const constructError = (message, type, name) => {
597
- const ErrorConstructor = getErrorConstructor(message, type);
598
- if (ErrorConstructor === DOMException && name) {
599
- return new ErrorConstructor(message, name);
600
- }
601
- if (ErrorConstructor === Error) {
602
- const error = new Error(message);
603
- if (name && name !== 'VError') {
604
- error.name = name;
605
- }
606
- return error;
607
- }
608
- return new ErrorConstructor(message);
746
+ const getAllExtensions$2 = async () => {
747
+ return invoke$3('ExtensionManagement.getAllExtensions');
609
748
  };
610
- const joinLines = lines => {
611
- return lines.join(NewLine);
749
+ const getFolderSize$2 = async uri => {
750
+ // @ts-ignore
751
+ return await invoke$3('FileSystem.getFolderSize', uri);
612
752
  };
613
- const splitLines = lines => {
614
- return lines.split(NewLine);
753
+ const getExtension$3 = async id => {
754
+ // @ts-ignore
755
+ return invoke$3('ExtensionManagement.getExtension', id);
615
756
  };
616
- const getCurrentStack = () => {
617
- const currentStack = joinLines(splitLines(new Error().stack || '').slice(2));
618
- return currentStack;
757
+ const openNativeFolder$1 = async uri => {
758
+ // @ts-ignore
759
+ await invoke$3('OpenNativeFolder.openNativeFolder', uri);
619
760
  };
620
- const getNewLineIndex = (string, startIndex = undefined) => {
621
- return string.indexOf(NewLine, startIndex);
761
+ const uninstallExtension$1 = async id => {
762
+ return invoke$3('ExtensionManagement.uninstall', id);
622
763
  };
623
- const getParentStack = error => {
624
- let parentStack = error.stack || error.data || error.message || '';
625
- if (parentStack.startsWith(' at')) {
626
- parentStack = error.message + NewLine + parentStack;
764
+ const RendererWorker = {
765
+ __proto__: null,
766
+ getAllExtensions: getAllExtensions$2,
767
+ getExtension: getExtension$3,
768
+ getFolderSize: getFolderSize$2,
769
+ openNativeFolder: openNativeFolder$1,
770
+ readFile: readFile$2,
771
+ sendMessagePortToMarkdownWorker: sendMessagePortToMarkdownWorker$2,
772
+ set: set$3$1,
773
+ setColorTheme: setColorTheme$2,
774
+ uninstallExtension: uninstallExtension$1};
775
+
776
+ const {
777
+ set: set$3,
778
+ getVirtualDom,
779
+ render
780
+ } = MarkdownWorker;
781
+
782
+ const getMarkdownVirtualDom = async (html, options) => {
783
+ string(html);
784
+ const dom = await getVirtualDom(html);
785
+ const newDom = [...dom];
786
+ if (options?.scrollToTopEnabled) {
787
+ newDom[0].childCount++;
788
+ const extraDom = getScrollToTopVirtualDom();
789
+ newDom.splice(1, 0, ...extraDom);
627
790
  }
628
- return parentStack;
791
+ return newDom;
629
792
  };
630
- const MethodNotFound = -32601;
631
- const Custom = -32001;
632
- const restoreJsonRpcError = error => {
633
- const currentStack = getCurrentStack();
634
- if (error && error instanceof Error) {
635
- if (typeof error.stack === 'string') {
636
- error.stack = error.stack + NewLine + currentStack;
637
- }
638
- return error;
639
- }
640
- if (error && error.code && error.code === MethodNotFound) {
641
- const restoredError = new JsonRpcError(error.message);
642
- const parentStack = getParentStack(error);
643
- restoredError.stack = parentStack + NewLine + currentStack;
644
- return restoredError;
645
- }
646
- if (error && error.message) {
647
- const restoredError = constructError(error.message, error.type, error.name);
648
- if (error.data) {
649
- if (error.data.stack && error.data.type && error.message) {
650
- restoredError.stack = error.data.type + ': ' + error.message + NewLine + error.data.stack + NewLine + currentStack;
651
- } else if (error.data.stack) {
652
- restoredError.stack = error.data.stack;
653
- }
654
- if (error.data.codeFrame) {
655
- // @ts-ignore
656
- restoredError.codeFrame = error.data.codeFrame;
657
- }
658
- if (error.data.code) {
659
- // @ts-ignore
660
- restoredError.code = error.data.code;
661
- }
662
- if (error.data.type) {
663
- // @ts-ignore
664
- restoredError.name = error.data.type;
665
- }
666
- } else {
667
- if (error.stack) {
668
- const lowerStack = restoredError.stack || '';
669
- // @ts-ignore
670
- const indexNewLine = getNewLineIndex(lowerStack);
671
- const parentStack = getParentStack(error);
672
- // @ts-ignore
673
- restoredError.stack = parentStack + lowerStack.slice(indexNewLine);
674
- }
675
- if (error.codeFrame) {
676
- // @ts-ignore
677
- restoredError.codeFrame = error.codeFrame;
678
- }
793
+
794
+ const getThemeItemMarkdown = (heading, items) => {
795
+ let markdown = '';
796
+ if (items.length > 0) {
797
+ markdown += `### ${heading}`;
798
+ markdown += '\n\n';
799
+ for (const item of items) {
800
+ markdown += `- ${item.label}`;
801
+ markdown += '\n';
679
802
  }
680
- return restoredError;
681
- }
682
- if (typeof error === 'string') {
683
- return new Error(`JsonRpc Error: ${error}`);
684
803
  }
685
- return new Error(`JsonRpc Error: ${error}`);
804
+ return markdown;
686
805
  };
687
- const unwrapJsonRpcResult = responseMessage => {
688
- if ('error' in responseMessage) {
689
- const restoredError = restoreJsonRpcError(responseMessage.error);
690
- throw restoredError;
691
- }
692
- if ('result' in responseMessage) {
693
- return responseMessage.result;
694
- }
695
- throw new JsonRpcError('unexpected response message');
806
+
807
+ const getColorThemeMarkdown = themes => {
808
+ const heading = 'Color Themes';
809
+ return getThemeItemMarkdown(heading, themes);
696
810
  };
697
- const warn = (...args) => {
698
- console.warn(...args);
811
+ const getIconThemeMarkdown = iconThemes => {
812
+ const heading = 'File Icon Themes';
813
+ return getThemeItemMarkdown(heading, iconThemes);
699
814
  };
700
- const resolve = (id, response) => {
701
- const fn = get$2(id);
702
- if (!fn) {
703
- console.log(response);
704
- warn(`callback ${id} may already be disposed`);
705
- return;
706
- }
707
- fn(response);
708
- remove(id);
815
+ const getProductIconThemeMarkdown = iconThemes => {
816
+ const heading = 'Product Icon Themes';
817
+ return getThemeItemMarkdown(heading, iconThemes);
709
818
  };
710
- const E_COMMAND_NOT_FOUND = 'E_COMMAND_NOT_FOUND';
711
- const getErrorType = prettyError => {
712
- if (prettyError && prettyError.type) {
713
- return prettyError.type;
714
- }
715
- if (prettyError && prettyError.constructor && prettyError.constructor.name) {
716
- return prettyError.constructor.name;
819
+ const getThemeMarkdown = (themes, iconThemes, productIconThemes) => {
820
+ let markdown = '';
821
+ markdown += getColorThemeMarkdown(themes);
822
+ markdown += getIconThemeMarkdown(iconThemes);
823
+ markdown += getProductIconThemeMarkdown(productIconThemes);
824
+ return markdown;
825
+ };
826
+
827
+ const renderMarkdown = async (markdown, options = {}) => {
828
+ const html = await render(markdown, options);
829
+ return html;
830
+ };
831
+
832
+ const getThemeDetails = async (extension, baseUrl) => {
833
+ const {
834
+ colorThemes,
835
+ iconThemes,
836
+ productIconThemes
837
+ } = extension;
838
+ const markdown = getThemeMarkdown(colorThemes || [], iconThemes || [], productIconThemes || []);
839
+ const rendered = await renderMarkdown(markdown, {
840
+ baseUrl
841
+ });
842
+ const themesMarkdownDom = await getMarkdownVirtualDom(rendered);
843
+ return {
844
+ themesMarkdownDom
845
+ };
846
+ };
847
+
848
+ const featureColorThemeEnabled = extension => {
849
+ if (!extension || typeof extension !== 'object' || !('colorThemes' in extension)) {
850
+ return false;
717
851
  }
718
- return undefined;
852
+ return Array.isArray(extension.colorThemes);
719
853
  };
720
- const isAlreadyStack = line => {
721
- return line.trim().startsWith('at ');
854
+
855
+ const featureIconThemeEnabled = extension => {
856
+ if (!extension || typeof extension !== 'object' || !('iconThemes' in extension)) {
857
+ return false;
858
+ }
859
+ return Array.isArray(extension.iconThemes);
722
860
  };
723
- const getStack = prettyError => {
724
- const stackString = prettyError.stack || '';
725
- const newLineIndex = stackString.indexOf('\n');
726
- if (newLineIndex !== -1 && !isAlreadyStack(stackString.slice(0, newLineIndex))) {
727
- return stackString.slice(newLineIndex + 1);
861
+
862
+ const featureProductIconThemeEnabled = extension => {
863
+ if (!extension || typeof extension !== 'object' || !('productIconThemes' in extension)) {
864
+ return false;
728
865
  }
729
- return stackString;
866
+ return Array.isArray(extension.productIconThemes);
730
867
  };
731
- const getErrorProperty = (error, prettyError) => {
732
- if (error && error.code === E_COMMAND_NOT_FOUND) {
733
- return {
734
- code: MethodNotFound,
735
- message: error.message,
736
- data: error.stack
737
- };
738
- }
739
- return {
740
- code: Custom,
741
- message: prettyError.message,
742
- data: {
743
- stack: getStack(prettyError),
744
- codeFrame: prettyError.codeFrame,
745
- type: getErrorType(prettyError),
746
- code: prettyError.code,
747
- name: prettyError.name
868
+
869
+ const featureThemeEnabled = extension => {
870
+ return featureColorThemeEnabled(extension) || featureIconThemeEnabled(extension) || featureProductIconThemeEnabled(extension);
871
+ };
872
+
873
+ const getVirtualDomChildCount = dom => {
874
+ const max = dom.length - 1;
875
+ let stack = [];
876
+ for (let i = max; i >= 0; i--) {
877
+ const element = dom[i];
878
+ if (element.childCount > 0) {
879
+ stack = stack.slice(element.childCount);
748
880
  }
749
- };
881
+ stack.unshift(element);
882
+ }
883
+ return stack.length;
750
884
  };
751
- const create$1$1 = (id, error) => {
752
- return {
753
- jsonrpc: Two,
754
- id,
755
- error
756
- };
885
+
886
+ const getFeatureThemesVirtualDom = themesDom => {
887
+ const childCount = getVirtualDomChildCount(themesDom);
888
+ const heading = theme();
889
+ return [{
890
+ type: VirtualDomElements.Div,
891
+ className: FeatureContent,
892
+ childCount: 2
893
+ }, ...getFeatureContentHeadingVirtualDom(heading), {
894
+ type: VirtualDomElements.Div,
895
+ className: DefaultMarkdown,
896
+ childCount
897
+ }, ...themesDom];
757
898
  };
758
- const getErrorResponse = (id, error, preparePrettyError, logError) => {
759
- const prettyError = preparePrettyError(error);
760
- logError(error, prettyError);
761
- const errorProperty = getErrorProperty(error, prettyError);
762
- return create$1$1(id, errorProperty);
899
+
900
+ const getThemeVirtualDom = state => {
901
+ return getFeatureThemesVirtualDom(state.themesMarkdownDom);
763
902
  };
764
- const create$6 = (message, result) => {
903
+
904
+ const toWebView = rawWebView => {
905
+ const {
906
+ id,
907
+ selector,
908
+ contentSecurityPolicy,
909
+ elements
910
+ } = rawWebView;
765
911
  return {
766
- jsonrpc: Two,
767
- id: message.id,
768
- result: result ?? null
912
+ id,
913
+ selectorString: JSON.stringify(selector),
914
+ contentSecurityPolicyString: JSON.stringify(contentSecurityPolicy),
915
+ elementsString: JSON.stringify(elements, null, 2)
769
916
  };
770
917
  };
771
- const getSuccessResponse = (message, result) => {
772
- const resultProperty = result ?? null;
773
- return create$6(message, resultProperty);
918
+
919
+ const getWebViews = extension => {
920
+ const rawWebViews = extension.webViews || [];
921
+ return rawWebViews.map(toWebView);
774
922
  };
775
- const getErrorResponseSimple = (id, error) => {
923
+
924
+ const getWebViewsDetails = async extension => {
925
+ const webViews = getWebViews(extension);
776
926
  return {
777
- jsonrpc: Two,
778
- id,
779
- error: {
780
- code: Custom,
781
- // @ts-ignore
782
- message: error.message,
783
- data: error
784
- }
927
+ webViews
785
928
  };
786
929
  };
787
- const getResponse = async (message, ipc, execute, preparePrettyError, logError, requiresSocket) => {
788
- try {
789
- const result = requiresSocket(message.method) ? await execute(message.method, ipc, ...message.params) : await execute(message.method, ...message.params);
790
- return getSuccessResponse(message, result);
791
- } catch (error) {
792
- if (ipc.canUseSimpleErrorResponse) {
793
- return getErrorResponseSimple(message.id, error);
794
- }
795
- return getErrorResponse(message.id, error, preparePrettyError, logError);
930
+
931
+ const featureWebViewsEnabled = extension => {
932
+ if (!extension || typeof extension !== 'object' || !('webViews' in extension)) {
933
+ return false;
796
934
  }
935
+ return Array.isArray(extension.webViews);
797
936
  };
798
- const defaultPreparePrettyError = error => {
799
- return error;
800
- };
801
- const defaultLogError = () => {
802
- // ignore
803
- };
804
- const defaultRequiresSocket = () => {
805
- return false;
806
- };
807
- const defaultResolve = resolve;
808
937
 
809
- // TODO maybe remove this in v6 or v7, only accept options object to simplify the code
810
- const normalizeParams = args => {
811
- if (args.length === 1) {
812
- const options = args[0];
813
- return {
814
- ipc: options.ipc,
815
- message: options.message,
816
- execute: options.execute,
817
- resolve: options.resolve || defaultResolve,
818
- preparePrettyError: options.preparePrettyError || defaultPreparePrettyError,
819
- logError: options.logError || defaultLogError,
820
- requiresSocket: options.requiresSocket || defaultRequiresSocket
821
- };
822
- }
823
- return {
824
- ipc: args[0],
825
- message: args[1],
826
- execute: args[2],
827
- resolve: args[3],
828
- preparePrettyError: args[4],
829
- logError: args[5],
830
- requiresSocket: args[6]
831
- };
938
+ const heading = {
939
+ type: VirtualDomElements.H2,
940
+ className: DefinitionListItemHeading,
941
+ childCount: 1
832
942
  };
833
- const handleJsonRpcMessage = async (...args) => {
834
- const options = normalizeParams(args);
835
- const {
836
- message,
837
- ipc,
838
- execute,
839
- resolve,
840
- preparePrettyError,
841
- logError,
842
- requiresSocket
843
- } = options;
844
- if ('id' in message) {
845
- if ('method' in message) {
846
- const response = await getResponse(message, ipc, execute, preparePrettyError, logError, requiresSocket);
847
- try {
848
- ipc.send(response);
849
- } catch (error) {
850
- const errorResponse = getErrorResponse(message.id, error, preparePrettyError, logError);
851
- ipc.send(errorResponse);
852
- }
853
- return;
854
- }
855
- resolve(message.id, message);
856
- return;
857
- }
858
- if ('method' in message) {
859
- await getResponse(message, ipc, execute, preparePrettyError, logError, requiresSocket);
860
- return;
861
- }
862
- throw new JsonRpcError('unexpected message');
943
+ const pre = {
944
+ type: VirtualDomElements.Pre,
945
+ className: DefinitionListItemValue,
946
+ childCount: 1
863
947
  };
864
- const invokeHelper = async (ipc, method, params, useSendAndTransfer) => {
865
- const {
866
- message,
867
- promise
868
- } = create$2$1(method, params);
869
- if (useSendAndTransfer && ipc.sendAndTransfer) {
870
- ipc.sendAndTransfer(message);
871
- } else {
872
- ipc.send(message);
873
- }
874
- const responseMessage = await promise;
875
- return unwrapJsonRpcResult(responseMessage);
948
+ const item = {
949
+ type: VirtualDomElements.Div,
950
+ className: DefinitionListItem,
951
+ childCount: 2
876
952
  };
877
- const send = (transport, method, ...params) => {
878
- const message = create$4$1(method, params);
879
- transport.send(message);
953
+ const getWebViewVirtualDom = webView => {
954
+ const {
955
+ id,
956
+ selectorString,
957
+ contentSecurityPolicyString,
958
+ elementsString
959
+ } = webView;
960
+ const textId = id$1();
961
+ const textSelector = selector();
962
+ const textContentSecurityPolicy = contentSecurityPolicy();
963
+ const textElements = elements();
964
+ return [{
965
+ type: VirtualDomElements.Div,
966
+ className: FeatureWebView,
967
+ childCount: 5
968
+ }, item, heading, text(textId), pre, text(id), item, heading, text(textSelector), pre, text(selectorString), item, heading, text(textContentSecurityPolicy), pre, text(contentSecurityPolicyString), item, heading, text(textElements), pre, text(elementsString)];
880
969
  };
881
- const invoke = (ipc, method, ...params) => {
882
- return invokeHelper(ipc, method, params, false);
970
+
971
+ const getFeatureWebViewsVirtualDom = webViews$1 => {
972
+ const heading = webViews();
973
+ return [{
974
+ type: VirtualDomElements.Div,
975
+ className: FeatureContent,
976
+ childCount: 2
977
+ }, ...getFeatureContentHeadingVirtualDom(heading), {
978
+ type: VirtualDomElements.Div,
979
+ childCount: webViews$1.length
980
+ }, ...webViews$1.flatMap(getWebViewVirtualDom)];
883
981
  };
884
- const invokeAndTransfer = (ipc, method, ...params) => {
885
- return invokeHelper(ipc, method, params, true);
982
+
983
+ const getWebViewsVirtualDom = state => {
984
+ return getFeatureWebViewsVirtualDom(state.webViews);
886
985
  };
887
986
 
888
- const commands$1 = Object.create(null);
889
- const register = commandMap => {
890
- Object.assign(commands$1, commandMap);
987
+ const registerAllFeatures = () => {
988
+ register$1({
989
+ id: Theme,
990
+ getLabel: theme,
991
+ isEnabled: featureThemeEnabled,
992
+ getDetails: getThemeDetails,
993
+ getVirtualDom: getThemeVirtualDom
994
+ });
995
+ register$1({
996
+ id: Commands,
997
+ getLabel: commands$1,
998
+ isEnabled: featureCommandsEnabled,
999
+ getDetails: getCommandsDetails,
1000
+ getVirtualDom: getCommandsVirtualDom
1001
+ });
1002
+ register$1({
1003
+ id: Settings,
1004
+ getLabel: settings,
1005
+ isEnabled: featureSettingsEnabled,
1006
+ getDetails: getSettingsDetails,
1007
+ getVirtualDom: getSettingsVirtualDom
1008
+ });
1009
+ register$1({
1010
+ id: JsonValidation,
1011
+ getLabel: jsonValidation,
1012
+ isEnabled: featureJsonValidationEnabled,
1013
+ getDetails: getJsonValidationDetails,
1014
+ getVirtualDom: getJsonValidationVirtualDom
1015
+ });
1016
+ register$1({
1017
+ id: ProgrammingLanguages,
1018
+ getLabel: programmingLanguages,
1019
+ isEnabled: featureProgrammingLanguagesEnabled,
1020
+ getDetails: getProgrammingLanguagesDetails,
1021
+ getVirtualDom: getProgrammingLanguagesVirtualDom
1022
+ });
1023
+ register$1({
1024
+ id: WebViews,
1025
+ getLabel: webViews,
1026
+ isEnabled: featureWebViewsEnabled,
1027
+ getDetails: getWebViewsDetails,
1028
+ getVirtualDom: getWebViewsVirtualDom
1029
+ });
1030
+ register$1({
1031
+ id: ActivationEvents,
1032
+ getLabel: activationEvents,
1033
+ isEnabled: featureActivationEventsEnabled,
1034
+ getDetails: getActivationEventsDetails,
1035
+ getVirtualDom: getActivationEventsVirtualDom
1036
+ });
891
1037
  };
892
- const getCommand = key => {
893
- return commands$1[key];
1038
+
1039
+ const normalizeLine = line => {
1040
+ if (line.startsWith('Error: ')) {
1041
+ return line.slice('Error: '.length);
1042
+ }
1043
+ if (line.startsWith('VError: ')) {
1044
+ return line.slice('VError: '.length);
1045
+ }
1046
+ return line;
894
1047
  };
895
- const execute = (command, ...args) => {
896
- const fn = getCommand(command);
897
- if (!fn) {
898
- throw new Error(`command not found ${command}`);
1048
+ const getCombinedMessage = (error, message) => {
1049
+ const stringifiedError = normalizeLine(`${error}`);
1050
+ if (message) {
1051
+ return `${message}: ${stringifiedError}`;
899
1052
  }
900
- return fn(...args);
1053
+ return stringifiedError;
901
1054
  };
902
-
903
- const createRpc = ipc => {
904
- const rpc = {
905
- // @ts-ignore
906
- ipc,
907
- /**
908
- * @deprecated
909
- */
910
- send(method, ...params) {
911
- send(ipc, method, ...params);
912
- },
913
- invoke(method, ...params) {
914
- return invoke(ipc, method, ...params);
915
- },
916
- invokeAndTransfer(method, ...params) {
917
- return invokeAndTransfer(ipc, method, ...params);
918
- },
919
- async dispose() {
920
- await ipc?.dispose();
1055
+ const NewLine$2 = '\n';
1056
+ const getNewLineIndex$1 = (string, startIndex = undefined) => {
1057
+ return string.indexOf(NewLine$2, startIndex);
1058
+ };
1059
+ const mergeStacks = (parent, child) => {
1060
+ if (!child) {
1061
+ return parent;
1062
+ }
1063
+ const parentNewLineIndex = getNewLineIndex$1(parent);
1064
+ const childNewLineIndex = getNewLineIndex$1(child);
1065
+ if (childNewLineIndex === -1) {
1066
+ return parent;
1067
+ }
1068
+ const parentFirstLine = parent.slice(0, parentNewLineIndex);
1069
+ const childRest = child.slice(childNewLineIndex);
1070
+ const childFirstLine = normalizeLine(child.slice(0, childNewLineIndex));
1071
+ if (parentFirstLine.includes(childFirstLine)) {
1072
+ return parentFirstLine + childRest;
1073
+ }
1074
+ return child;
1075
+ };
1076
+ class VError extends Error {
1077
+ constructor(error, message) {
1078
+ const combinedMessage = getCombinedMessage(error, message);
1079
+ super(combinedMessage);
1080
+ this.name = 'VError';
1081
+ if (error instanceof Error) {
1082
+ this.stack = mergeStacks(this.stack, error.stack);
921
1083
  }
922
- };
923
- return rpc;
1084
+ if (error.codeFrame) {
1085
+ // @ts-ignore
1086
+ this.codeFrame = error.codeFrame;
1087
+ }
1088
+ if (error.code) {
1089
+ // @ts-ignore
1090
+ this.code = error.code;
1091
+ }
1092
+ }
1093
+ }
1094
+
1095
+ const isMessagePort = value => {
1096
+ return value && value instanceof MessagePort;
924
1097
  };
925
- const requiresSocket = () => {
926
- return false;
1098
+ const isMessagePortMain = value => {
1099
+ return value && value.constructor && value.constructor.name === 'MessagePortMain';
927
1100
  };
928
- const preparePrettyError = error => {
929
- return error;
1101
+ const isOffscreenCanvas = value => {
1102
+ return typeof OffscreenCanvas !== 'undefined' && value instanceof OffscreenCanvas;
930
1103
  };
931
- const logError = () => {
932
- // handled by renderer worker
1104
+ const isInstanceOf = (value, constructorName) => {
1105
+ return value?.constructor?.name === constructorName;
933
1106
  };
934
- const handleMessage = event => {
935
- const actualRequiresSocket = event?.target?.requiresSocket || requiresSocket;
936
- const actualExecute = event?.target?.execute || execute;
937
- return handleJsonRpcMessage(event.target, event.data, actualExecute, resolve, preparePrettyError, logError, actualRequiresSocket);
1107
+ const isSocket = value => {
1108
+ return isInstanceOf(value, 'Socket');
938
1109
  };
939
- const handleIpc = ipc => {
940
- if ('addEventListener' in ipc) {
941
- ipc.addEventListener('message', handleMessage);
942
- } else if ('on' in ipc) {
943
- // deprecated
944
- ipc.on('message', handleMessage);
1110
+ const transferrables = [isMessagePort, isMessagePortMain, isOffscreenCanvas, isSocket];
1111
+ const isTransferrable = value => {
1112
+ for (const fn of transferrables) {
1113
+ if (fn(value)) {
1114
+ return true;
1115
+ }
945
1116
  }
1117
+ return false;
946
1118
  };
947
- const listen$1 = async (module, options) => {
948
- const rawIpc = await module.listen(options);
949
- if (module.signal) {
950
- module.signal(rawIpc);
1119
+ const walkValue = (value, transferrables, isTransferrable) => {
1120
+ if (!value) {
1121
+ return;
1122
+ }
1123
+ if (isTransferrable(value)) {
1124
+ transferrables.push(value);
1125
+ return;
1126
+ }
1127
+ if (Array.isArray(value)) {
1128
+ for (const item of value) {
1129
+ walkValue(item, transferrables, isTransferrable);
1130
+ }
1131
+ return;
1132
+ }
1133
+ if (typeof value === 'object') {
1134
+ for (const property of Object.values(value)) {
1135
+ walkValue(property, transferrables, isTransferrable);
1136
+ }
1137
+ return;
951
1138
  }
952
- const ipc = module.wrap(rawIpc);
953
- return ipc;
954
- };
955
- const create$5 = async ({
956
- commandMap,
957
- messagePort
958
- }) => {
959
- // TODO create a commandMap per rpc instance
960
- register(commandMap);
961
- const rawIpc = await IpcParentWithMessagePort$1.create({
962
- messagePort,
963
- isMessagePortOpen: true
964
- });
965
- const ipc = IpcParentWithMessagePort$1.wrap(rawIpc);
966
- handleIpc(ipc);
967
- const rpc = createRpc(ipc);
968
- messagePort.start();
969
- return rpc;
970
1139
  };
971
- const create$3 = async ({
972
- commandMap,
973
- send
974
- }) => {
975
- const {
976
- port1,
977
- port2
978
- } = new MessageChannel();
979
- await send(port1);
980
- return create$5({
981
- commandMap,
982
- messagePort: port2
983
- });
1140
+ const getTransferrables = value => {
1141
+ const transferrables = [];
1142
+ walkValue(value, transferrables, isTransferrable);
1143
+ return transferrables;
984
1144
  };
985
- const TransferMessagePortRpcParent = {
986
- __proto__: null,
987
- create: create$3
1145
+ const attachEvents = that => {
1146
+ const handleMessage = (...args) => {
1147
+ const data = that.getData(...args);
1148
+ that.dispatchEvent(new MessageEvent('message', {
1149
+ data
1150
+ }));
1151
+ };
1152
+ that.onMessage(handleMessage);
1153
+ const handleClose = event => {
1154
+ that.dispatchEvent(new Event('close'));
1155
+ };
1156
+ that.onClose(handleClose);
988
1157
  };
989
- const create$4 = async ({
990
- commandMap
991
- }) => {
992
- // TODO create a commandMap per rpc instance
993
- register(commandMap);
994
- const ipc = await listen$1(IpcChildWithModuleWorkerAndMessagePort$1);
995
- handleIpc(ipc);
996
- const rpc = createRpc(ipc);
997
- return rpc;
1158
+ class Ipc extends EventTarget {
1159
+ constructor(rawIpc) {
1160
+ super();
1161
+ this._rawIpc = rawIpc;
1162
+ attachEvents(this);
1163
+ }
1164
+ }
1165
+ const E_INCOMPATIBLE_NATIVE_MODULE = 'E_INCOMPATIBLE_NATIVE_MODULE';
1166
+ const E_MODULES_NOT_SUPPORTED_IN_ELECTRON = 'E_MODULES_NOT_SUPPORTED_IN_ELECTRON';
1167
+ const ERR_MODULE_NOT_FOUND = 'ERR_MODULE_NOT_FOUND';
1168
+ const NewLine$1 = '\n';
1169
+ const joinLines$1 = lines => {
1170
+ return lines.join(NewLine$1);
998
1171
  };
999
- const WebWorkerRpcClient = {
1000
- __proto__: null,
1001
- create: create$4
1172
+ const RE_AT = /^\s+at/;
1173
+ const RE_AT_PROMISE_INDEX = /^\s*at async Promise.all \(index \d+\)$/;
1174
+ const isNormalStackLine = line => {
1175
+ return RE_AT.test(line) && !RE_AT_PROMISE_INDEX.test(line);
1002
1176
  };
1003
-
1004
- const create$2 = () => {
1005
- const states = Object.create(null);
1006
- return {
1007
- get(uid) {
1008
- return states[uid];
1009
- },
1010
- set(uid, oldState, newState) {
1011
- states[uid] = {
1012
- oldState,
1013
- newState
1014
- };
1015
- },
1016
- dispose(uid) {
1017
- delete states[uid];
1018
- },
1019
- getKeys() {
1020
- return Object.keys(states).map(key => {
1021
- return Number.parseInt(key);
1022
- });
1023
- },
1024
- clear() {
1025
- for (const key of Object.keys(states)) {
1026
- delete states[key];
1027
- }
1028
- },
1029
- wrapCommand(fn) {
1030
- const wrapped = async (uid, ...args) => {
1031
- const {
1032
- newState
1033
- } = states[uid];
1034
- const newerState = await fn(newState, ...args);
1035
- if (newState === newerState) {
1036
- return;
1037
- }
1038
- const latest = states[uid];
1039
- states[uid] = {
1040
- oldState: latest.oldState,
1041
- newState: newerState
1042
- };
1043
- };
1044
- return wrapped;
1045
- },
1046
- diff(uid, modules, numbers) {
1047
- const {
1048
- oldState,
1049
- newState
1050
- } = states[uid];
1051
- const diffResult = [];
1052
- for (let i = 0; i < modules.length; i++) {
1053
- const fn = modules[i];
1054
- if (!fn(oldState, newState)) {
1055
- diffResult.push(numbers[i]);
1056
- }
1057
- }
1058
- return diffResult;
1177
+ const getDetails = lines => {
1178
+ const index = lines.findIndex(isNormalStackLine);
1179
+ if (index === -1) {
1180
+ return {
1181
+ actualMessage: joinLines$1(lines),
1182
+ rest: []
1183
+ };
1184
+ }
1185
+ let lastIndex = index - 1;
1186
+ while (++lastIndex < lines.length) {
1187
+ if (!isNormalStackLine(lines[lastIndex])) {
1188
+ break;
1059
1189
  }
1190
+ }
1191
+ return {
1192
+ actualMessage: lines[index - 1],
1193
+ rest: lines.slice(index, lastIndex)
1060
1194
  };
1061
1195
  };
1062
- const terminate = () => {
1063
- globalThis.close();
1196
+ const splitLines$1 = lines => {
1197
+ return lines.split(NewLine$1);
1064
1198
  };
1065
-
1066
- const copyImage = state => {
1067
- return state;
1199
+ const RE_MESSAGE_CODE_BLOCK_START = /^Error: The module '.*'$/;
1200
+ const RE_MESSAGE_CODE_BLOCK_END = /^\s* at/;
1201
+ const isMessageCodeBlockStartIndex = line => {
1202
+ return RE_MESSAGE_CODE_BLOCK_START.test(line);
1068
1203
  };
1069
-
1070
- const {
1071
- get: get$1,
1072
- set: set$2,
1073
- dispose: dispose$1,
1074
- wrapCommand
1075
- } = create$2();
1076
-
1077
- const create$1 = (uid, uri, x, y, width, height, platform, assetDir) => {
1078
- const state = {
1079
- assetDir: assetDir || '',
1080
- activationEvents: [],
1081
- baseUrl: '',
1082
- builtinExtensionsBadgeEnabled: true,
1083
- categories: [],
1084
- changelogVirtualDom: [],
1085
- commands: [],
1086
- description: '',
1087
- detailsVirtualDom: [],
1088
- displaySize: '',
1089
- entries: [],
1090
- extension: {},
1091
- extensionId: '',
1092
- extensionVersion: '',
1093
- features: [],
1094
- featuresVirtualDom: [],
1095
- folderSize: 0,
1096
- hasColorTheme: false,
1097
- iconSrc: '',
1098
- isBuiltin: false,
1099
- jsonValidation: [],
1100
- name: '',
1101
- platform,
1102
- programmingLanguages: [],
1103
- readmeScrollTop: 0,
1104
- resources: [],
1105
- scrollToTopButtonEnabled: false,
1106
- secondEntries: [],
1107
- selectedFeature: '',
1108
- selectedTab: '',
1109
- settings: [],
1110
- settingsButtonEnabled: false,
1111
- showAdditionalDetailsBreakpoint: 600,
1112
- sizeOnDisk: 0,
1113
- sizeValue: 0,
1114
- themesMarkdownDom: [],
1115
- uri,
1116
- webViews: [],
1117
- width,
1118
- scrollSource: 0
1119
- };
1120
- set$2(uid, state, state);
1204
+ const isMessageCodeBlockEndIndex = line => {
1205
+ return RE_MESSAGE_CODE_BLOCK_END.test(line);
1121
1206
  };
1122
-
1123
- const RenderFocus = 2;
1124
- const RenderItems = 3;
1125
- const RenderScrollTop = 4;
1126
-
1127
- const diffType$2 = RenderFocus;
1128
- const isEqual$2 = (oldState, newState) => {
1129
- return oldState === newState;
1207
+ const getMessageCodeBlock = stderr => {
1208
+ const lines = splitLines$1(stderr);
1209
+ const startIndex = lines.findIndex(isMessageCodeBlockStartIndex);
1210
+ const endIndex = startIndex + lines.slice(startIndex).findIndex(isMessageCodeBlockEndIndex, startIndex);
1211
+ const relevantLines = lines.slice(startIndex, endIndex);
1212
+ const relevantMessage = relevantLines.join(' ').slice('Error: '.length);
1213
+ return relevantMessage;
1130
1214
  };
1131
-
1132
- const diffType$1 = RenderItems;
1133
- const isEqual$1 = (oldState, newState) => {
1134
- return oldState === newState;
1215
+ const isModuleNotFoundMessage = line => {
1216
+ return line.includes('[ERR_MODULE_NOT_FOUND]');
1135
1217
  };
1136
-
1137
- const User = 1;
1138
-
1139
- const diffType = RenderScrollTop;
1140
- const isEqual = (oldState, newState) => {
1141
- return newState.scrollSource === User || oldState.readmeScrollTop === newState.readmeScrollTop;
1218
+ const getModuleNotFoundError = stderr => {
1219
+ const lines = splitLines$1(stderr);
1220
+ const messageIndex = lines.findIndex(isModuleNotFoundMessage);
1221
+ const message = lines[messageIndex];
1222
+ return {
1223
+ message,
1224
+ code: ERR_MODULE_NOT_FOUND
1225
+ };
1142
1226
  };
1143
-
1144
- const modules = [isEqual$1, isEqual$2, isEqual];
1145
- const numbers = [diffType$1, diffType$2, diffType];
1146
-
1147
- const diff2 = uid => {
1148
- const {
1149
- oldState,
1150
- newState
1151
- } = get$1(uid);
1152
- const diffResult = [];
1153
- for (let i = 0; i < modules.length; i++) {
1154
- const fn = modules[i];
1155
- if (!fn(oldState, newState)) {
1156
- diffResult.push(numbers[i]);
1157
- }
1227
+ const isModuleNotFoundError = stderr => {
1228
+ if (!stderr) {
1229
+ return false;
1158
1230
  }
1159
- return diffResult;
1160
- };
1161
-
1162
- const dispose = uid => {
1163
- dispose$1(uid);
1164
- };
1165
-
1166
- const commandIds = ['copyImage', 'getMenuEntries', 'handleClickCategory', 'handleClickDisable', 'handleClickScrollToTop', 'handleClickSettings', 'handleClickSetColorTheme', 'handleClickSize', 'handleClickUninstall', 'handleFeaturesClick', 'handleIconError', 'handleTabsClick', 'handleWheel', 'renderEventListeners', 'resize', 'saveState', 'selectTab', 'terminate'];
1167
-
1168
- const getCommandIds = () => {
1169
- return commandIds;
1231
+ return stderr.includes('ERR_MODULE_NOT_FOUND');
1170
1232
  };
1171
-
1172
- const emptyObject = {};
1173
- const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
1174
- const i18nString = (key, placeholders = emptyObject) => {
1175
- if (placeholders === emptyObject) {
1176
- return key;
1233
+ const isModulesSyntaxError = stderr => {
1234
+ if (!stderr) {
1235
+ return false;
1177
1236
  }
1178
- const replacer = (match, rest) => {
1179
- return placeholders[rest];
1180
- };
1181
- return key.replaceAll(RE_PLACEHOLDER, replacer);
1182
- };
1183
-
1184
- const Installation = 'Installation';
1185
- const Marketplace = 'Marketplace';
1186
- const Categories$1 = 'Categories';
1187
- const Resources$1 = 'Resources';
1188
- const Changelog$2 = 'Changelog';
1189
- const Commands$1 = 'Commands';
1190
- const ContentSecurityPolicy = 'ContentSecurityPolicy';
1191
- const Copy = 'Copy';
1192
- const Details$1 = 'Details';
1193
- const Disable$1 = 'Disable';
1194
- const Elements = 'Elements';
1195
- const Features$2 = 'Features';
1196
- const FileMatch = 'File Match';
1197
- const None$1 = 'None';
1198
- const Id = 'ID';
1199
- const JsonValidation$1 = 'Json Validation';
1200
- const Label = 'Label';
1201
- const OpenImageInNewTab = 'Open Image in New Tab';
1202
- const OpenInNewTab = 'Open in New Tab';
1203
- const ProgrammingLanguages$1 = 'Programming Languages';
1204
- const SaveImageAs = 'Save Image as';
1205
- const Schema = 'Schema';
1206
- const ScrollToTop$1 = 'Scroll to top';
1207
- const Selector = 'Selector';
1208
- const Settings$1 = 'Settings';
1209
- const SetColorTheme$1 = 'Set Color Theme';
1210
- const Theme$1 = 'Theme';
1211
- const Uninstall$1 = 'Uninstall';
1212
- const WebViews$1 = 'WebViews';
1213
-
1214
- const installation = () => {
1215
- return i18nString(Installation);
1237
+ return stderr.includes('SyntaxError: Cannot use import statement outside a module');
1216
1238
  };
1217
- const marketplace = () => {
1218
- return i18nString(Marketplace);
1239
+ const RE_NATIVE_MODULE_ERROR = /^innerError Error: Cannot find module '.*.node'/;
1240
+ const RE_NATIVE_MODULE_ERROR_2 = /was compiled against a different Node.js version/;
1241
+ const isUnhelpfulNativeModuleError = stderr => {
1242
+ return RE_NATIVE_MODULE_ERROR.test(stderr) && RE_NATIVE_MODULE_ERROR_2.test(stderr);
1219
1243
  };
1220
- const categories = () => {
1221
- return i18nString(Categories$1);
1244
+ const getNativeModuleErrorMessage = stderr => {
1245
+ const message = getMessageCodeBlock(stderr);
1246
+ return {
1247
+ message: `Incompatible native node module: ${message}`,
1248
+ code: E_INCOMPATIBLE_NATIVE_MODULE
1249
+ };
1222
1250
  };
1223
- const resources = () => {
1224
- return i18nString(Resources$1);
1251
+ const getModuleSyntaxError = () => {
1252
+ return {
1253
+ message: `ES Modules are not supported in electron`,
1254
+ code: E_MODULES_NOT_SUPPORTED_IN_ELECTRON
1255
+ };
1225
1256
  };
1226
- const copy = () => {
1227
- return i18nString(Copy);
1257
+ const getHelpfulChildProcessError = (stdout, stderr) => {
1258
+ if (isUnhelpfulNativeModuleError(stderr)) {
1259
+ return getNativeModuleErrorMessage(stderr);
1260
+ }
1261
+ if (isModulesSyntaxError(stderr)) {
1262
+ return getModuleSyntaxError();
1263
+ }
1264
+ if (isModuleNotFoundError(stderr)) {
1265
+ return getModuleNotFoundError(stderr);
1266
+ }
1267
+ const lines = splitLines$1(stderr);
1268
+ const {
1269
+ actualMessage,
1270
+ rest
1271
+ } = getDetails(lines);
1272
+ return {
1273
+ message: actualMessage,
1274
+ code: '',
1275
+ stack: rest
1276
+ };
1228
1277
  };
1229
- const changelog = () => {
1230
- return i18nString(Changelog$2);
1278
+ class IpcError extends VError {
1279
+ // @ts-ignore
1280
+ constructor(betterMessage, stdout = '', stderr = '') {
1281
+ if (stdout || stderr) {
1282
+ // @ts-ignore
1283
+ const {
1284
+ message,
1285
+ code,
1286
+ stack
1287
+ } = getHelpfulChildProcessError(stdout, stderr);
1288
+ const cause = new Error(message);
1289
+ // @ts-ignore
1290
+ cause.code = code;
1291
+ cause.stack = stack;
1292
+ super(cause, betterMessage);
1293
+ } else {
1294
+ super(betterMessage);
1295
+ }
1296
+ // @ts-ignore
1297
+ this.name = 'IpcError';
1298
+ // @ts-ignore
1299
+ this.stdout = stdout;
1300
+ // @ts-ignore
1301
+ this.stderr = stderr;
1302
+ }
1303
+ }
1304
+ const readyMessage = 'ready';
1305
+ const getData$2 = event => {
1306
+ return event.data;
1231
1307
  };
1232
- const details = () => {
1233
- return i18nString(Details$1);
1308
+ const listen$7 = () => {
1309
+ // @ts-ignore
1310
+ if (typeof WorkerGlobalScope === 'undefined') {
1311
+ throw new TypeError('module is not in web worker scope');
1312
+ }
1313
+ return globalThis;
1234
1314
  };
1235
- const disable = () => {
1236
- return i18nString(Disable$1);
1315
+ const signal$8 = global => {
1316
+ global.postMessage(readyMessage);
1237
1317
  };
1238
- const features = () => {
1239
- return i18nString(Features$2);
1240
- };
1241
- const none = () => {
1242
- return i18nString(None$1);
1243
- };
1244
- const openInNewTab = () => {
1245
- return i18nString(OpenInNewTab);
1318
+ class IpcChildWithModuleWorker extends Ipc {
1319
+ getData(event) {
1320
+ return getData$2(event);
1321
+ }
1322
+ send(message) {
1323
+ // @ts-ignore
1324
+ this._rawIpc.postMessage(message);
1325
+ }
1326
+ sendAndTransfer(message) {
1327
+ const transfer = getTransferrables(message);
1328
+ // @ts-ignore
1329
+ this._rawIpc.postMessage(message, transfer);
1330
+ }
1331
+ dispose() {
1332
+ // ignore
1333
+ }
1334
+ onClose(callback) {
1335
+ // ignore
1336
+ }
1337
+ onMessage(callback) {
1338
+ this._rawIpc.addEventListener('message', callback);
1339
+ }
1340
+ }
1341
+ const wrap$f = global => {
1342
+ return new IpcChildWithModuleWorker(global);
1246
1343
  };
1247
- const label = () => {
1248
- return i18nString(Label);
1344
+ const waitForFirstMessage = async port => {
1345
+ const {
1346
+ resolve,
1347
+ promise
1348
+ } = Promise.withResolvers();
1349
+ port.addEventListener('message', resolve, {
1350
+ once: true
1351
+ });
1352
+ const event = await promise;
1353
+ // @ts-ignore
1354
+ return event.data;
1249
1355
  };
1250
- const openImageInNewTab = () => {
1251
- return i18nString(OpenImageInNewTab);
1356
+ const listen$6 = async () => {
1357
+ const parentIpcRaw = listen$7();
1358
+ signal$8(parentIpcRaw);
1359
+ const parentIpc = wrap$f(parentIpcRaw);
1360
+ const firstMessage = await waitForFirstMessage(parentIpc);
1361
+ if (firstMessage.method !== 'initialize') {
1362
+ throw new IpcError('unexpected first message');
1363
+ }
1364
+ const type = firstMessage.params[0];
1365
+ if (type === 'message-port') {
1366
+ parentIpc.send({
1367
+ jsonrpc: '2.0',
1368
+ id: firstMessage.id,
1369
+ result: null
1370
+ });
1371
+ parentIpc.dispose();
1372
+ const port = firstMessage.params[1];
1373
+ return port;
1374
+ }
1375
+ return globalThis;
1252
1376
  };
1253
- const saveImageAs = () => {
1254
- return i18nString(SaveImageAs);
1377
+ class IpcChildWithModuleWorkerAndMessagePort extends Ipc {
1378
+ getData(event) {
1379
+ return getData$2(event);
1380
+ }
1381
+ send(message) {
1382
+ this._rawIpc.postMessage(message);
1383
+ }
1384
+ sendAndTransfer(message) {
1385
+ const transfer = getTransferrables(message);
1386
+ this._rawIpc.postMessage(message, transfer);
1387
+ }
1388
+ dispose() {
1389
+ if (this._rawIpc.close) {
1390
+ this._rawIpc.close();
1391
+ }
1392
+ }
1393
+ onClose(callback) {
1394
+ // ignore
1395
+ }
1396
+ onMessage(callback) {
1397
+ this._rawIpc.addEventListener('message', callback);
1398
+ this._rawIpc.start();
1399
+ }
1400
+ }
1401
+ const wrap$e = port => {
1402
+ return new IpcChildWithModuleWorkerAndMessagePort(port);
1255
1403
  };
1256
- const fileMatch = () => {
1257
- return i18nString(FileMatch);
1404
+ const IpcChildWithModuleWorkerAndMessagePort$1 = {
1405
+ __proto__: null,
1406
+ listen: listen$6,
1407
+ wrap: wrap$e
1258
1408
  };
1259
- const schema = () => {
1260
- return i18nString(Schema);
1409
+ const addListener = (emitter, type, callback) => {
1410
+ if ('addEventListener' in emitter) {
1411
+ emitter.addEventListener(type, callback);
1412
+ } else {
1413
+ emitter.on(type, callback);
1414
+ }
1261
1415
  };
1262
- const setColorTheme$3 = () => {
1263
- return i18nString(SetColorTheme$1);
1416
+ const removeListener = (emitter, type, callback) => {
1417
+ if ('removeEventListener' in emitter) {
1418
+ emitter.removeEventListener(type, callback);
1419
+ } else {
1420
+ emitter.off(type, callback);
1421
+ }
1264
1422
  };
1265
- const theme = () => {
1266
- return i18nString(Theme$1);
1423
+ const getFirstEvent = (eventEmitter, eventMap) => {
1424
+ const {
1425
+ resolve,
1426
+ promise
1427
+ } = Promise.withResolvers();
1428
+ const listenerMap = Object.create(null);
1429
+ const cleanup = value => {
1430
+ for (const event of Object.keys(eventMap)) {
1431
+ removeListener(eventEmitter, event, listenerMap[event]);
1432
+ }
1433
+ resolve(value);
1434
+ };
1435
+ for (const [event, type] of Object.entries(eventMap)) {
1436
+ const listener = event => {
1437
+ cleanup({
1438
+ type,
1439
+ event
1440
+ });
1441
+ };
1442
+ addListener(eventEmitter, event, listener);
1443
+ listenerMap[event] = listener;
1444
+ }
1445
+ return promise;
1267
1446
  };
1268
- const commands = () => {
1269
- return i18nString(Commands$1);
1447
+ const Message$1 = 3;
1448
+ const create$5$1 = async ({
1449
+ messagePort,
1450
+ isMessagePortOpen
1451
+ }) => {
1452
+ if (!isMessagePort(messagePort)) {
1453
+ throw new IpcError('port must be of type MessagePort');
1454
+ }
1455
+ if (isMessagePortOpen) {
1456
+ return messagePort;
1457
+ }
1458
+ const eventPromise = getFirstEvent(messagePort, {
1459
+ message: Message$1
1460
+ });
1461
+ messagePort.start();
1462
+ const {
1463
+ type,
1464
+ event
1465
+ } = await eventPromise;
1466
+ if (type !== Message$1) {
1467
+ throw new IpcError('Failed to wait for ipc message');
1468
+ }
1469
+ if (event.data !== readyMessage) {
1470
+ throw new IpcError('unexpected first message');
1471
+ }
1472
+ return messagePort;
1270
1473
  };
1271
- const webViews = () => {
1272
- return i18nString(WebViews$1);
1474
+ const signal$1 = messagePort => {
1475
+ messagePort.start();
1273
1476
  };
1274
- const jsonValidation = () => {
1275
- return i18nString(JsonValidation$1);
1477
+ class IpcParentWithMessagePort extends Ipc {
1478
+ getData = getData$2;
1479
+ send(message) {
1480
+ this._rawIpc.postMessage(message);
1481
+ }
1482
+ sendAndTransfer(message) {
1483
+ const transfer = getTransferrables(message);
1484
+ this._rawIpc.postMessage(message, transfer);
1485
+ }
1486
+ dispose() {
1487
+ this._rawIpc.close();
1488
+ }
1489
+ onMessage(callback) {
1490
+ this._rawIpc.addEventListener('message', callback);
1491
+ }
1492
+ onClose(callback) {}
1493
+ }
1494
+ const wrap$5 = messagePort => {
1495
+ return new IpcParentWithMessagePort(messagePort);
1276
1496
  };
1277
- const programmingLanguages = () => {
1278
- return i18nString(ProgrammingLanguages$1);
1497
+ const IpcParentWithMessagePort$1 = {
1498
+ __proto__: null,
1499
+ create: create$5$1,
1500
+ signal: signal$1,
1501
+ wrap: wrap$5
1279
1502
  };
1280
- const settings = () => {
1281
- return i18nString(Settings$1);
1503
+
1504
+ const Two = '2.0';
1505
+ const create$4 = (method, params) => {
1506
+ return {
1507
+ jsonrpc: Two,
1508
+ method,
1509
+ params
1510
+ };
1282
1511
  };
1283
- const id = () => {
1284
- return i18nString(Id);
1512
+ const callbacks = Object.create(null);
1513
+ const set$2 = (id, fn) => {
1514
+ callbacks[id] = fn;
1285
1515
  };
1286
- const selector = () => {
1287
- return i18nString(Selector);
1516
+ const get$1 = id => {
1517
+ return callbacks[id];
1288
1518
  };
1289
- const contentSecurityPolicy = () => {
1290
- return i18nString(ContentSecurityPolicy);
1519
+ const remove = id => {
1520
+ delete callbacks[id];
1291
1521
  };
1292
- const elements = () => {
1293
- return i18nString(Elements);
1522
+ let id = 0;
1523
+ const create$3$1 = () => {
1524
+ return ++id;
1294
1525
  };
1295
- const uninstall = () => {
1296
- return i18nString(Uninstall$1);
1526
+ const registerPromise = () => {
1527
+ const id = create$3$1();
1528
+ const {
1529
+ resolve,
1530
+ promise
1531
+ } = Promise.withResolvers();
1532
+ set$2(id, resolve);
1533
+ return {
1534
+ id,
1535
+ promise
1536
+ };
1297
1537
  };
1298
- const scrollToTop = () => {
1299
- return i18nString(ScrollToTop$1);
1538
+ const create$2$1 = (method, params) => {
1539
+ const {
1540
+ id,
1541
+ promise
1542
+ } = registerPromise();
1543
+ const message = {
1544
+ jsonrpc: Two,
1545
+ method,
1546
+ params,
1547
+ id
1548
+ };
1549
+ return {
1550
+ message,
1551
+ promise
1552
+ };
1300
1553
  };
1301
-
1302
- const None = 0;
1303
-
1304
- const getCopyMenuEntry = () => ({
1305
- id: 'copy',
1306
- label: copy(),
1307
- flags: None,
1308
- command: 'ClipBoard.execCopy'
1309
- });
1310
-
1311
- const getImageMenuEntries = props => {
1312
- if (!props.isImage) {
1313
- return [];
1554
+ class JsonRpcError extends Error {
1555
+ constructor(message) {
1556
+ super(message);
1557
+ this.name = 'JsonRpcError';
1314
1558
  }
1315
- return [{
1316
- id: 'openImageInNewTab',
1317
- label: openImageInNewTab(),
1318
- flags: None,
1319
- command: 'Open.openUrl',
1320
- args: [props.url || '']
1321
- }, {
1322
- id: 'saveImageAs',
1323
- label: saveImageAs(),
1324
- flags: None,
1325
- command: 'SaveFileAs.saveFileAs',
1326
- args: ['image.png', props.url || '']
1327
- }];
1328
- };
1329
-
1330
- const getLinkMenuEntries = props => {
1331
- if (!props.isLink) {
1332
- return [];
1559
+ }
1560
+ const NewLine = '\n';
1561
+ const DomException = 'DOMException';
1562
+ const ReferenceError$1 = 'ReferenceError';
1563
+ const SyntaxError$1 = 'SyntaxError';
1564
+ const TypeError$1 = 'TypeError';
1565
+ const getErrorConstructor = (message, type) => {
1566
+ if (type) {
1567
+ switch (type) {
1568
+ case DomException:
1569
+ return DOMException;
1570
+ case TypeError$1:
1571
+ return TypeError;
1572
+ case SyntaxError$1:
1573
+ return SyntaxError;
1574
+ case ReferenceError$1:
1575
+ return ReferenceError;
1576
+ default:
1577
+ return Error;
1578
+ }
1333
1579
  }
1334
- return [{
1335
- id: 'openInNewTab',
1336
- label: openInNewTab(),
1337
- flags: None,
1338
- command: 'Open.openUrl',
1339
- args: [props.url || '']
1340
- }];
1580
+ if (message.startsWith('TypeError: ')) {
1581
+ return TypeError;
1582
+ }
1583
+ if (message.startsWith('SyntaxError: ')) {
1584
+ return SyntaxError;
1585
+ }
1586
+ if (message.startsWith('ReferenceError: ')) {
1587
+ return ReferenceError;
1588
+ }
1589
+ return Error;
1341
1590
  };
1342
-
1343
- const getMenuEntries = props => [...getLinkMenuEntries(props), ...getImageMenuEntries(props), getCopyMenuEntry()];
1344
-
1345
- const handleClickCategory = async (state, categoryId) => {
1346
- // TODO: Implement category click functionality
1347
- return state;
1591
+ const constructError = (message, type, name) => {
1592
+ const ErrorConstructor = getErrorConstructor(message, type);
1593
+ if (ErrorConstructor === DOMException && name) {
1594
+ return new ErrorConstructor(message, name);
1595
+ }
1596
+ if (ErrorConstructor === Error) {
1597
+ const error = new Error(message);
1598
+ if (name && name !== 'VError') {
1599
+ error.name = name;
1600
+ }
1601
+ return error;
1602
+ }
1603
+ return new ErrorConstructor(message);
1348
1604
  };
1349
-
1350
- const handleClickDisable = async state => {
1351
- return state;
1605
+ const joinLines = lines => {
1606
+ return lines.join(NewLine);
1352
1607
  };
1353
-
1354
- const Text$1 = 1;
1355
- const Code$2 = 2;
1356
-
1357
- const getCommandTableEntry = command => {
1358
- // TODO watch out for command being null/undefined/number/string/array
1359
- const {
1360
- id,
1361
- label
1362
- } = command;
1363
- return [{
1364
- type: Code$2,
1365
- value: id
1366
- }, {
1367
- type: Text$1,
1368
- value: label
1369
- }];
1608
+ const splitLines = lines => {
1609
+ return lines.split(NewLine);
1370
1610
  };
1371
-
1372
- const getFeatureDetailsCommand = extension => {
1373
- const commands = extension.commands || [];
1374
- const rows = commands.map(getCommandTableEntry);
1375
- return {
1376
- commands: rows
1377
- };
1611
+ const getCurrentStack = () => {
1612
+ const currentStack = joinLines(splitLines(new Error().stack || '').slice(2));
1613
+ return currentStack;
1378
1614
  };
1379
-
1380
- const getJsonValidationTableEntry = validation => {
1381
- const {
1382
- fileMatch,
1383
- schema
1384
- } = validation;
1385
- return [{
1386
- type: Code$2,
1387
- value: fileMatch
1388
- }, {
1389
- type: Code$2,
1390
- value: schema
1391
- }];
1615
+ const getNewLineIndex = (string, startIndex = undefined) => {
1616
+ return string.indexOf(NewLine, startIndex);
1392
1617
  };
1393
-
1394
- const getFeatureDetailsJsonValidation = extension => {
1395
- const validations = extension.jsonValidation || [];
1396
- const rows = validations.map(getJsonValidationTableEntry);
1397
- return {
1398
- jsonValidation: rows
1399
- };
1618
+ const getParentStack = error => {
1619
+ let parentStack = error.stack || error.data || error.message || '';
1620
+ if (parentStack.startsWith(' at')) {
1621
+ parentStack = error.message + NewLine + parentStack;
1622
+ }
1623
+ return parentStack;
1400
1624
  };
1401
-
1402
- const getFeatureDetailsProgrammingLanguages = extension => {
1403
- return {
1404
- programmingLanguages: []
1405
- };
1625
+ const MethodNotFound = -32601;
1626
+ const Custom = -32001;
1627
+ const restoreJsonRpcError = error => {
1628
+ const currentStack = getCurrentStack();
1629
+ if (error && error instanceof Error) {
1630
+ if (typeof error.stack === 'string') {
1631
+ error.stack = error.stack + NewLine + currentStack;
1632
+ }
1633
+ return error;
1634
+ }
1635
+ if (error && error.code && error.code === MethodNotFound) {
1636
+ const restoredError = new JsonRpcError(error.message);
1637
+ const parentStack = getParentStack(error);
1638
+ restoredError.stack = parentStack + NewLine + currentStack;
1639
+ return restoredError;
1640
+ }
1641
+ if (error && error.message) {
1642
+ const restoredError = constructError(error.message, error.type, error.name);
1643
+ if (error.data) {
1644
+ if (error.data.stack && error.data.type && error.message) {
1645
+ restoredError.stack = error.data.type + ': ' + error.message + NewLine + error.data.stack + NewLine + currentStack;
1646
+ } else if (error.data.stack) {
1647
+ restoredError.stack = error.data.stack;
1648
+ }
1649
+ if (error.data.codeFrame) {
1650
+ // @ts-ignore
1651
+ restoredError.codeFrame = error.data.codeFrame;
1652
+ }
1653
+ if (error.data.code) {
1654
+ // @ts-ignore
1655
+ restoredError.code = error.data.code;
1656
+ }
1657
+ if (error.data.type) {
1658
+ // @ts-ignore
1659
+ restoredError.name = error.data.type;
1660
+ }
1661
+ } else {
1662
+ if (error.stack) {
1663
+ const lowerStack = restoredError.stack || '';
1664
+ // @ts-ignore
1665
+ const indexNewLine = getNewLineIndex(lowerStack);
1666
+ const parentStack = getParentStack(error);
1667
+ // @ts-ignore
1668
+ restoredError.stack = parentStack + lowerStack.slice(indexNewLine);
1669
+ }
1670
+ if (error.codeFrame) {
1671
+ // @ts-ignore
1672
+ restoredError.codeFrame = error.codeFrame;
1673
+ }
1674
+ }
1675
+ return restoredError;
1676
+ }
1677
+ if (typeof error === 'string') {
1678
+ return new Error(`JsonRpc Error: ${error}`);
1679
+ }
1680
+ return new Error(`JsonRpc Error: ${error}`);
1406
1681
  };
1407
-
1408
- const getSettingsTableEntry = setting => {
1409
- const {
1410
- id,
1411
- label
1412
- } = setting;
1413
- // TODO watch out for null/undefined/number/string/array
1414
- return [{
1415
- type: Text$1,
1416
- value: id
1417
- }, {
1418
- type: Text$1,
1419
- value: label
1420
- }];
1682
+ const unwrapJsonRpcResult = responseMessage => {
1683
+ if ('error' in responseMessage) {
1684
+ const restoredError = restoreJsonRpcError(responseMessage.error);
1685
+ throw restoredError;
1686
+ }
1687
+ if ('result' in responseMessage) {
1688
+ return responseMessage.result;
1689
+ }
1690
+ throw new JsonRpcError('unexpected response message');
1421
1691
  };
1422
-
1423
- const getFeatureDetailsSettings = extension => {
1424
- const settings = extension.settings || [];
1425
- const rows = settings.map(getSettingsTableEntry);
1426
- return {
1427
- settings: rows
1428
- };
1692
+ const warn = (...args) => {
1693
+ console.warn(...args);
1429
1694
  };
1430
-
1431
- const Panel = 'panel';
1432
- const Tab$1 = 'tab';
1433
- const TabList = 'tablist';
1434
- const AriaRoles = {
1435
- __proto__: null,
1436
- Panel,
1437
- Tab: Tab$1,
1438
- TabList};
1439
- const mergeClassNames = (...classNames) => {
1440
- return classNames.filter(Boolean).join(' ');
1695
+ const resolve = (id, response) => {
1696
+ const fn = get$1(id);
1697
+ if (!fn) {
1698
+ console.log(response);
1699
+ warn(`callback ${id} may already be disposed`);
1700
+ return;
1701
+ }
1702
+ fn(response);
1703
+ remove(id);
1441
1704
  };
1442
- const Button$1 = 1;
1443
- const Div = 4;
1444
- const H1 = 5;
1445
- const Span = 8;
1446
- const Table$1 = 9;
1447
- const TBody = 10;
1448
- const Td = 11;
1449
- const Text = 12;
1450
- const Th = 13;
1451
- const THead = 14;
1452
- const Tr = 15;
1453
- const Img = 17;
1454
- const H2 = 22;
1455
- const Dd = 43;
1456
- const Dl = 44;
1457
- const Pre = 51;
1458
- const A = 53;
1459
- const Code$1 = 65;
1460
- const Dt = 67;
1461
- const VirtualDomElements = {
1462
- __proto__: null,
1463
- A,
1464
- Button: Button$1,
1465
- Code: Code$1,
1466
- Dd,
1467
- Div,
1468
- Dl,
1469
- Dt,
1470
- H1,
1471
- H2,
1472
- Img,
1473
- Pre,
1474
- Span,
1475
- TBody,
1476
- THead,
1477
- Table: Table$1,
1478
- Td,
1479
- Th,
1480
- Tr};
1481
- const text = data => {
1705
+ const E_COMMAND_NOT_FOUND = 'E_COMMAND_NOT_FOUND';
1706
+ const getErrorType = prettyError => {
1707
+ if (prettyError && prettyError.type) {
1708
+ return prettyError.type;
1709
+ }
1710
+ if (prettyError && prettyError.constructor && prettyError.constructor.name) {
1711
+ return prettyError.constructor.name;
1712
+ }
1713
+ return undefined;
1714
+ };
1715
+ const isAlreadyStack = line => {
1716
+ return line.trim().startsWith('at ');
1717
+ };
1718
+ const getStack = prettyError => {
1719
+ const stackString = prettyError.stack || '';
1720
+ const newLineIndex = stackString.indexOf('\n');
1721
+ if (newLineIndex !== -1 && !isAlreadyStack(stackString.slice(0, newLineIndex))) {
1722
+ return stackString.slice(newLineIndex + 1);
1723
+ }
1724
+ return stackString;
1725
+ };
1726
+ const getErrorProperty = (error, prettyError) => {
1727
+ if (error && error.code === E_COMMAND_NOT_FOUND) {
1728
+ return {
1729
+ code: MethodNotFound,
1730
+ message: error.message,
1731
+ data: error.stack
1732
+ };
1733
+ }
1482
1734
  return {
1483
- type: Text,
1484
- text: data,
1485
- childCount: 0
1735
+ code: Custom,
1736
+ message: prettyError.message,
1737
+ data: {
1738
+ stack: getStack(prettyError),
1739
+ codeFrame: prettyError.codeFrame,
1740
+ type: getErrorType(prettyError),
1741
+ code: prettyError.code,
1742
+ name: prettyError.name
1743
+ }
1486
1744
  };
1487
1745
  };
1746
+ const create$1$1 = (id, error) => {
1747
+ return {
1748
+ jsonrpc: Two,
1749
+ id,
1750
+ error
1751
+ };
1752
+ };
1753
+ const getErrorResponse = (id, error, preparePrettyError, logError) => {
1754
+ const prettyError = preparePrettyError(error);
1755
+ logError(error, prettyError);
1756
+ const errorProperty = getErrorProperty(error, prettyError);
1757
+ return create$1$1(id, errorProperty);
1758
+ };
1759
+ const create$6 = (message, result) => {
1760
+ return {
1761
+ jsonrpc: Two,
1762
+ id: message.id,
1763
+ result: result ?? null
1764
+ };
1765
+ };
1766
+ const getSuccessResponse = (message, result) => {
1767
+ const resultProperty = result ?? null;
1768
+ return create$6(message, resultProperty);
1769
+ };
1770
+ const getErrorResponseSimple = (id, error) => {
1771
+ return {
1772
+ jsonrpc: Two,
1773
+ id,
1774
+ error: {
1775
+ code: Custom,
1776
+ // @ts-ignore
1777
+ message: error.message,
1778
+ data: error
1779
+ }
1780
+ };
1781
+ };
1782
+ const getResponse = async (message, ipc, execute, preparePrettyError, logError, requiresSocket) => {
1783
+ try {
1784
+ const result = requiresSocket(message.method) ? await execute(message.method, ipc, ...message.params) : await execute(message.method, ...message.params);
1785
+ return getSuccessResponse(message, result);
1786
+ } catch (error) {
1787
+ if (ipc.canUseSimpleErrorResponse) {
1788
+ return getErrorResponseSimple(message.id, error);
1789
+ }
1790
+ return getErrorResponse(message.id, error, preparePrettyError, logError);
1791
+ }
1792
+ };
1793
+ const defaultPreparePrettyError = error => {
1794
+ return error;
1795
+ };
1796
+ const defaultLogError = () => {
1797
+ // ignore
1798
+ };
1799
+ const defaultRequiresSocket = () => {
1800
+ return false;
1801
+ };
1802
+ const defaultResolve = resolve;
1488
1803
 
1489
- const AdditionalDetails = 'AdditionalDetails';
1490
- const AdditionalDetailsEntry = 'AdditionalDetailsEntry';
1491
- const AdditionalDetailsTitle = 'AdditionalDetailsTitle';
1492
- const Aside = 'Aside';
1493
- const Button = 'Button';
1494
- const ButtonPrimary = 'ButtonPrimary';
1495
- const Categories = 'Categories';
1496
- const Category = 'Category';
1497
- const Changelog$1 = 'Changelog';
1498
- const Code = 'Code';
1499
- const DefaultMarkdown = 'DefaultMarkdown';
1500
- const DefinitionListItem = 'DefinitionListItem';
1501
- const DefinitionListItemHeading = 'DefinitionListItemHeading';
1502
- const DefinitionListItemValue = 'DefinitionListItemValue';
1503
- const ExtensionDetail = 'ExtensionDetail';
1504
- const ExtensionDetailDescription = 'ExtensionDetailDescription';
1505
- const ExtensionDetailHeader = 'ExtensionDetailHeader';
1506
- const ExtensionDetailHeaderActions = 'ExtensionDetailHeaderActions';
1507
- const ExtensionDetailHeaderDetails = 'ExtensionDetailHeaderDetails';
1508
- const ExtensionDetailIcon = 'ExtensionDetailIcon';
1509
- const ExtensionDetailName = 'ExtensionDetailName';
1510
- const ExtensionDetailNameBadge = 'ExtensionDetailNameBadge';
1511
- const ExtensionDetailPanel = 'ExtensionDetailPanel';
1512
- const ExtensionDetailTab = 'ExtensionDetailTab';
1513
- const ExtensionDetailTabs = 'ExtensionDetailTabs';
1514
- const ExtensionDetailTabSelected = 'ExtensionDetailTabSelected';
1515
- const Feature = 'Feature';
1516
- const FeatureContent = 'FeatureContent';
1517
- const Features$1 = 'Features';
1518
- const FeaturesList = 'FeaturesList';
1519
- const FeatureWebView = 'FeatureWebView';
1520
- const Large$1 = 'Large';
1521
- const Link = 'Link';
1522
- const MoreInfo = 'MoreInfo';
1523
- const MoreInfoEntry = 'MoreInfoEntry';
1524
- const MoreInfoEntryKey = 'MoreInfoEntryKey';
1525
- const MoreInfoEntryOdd = 'MoreInfoEntryOdd';
1526
- const MoreInfoEntryValue = 'MoreInfoEntryValue';
1527
- const Normal$1 = 'Normal';
1528
- const Resource = 'Resource';
1529
- const Resources = 'Resources';
1530
- const Sash = 'Sash';
1531
- const SashVertical = 'SashVertical';
1532
- const ScrollToTopButton = 'ScrollToTopButton';
1533
- const SettingsButton = 'SettingsButton';
1534
- const SettingsIcon = 'SettingsIcon';
1535
- const Small$1 = 'Small';
1536
- const Table = 'Table';
1537
- const TableCell = 'TableCell';
1538
- const TableHeading = 'TableHeading';
1539
- const Viewlet = 'Viewlet';
1540
-
1541
- const HandleClickCategory = 'handleClickCategory';
1542
- const HandleClickDisable = 'handleClickDisable';
1543
- const HandleClickScrollToTop = 'handleClickScrollToTop';
1544
- const HandleClickSetColorTheme = 'handleClickSetColorTheme';
1545
- const HandleClickSettings = 'handleClickSettings';
1546
- const HandleClickSize = 'handleClickSize';
1547
- const HandleClickUninstall = 'handleClickUninstall';
1548
- const HandleFeaturesClick = 'handleFeaturesClick';
1549
- const HandleIconError = 'handleIconError';
1550
- const HandleReadmeContextMenu = 'handleReadmeContextMenu';
1551
- const HandleReadmeWheel = 'handleReadmeWheel';
1552
- const HandleTabsClick = 'handleTabsClick';
1804
+ // TODO maybe remove this in v6 or v7, only accept options object to simplify the code
1805
+ const normalizeParams = args => {
1806
+ if (args.length === 1) {
1807
+ const options = args[0];
1808
+ return {
1809
+ ipc: options.ipc,
1810
+ message: options.message,
1811
+ execute: options.execute,
1812
+ resolve: options.resolve || defaultResolve,
1813
+ preparePrettyError: options.preparePrettyError || defaultPreparePrettyError,
1814
+ logError: options.logError || defaultLogError,
1815
+ requiresSocket: options.requiresSocket || defaultRequiresSocket
1816
+ };
1817
+ }
1818
+ return {
1819
+ ipc: args[0],
1820
+ message: args[1],
1821
+ execute: args[2],
1822
+ resolve: args[3],
1823
+ preparePrettyError: args[4],
1824
+ logError: args[5],
1825
+ requiresSocket: args[6]
1826
+ };
1827
+ };
1828
+ const handleJsonRpcMessage = async (...args) => {
1829
+ const options = normalizeParams(args);
1830
+ const {
1831
+ message,
1832
+ ipc,
1833
+ execute,
1834
+ resolve,
1835
+ preparePrettyError,
1836
+ logError,
1837
+ requiresSocket
1838
+ } = options;
1839
+ if ('id' in message) {
1840
+ if ('method' in message) {
1841
+ const response = await getResponse(message, ipc, execute, preparePrettyError, logError, requiresSocket);
1842
+ try {
1843
+ ipc.send(response);
1844
+ } catch (error) {
1845
+ const errorResponse = getErrorResponse(message.id, error, preparePrettyError, logError);
1846
+ ipc.send(errorResponse);
1847
+ }
1848
+ return;
1849
+ }
1850
+ resolve(message.id, message);
1851
+ return;
1852
+ }
1853
+ if ('method' in message) {
1854
+ await getResponse(message, ipc, execute, preparePrettyError, logError, requiresSocket);
1855
+ return;
1856
+ }
1857
+ throw new JsonRpcError('unexpected message');
1858
+ };
1859
+ const invokeHelper = async (ipc, method, params, useSendAndTransfer) => {
1860
+ const {
1861
+ message,
1862
+ promise
1863
+ } = create$2$1(method, params);
1864
+ if (useSendAndTransfer && ipc.sendAndTransfer) {
1865
+ ipc.sendAndTransfer(message);
1866
+ } else {
1867
+ ipc.send(message);
1868
+ }
1869
+ const responseMessage = await promise;
1870
+ return unwrapJsonRpcResult(responseMessage);
1871
+ };
1872
+ const send = (transport, method, ...params) => {
1873
+ const message = create$4(method, params);
1874
+ transport.send(message);
1875
+ };
1876
+ const invoke = (ipc, method, ...params) => {
1877
+ return invokeHelper(ipc, method, params, false);
1878
+ };
1879
+ const invokeAndTransfer = (ipc, method, ...params) => {
1880
+ return invokeHelper(ipc, method, params, true);
1881
+ };
1553
1882
 
1554
- const Changelog = 'Changelog';
1555
- const Commands = 'Commands';
1556
- const Details = 'Details';
1557
- const Disable = 'Disable';
1558
- const Features = 'Features';
1559
- const JsonValidation = 'JsonValidation';
1560
- const ProgrammingLanguages = 'ProgrammingLanguages';
1561
- const SetColorTheme = 'SetColorTheme';
1562
- const Settings = 'Settings';
1563
- const Theme = 'Theme';
1564
- const Uninstall = 'Uninstall';
1565
- const WebViews = 'WebViews';
1566
- const ScrollToTop = 'scrolltotop';
1883
+ const commands = Object.create(null);
1884
+ const register = commandMap => {
1885
+ Object.assign(commands, commandMap);
1886
+ };
1887
+ const getCommand = key => {
1888
+ return commands[key];
1889
+ };
1890
+ const execute = (command, ...args) => {
1891
+ const fn = getCommand(command);
1892
+ if (!fn) {
1893
+ throw new Error(`command not found ${command}`);
1894
+ }
1895
+ return fn(...args);
1896
+ };
1567
1897
 
1568
- const getScrollToTopVirtualDom = scrollToTopButtonEnabled => {
1569
- return [{
1570
- type: VirtualDomElements.Button,
1571
- className: ScrollToTopButton,
1572
- childCount: 0,
1573
- onClick: HandleClickScrollToTop,
1574
- ariaLabel: scrollToTop(),
1575
- name: ScrollToTop
1576
- }];
1898
+ const createRpc = ipc => {
1899
+ const rpc = {
1900
+ // @ts-ignore
1901
+ ipc,
1902
+ /**
1903
+ * @deprecated
1904
+ */
1905
+ send(method, ...params) {
1906
+ send(ipc, method, ...params);
1907
+ },
1908
+ invoke(method, ...params) {
1909
+ return invoke(ipc, method, ...params);
1910
+ },
1911
+ invokeAndTransfer(method, ...params) {
1912
+ return invokeAndTransfer(ipc, method, ...params);
1913
+ },
1914
+ async dispose() {
1915
+ await ipc?.dispose();
1916
+ }
1917
+ };
1918
+ return rpc;
1919
+ };
1920
+ const requiresSocket = () => {
1921
+ return false;
1922
+ };
1923
+ const preparePrettyError = error => {
1924
+ return error;
1925
+ };
1926
+ const logError = () => {
1927
+ // handled by renderer worker
1928
+ };
1929
+ const handleMessage = event => {
1930
+ const actualRequiresSocket = event?.target?.requiresSocket || requiresSocket;
1931
+ const actualExecute = event?.target?.execute || execute;
1932
+ return handleJsonRpcMessage(event.target, event.data, actualExecute, resolve, preparePrettyError, logError, actualRequiresSocket);
1933
+ };
1934
+ const handleIpc = ipc => {
1935
+ if ('addEventListener' in ipc) {
1936
+ ipc.addEventListener('message', handleMessage);
1937
+ } else if ('on' in ipc) {
1938
+ // deprecated
1939
+ ipc.on('message', handleMessage);
1940
+ }
1941
+ };
1942
+ const listen$1 = async (module, options) => {
1943
+ const rawIpc = await module.listen(options);
1944
+ if (module.signal) {
1945
+ module.signal(rawIpc);
1946
+ }
1947
+ const ipc = module.wrap(rawIpc);
1948
+ return ipc;
1949
+ };
1950
+ const create$5 = async ({
1951
+ commandMap,
1952
+ messagePort
1953
+ }) => {
1954
+ // TODO create a commandMap per rpc instance
1955
+ register(commandMap);
1956
+ const rawIpc = await IpcParentWithMessagePort$1.create({
1957
+ messagePort,
1958
+ isMessagePortOpen: true
1959
+ });
1960
+ const ipc = IpcParentWithMessagePort$1.wrap(rawIpc);
1961
+ handleIpc(ipc);
1962
+ const rpc = createRpc(ipc);
1963
+ messagePort.start();
1964
+ return rpc;
1965
+ };
1966
+ const create$3 = async ({
1967
+ commandMap,
1968
+ send
1969
+ }) => {
1970
+ const {
1971
+ port1,
1972
+ port2
1973
+ } = new MessageChannel();
1974
+ await send(port1);
1975
+ return create$5({
1976
+ commandMap,
1977
+ messagePort: port2
1978
+ });
1979
+ };
1980
+ const TransferMessagePortRpcParent = {
1981
+ __proto__: null,
1982
+ create: create$3
1577
1983
  };
1578
-
1579
- const rpcs = Object.create(null);
1580
- const set$g = (id, rpc) => {
1581
- rpcs[id] = rpc;
1984
+ const create$2 = async ({
1985
+ commandMap
1986
+ }) => {
1987
+ // TODO create a commandMap per rpc instance
1988
+ register(commandMap);
1989
+ const ipc = await listen$1(IpcChildWithModuleWorkerAndMessagePort$1);
1990
+ handleIpc(ipc);
1991
+ const rpc = createRpc(ipc);
1992
+ return rpc;
1582
1993
  };
1583
- const get = id => {
1584
- return rpcs[id];
1994
+ const WebWorkerRpcClient = {
1995
+ __proto__: null,
1996
+ create: create$2
1585
1997
  };
1586
1998
 
1587
- /* eslint-disable @typescript-eslint/explicit-function-return-type */
1588
-
1589
- const create = rpcId => {
1999
+ const create$1 = () => {
2000
+ const states = Object.create(null);
1590
2001
  return {
1591
- // @ts-ignore
1592
- invoke(method, ...params) {
1593
- const rpc = get(rpcId);
1594
- // @ts-ignore
1595
- return rpc.invoke(method, ...params);
2002
+ get(uid) {
2003
+ return states[uid];
1596
2004
  },
1597
- // @ts-ignore
1598
- invokeAndTransfer(method, ...params) {
1599
- const rpc = get(rpcId);
1600
- // @ts-ignore
1601
- return rpc.invokeAndTransfer(method, ...params);
2005
+ set(uid, oldState, newState) {
2006
+ states[uid] = {
2007
+ oldState,
2008
+ newState
2009
+ };
1602
2010
  },
1603
- set(rpc) {
1604
- set$g(rpcId, rpc);
2011
+ dispose(uid) {
2012
+ delete states[uid];
1605
2013
  },
1606
- async dispose() {
1607
- const rpc = get(rpcId);
1608
- await rpc.dispose();
2014
+ getKeys() {
2015
+ return Object.keys(states).map(key => {
2016
+ return Number.parseInt(key);
2017
+ });
2018
+ },
2019
+ clear() {
2020
+ for (const key of Object.keys(states)) {
2021
+ delete states[key];
2022
+ }
2023
+ },
2024
+ wrapCommand(fn) {
2025
+ const wrapped = async (uid, ...args) => {
2026
+ const {
2027
+ newState
2028
+ } = states[uid];
2029
+ const newerState = await fn(newState, ...args);
2030
+ if (newState === newerState) {
2031
+ return;
2032
+ }
2033
+ const latest = states[uid];
2034
+ states[uid] = {
2035
+ oldState: latest.oldState,
2036
+ newState: newerState
2037
+ };
2038
+ };
2039
+ return wrapped;
2040
+ },
2041
+ diff(uid, modules, numbers) {
2042
+ const {
2043
+ oldState,
2044
+ newState
2045
+ } = states[uid];
2046
+ const diffResult = [];
2047
+ for (let i = 0; i < modules.length; i++) {
2048
+ const fn = modules[i];
2049
+ if (!fn(oldState, newState)) {
2050
+ diffResult.push(numbers[i]);
2051
+ }
2052
+ }
2053
+ return diffResult;
1609
2054
  }
1610
2055
  };
1611
2056
  };
1612
- const RendererWorker$1 = 1;
1613
- const MarkdownWorker$1 = 300;
1614
- const {
1615
- invoke: invoke$5,
1616
- set: set$5} = create(MarkdownWorker$1);
1617
- const getVirtualDom$1 = async html => {
1618
- // @ts-ignore
1619
- return invoke$5('Markdown.getVirtualDom', html);
1620
- };
1621
- const render$1 = async (markdown, options) => {
1622
- // @ts-ignore
1623
- return invoke$5('Markdown.render', markdown, options);
1624
- };
1625
- const MarkdownWorker = {
1626
- __proto__: null,
1627
- getVirtualDom: getVirtualDom$1,
1628
- render: render$1,
1629
- set: set$5
1630
- };
1631
- const {
1632
- invoke: invoke$3,
1633
- invokeAndTransfer: invokeAndTransfer$3,
1634
- set: set$3} = create(RendererWorker$1);
1635
- const setColorTheme$2 = async id => {
1636
- // @ts-ignore
1637
- return invoke$3(/* ColorTheme.setColorTheme */'ColorTheme.setColorTheme', /* colorThemeId */id);
1638
- };
1639
- const sendMessagePortToMarkdownWorker$2 = async (port, rpcId) => {
1640
- const command = 'Markdown.handleMessagePort';
1641
- // @ts-ignore
1642
- await invokeAndTransfer$3('SendMessagePortToExtensionHostWorker.sendMessagePortToMarkdownWorker', port, command, rpcId);
1643
- };
1644
- const readFile$2 = async uri => {
1645
- return invoke$3('FileSystem.readFile', uri);
1646
- };
1647
- const getAllExtensions$2 = async () => {
1648
- return invoke$3('ExtensionManagement.getAllExtensions');
1649
- };
1650
- const getFolderSize$2 = async uri => {
1651
- // @ts-ignore
1652
- return await invoke$3('FileSystem.getFolderSize', uri);
1653
- };
1654
- const getExtension$3 = async id => {
1655
- // @ts-ignore
1656
- return invoke$3('ExtensionManagement.getExtension', id);
2057
+ const terminate = () => {
2058
+ globalThis.close();
1657
2059
  };
1658
- const openNativeFolder$1 = async uri => {
1659
- // @ts-ignore
1660
- await invoke$3('OpenNativeFolder.openNativeFolder', uri);
2060
+
2061
+ const copyImage = state => {
2062
+ return state;
1661
2063
  };
1662
- const RendererWorker = {
1663
- __proto__: null,
1664
- getAllExtensions: getAllExtensions$2,
1665
- getExtension: getExtension$3,
1666
- getFolderSize: getFolderSize$2,
1667
- openNativeFolder: openNativeFolder$1,
1668
- readFile: readFile$2,
1669
- sendMessagePortToMarkdownWorker: sendMessagePortToMarkdownWorker$2,
1670
- set: set$3,
1671
- setColorTheme: setColorTheme$2};
1672
2064
 
1673
2065
  const {
2066
+ get,
1674
2067
  set: set$1,
1675
- getVirtualDom,
1676
- render
1677
- } = MarkdownWorker;
2068
+ dispose: dispose$1,
2069
+ wrapCommand
2070
+ } = create$1();
1678
2071
 
1679
- const getMarkdownVirtualDom = async (html, options) => {
1680
- string(html);
1681
- const dom = await getVirtualDom(html);
1682
- const newDom = [...dom];
1683
- if (options?.scrollToTopEnabled) {
1684
- newDom[0].childCount++;
1685
- const extraDom = getScrollToTopVirtualDom();
1686
- newDom.splice(1, 0, ...extraDom);
1687
- }
1688
- return newDom;
2072
+ const create = (uid, uri, x, y, width, height, platform, assetDir) => {
2073
+ const state = {
2074
+ activationEvents: [],
2075
+ assetDir: assetDir || '',
2076
+ badge: '',
2077
+ baseUrl: '',
2078
+ builtinExtensionsBadgeEnabled: true,
2079
+ categories: [],
2080
+ changelogVirtualDom: [],
2081
+ commands: [],
2082
+ description: '',
2083
+ detailsVirtualDom: [],
2084
+ displaySize: '',
2085
+ entries: [],
2086
+ extension: {},
2087
+ extensionId: '',
2088
+ extensionVersion: '',
2089
+ features: [],
2090
+ featuresVirtualDom: [],
2091
+ folderSize: 0,
2092
+ hasColorTheme: false,
2093
+ iconSrc: '',
2094
+ isBuiltin: false,
2095
+ jsonValidation: [],
2096
+ name: '',
2097
+ platform,
2098
+ programmingLanguages: [],
2099
+ readmeScrollTop: 0,
2100
+ resources: [],
2101
+ scrollSource: 0,
2102
+ scrollToTopButtonEnabled: false,
2103
+ secondEntries: [],
2104
+ selectedFeature: '',
2105
+ selectedTab: '',
2106
+ settings: [],
2107
+ settingsButtonEnabled: false,
2108
+ showAdditionalDetailsBreakpoint: 600,
2109
+ sizeOnDisk: 0,
2110
+ sizeValue: 0,
2111
+ themesMarkdownDom: [],
2112
+ uri,
2113
+ webViews: [],
2114
+ width
2115
+ };
2116
+ set$1(uid, state, state);
1689
2117
  };
1690
2118
 
1691
- const getThemeItemMarkdown = (heading, items) => {
1692
- let markdown = '';
1693
- if (items.length > 0) {
1694
- markdown += `### ${heading}`;
1695
- markdown += '\n\n';
1696
- for (const item of items) {
1697
- markdown += `- ${item.label}`;
1698
- markdown += '\n';
1699
- }
1700
- }
1701
- return markdown;
1702
- };
2119
+ const RenderFocus = 2;
2120
+ const RenderItems = 3;
2121
+ const RenderScrollTop = 4;
1703
2122
 
1704
- const getColorThemeMarkdown = themes => {
1705
- const heading = 'Color Themes';
1706
- return getThemeItemMarkdown(heading, themes);
2123
+ const diffType$2 = RenderFocus;
2124
+ const isEqual$2 = (oldState, newState) => {
2125
+ return oldState === newState;
1707
2126
  };
1708
- const getIconThemeMarkdown = iconThemes => {
1709
- const heading = 'File Icon Themes';
1710
- return getThemeItemMarkdown(heading, iconThemes);
2127
+
2128
+ const diffType$1 = RenderItems;
2129
+ const isEqual$1 = (oldState, newState) => {
2130
+ return oldState === newState;
1711
2131
  };
1712
- const getProductIconThemeMarkdown = iconThemes => {
1713
- const heading = 'Product Icon Themes';
1714
- return getThemeItemMarkdown(heading, iconThemes);
2132
+
2133
+ const User = 1;
2134
+
2135
+ const diffType = RenderScrollTop;
2136
+ const isEqual = (oldState, newState) => {
2137
+ return newState.scrollSource === User || oldState.readmeScrollTop === newState.readmeScrollTop;
1715
2138
  };
1716
- const getThemeMarkdown = (themes, iconThemes, productIconThemes) => {
1717
- let markdown = '';
1718
- markdown += getColorThemeMarkdown(themes);
1719
- markdown += getIconThemeMarkdown(iconThemes);
1720
- markdown += getProductIconThemeMarkdown(productIconThemes);
1721
- return markdown;
2139
+
2140
+ const modules = [isEqual$1, isEqual$2, isEqual];
2141
+ const numbers = [diffType$1, diffType$2, diffType];
2142
+
2143
+ const diff2 = uid => {
2144
+ const {
2145
+ oldState,
2146
+ newState
2147
+ } = get(uid);
2148
+ const diffResult = [];
2149
+ for (let i = 0; i < modules.length; i++) {
2150
+ const fn = modules[i];
2151
+ if (!fn(oldState, newState)) {
2152
+ diffResult.push(numbers[i]);
2153
+ }
2154
+ }
2155
+ return diffResult;
1722
2156
  };
1723
2157
 
1724
- const renderMarkdown = async (markdown, options = {}) => {
1725
- const html = await render(markdown, options);
1726
- return html;
2158
+ const dispose = uid => {
2159
+ dispose$1(uid);
1727
2160
  };
1728
2161
 
1729
- const getFeatureDetailsTheme = async (extension, baseUrl) => {
1730
- // Only generate theme markdown when the selected feature is actually "Theme"
1731
- const {
1732
- colorThemes,
1733
- iconThemes,
1734
- productIconThemes
1735
- } = extension;
1736
- const markdown = getThemeMarkdown(colorThemes || [], iconThemes || [], productIconThemes || []);
1737
- const rendered = await renderMarkdown(markdown, {
1738
- baseUrl
1739
- });
1740
- const themesMarkdownDom = await getMarkdownVirtualDom(rendered);
1741
- return {
1742
- themesMarkdownDom
1743
- };
2162
+ const commandIds = ['copyImage', 'getMenuEntries', 'handleClickCategory', 'handleClickDisable', 'handleClickScrollToTop', 'handleClickSettings', 'handleClickSetColorTheme', 'handleClickSize', 'handleClickUninstall', 'handleFeaturesClick', 'handleIconError', 'handleTabsClick', 'handleWheel', 'renderEventListeners', 'resize', 'saveState', 'selectTab', 'terminate'];
2163
+
2164
+ const getCommandIds = () => {
2165
+ return commandIds;
1744
2166
  };
1745
2167
 
1746
- const toWebView = rawWebView => {
1747
- const {
1748
- id,
1749
- selector,
1750
- contentSecurityPolicy,
1751
- elements
1752
- } = rawWebView;
1753
- return {
1754
- id,
1755
- selectorString: JSON.stringify(selector),
1756
- contentSecurityPolicyString: JSON.stringify(contentSecurityPolicy),
1757
- elementsString: JSON.stringify(elements, null, 2)
1758
- };
2168
+ const None = 0;
2169
+
2170
+ const getCopyMenuEntry = () => ({
2171
+ id: 'copy',
2172
+ label: copy(),
2173
+ flags: None,
2174
+ command: 'ClipBoard.execCopy'
2175
+ });
2176
+
2177
+ const getImageMenuEntries = props => {
2178
+ if (!props.isImage) {
2179
+ return [];
2180
+ }
2181
+ return [{
2182
+ id: 'openImageInNewTab',
2183
+ label: openImageInNewTab(),
2184
+ flags: None,
2185
+ command: 'Open.openUrl',
2186
+ args: [props.url || '']
2187
+ }, {
2188
+ id: 'saveImageAs',
2189
+ label: saveImageAs(),
2190
+ flags: None,
2191
+ command: 'SaveFileAs.saveFileAs',
2192
+ args: ['image.png', props.url || '']
2193
+ }];
1759
2194
  };
1760
2195
 
1761
- const getWebViews = extension => {
1762
- const rawWebViews = extension.webViews || [];
1763
- return rawWebViews.map(toWebView);
2196
+ const getLinkMenuEntries = props => {
2197
+ if (!props.isLink) {
2198
+ return [];
2199
+ }
2200
+ return [{
2201
+ id: 'openInNewTab',
2202
+ label: openInNewTab(),
2203
+ flags: None,
2204
+ command: 'Open.openUrl',
2205
+ args: [props.url || '']
2206
+ }];
1764
2207
  };
1765
2208
 
1766
- const getFeatureDetailsWebView = extension => {
1767
- const webViews = getWebViews(extension);
1768
- return {
1769
- webViews
1770
- };
2209
+ const getMenuEntries = props => [...getLinkMenuEntries(props), ...getImageMenuEntries(props), getCopyMenuEntry()];
2210
+
2211
+ const handleClickCategory = async (state, categoryId) => {
2212
+ // TODO: Implement category click functionality
2213
+ return state;
1771
2214
  };
1772
2215
 
1773
- const getFeatureDetailsHandler = featureName => {
1774
- switch (featureName) {
1775
- case Commands:
1776
- return getFeatureDetailsCommand;
1777
- case JsonValidation:
1778
- return getFeatureDetailsJsonValidation;
1779
- case ProgrammingLanguages:
1780
- return getFeatureDetailsProgrammingLanguages;
1781
- case Settings:
1782
- return getFeatureDetailsSettings;
1783
- case WebViews:
1784
- return getFeatureDetailsWebView;
1785
- case Theme:
1786
- return getFeatureDetailsTheme;
1787
- default:
1788
- throw new Error(`unknown feature details handler: ${featureName}`);
1789
- }
2216
+ const handleClickDisable = async state => {
2217
+ return state;
1790
2218
  };
1791
2219
 
1792
2220
  const selectFeature = async (state, name) => {
@@ -1845,6 +2273,7 @@ const {
1845
2273
  readFile: readFile$1,
1846
2274
  set,
1847
2275
  setColorTheme: setColorTheme$1,
2276
+ uninstallExtension,
1848
2277
  sendMessagePortToMarkdownWorker: sendMessagePortToMarkdownWorker$1
1849
2278
  } = RendererWorker;
1850
2279
 
@@ -1884,6 +2313,10 @@ const handleClickSize = async state => {
1884
2313
  };
1885
2314
 
1886
2315
  const handleClickUninstall = async state => {
2316
+ const {
2317
+ id
2318
+ } = state.extension;
2319
+ await uninstallExtension(id);
1887
2320
  return state;
1888
2321
  };
1889
2322
 
@@ -1999,7 +2432,8 @@ const selectTabFeatures = async state => {
1999
2432
  const {
2000
2433
  extension,
2001
2434
  baseUrl,
2002
- selectedFeature
2435
+ selectedFeature,
2436
+ features
2003
2437
  } = state;
2004
2438
  const actualSelectedFeature = selectedFeature || Theme;
2005
2439
  const fn = getFeatureDetailsHandler(actualSelectedFeature);
@@ -2007,6 +2441,7 @@ const selectTabFeatures = async state => {
2007
2441
  return {
2008
2442
  ...state,
2009
2443
  selectedTab: Features,
2444
+ selectedFeature: features[0].id || '',
2010
2445
  ...partialNewState
2011
2446
  };
2012
2447
  };
@@ -2060,7 +2495,7 @@ const createMarkdownWorkerRpc = async () => {
2060
2495
 
2061
2496
  const initializeMarkdownWorker = async () => {
2062
2497
  const rpc = await createMarkdownWorkerRpc();
2063
- set$1(rpc);
2498
+ set$3(rpc);
2064
2499
  };
2065
2500
 
2066
2501
  const initialize = async () => {
@@ -2068,57 +2503,10 @@ const initialize = async () => {
2068
2503
  // TODO create connection to file system worker
2069
2504
  };
2070
2505
 
2071
- const isLanguageBasicsExtension = extension => {
2072
- return extension.name && extension.name.startsWith('Language Basics');
2073
- };
2074
-
2075
- const isThemeExtension = extension => {
2076
- return extension.name && extension.name.endsWith(' Theme');
2077
- };
2078
-
2079
2506
  const Web = 1;
2080
2507
  const Electron = 2;
2081
2508
  const Remote = 3;
2082
2509
 
2083
- const getIcon = (extension, platform, assetDir) => {
2084
- if (!extension) {
2085
- return extensionDefaultIcon(assetDir);
2086
- }
2087
- if (!extension.path || !extension.icon) {
2088
- if (isLanguageBasicsExtension(extension)) {
2089
- return extensionLanguageBasics(assetDir);
2090
- }
2091
- if (isThemeExtension(extension)) {
2092
- return extensionTheme(assetDir);
2093
- }
2094
- return extensionDefaultIcon(assetDir);
2095
- }
2096
- if (platform === Remote || platform === Electron) {
2097
- if (extension.builtin) {
2098
- return `${assetDir}/extensions/${extension.id}/${extension.icon}`;
2099
- }
2100
- return `/remote/${extension.path}/${extension.icon}`; // TODO support windows paths
2101
- }
2102
- return '';
2103
- };
2104
-
2105
- const getDescription = extension => {
2106
- if (!extension || !extension.description) {
2107
- return 'n/a';
2108
- }
2109
- return extension.description;
2110
- };
2111
-
2112
- const getName = extension => {
2113
- if (extension && extension.name) {
2114
- return extension.name;
2115
- }
2116
- if (extension && extension.id) {
2117
- return extension.id;
2118
- }
2119
- return 'n/a';
2120
- };
2121
-
2122
2510
  const getAllExtensions = async platform => {
2123
2511
  if (platform === Web) {
2124
2512
  return [];
@@ -2148,6 +2536,13 @@ const getExtension = async (id, platform) => {
2148
2536
  }
2149
2537
  };
2150
2538
 
2539
+ class ExtensionNotFoundError extends Error {
2540
+ constructor(extensionId) {
2541
+ super(`extension not found: ${extensionId}`);
2542
+ this.name = 'ExtensionNotFoundError';
2543
+ }
2544
+ }
2545
+
2151
2546
  const getRemoteSrc = uri => {
2152
2547
  const src = `/remote${uri}`;
2153
2548
  return src;
@@ -2281,48 +2676,6 @@ const getExtensionIdFromUri = uri => {
2281
2676
  return id;
2282
2677
  };
2283
2678
 
2284
- const hasThemes = extension => {
2285
- return extension && (extension.colorThemes || extension.iconThemes || extension.productIconThemes);
2286
- };
2287
- const hasCommands = extension => {
2288
- return extension && extension.commands;
2289
- };
2290
- const hasJsonValidation = extension => {
2291
- return extension && extension.jsonValidation;
2292
- };
2293
- const hasProgrammingLanguages = extension => {
2294
- return extension && extension.programmingLanguages;
2295
- };
2296
- const hasSettings = extension => {
2297
- return extension && extension.settings;
2298
- };
2299
- const hasWebViews = extension => {
2300
- return extension && extension.webViews;
2301
- };
2302
- const ifElseFeature = (id, label, isEnabled, selectedFeature, extension) => {
2303
- if (!isEnabled(extension)) {
2304
- return [];
2305
- }
2306
- return [{
2307
- id,
2308
- label,
2309
- selected: selectedFeature === id
2310
- }];
2311
- };
2312
- const getFeatures = (selectedFeature, extension) => {
2313
- if (!selectedFeature) {
2314
- selectedFeature = Theme;
2315
- }
2316
- const textTheme = theme();
2317
- const textCommands = commands();
2318
- const textJsonValidation = jsonValidation();
2319
- const programmingLanguages$1 = programmingLanguages();
2320
- const settings$1 = settings();
2321
- const webViews$1 = webViews();
2322
- const features = [...ifElseFeature(Theme, textTheme, hasThemes, selectedFeature, extension), ...ifElseFeature(Commands, textCommands, hasCommands, selectedFeature, extension), ...ifElseFeature(JsonValidation, textJsonValidation, hasJsonValidation, selectedFeature, extension), ...ifElseFeature(ProgrammingLanguages, programmingLanguages$1, hasProgrammingLanguages, selectedFeature, extension), ...ifElseFeature(Settings, settings$1, hasSettings, selectedFeature, extension), ...ifElseFeature(WebViews, webViews$1, hasWebViews, selectedFeature, extension)];
2323
- return features;
2324
- };
2325
-
2326
2679
  const getFolderSize = async uri => {
2327
2680
  if (!uri) {
2328
2681
  throw new VError(`uri is required`);
@@ -2374,10 +2727,98 @@ const getViewletSize = width => {
2374
2727
  return Large;
2375
2728
  };
2376
2729
 
2730
+ const isLanguageBasicsExtension = extension => {
2731
+ return extension.name && extension.name.startsWith('Language Basics');
2732
+ };
2733
+
2734
+ const isThemeExtension = extension => {
2735
+ return extension.name && extension.name.endsWith(' Theme');
2736
+ };
2737
+
2738
+ const getIcon = (extension, platform, assetDir) => {
2739
+ if (!extension) {
2740
+ return extensionDefaultIcon(assetDir);
2741
+ }
2742
+ if (!extension.path || !extension.icon) {
2743
+ if (isLanguageBasicsExtension(extension)) {
2744
+ return extensionLanguageBasics(assetDir);
2745
+ }
2746
+ if (isThemeExtension(extension)) {
2747
+ return extensionTheme(assetDir);
2748
+ }
2749
+ return extensionDefaultIcon(assetDir);
2750
+ }
2751
+ if (platform === Remote || platform === Electron) {
2752
+ if (extension.builtin) {
2753
+ return `${assetDir}/extensions/${extension.id}/${extension.icon}`;
2754
+ }
2755
+ return `/remote/${extension.path}/${extension.icon}`; // TODO support windows paths
2756
+ }
2757
+ return '';
2758
+ };
2759
+
2760
+ const getDescription = extension => {
2761
+ if (!extension || !extension.description) {
2762
+ return 'n/a';
2763
+ }
2764
+ return extension.description;
2765
+ };
2766
+
2767
+ const getName = extension => {
2768
+ if (extension && extension.name) {
2769
+ return extension.name;
2770
+ }
2771
+ if (extension && extension.id) {
2772
+ return extension.id;
2773
+ }
2774
+ return 'n/a';
2775
+ };
2776
+
2777
+ const getBadge = (builtin, badgeEnabled) => {
2778
+ if (builtin && badgeEnabled) {
2779
+ return 'builtin';
2780
+ }
2781
+ return '';
2782
+ };
2783
+
2377
2784
  const hasColorThemes = extension => {
2378
2785
  return Boolean(extension && extension.colorThemes && extension.colorThemes.length > 0);
2379
2786
  };
2380
2787
 
2788
+ const loadHeaderContent = (state, platform, extension) => {
2789
+ const {
2790
+ assetDir,
2791
+ builtinExtensionsBadgeEnabled
2792
+ } = state;
2793
+ const iconSrc = getIcon(extension, platform, assetDir);
2794
+ const description = getDescription(extension);
2795
+ const name = getName(extension);
2796
+ const extensionUri = extension.uri || extension.path;
2797
+ const extensionId = extension?.id || 'n/a';
2798
+ const extensionVersion = extension?.version || 'n/a';
2799
+ const hasColorTheme = hasColorThemes(extension);
2800
+ const isBuiltin = extension?.builtin;
2801
+ const badge = getBadge(isBuiltin, builtinExtensionsBadgeEnabled);
2802
+ return {
2803
+ badge,
2804
+ description,
2805
+ extension,
2806
+ extensionId,
2807
+ extensionUri,
2808
+ extensionVersion,
2809
+ hasColorTheme,
2810
+ iconSrc,
2811
+ name
2812
+ };
2813
+ };
2814
+
2815
+ const getSavedReadmeScrollTop = savedState => {
2816
+ if (savedState && typeof savedState === 'object' && 'readmeScrollTop' in savedState && typeof savedState.readmeScrollTop === 'number') {
2817
+ return savedState.readmeScrollTop;
2818
+ }
2819
+ return 0;
2820
+ };
2821
+
2381
2822
  const getSavedSelectedFeature = savedState => {
2382
2823
  if (savedState && typeof savedState === 'object' && 'selectedFeature' in savedState && typeof savedState.selectedFeature === 'string') {
2383
2824
  return savedState.selectedFeature;
@@ -2395,23 +2836,35 @@ const getSavedSelectedTab = savedState => {
2395
2836
  const restoreState = savedState => {
2396
2837
  const selectedTab = getSavedSelectedTab(savedState);
2397
2838
  const selectedFeature = getSavedSelectedFeature(savedState);
2839
+ const readmeScrollTop = getSavedReadmeScrollTop(savedState);
2398
2840
  return {
2399
2841
  selectedFeature,
2400
- selectedTab
2842
+ selectedTab,
2843
+ readmeScrollTop
2401
2844
  };
2402
2845
  };
2403
2846
 
2404
2847
  const loadContent = async (state, platform, savedState) => {
2405
2848
  const {
2406
- uri,
2407
2849
  width,
2408
- assetDir
2850
+ uri
2409
2851
  } = state;
2410
2852
  const id = getExtensionIdFromUri(uri);
2411
2853
  const extension = await getExtension(id, platform);
2412
2854
  if (!extension) {
2413
- throw new Error(`extension not found: ${id}`);
2855
+ throw new ExtensionNotFoundError(id);
2414
2856
  }
2857
+ const headerData = loadHeaderContent(state, platform, extension);
2858
+ const {
2859
+ badge,
2860
+ description,
2861
+ extensionId,
2862
+ extensionUri,
2863
+ extensionVersion,
2864
+ hasColorTheme,
2865
+ iconSrc,
2866
+ name
2867
+ } = headerData;
2415
2868
  const readmeContent = await loadReadmeContent(extension.path);
2416
2869
  const baseUrl = getBaseUrl(extension.path, platform);
2417
2870
  const readmeHtml = await renderMarkdown(readmeContent, {
@@ -2420,16 +2873,13 @@ const loadContent = async (state, platform, savedState) => {
2420
2873
  const detailsVirtualDom = await getMarkdownVirtualDom(readmeHtml, {
2421
2874
  scrollToTopEnabled: true
2422
2875
  });
2423
- const iconSrc = getIcon(extension, platform, assetDir);
2424
- const description = getDescription(extension);
2425
- const name = getName(extension);
2426
2876
  const size = getViewletSize(width);
2427
2877
  const {
2428
2878
  selectedFeature,
2429
- selectedTab
2879
+ selectedTab,
2880
+ readmeScrollTop
2430
2881
  } = restoreState(savedState);
2431
- const features = getFeatures(selectedFeature, extension);
2432
- const extensionUri = extension.uri || extension.path;
2882
+ const features = getFeatures(selectedFeature || Theme, extension);
2433
2883
  const folderSize = await getFolderSize(extensionUri);
2434
2884
  const displaySize = getDisplaySize(size);
2435
2885
  const entries = getEntries();
@@ -2438,11 +2888,9 @@ const loadContent = async (state, platform, savedState) => {
2438
2888
  const resources = getResources();
2439
2889
  const sizeValue = getViewletSize(width || 0);
2440
2890
  const isBuiltin = extension?.builtin;
2441
- const hasColorTheme = hasColorThemes(extension);
2442
- const extensionId = extension?.id || 'n/a';
2443
- const extensionVersion = extension?.version || 'n/a';
2444
2891
  return {
2445
2892
  ...state,
2893
+ badge,
2446
2894
  baseUrl,
2447
2895
  categories,
2448
2896
  description,
@@ -2450,20 +2898,21 @@ const loadContent = async (state, platform, savedState) => {
2450
2898
  displaySize,
2451
2899
  entries,
2452
2900
  extension,
2901
+ extensionId,
2902
+ extensionVersion,
2453
2903
  features,
2454
2904
  folderSize,
2455
2905
  hasColorTheme,
2456
2906
  iconSrc,
2457
2907
  isBuiltin,
2458
2908
  name,
2909
+ readmeScrollTop,
2459
2910
  resources,
2911
+ scrollToTopButtonEnabled: true,
2460
2912
  secondEntries,
2461
2913
  selectedTab,
2462
2914
  sizeOnDisk: size,
2463
- sizeValue,
2464
- extensionId,
2465
- extensionVersion,
2466
- scrollToTopButtonEnabled: true
2915
+ sizeValue
2467
2916
  };
2468
2917
  };
2469
2918
 
@@ -2471,13 +2920,6 @@ const loadContent2 = async (state, savedState) => {
2471
2920
  return loadContent(state, state.platform, savedState);
2472
2921
  };
2473
2922
 
2474
- const getBadge = (builtin, badgeEnabled) => {
2475
- if (builtin && badgeEnabled) {
2476
- return 'builtin';
2477
- }
2478
- return '';
2479
- };
2480
-
2481
2923
  const getExtensionDetailButtons = (hasColorTheme, isBuiltin) => {
2482
2924
  const allActions = [{
2483
2925
  label: setColorTheme$3(),
@@ -2542,7 +2984,7 @@ const getCategoriesDom = categories => {
2542
2984
  }, ...categories.flatMap(getCategoryVirtualDom)];
2543
2985
  };
2544
2986
 
2545
- const parentNode$1 = {
2987
+ const parentNode = {
2546
2988
  type: VirtualDomElements.Dt,
2547
2989
  className: MoreInfoEntryKey,
2548
2990
  childCount: 1
@@ -2551,425 +2993,175 @@ const getMoreInfoEntryKeyVirtualDom = item => {
2551
2993
  const {
2552
2994
  key
2553
2995
  } = item;
2554
- return [parentNode$1, text(key)];
2996
+ return [parentNode, text(key)];
2555
2997
  };
2556
2998
 
2557
- const getTag = (onClick, code) => {
2558
- if (onClick) {
2559
- return VirtualDomElements.A;
2560
- }
2561
- if (code) {
2562
- return VirtualDomElements.Code;
2563
- }
2564
- return VirtualDomElements.Dd;
2565
- };
2566
- const getClassName = (onClick, code) => {
2999
+ const getMoreInfoEntryValueClassName = (onClick, code) => {
2567
3000
  if (onClick) {
2568
3001
  return mergeClassNames(MoreInfoEntryValue, Link);
2569
3002
  }
2570
3003
  if (code) {
2571
- return mergeClassNames(MoreInfoEntryValue, Code);
3004
+ return mergeClassNames(MoreInfoEntryValue, Code$1);
2572
3005
  }
2573
3006
  return MoreInfoEntryValue;
2574
3007
  };
2575
- const getMoreInfoEntryValueVirtualDom = item => {
2576
- const {
2577
- value,
2578
- onClick,
2579
- code,
2580
- title
2581
- } = item;
2582
- const type = getTag(onClick, code);
2583
- const className = getClassName(onClick, code);
2584
- return [{
2585
- type: type,
2586
- className,
2587
- childCount: 1,
2588
- onClick,
2589
- title
2590
- }, text(value)];
2591
- };
2592
-
2593
- const parentNodeEven = {
2594
- type: VirtualDomElements.Dt,
2595
- className: MoreInfoEntry,
2596
- childCount: 2
2597
- };
2598
- const parentNodeOdd = {
2599
- type: VirtualDomElements.Dt,
2600
- className: mergeClassNames(MoreInfoEntry, MoreInfoEntryOdd),
2601
- childCount: 2
2602
- };
2603
- const getMoreInfoEntryVirtualDom = item => {
2604
- const {
2605
- odd
2606
- } = item;
2607
- const node = odd ? parentNodeOdd : parentNodeEven;
2608
- return [node, ...getMoreInfoEntryKeyVirtualDom(item), ...getMoreInfoEntryValueVirtualDom(item)];
2609
- };
2610
-
2611
- const getMoreInfoVirtualDom = items => {
2612
- return [{
2613
- type: VirtualDomElements.Dl,
2614
- className: MoreInfo,
2615
- childCount: items.length
2616
- }, ...items.flatMap(getMoreInfoEntryVirtualDom)];
2617
- };
2618
-
2619
- const resourceNode = {
2620
- // TODO use link with url
2621
- type: VirtualDomElements.Div,
2622
- className: Resource,
2623
- childCount: 1
2624
- };
2625
- const getResourceVirtualDom = resource => {
2626
- const {
2627
- label
2628
- } = resource;
2629
- return [resourceNode, text(label)];
2630
- };
2631
-
2632
- const getResourcesVirtualDom = resources => {
2633
- return [{
2634
- type: VirtualDomElements.Div,
2635
- className: Resources,
2636
- childCount: resources.length
2637
- }, ...resources.flatMap(getResourceVirtualDom)];
2638
- };
2639
-
2640
- const getAdditionalDetailsVirtualDom = (showAdditionalDetails, firstHeading, entries, secondHeading, secondEntries, thirdHeading, categories, fourthHeading, resources) => {
2641
- if (!showAdditionalDetails) {
2642
- return [];
2643
- }
2644
- return [{
2645
- type: VirtualDomElements.Div,
2646
- className: Aside,
2647
- childCount: 1
2648
- }, {
2649
- type: VirtualDomElements.Div,
2650
- className: AdditionalDetails,
2651
- tabIndex: 0,
2652
- childCount: 4
2653
- }, ...getAdditionalDetailsEntryVirtualDom(firstHeading, entries, getMoreInfoVirtualDom), ...getAdditionalDetailsEntryVirtualDom(secondHeading, secondEntries, getMoreInfoVirtualDom), ...getAdditionalDetailsEntryVirtualDom(thirdHeading, categories, getCategoriesDom), ...getAdditionalDetailsEntryVirtualDom(fourthHeading, resources, getResourcesVirtualDom)];
2654
- };
2655
-
2656
- const getInstallationEntries = (displaySize, extensionId, extensionVersion, extensionUri) => {
2657
- const entries = [{
2658
- key: 'Identifier',
2659
- value: extensionId,
2660
- odd: true,
2661
- code: true
2662
- }, {
2663
- key: 'Version',
2664
- value: extensionVersion,
2665
- code: true
2666
- }, {
2667
- key: 'Last Updated',
2668
- value: 'n/a',
2669
- odd: true
2670
- }, {
2671
- key: 'Size',
2672
- value: displaySize,
2673
- onClick: HandleClickSize,
2674
- title: extensionUri
2675
- }];
2676
- return entries;
2677
- };
2678
-
2679
- const getMarketplaceEntries = () => {
2680
- return [{
2681
- key: 'Published',
2682
- value: 'n/a',
2683
- odd: true
2684
- }, {
2685
- key: 'Last Released',
2686
- value: 'n/a'
2687
- }];
2688
- };
2689
-
2690
- // import * as GetScrollToTopVirtualDom from '../GetScrollToTopVirtualDom/GetScrollToTopVirtualDom.ts'
2691
-
2692
- const getChildCount = (additionalDetails, scrollToTopEnabled) => {
2693
- let count = 1;
2694
- if (additionalDetails) {
2695
- count++;
2696
- }
2697
- // if (scrollToTopEnabled) {
2698
- // count++
2699
- // }
2700
- return count;
2701
- };
2702
- const getDetailsVirtualDom = (sanitizedReadmeHtml, displaySize, extensionId, extensionVersion, width, extensionUri, scrollToTopButtonEnabled, categories$1, resources$1, showAdditionalDetailsBreakpoint // new parameter, no default
2703
- ) => {
2704
- const firstHeading = installation();
2705
- const entries = getInstallationEntries(displaySize, extensionId, extensionVersion, extensionUri);
2706
- const secondHeading = marketplace();
2707
- const secondEntries = getMarketplaceEntries();
2708
- const thirdHeading = categories();
2709
- const fourthHeading = resources();
2710
- const showAdditionalDetails = width > showAdditionalDetailsBreakpoint;
2711
- const childCount = getChildCount(showAdditionalDetails);
2712
- const dom = [{
2713
- type: VirtualDomElements.Div,
2714
- className: ExtensionDetailPanel,
2715
- childCount: childCount,
2716
- role: AriaRoles.Panel
2717
- },
2718
- // ...GetScrollToTopVirtualDom.getScrollToTopVirtualDom(scrollToTopButtonEnabled),
2719
- ...sanitizedReadmeHtml, ...getAdditionalDetailsVirtualDom(showAdditionalDetails, firstHeading, entries, secondHeading, secondEntries, thirdHeading, categories$1, fourthHeading, resources$1)];
2720
- return dom;
2721
- };
2722
-
2723
- const getCommandTableEntries = rows => {
2724
- const id$1 = id();
2725
- const label$1 = label();
2726
- return {
2727
- headings: [id$1, label$1],
2728
- rows
2729
- };
2730
- };
2731
-
2732
- const getFeatureContentHeadingVirtualDom = heading => {
2733
- return [{
2734
- type: VirtualDomElements.H1,
2735
- childCount: 1
2736
- }, text(heading)];
2737
- };
2738
-
2739
- const getTableHeadingVirtualDom = heading => {
2740
- return [{
2741
- type: VirtualDomElements.Th,
2742
- className: TableHeading,
2743
- childCount: 1
2744
- }, text(heading)];
2745
- };
2746
3008
 
2747
- const getCellCodeVirtualDom = value => {
2748
- return [{
2749
- type: VirtualDomElements.Td,
2750
- className: TableCell,
2751
- childCount: 1
2752
- }, {
2753
- type: VirtualDomElements.Code,
2754
- childCount: 1
2755
- }, text(value)];
2756
- };
2757
-
2758
- const getCellTextVirtualDom = value => {
2759
- return [{
2760
- type: VirtualDomElements.Td,
2761
- className: TableCell,
2762
- childCount: 1
2763
- }, text(value)];
2764
- };
2765
-
2766
- const getCellRenderer = type => {
2767
- switch (type) {
2768
- case Code$2:
2769
- return getCellCodeVirtualDom;
2770
- case Text$1:
2771
- return getCellTextVirtualDom;
2772
- default:
2773
- throw new Error(`unexpected cell type ${type}`);
3009
+ const getMoreInfoEntryValueTag = (onClick, code) => {
3010
+ if (onClick) {
3011
+ return VirtualDomElements.A;
2774
3012
  }
3013
+ if (code) {
3014
+ return VirtualDomElements.Code;
3015
+ }
3016
+ return VirtualDomElements.Dd;
2775
3017
  };
2776
3018
 
2777
- const getCellVirtualDom = entry => {
2778
- const {
2779
- value,
2780
- type
2781
- } = entry;
2782
- const fn = getCellRenderer(type);
2783
- return fn(value);
2784
- };
2785
-
2786
- const getTableRowVirtualDom = entries => {
2787
- return [{
2788
- type: VirtualDomElements.Tr,
2789
- childCount: entries.length
2790
- }, ...entries.flatMap(getCellVirtualDom)];
2791
- };
2792
-
2793
- const getTableVirtualDom = tableInfo => {
2794
- const {
2795
- headings,
2796
- rows
2797
- } = tableInfo;
2798
- return [{
2799
- type: VirtualDomElements.Table,
2800
- className: Table,
2801
- childCount: 2
2802
- }, {
2803
- type: VirtualDomElements.THead,
2804
- childCount: 1
2805
- }, {
2806
- type: VirtualDomElements.Tr,
2807
- childCount: headings.length
2808
- }, ...headings.flatMap(getTableHeadingVirtualDom), {
2809
- type: VirtualDomElements.TBody,
2810
- childCount: rows.length
2811
- }, ...rows.flatMap(getTableRowVirtualDom)];
2812
- };
2813
-
2814
- // TODO have typed view-model
2815
- const getFeatureCommandsVirtualDom = commands$1 => {
2816
- const heading = commands();
2817
- const tableInfo = getCommandTableEntries(commands$1);
3019
+ const getMoreInfoEntryValueVirtualDom = item => {
3020
+ const {
3021
+ value,
3022
+ onClick,
3023
+ code,
3024
+ title
3025
+ } = item;
3026
+ const type = getMoreInfoEntryValueTag(onClick, code);
3027
+ const className = getMoreInfoEntryValueClassName(onClick, code);
2818
3028
  return [{
2819
- type: VirtualDomElements.Div,
2820
- className: FeatureContent,
2821
- childCount: 2
2822
- }, ...getFeatureContentHeadingVirtualDom(heading), ...getTableVirtualDom(tableInfo)];
3029
+ type: type,
3030
+ className,
3031
+ childCount: 1,
3032
+ onClick,
3033
+ title
3034
+ }, text(value)];
2823
3035
  };
2824
3036
 
2825
- const getJsonValidationTableEntries = rows => {
2826
- return {
2827
- headings: [fileMatch(), schema()],
2828
- rows
2829
- };
3037
+ const parentNodeEven = {
3038
+ type: VirtualDomElements.Dt,
3039
+ className: MoreInfoEntry,
3040
+ childCount: 2
2830
3041
  };
2831
-
2832
- const parentNode = {
2833
- type: VirtualDomElements.Div,
2834
- className: FeatureContent,
3042
+ const parentNodeOdd = {
3043
+ type: VirtualDomElements.Dt,
3044
+ className: mergeClassNames(MoreInfoEntry, MoreInfoEntryOdd),
2835
3045
  childCount: 2
2836
3046
  };
2837
- const getFeatureJsonValidationVirtualDom = jsonValidation$1 => {
2838
- const heading = jsonValidation();
2839
- const tableInfo = getJsonValidationTableEntries(jsonValidation$1);
2840
- return [parentNode, ...getFeatureContentHeadingVirtualDom(heading), ...getTableVirtualDom(tableInfo)];
3047
+ const getMoreInfoEntryVirtualDom = item => {
3048
+ const {
3049
+ odd
3050
+ } = item;
3051
+ const node = odd ? parentNodeOdd : parentNodeEven;
3052
+ return [node, ...getMoreInfoEntryKeyVirtualDom(item), ...getMoreInfoEntryValueVirtualDom(item)];
2841
3053
  };
2842
3054
 
2843
- const getFeatureNotImplementedVirtualDom = () => {
2844
- const heading = 'Not implemented';
3055
+ const getMoreInfoVirtualDom = items => {
2845
3056
  return [{
2846
- type: VirtualDomElements.Div,
2847
- className: FeatureContent,
2848
- childCount: 1
2849
- }, {
2850
- type: VirtualDomElements.H1,
2851
- childCount: 1
2852
- }, text(heading)];
3057
+ type: VirtualDomElements.Dl,
3058
+ className: MoreInfo,
3059
+ childCount: items.length
3060
+ }, ...items.flatMap(getMoreInfoEntryVirtualDom)];
2853
3061
  };
2854
3062
 
2855
- const getFeatureProgrammingLanguagesVirtualDom = () => {
2856
- const heading = programmingLanguages();
2857
- // TODO
2858
- return [{
2859
- type: VirtualDomElements.Div,
2860
- className: FeatureContent,
2861
- childCount: 1
2862
- }, ...getFeatureContentHeadingVirtualDom(heading)];
3063
+ const resourceNode = {
3064
+ // TODO use link with url
3065
+ type: VirtualDomElements.Div,
3066
+ className: Resource,
3067
+ childCount: 1
2863
3068
  };
2864
-
2865
- const getSettingsTableEntries = rows => {
2866
- const textId = id();
2867
- const textLabel = label();
2868
- return {
2869
- headings: [textId, textLabel],
2870
- rows
2871
- };
3069
+ const getResourceVirtualDom = resource => {
3070
+ const {
3071
+ label
3072
+ } = resource;
3073
+ return [resourceNode, text(label)];
2872
3074
  };
2873
3075
 
2874
- const getFeatureSettingsVirtualDom = rows => {
2875
- const heading = settings();
2876
- const tableInfo = getSettingsTableEntries(rows);
3076
+ const getResourcesVirtualDom = resources => {
2877
3077
  return [{
2878
3078
  type: VirtualDomElements.Div,
2879
- className: FeatureContent,
2880
- childCount: 2
2881
- }, ...getFeatureContentHeadingVirtualDom(heading), ...getTableVirtualDom(tableInfo)];
3079
+ className: Resources,
3080
+ childCount: resources.length
3081
+ }, ...resources.flatMap(getResourceVirtualDom)];
2882
3082
  };
2883
3083
 
2884
- const getVirtualDomChildCount = dom => {
2885
- const max = dom.length - 1;
2886
- let stack = [];
2887
- for (let i = max; i >= 0; i--) {
2888
- const element = dom[i];
2889
- if (element.childCount > 0) {
2890
- stack = stack.slice(element.childCount);
2891
- }
2892
- stack.unshift(element);
3084
+ const getAdditionalDetailsVirtualDom = (showAdditionalDetails, firstHeading, entries, secondHeading, secondEntries, thirdHeading, categories, fourthHeading, resources) => {
3085
+ if (!showAdditionalDetails) {
3086
+ return [];
2893
3087
  }
2894
- return stack.length;
2895
- };
2896
-
2897
- const getFeatureThemesVirtualDom = themesDom => {
2898
- const childCount = getVirtualDomChildCount(themesDom);
2899
- const heading = theme();
2900
3088
  return [{
2901
3089
  type: VirtualDomElements.Div,
2902
- className: FeatureContent,
2903
- childCount: 2
2904
- }, ...getFeatureContentHeadingVirtualDom(heading), {
3090
+ className: Aside,
3091
+ childCount: 1
3092
+ }, {
2905
3093
  type: VirtualDomElements.Div,
2906
- className: DefaultMarkdown,
2907
- childCount
2908
- }, ...themesDom];
3094
+ className: AdditionalDetails,
3095
+ tabIndex: 0,
3096
+ childCount: 4
3097
+ }, ...getAdditionalDetailsEntryVirtualDom(firstHeading, entries, getMoreInfoVirtualDom), ...getAdditionalDetailsEntryVirtualDom(secondHeading, secondEntries, getMoreInfoVirtualDom), ...getAdditionalDetailsEntryVirtualDom(thirdHeading, categories, getCategoriesDom), ...getAdditionalDetailsEntryVirtualDom(fourthHeading, resources, getResourcesVirtualDom)];
2909
3098
  };
2910
3099
 
2911
- const heading = {
2912
- type: VirtualDomElements.H2,
2913
- className: DefinitionListItemHeading,
2914
- childCount: 1
2915
- };
2916
- const pre = {
2917
- type: VirtualDomElements.Pre,
2918
- className: DefinitionListItemValue,
2919
- childCount: 1
2920
- };
2921
- const item = {
2922
- type: VirtualDomElements.Div,
2923
- className: DefinitionListItem,
2924
- childCount: 2
2925
- };
2926
- const getWebViewVirtualDom = webView => {
2927
- const {
2928
- id: id$1,
2929
- selectorString,
2930
- contentSecurityPolicyString,
2931
- elementsString
2932
- } = webView;
2933
- const textId = id();
2934
- const textSelector = selector();
2935
- const textContentSecurityPolicy = contentSecurityPolicy();
2936
- const textElements = elements();
2937
- return [{
2938
- type: VirtualDomElements.Div,
2939
- className: FeatureWebView,
2940
- childCount: 5
2941
- }, item, heading, text(textId), pre, text(id$1), item, heading, text(textSelector), pre, text(selectorString), item, heading, text(textContentSecurityPolicy), pre, text(contentSecurityPolicyString), item, heading, text(textElements), pre, text(elementsString)];
3100
+ const getInstallationEntries = (displaySize, extensionId, extensionVersion, extensionUri) => {
3101
+ const entries = [{
3102
+ key: 'Identifier',
3103
+ value: extensionId,
3104
+ odd: true,
3105
+ code: true
3106
+ }, {
3107
+ key: 'Version',
3108
+ value: extensionVersion,
3109
+ code: true
3110
+ }, {
3111
+ key: 'Last Updated',
3112
+ value: 'n/a',
3113
+ odd: true
3114
+ }, {
3115
+ key: 'Size',
3116
+ value: displaySize,
3117
+ onClick: HandleClickSize,
3118
+ title: extensionUri
3119
+ }];
3120
+ return entries;
2942
3121
  };
2943
3122
 
2944
- const getFeatureWebViewsVirtualDom = webViews$1 => {
2945
- const heading = webViews();
3123
+ const getMarketplaceEntries = () => {
2946
3124
  return [{
2947
- type: VirtualDomElements.Div,
2948
- className: FeatureContent,
2949
- childCount: 2
2950
- }, ...getFeatureContentHeadingVirtualDom(heading), {
2951
- type: VirtualDomElements.Div,
2952
- childCount: webViews$1.length
2953
- }, ...webViews$1.flatMap(getWebViewVirtualDom)];
3125
+ key: 'Published',
3126
+ value: 'n/a',
3127
+ odd: true
3128
+ }, {
3129
+ key: 'Last Released',
3130
+ value: 'n/a'
3131
+ }];
2954
3132
  };
2955
3133
 
2956
- const getFeatureContentVirtualDom = (themesDom, selectedFeature, commands, jsonValidation, settings, webViews) => {
2957
- switch (selectedFeature) {
2958
- case Theme:
2959
- return getFeatureThemesVirtualDom(themesDom);
2960
- case Commands:
2961
- return getFeatureCommandsVirtualDom(commands);
2962
- case JsonValidation:
2963
- return getFeatureJsonValidationVirtualDom(jsonValidation);
2964
- case ProgrammingLanguages:
2965
- return getFeatureProgrammingLanguagesVirtualDom();
2966
- case Settings:
2967
- return getFeatureSettingsVirtualDom(settings);
2968
- case WebViews:
2969
- return getFeatureWebViewsVirtualDom(webViews);
2970
- default:
2971
- return getFeatureNotImplementedVirtualDom();
3134
+ // import * as GetScrollToTopVirtualDom from '../GetScrollToTopVirtualDom/GetScrollToTopVirtualDom.ts'
3135
+
3136
+ const getChildCount = (additionalDetails, scrollToTopEnabled) => {
3137
+ let count = 1;
3138
+ if (additionalDetails) {
3139
+ count++;
2972
3140
  }
3141
+ // if (scrollToTopEnabled) {
3142
+ // count++
3143
+ // }
3144
+ return count;
3145
+ };
3146
+ const getDetailsVirtualDom = (sanitizedReadmeHtml, displaySize, extensionId, extensionVersion, width, extensionUri, scrollToTopButtonEnabled, categories$1, resources$1, showAdditionalDetailsBreakpoint // new parameter, no default
3147
+ ) => {
3148
+ const firstHeading = installation();
3149
+ const entries = getInstallationEntries(displaySize, extensionId, extensionVersion, extensionUri);
3150
+ const secondHeading = marketplace();
3151
+ const secondEntries = getMarketplaceEntries();
3152
+ const thirdHeading = categories();
3153
+ const fourthHeading = resources();
3154
+ const showAdditionalDetails = width > showAdditionalDetailsBreakpoint;
3155
+ const childCount = getChildCount(showAdditionalDetails);
3156
+ const dom = [{
3157
+ type: VirtualDomElements.Div,
3158
+ className: ExtensionDetailPanel,
3159
+ childCount: childCount,
3160
+ role: AriaRoles.Panel
3161
+ },
3162
+ // ...GetScrollToTopVirtualDom.getScrollToTopVirtualDom(scrollToTopButtonEnabled),
3163
+ ...sanitizedReadmeHtml, ...getAdditionalDetailsVirtualDom(showAdditionalDetails, firstHeading, entries, secondHeading, secondEntries, thirdHeading, categories$1, fourthHeading, resources$1)];
3164
+ return dom;
2973
3165
  };
2974
3166
 
2975
3167
  const getFeatureListItemVirtualDom = feature => {
@@ -2998,15 +3190,17 @@ const getFeatureListVirtualDom = features => {
2998
3190
  }, ...features.flatMap(getFeatureListItemVirtualDom)];
2999
3191
  };
3000
3192
 
3001
- const getFeaturesVirtualDom = (features, themesDom, selectedFeature, commands, jsonValidation, settings, webViews) => {
3193
+ const getFeaturesVirtualDom = (features, selectedFeature, state) => {
3002
3194
  if (features.length === 0) {
3003
3195
  const none$1 = none();
3004
3196
  return [{
3005
3197
  type: VirtualDomElements.Div,
3006
3198
  className: Features$1,
3007
- childCount: 3
3199
+ childCount: 1
3008
3200
  }, text(none$1)];
3009
3201
  }
3202
+ const fn = getFeatureVirtualDomHandler(selectedFeature);
3203
+ const featureVirtualDom = fn(state);
3010
3204
  return [{
3011
3205
  type: VirtualDomElements.Div,
3012
3206
  className: Features$1,
@@ -3015,15 +3209,15 @@ const getFeaturesVirtualDom = (features, themesDom, selectedFeature, commands, j
3015
3209
  type: VirtualDomElements.Div,
3016
3210
  className: mergeClassNames(Sash, SashVertical),
3017
3211
  childCount: 0
3018
- }, ...getFeatureContentVirtualDom(themesDom, selectedFeature, commands, jsonValidation, settings, webViews)];
3212
+ }, ...featureVirtualDom];
3019
3213
  };
3020
3214
 
3021
- const getExtensionDetailContentVirtualDom = (sanitizedReadmeHtml, themesDom, selectedTab, features, displaySize, extensionId, extensionVersion, selectedFeature, width, scrollToTopButtonEnabled, categories, resources, breakpoint, commands, jsonValidation, settings, webViews, extensionUri, changelogDom) => {
3215
+ const getExtensionDetailContentVirtualDom = (sanitizedReadmeHtml, themesDom, selectedTab, features, displaySize, extensionId, extensionVersion, selectedFeature, width, scrollToTopButtonEnabled, categories, resources, breakpoint, commands, jsonValidation, settings, webViews, extensionUri, changelogDom, activationEvents, state) => {
3022
3216
  switch (selectedTab) {
3023
3217
  case Details:
3024
3218
  return getDetailsVirtualDom(sanitizedReadmeHtml, displaySize, extensionId, extensionVersion, width, extensionUri, scrollToTopButtonEnabled, categories, resources, breakpoint);
3025
3219
  case Features:
3026
- return getFeaturesVirtualDom(features, themesDom, selectedFeature, commands, jsonValidation, settings, webViews);
3220
+ return getFeaturesVirtualDom(state.features, state.selectedFeature, state);
3027
3221
  case Changelog:
3028
3222
  return getChangelogVirtualDom(changelogDom);
3029
3223
  default:
@@ -3129,7 +3323,7 @@ const getTabs = selectedTab => {
3129
3323
  name: Details,
3130
3324
  selected: selectedTab === Details
3131
3325
  }, {
3132
- label: features(),
3326
+ label: features$1(),
3133
3327
  name: Features,
3134
3328
  selected: selectedTab === Features
3135
3329
  }, {
@@ -3192,43 +3386,43 @@ const getExtensionDetailVirtualDom = (newState, selectedTab) => {
3192
3386
  // 3. virtual dom
3193
3387
  // 4. dom
3194
3388
  const {
3195
- displaySize,
3196
- themesMarkdownDom,
3197
- selectedFeature,
3198
- sizeValue,
3199
- isBuiltin,
3389
+ activationEvents,
3200
3390
  categories,
3201
- resources,
3202
- showAdditionalDetailsBreakpoint,
3203
- scrollToTopButtonEnabled,
3204
- hasColorTheme,
3205
- builtinExtensionsBadgeEnabled,
3206
- settingsButtonEnabled,
3207
- name,
3208
- iconSrc,
3391
+ changelogVirtualDom,
3392
+ commands,
3209
3393
  description,
3210
3394
  detailsVirtualDom,
3211
- features,
3395
+ displaySize,
3396
+ extension,
3212
3397
  extensionId,
3213
3398
  extensionVersion,
3214
- commands,
3399
+ features,
3400
+ hasColorTheme,
3401
+ iconSrc,
3402
+ isBuiltin,
3215
3403
  jsonValidation,
3404
+ name,
3405
+ resources,
3406
+ scrollToTopButtonEnabled,
3407
+ selectedFeature,
3216
3408
  settings,
3409
+ settingsButtonEnabled,
3410
+ showAdditionalDetailsBreakpoint,
3411
+ sizeValue,
3412
+ themesMarkdownDom,
3217
3413
  webViews,
3218
- extension,
3219
- changelogVirtualDom
3414
+ badge
3220
3415
  } = newState;
3221
3416
  const extensionUri = extension.uri || extension.path || '';
3222
3417
  const width = newState?.width || 500;
3223
3418
  const tabs = getTabs(selectedTab);
3224
3419
  const sizeClass = getClassNames(sizeValue);
3225
- const buttonDefs = getExtensionDetailButtons(hasColorTheme, isBuiltin);
3226
- const badge = getBadge(isBuiltin, builtinExtensionsBadgeEnabled); // TODO compute in loadContent
3420
+ const buttonDefs = getExtensionDetailButtons(hasColorTheme, isBuiltin); // TODO compute in loadContent
3227
3421
  const dom = [{
3228
3422
  type: VirtualDomElements.Div,
3229
3423
  className: mergeClassNames(Viewlet, ExtensionDetail, sizeClass),
3230
3424
  childCount: 3
3231
- }, ...getExtensionDetailHeaderVirtualDom(name, iconSrc, description, badge, buttonDefs, settingsButtonEnabled), ...getTabsVirtualDom(tabs), ...getExtensionDetailContentVirtualDom(detailsVirtualDom, themesMarkdownDom, selectedTab, features, displaySize, extensionId, extensionVersion, selectedFeature, width, scrollToTopButtonEnabled, categories, resources, showAdditionalDetailsBreakpoint, commands, jsonValidation, settings, webViews, extensionUri, changelogVirtualDom)];
3425
+ }, ...getExtensionDetailHeaderVirtualDom(name, iconSrc, description, badge, buttonDefs, settingsButtonEnabled), ...getTabsVirtualDom(tabs), ...getExtensionDetailContentVirtualDom(detailsVirtualDom, themesMarkdownDom, selectedTab, features, displaySize, extensionId, extensionVersion, selectedFeature, width, scrollToTopButtonEnabled, categories, resources, showAdditionalDetailsBreakpoint, commands, jsonValidation, settings, webViews, extensionUri, changelogVirtualDom, activationEvents, newState)];
3232
3426
  return dom;
3233
3427
  };
3234
3428
 
@@ -3271,8 +3465,8 @@ const render2 = (uid, diffResult) => {
3271
3465
  const {
3272
3466
  oldState,
3273
3467
  newState
3274
- } = get$1(uid);
3275
- set$2(uid, oldState, newState);
3468
+ } = get(uid);
3469
+ set$1(uid, oldState, newState);
3276
3470
  const commands = applyRender(oldState, newState, diffResult);
3277
3471
  return commands;
3278
3472
  };
@@ -3327,20 +3521,22 @@ const resize = (state, dimensions) => {
3327
3521
  const saveState = uid => {
3328
3522
  const {
3329
3523
  newState
3330
- } = get$1(uid);
3524
+ } = get(uid);
3331
3525
  const {
3332
3526
  selectedTab,
3333
- selectedFeature
3527
+ selectedFeature,
3528
+ readmeScrollTop
3334
3529
  } = newState;
3335
3530
  return {
3336
3531
  selectedTab,
3337
- selectedFeature
3532
+ selectedFeature,
3533
+ readmeScrollTop
3338
3534
  };
3339
3535
  };
3340
3536
 
3341
3537
  const commandMap = {
3342
3538
  'ExtensionDetail.copyImage': wrapCommand(copyImage),
3343
- 'ExtensionDetail.create': create$1,
3539
+ 'ExtensionDetail.create': create,
3344
3540
  'ExtensionDetail.diff2': diff2,
3345
3541
  'ExtensionDetail.dispose': dispose,
3346
3542
  'ExtensionDetail.getCommandIds': getCommandIds,
@@ -3374,6 +3570,7 @@ const listen = async () => {
3374
3570
  };
3375
3571
 
3376
3572
  const main = async () => {
3573
+ registerAllFeatures();
3377
3574
  await listen();
3378
3575
  };
3379
3576