@lvce-editor/extension-detail-view 3.37.0 → 3.39.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,2222 @@
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 HandleReadmeScroll = 'handleReadmeScroll';
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].onScroll = HandleReadmeScroll;
788
+ newDom[0].childCount++;
789
+ const extraDom = getScrollToTopVirtualDom();
790
+ newDom.splice(1, 0, ...extraDom);
627
791
  }
628
- return parentStack;
792
+ return newDom;
629
793
  };
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
- }
794
+
795
+ const getThemeItemMarkdown = (heading, items) => {
796
+ let markdown = '';
797
+ if (items.length > 0) {
798
+ markdown += `### ${heading}`;
799
+ markdown += '\n\n';
800
+ for (const item of items) {
801
+ markdown += `- ${item.label}`;
802
+ markdown += '\n';
679
803
  }
680
- return restoredError;
681
- }
682
- if (typeof error === 'string') {
683
- return new Error(`JsonRpc Error: ${error}`);
684
804
  }
685
- return new Error(`JsonRpc Error: ${error}`);
805
+ return markdown;
686
806
  };
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');
807
+
808
+ const getColorThemeMarkdown = themes => {
809
+ const heading = 'Color Themes';
810
+ return getThemeItemMarkdown(heading, themes);
696
811
  };
697
- const warn = (...args) => {
698
- console.warn(...args);
812
+ const getIconThemeMarkdown = iconThemes => {
813
+ const heading = 'File Icon Themes';
814
+ return getThemeItemMarkdown(heading, iconThemes);
699
815
  };
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);
816
+ const getProductIconThemeMarkdown = iconThemes => {
817
+ const heading = 'Product Icon Themes';
818
+ return getThemeItemMarkdown(heading, iconThemes);
709
819
  };
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;
717
- }
718
- return undefined;
820
+ const getThemeMarkdown = (themes, iconThemes, productIconThemes) => {
821
+ let markdown = '';
822
+ markdown += getColorThemeMarkdown(themes);
823
+ markdown += getIconThemeMarkdown(iconThemes);
824
+ markdown += getProductIconThemeMarkdown(productIconThemes);
825
+ return markdown;
719
826
  };
720
- const isAlreadyStack = line => {
721
- return line.trim().startsWith('at ');
827
+
828
+ const renderMarkdown = async (markdown, options = {}) => {
829
+ const html = await render(markdown, options);
830
+ return html;
722
831
  };
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);
832
+
833
+ const getThemeDetails = async (extension, baseUrl) => {
834
+ const {
835
+ colorThemes,
836
+ iconThemes,
837
+ productIconThemes
838
+ } = extension;
839
+ const markdown = getThemeMarkdown(colorThemes || [], iconThemes || [], productIconThemes || []);
840
+ const rendered = await renderMarkdown(markdown, {
841
+ baseUrl
842
+ });
843
+ const themesMarkdownDom = await getMarkdownVirtualDom(rendered);
844
+ return {
845
+ themesMarkdownDom
846
+ };
847
+ };
848
+
849
+ const featureColorThemeEnabled = extension => {
850
+ if (!extension || typeof extension !== 'object' || !('colorThemes' in extension)) {
851
+ return false;
728
852
  }
729
- return stackString;
853
+ return Array.isArray(extension.colorThemes);
730
854
  };
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
- };
855
+
856
+ const featureIconThemeEnabled = extension => {
857
+ if (!extension || typeof extension !== 'object' || !('iconThemes' in extension)) {
858
+ return false;
738
859
  }
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
748
- }
749
- };
860
+ return Array.isArray(extension.iconThemes);
750
861
  };
751
- const create$1$1 = (id, error) => {
752
- return {
753
- jsonrpc: Two,
754
- id,
755
- error
756
- };
862
+
863
+ const featureProductIconThemeEnabled = extension => {
864
+ if (!extension || typeof extension !== 'object' || !('productIconThemes' in extension)) {
865
+ return false;
866
+ }
867
+ return Array.isArray(extension.productIconThemes);
757
868
  };
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);
869
+
870
+ const featureThemeEnabled = extension => {
871
+ return featureColorThemeEnabled(extension) || featureIconThemeEnabled(extension) || featureProductIconThemeEnabled(extension);
763
872
  };
764
- const create$6 = (message, result) => {
765
- return {
766
- jsonrpc: Two,
767
- id: message.id,
768
- result: result ?? null
769
- };
873
+
874
+ const getVirtualDomChildCount = dom => {
875
+ const max = dom.length - 1;
876
+ let stack = [];
877
+ for (let i = max; i >= 0; i--) {
878
+ const element = dom[i];
879
+ if (element.childCount > 0) {
880
+ stack = stack.slice(element.childCount);
881
+ }
882
+ stack.unshift(element);
883
+ }
884
+ return stack.length;
770
885
  };
771
- const getSuccessResponse = (message, result) => {
772
- const resultProperty = result ?? null;
773
- return create$6(message, resultProperty);
886
+
887
+ const getFeatureThemesVirtualDom = themesDom => {
888
+ const childCount = getVirtualDomChildCount(themesDom);
889
+ const heading = theme();
890
+ return [{
891
+ type: VirtualDomElements.Div,
892
+ className: FeatureContent,
893
+ childCount: 2
894
+ }, ...getFeatureContentHeadingVirtualDom(heading), {
895
+ type: VirtualDomElements.Div,
896
+ className: DefaultMarkdown,
897
+ childCount
898
+ }, ...themesDom];
774
899
  };
775
- const getErrorResponseSimple = (id, error) => {
900
+
901
+ const getThemeVirtualDom = state => {
902
+ return getFeatureThemesVirtualDom(state.themesMarkdownDom);
903
+ };
904
+
905
+ const toWebView = rawWebView => {
906
+ const {
907
+ id,
908
+ selector,
909
+ contentSecurityPolicy,
910
+ elements
911
+ } = rawWebView;
776
912
  return {
777
- jsonrpc: Two,
778
913
  id,
779
- error: {
780
- code: Custom,
781
- // @ts-ignore
782
- message: error.message,
783
- data: error
784
- }
914
+ selectorString: JSON.stringify(selector),
915
+ contentSecurityPolicyString: JSON.stringify(contentSecurityPolicy),
916
+ elementsString: JSON.stringify(elements, null, 2)
785
917
  };
786
918
  };
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);
796
- }
797
- };
798
- const defaultPreparePrettyError = error => {
799
- return error;
800
- };
801
- const defaultLogError = () => {
802
- // ignore
803
- };
804
- const defaultRequiresSocket = () => {
805
- return false;
919
+
920
+ const getWebViews = extension => {
921
+ const rawWebViews = extension.webViews || [];
922
+ return rawWebViews.map(toWebView);
806
923
  };
807
- const defaultResolve = resolve;
808
924
 
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
- }
925
+ const getWebViewsDetails = async extension => {
926
+ const webViews = getWebViews(extension);
823
927
  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]
928
+ webViews
831
929
  };
832
930
  };
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;
931
+
932
+ const featureWebViewsEnabled = extension => {
933
+ if (!extension || typeof extension !== 'object' || !('webViews' in extension)) {
934
+ return false;
861
935
  }
862
- throw new JsonRpcError('unexpected message');
936
+ return Array.isArray(extension.webViews);
863
937
  };
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);
938
+
939
+ const heading = {
940
+ type: VirtualDomElements.H2,
941
+ className: DefinitionListItemHeading,
942
+ childCount: 1
876
943
  };
877
- const send = (transport, method, ...params) => {
878
- const message = create$4$1(method, params);
879
- transport.send(message);
944
+ const pre = {
945
+ type: VirtualDomElements.Pre,
946
+ className: DefinitionListItemValue,
947
+ childCount: 1
880
948
  };
881
- const invoke = (ipc, method, ...params) => {
882
- return invokeHelper(ipc, method, params, false);
949
+ const item = {
950
+ type: VirtualDomElements.Div,
951
+ className: DefinitionListItem,
952
+ childCount: 2
883
953
  };
884
- const invokeAndTransfer = (ipc, method, ...params) => {
885
- return invokeHelper(ipc, method, params, true);
954
+ const getWebViewVirtualDom = webView => {
955
+ const {
956
+ id,
957
+ selectorString,
958
+ contentSecurityPolicyString,
959
+ elementsString
960
+ } = webView;
961
+ const textId = id$1();
962
+ const textSelector = selector();
963
+ const textContentSecurityPolicy = contentSecurityPolicy();
964
+ const textElements = elements();
965
+ return [{
966
+ type: VirtualDomElements.Div,
967
+ className: FeatureWebView,
968
+ childCount: 5
969
+ }, 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)];
886
970
  };
887
971
 
888
- const commands$1 = Object.create(null);
889
- const register = commandMap => {
890
- Object.assign(commands$1, commandMap);
891
- };
892
- const getCommand = key => {
893
- return commands$1[key];
894
- };
895
- const execute = (command, ...args) => {
896
- const fn = getCommand(command);
897
- if (!fn) {
898
- throw new Error(`command not found ${command}`);
899
- }
900
- return fn(...args);
972
+ const getFeatureWebViewsVirtualDom = webViews$1 => {
973
+ const heading = webViews();
974
+ return [{
975
+ type: VirtualDomElements.Div,
976
+ className: FeatureContent,
977
+ childCount: 2
978
+ }, ...getFeatureContentHeadingVirtualDom(heading), {
979
+ type: VirtualDomElements.Div,
980
+ childCount: webViews$1.length
981
+ }, ...webViews$1.flatMap(getWebViewVirtualDom)];
901
982
  };
902
983
 
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();
921
- }
922
- };
923
- return rpc;
984
+ const getWebViewsVirtualDom = state => {
985
+ return getFeatureWebViewsVirtualDom(state.webViews);
924
986
  };
925
- const requiresSocket = () => {
926
- return false;
987
+
988
+ const registerAllFeatures = () => {
989
+ register$1({
990
+ id: Theme,
991
+ getLabel: theme,
992
+ isEnabled: featureThemeEnabled,
993
+ getDetails: getThemeDetails,
994
+ getVirtualDom: getThemeVirtualDom
995
+ });
996
+ register$1({
997
+ id: Commands,
998
+ getLabel: commands$1,
999
+ isEnabled: featureCommandsEnabled,
1000
+ getDetails: getCommandsDetails,
1001
+ getVirtualDom: getCommandsVirtualDom
1002
+ });
1003
+ register$1({
1004
+ id: Settings,
1005
+ getLabel: settings,
1006
+ isEnabled: featureSettingsEnabled,
1007
+ getDetails: getSettingsDetails,
1008
+ getVirtualDom: getSettingsVirtualDom
1009
+ });
1010
+ register$1({
1011
+ id: JsonValidation,
1012
+ getLabel: jsonValidation,
1013
+ isEnabled: featureJsonValidationEnabled,
1014
+ getDetails: getJsonValidationDetails,
1015
+ getVirtualDom: getJsonValidationVirtualDom
1016
+ });
1017
+ register$1({
1018
+ id: ProgrammingLanguages,
1019
+ getLabel: programmingLanguages,
1020
+ isEnabled: featureProgrammingLanguagesEnabled,
1021
+ getDetails: getProgrammingLanguagesDetails,
1022
+ getVirtualDom: getProgrammingLanguagesVirtualDom
1023
+ });
1024
+ register$1({
1025
+ id: WebViews,
1026
+ getLabel: webViews,
1027
+ isEnabled: featureWebViewsEnabled,
1028
+ getDetails: getWebViewsDetails,
1029
+ getVirtualDom: getWebViewsVirtualDom
1030
+ });
1031
+ register$1({
1032
+ id: ActivationEvents,
1033
+ getLabel: activationEvents,
1034
+ isEnabled: featureActivationEventsEnabled,
1035
+ getDetails: getActivationEventsDetails,
1036
+ getVirtualDom: getActivationEventsVirtualDom
1037
+ });
927
1038
  };
928
- const preparePrettyError = error => {
929
- return error;
1039
+
1040
+ const normalizeLine = line => {
1041
+ if (line.startsWith('Error: ')) {
1042
+ return line.slice('Error: '.length);
1043
+ }
1044
+ if (line.startsWith('VError: ')) {
1045
+ return line.slice('VError: '.length);
1046
+ }
1047
+ return line;
930
1048
  };
931
- const logError = () => {
932
- // handled by renderer worker
1049
+ const getCombinedMessage = (error, message) => {
1050
+ const stringifiedError = normalizeLine(`${error}`);
1051
+ if (message) {
1052
+ return `${message}: ${stringifiedError}`;
1053
+ }
1054
+ return stringifiedError;
933
1055
  };
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);
1056
+ const NewLine$2 = '\n';
1057
+ const getNewLineIndex$1 = (string, startIndex = undefined) => {
1058
+ return string.indexOf(NewLine$2, startIndex);
938
1059
  };
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);
1060
+ const mergeStacks = (parent, child) => {
1061
+ if (!child) {
1062
+ return parent;
1063
+ }
1064
+ const parentNewLineIndex = getNewLineIndex$1(parent);
1065
+ const childNewLineIndex = getNewLineIndex$1(child);
1066
+ if (childNewLineIndex === -1) {
1067
+ return parent;
1068
+ }
1069
+ const parentFirstLine = parent.slice(0, parentNewLineIndex);
1070
+ const childRest = child.slice(childNewLineIndex);
1071
+ const childFirstLine = normalizeLine(child.slice(0, childNewLineIndex));
1072
+ if (parentFirstLine.includes(childFirstLine)) {
1073
+ return parentFirstLine + childRest;
945
1074
  }
1075
+ return child;
946
1076
  };
947
- const listen$1 = async (module, options) => {
948
- const rawIpc = await module.listen(options);
949
- if (module.signal) {
950
- module.signal(rawIpc);
1077
+ class VError extends Error {
1078
+ constructor(error, message) {
1079
+ const combinedMessage = getCombinedMessage(error, message);
1080
+ super(combinedMessage);
1081
+ this.name = 'VError';
1082
+ if (error instanceof Error) {
1083
+ this.stack = mergeStacks(this.stack, error.stack);
1084
+ }
1085
+ if (error.codeFrame) {
1086
+ // @ts-ignore
1087
+ this.codeFrame = error.codeFrame;
1088
+ }
1089
+ if (error.code) {
1090
+ // @ts-ignore
1091
+ this.code = error.code;
1092
+ }
951
1093
  }
952
- const ipc = module.wrap(rawIpc);
953
- return ipc;
1094
+ }
1095
+
1096
+ const isMessagePort = value => {
1097
+ return value && value instanceof MessagePort;
954
1098
  };
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;
1099
+ const isMessagePortMain = value => {
1100
+ return value && value.constructor && value.constructor.name === 'MessagePortMain';
970
1101
  };
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
- });
1102
+ const isOffscreenCanvas = value => {
1103
+ return typeof OffscreenCanvas !== 'undefined' && value instanceof OffscreenCanvas;
984
1104
  };
985
- const TransferMessagePortRpcParent = {
986
- __proto__: null,
987
- create: create$3
1105
+ const isInstanceOf = (value, constructorName) => {
1106
+ return value?.constructor?.name === constructorName;
988
1107
  };
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;
1108
+ const isSocket = value => {
1109
+ return isInstanceOf(value, 'Socket');
998
1110
  };
999
- const WebWorkerRpcClient = {
1000
- __proto__: null,
1001
- create: create$4
1111
+ const transferrables = [isMessagePort, isMessagePortMain, isOffscreenCanvas, isSocket];
1112
+ const isTransferrable = value => {
1113
+ for (const fn of transferrables) {
1114
+ if (fn(value)) {
1115
+ return true;
1116
+ }
1117
+ }
1118
+ return false;
1002
1119
  };
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;
1120
+ const walkValue = (value, transferrables, isTransferrable) => {
1121
+ if (!value) {
1122
+ return;
1123
+ }
1124
+ if (isTransferrable(value)) {
1125
+ transferrables.push(value);
1126
+ return;
1127
+ }
1128
+ if (Array.isArray(value)) {
1129
+ for (const item of value) {
1130
+ walkValue(item, transferrables, isTransferrable);
1131
+ }
1132
+ return;
1133
+ }
1134
+ if (typeof value === 'object') {
1135
+ for (const property of Object.values(value)) {
1136
+ walkValue(property, transferrables, isTransferrable);
1059
1137
  }
1138
+ return;
1139
+ }
1140
+ };
1141
+ const getTransferrables = value => {
1142
+ const transferrables = [];
1143
+ walkValue(value, transferrables, isTransferrable);
1144
+ return transferrables;
1145
+ };
1146
+ const attachEvents = that => {
1147
+ const handleMessage = (...args) => {
1148
+ const data = that.getData(...args);
1149
+ that.dispatchEvent(new MessageEvent('message', {
1150
+ data
1151
+ }));
1152
+ };
1153
+ that.onMessage(handleMessage);
1154
+ const handleClose = event => {
1155
+ that.dispatchEvent(new Event('close'));
1060
1156
  };
1157
+ that.onClose(handleClose);
1061
1158
  };
1062
- const terminate = () => {
1063
- globalThis.close();
1159
+ class Ipc extends EventTarget {
1160
+ constructor(rawIpc) {
1161
+ super();
1162
+ this._rawIpc = rawIpc;
1163
+ attachEvents(this);
1164
+ }
1165
+ }
1166
+ const E_INCOMPATIBLE_NATIVE_MODULE = 'E_INCOMPATIBLE_NATIVE_MODULE';
1167
+ const E_MODULES_NOT_SUPPORTED_IN_ELECTRON = 'E_MODULES_NOT_SUPPORTED_IN_ELECTRON';
1168
+ const ERR_MODULE_NOT_FOUND = 'ERR_MODULE_NOT_FOUND';
1169
+ const NewLine$1 = '\n';
1170
+ const joinLines$1 = lines => {
1171
+ return lines.join(NewLine$1);
1064
1172
  };
1065
-
1066
- const copyImage = state => {
1067
- return state;
1173
+ const RE_AT = /^\s+at/;
1174
+ const RE_AT_PROMISE_INDEX = /^\s*at async Promise.all \(index \d+\)$/;
1175
+ const isNormalStackLine = line => {
1176
+ return RE_AT.test(line) && !RE_AT_PROMISE_INDEX.test(line);
1068
1177
  };
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
1178
+ const getDetails = lines => {
1179
+ const index = lines.findIndex(isNormalStackLine);
1180
+ if (index === -1) {
1181
+ return {
1182
+ actualMessage: joinLines$1(lines),
1183
+ rest: []
1184
+ };
1185
+ }
1186
+ let lastIndex = index - 1;
1187
+ while (++lastIndex < lines.length) {
1188
+ if (!isNormalStackLine(lines[lastIndex])) {
1189
+ break;
1190
+ }
1191
+ }
1192
+ return {
1193
+ actualMessage: lines[index - 1],
1194
+ rest: lines.slice(index, lastIndex)
1119
1195
  };
1120
- set$2(uid, state, state);
1121
1196
  };
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;
1130
- };
1131
-
1132
- const diffType$1 = RenderItems;
1133
- const isEqual$1 = (oldState, newState) => {
1134
- return oldState === newState;
1197
+ const splitLines$1 = lines => {
1198
+ return lines.split(NewLine$1);
1135
1199
  };
1136
-
1137
- const User = 1;
1138
-
1139
- const diffType = RenderScrollTop;
1140
- const isEqual = (oldState, newState) => {
1141
- return newState.scrollSource === User || oldState.readmeScrollTop === newState.readmeScrollTop;
1200
+ const RE_MESSAGE_CODE_BLOCK_START = /^Error: The module '.*'$/;
1201
+ const RE_MESSAGE_CODE_BLOCK_END = /^\s* at/;
1202
+ const isMessageCodeBlockStartIndex = line => {
1203
+ return RE_MESSAGE_CODE_BLOCK_START.test(line);
1142
1204
  };
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
- }
1158
- }
1159
- return diffResult;
1205
+ const isMessageCodeBlockEndIndex = line => {
1206
+ return RE_MESSAGE_CODE_BLOCK_END.test(line);
1160
1207
  };
1161
-
1162
- const dispose = uid => {
1163
- dispose$1(uid);
1208
+ const getMessageCodeBlock = stderr => {
1209
+ const lines = splitLines$1(stderr);
1210
+ const startIndex = lines.findIndex(isMessageCodeBlockStartIndex);
1211
+ const endIndex = startIndex + lines.slice(startIndex).findIndex(isMessageCodeBlockEndIndex, startIndex);
1212
+ const relevantLines = lines.slice(startIndex, endIndex);
1213
+ const relevantMessage = relevantLines.join(' ').slice('Error: '.length);
1214
+ return relevantMessage;
1164
1215
  };
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;
1216
+ const isModuleNotFoundMessage = line => {
1217
+ return line.includes('[ERR_MODULE_NOT_FOUND]');
1170
1218
  };
1171
-
1172
- const emptyObject = {};
1173
- const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
1174
- const i18nString = (key, placeholders = emptyObject) => {
1175
- if (placeholders === emptyObject) {
1176
- return key;
1177
- }
1178
- const replacer = (match, rest) => {
1179
- return placeholders[rest];
1219
+ const getModuleNotFoundError = stderr => {
1220
+ const lines = splitLines$1(stderr);
1221
+ const messageIndex = lines.findIndex(isModuleNotFoundMessage);
1222
+ const message = lines[messageIndex];
1223
+ return {
1224
+ message,
1225
+ code: ERR_MODULE_NOT_FOUND
1180
1226
  };
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);
1216
1227
  };
1217
- const marketplace = () => {
1218
- return i18nString(Marketplace);
1219
- };
1220
- const categories = () => {
1221
- return i18nString(Categories$1);
1228
+ const isModuleNotFoundError = stderr => {
1229
+ if (!stderr) {
1230
+ return false;
1231
+ }
1232
+ return stderr.includes('ERR_MODULE_NOT_FOUND');
1222
1233
  };
1223
- const resources = () => {
1224
- return i18nString(Resources$1);
1234
+ const isModulesSyntaxError = stderr => {
1235
+ if (!stderr) {
1236
+ return false;
1237
+ }
1238
+ return stderr.includes('SyntaxError: Cannot use import statement outside a module');
1225
1239
  };
1226
- const copy = () => {
1227
- return i18nString(Copy);
1240
+ const RE_NATIVE_MODULE_ERROR = /^innerError Error: Cannot find module '.*.node'/;
1241
+ const RE_NATIVE_MODULE_ERROR_2 = /was compiled against a different Node.js version/;
1242
+ const isUnhelpfulNativeModuleError = stderr => {
1243
+ return RE_NATIVE_MODULE_ERROR.test(stderr) && RE_NATIVE_MODULE_ERROR_2.test(stderr);
1228
1244
  };
1229
- const changelog = () => {
1230
- return i18nString(Changelog$2);
1245
+ const getNativeModuleErrorMessage = stderr => {
1246
+ const message = getMessageCodeBlock(stderr);
1247
+ return {
1248
+ message: `Incompatible native node module: ${message}`,
1249
+ code: E_INCOMPATIBLE_NATIVE_MODULE
1250
+ };
1231
1251
  };
1232
- const details = () => {
1233
- return i18nString(Details$1);
1252
+ const getModuleSyntaxError = () => {
1253
+ return {
1254
+ message: `ES Modules are not supported in electron`,
1255
+ code: E_MODULES_NOT_SUPPORTED_IN_ELECTRON
1256
+ };
1234
1257
  };
1235
- const disable = () => {
1236
- return i18nString(Disable$1);
1258
+ const getHelpfulChildProcessError = (stdout, stderr) => {
1259
+ if (isUnhelpfulNativeModuleError(stderr)) {
1260
+ return getNativeModuleErrorMessage(stderr);
1261
+ }
1262
+ if (isModulesSyntaxError(stderr)) {
1263
+ return getModuleSyntaxError();
1264
+ }
1265
+ if (isModuleNotFoundError(stderr)) {
1266
+ return getModuleNotFoundError(stderr);
1267
+ }
1268
+ const lines = splitLines$1(stderr);
1269
+ const {
1270
+ actualMessage,
1271
+ rest
1272
+ } = getDetails(lines);
1273
+ return {
1274
+ message: actualMessage,
1275
+ code: '',
1276
+ stack: rest
1277
+ };
1237
1278
  };
1238
- const features = () => {
1239
- return i18nString(Features$2);
1279
+ class IpcError extends VError {
1280
+ // @ts-ignore
1281
+ constructor(betterMessage, stdout = '', stderr = '') {
1282
+ if (stdout || stderr) {
1283
+ // @ts-ignore
1284
+ const {
1285
+ message,
1286
+ code,
1287
+ stack
1288
+ } = getHelpfulChildProcessError(stdout, stderr);
1289
+ const cause = new Error(message);
1290
+ // @ts-ignore
1291
+ cause.code = code;
1292
+ cause.stack = stack;
1293
+ super(cause, betterMessage);
1294
+ } else {
1295
+ super(betterMessage);
1296
+ }
1297
+ // @ts-ignore
1298
+ this.name = 'IpcError';
1299
+ // @ts-ignore
1300
+ this.stdout = stdout;
1301
+ // @ts-ignore
1302
+ this.stderr = stderr;
1303
+ }
1304
+ }
1305
+ const readyMessage = 'ready';
1306
+ const getData$2 = event => {
1307
+ return event.data;
1240
1308
  };
1241
- const none = () => {
1242
- return i18nString(None$1);
1309
+ const listen$7 = () => {
1310
+ // @ts-ignore
1311
+ if (typeof WorkerGlobalScope === 'undefined') {
1312
+ throw new TypeError('module is not in web worker scope');
1313
+ }
1314
+ return globalThis;
1243
1315
  };
1244
- const openInNewTab = () => {
1245
- return i18nString(OpenInNewTab);
1316
+ const signal$8 = global => {
1317
+ global.postMessage(readyMessage);
1246
1318
  };
1247
- const label = () => {
1248
- return i18nString(Label);
1249
- };
1250
- const openImageInNewTab = () => {
1251
- return i18nString(OpenImageInNewTab);
1319
+ class IpcChildWithModuleWorker extends Ipc {
1320
+ getData(event) {
1321
+ return getData$2(event);
1322
+ }
1323
+ send(message) {
1324
+ // @ts-ignore
1325
+ this._rawIpc.postMessage(message);
1326
+ }
1327
+ sendAndTransfer(message) {
1328
+ const transfer = getTransferrables(message);
1329
+ // @ts-ignore
1330
+ this._rawIpc.postMessage(message, transfer);
1331
+ }
1332
+ dispose() {
1333
+ // ignore
1334
+ }
1335
+ onClose(callback) {
1336
+ // ignore
1337
+ }
1338
+ onMessage(callback) {
1339
+ this._rawIpc.addEventListener('message', callback);
1340
+ }
1341
+ }
1342
+ const wrap$f = global => {
1343
+ return new IpcChildWithModuleWorker(global);
1252
1344
  };
1253
- const saveImageAs = () => {
1254
- return i18nString(SaveImageAs);
1345
+ const waitForFirstMessage = async port => {
1346
+ const {
1347
+ resolve,
1348
+ promise
1349
+ } = Promise.withResolvers();
1350
+ port.addEventListener('message', resolve, {
1351
+ once: true
1352
+ });
1353
+ const event = await promise;
1354
+ // @ts-ignore
1355
+ return event.data;
1255
1356
  };
1256
- const fileMatch = () => {
1257
- return i18nString(FileMatch);
1357
+ const listen$6 = async () => {
1358
+ const parentIpcRaw = listen$7();
1359
+ signal$8(parentIpcRaw);
1360
+ const parentIpc = wrap$f(parentIpcRaw);
1361
+ const firstMessage = await waitForFirstMessage(parentIpc);
1362
+ if (firstMessage.method !== 'initialize') {
1363
+ throw new IpcError('unexpected first message');
1364
+ }
1365
+ const type = firstMessage.params[0];
1366
+ if (type === 'message-port') {
1367
+ parentIpc.send({
1368
+ jsonrpc: '2.0',
1369
+ id: firstMessage.id,
1370
+ result: null
1371
+ });
1372
+ parentIpc.dispose();
1373
+ const port = firstMessage.params[1];
1374
+ return port;
1375
+ }
1376
+ return globalThis;
1258
1377
  };
1259
- const schema = () => {
1260
- return i18nString(Schema);
1378
+ class IpcChildWithModuleWorkerAndMessagePort extends Ipc {
1379
+ getData(event) {
1380
+ return getData$2(event);
1381
+ }
1382
+ send(message) {
1383
+ this._rawIpc.postMessage(message);
1384
+ }
1385
+ sendAndTransfer(message) {
1386
+ const transfer = getTransferrables(message);
1387
+ this._rawIpc.postMessage(message, transfer);
1388
+ }
1389
+ dispose() {
1390
+ if (this._rawIpc.close) {
1391
+ this._rawIpc.close();
1392
+ }
1393
+ }
1394
+ onClose(callback) {
1395
+ // ignore
1396
+ }
1397
+ onMessage(callback) {
1398
+ this._rawIpc.addEventListener('message', callback);
1399
+ this._rawIpc.start();
1400
+ }
1401
+ }
1402
+ const wrap$e = port => {
1403
+ return new IpcChildWithModuleWorkerAndMessagePort(port);
1261
1404
  };
1262
- const setColorTheme$3 = () => {
1263
- return i18nString(SetColorTheme$1);
1405
+ const IpcChildWithModuleWorkerAndMessagePort$1 = {
1406
+ __proto__: null,
1407
+ listen: listen$6,
1408
+ wrap: wrap$e
1264
1409
  };
1265
- const theme = () => {
1266
- return i18nString(Theme$1);
1410
+ const addListener = (emitter, type, callback) => {
1411
+ if ('addEventListener' in emitter) {
1412
+ emitter.addEventListener(type, callback);
1413
+ } else {
1414
+ emitter.on(type, callback);
1415
+ }
1267
1416
  };
1268
- const commands = () => {
1269
- return i18nString(Commands$1);
1417
+ const removeListener = (emitter, type, callback) => {
1418
+ if ('removeEventListener' in emitter) {
1419
+ emitter.removeEventListener(type, callback);
1420
+ } else {
1421
+ emitter.off(type, callback);
1422
+ }
1270
1423
  };
1271
- const webViews = () => {
1272
- return i18nString(WebViews$1);
1424
+ const getFirstEvent = (eventEmitter, eventMap) => {
1425
+ const {
1426
+ resolve,
1427
+ promise
1428
+ } = Promise.withResolvers();
1429
+ const listenerMap = Object.create(null);
1430
+ const cleanup = value => {
1431
+ for (const event of Object.keys(eventMap)) {
1432
+ removeListener(eventEmitter, event, listenerMap[event]);
1433
+ }
1434
+ resolve(value);
1435
+ };
1436
+ for (const [event, type] of Object.entries(eventMap)) {
1437
+ const listener = event => {
1438
+ cleanup({
1439
+ type,
1440
+ event
1441
+ });
1442
+ };
1443
+ addListener(eventEmitter, event, listener);
1444
+ listenerMap[event] = listener;
1445
+ }
1446
+ return promise;
1273
1447
  };
1274
- const jsonValidation = () => {
1275
- return i18nString(JsonValidation$1);
1448
+ const Message$1 = 3;
1449
+ const create$5$1 = async ({
1450
+ messagePort,
1451
+ isMessagePortOpen
1452
+ }) => {
1453
+ if (!isMessagePort(messagePort)) {
1454
+ throw new IpcError('port must be of type MessagePort');
1455
+ }
1456
+ if (isMessagePortOpen) {
1457
+ return messagePort;
1458
+ }
1459
+ const eventPromise = getFirstEvent(messagePort, {
1460
+ message: Message$1
1461
+ });
1462
+ messagePort.start();
1463
+ const {
1464
+ type,
1465
+ event
1466
+ } = await eventPromise;
1467
+ if (type !== Message$1) {
1468
+ throw new IpcError('Failed to wait for ipc message');
1469
+ }
1470
+ if (event.data !== readyMessage) {
1471
+ throw new IpcError('unexpected first message');
1472
+ }
1473
+ return messagePort;
1276
1474
  };
1277
- const programmingLanguages = () => {
1278
- return i18nString(ProgrammingLanguages$1);
1475
+ const signal$1 = messagePort => {
1476
+ messagePort.start();
1279
1477
  };
1280
- const settings = () => {
1281
- return i18nString(Settings$1);
1478
+ class IpcParentWithMessagePort extends Ipc {
1479
+ getData = getData$2;
1480
+ send(message) {
1481
+ this._rawIpc.postMessage(message);
1482
+ }
1483
+ sendAndTransfer(message) {
1484
+ const transfer = getTransferrables(message);
1485
+ this._rawIpc.postMessage(message, transfer);
1486
+ }
1487
+ dispose() {
1488
+ this._rawIpc.close();
1489
+ }
1490
+ onMessage(callback) {
1491
+ this._rawIpc.addEventListener('message', callback);
1492
+ }
1493
+ onClose(callback) {}
1494
+ }
1495
+ const wrap$5 = messagePort => {
1496
+ return new IpcParentWithMessagePort(messagePort);
1282
1497
  };
1283
- const id = () => {
1284
- return i18nString(Id);
1498
+ const IpcParentWithMessagePort$1 = {
1499
+ __proto__: null,
1500
+ create: create$5$1,
1501
+ signal: signal$1,
1502
+ wrap: wrap$5
1285
1503
  };
1286
- const selector = () => {
1287
- return i18nString(Selector);
1504
+
1505
+ const Two = '2.0';
1506
+ const create$4 = (method, params) => {
1507
+ return {
1508
+ jsonrpc: Two,
1509
+ method,
1510
+ params
1511
+ };
1288
1512
  };
1289
- const contentSecurityPolicy = () => {
1290
- return i18nString(ContentSecurityPolicy);
1513
+ const callbacks = Object.create(null);
1514
+ const set$2 = (id, fn) => {
1515
+ callbacks[id] = fn;
1291
1516
  };
1292
- const elements = () => {
1293
- return i18nString(Elements);
1517
+ const get$1 = id => {
1518
+ return callbacks[id];
1294
1519
  };
1295
- const uninstall = () => {
1296
- return i18nString(Uninstall$1);
1520
+ const remove = id => {
1521
+ delete callbacks[id];
1297
1522
  };
1298
- const scrollToTop = () => {
1299
- return i18nString(ScrollToTop$1);
1523
+ let id = 0;
1524
+ const create$3$1 = () => {
1525
+ return ++id;
1300
1526
  };
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 [];
1314
- }
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
- }];
1527
+ const registerPromise = () => {
1528
+ const id = create$3$1();
1529
+ const {
1530
+ resolve,
1531
+ promise
1532
+ } = Promise.withResolvers();
1533
+ set$2(id, resolve);
1534
+ return {
1535
+ id,
1536
+ promise
1537
+ };
1328
1538
  };
1329
-
1330
- const getLinkMenuEntries = props => {
1331
- if (!props.isLink) {
1332
- return [];
1539
+ const create$2$1 = (method, params) => {
1540
+ const {
1541
+ id,
1542
+ promise
1543
+ } = registerPromise();
1544
+ const message = {
1545
+ jsonrpc: Two,
1546
+ method,
1547
+ params,
1548
+ id
1549
+ };
1550
+ return {
1551
+ message,
1552
+ promise
1553
+ };
1554
+ };
1555
+ class JsonRpcError extends Error {
1556
+ constructor(message) {
1557
+ super(message);
1558
+ this.name = 'JsonRpcError';
1333
1559
  }
1334
- return [{
1335
- id: 'openInNewTab',
1336
- label: openInNewTab(),
1337
- flags: None,
1338
- command: 'Open.openUrl',
1339
- args: [props.url || '']
1340
- }];
1560
+ }
1561
+ const NewLine = '\n';
1562
+ const DomException = 'DOMException';
1563
+ const ReferenceError$1 = 'ReferenceError';
1564
+ const SyntaxError$1 = 'SyntaxError';
1565
+ const TypeError$1 = 'TypeError';
1566
+ const getErrorConstructor = (message, type) => {
1567
+ if (type) {
1568
+ switch (type) {
1569
+ case DomException:
1570
+ return DOMException;
1571
+ case TypeError$1:
1572
+ return TypeError;
1573
+ case SyntaxError$1:
1574
+ return SyntaxError;
1575
+ case ReferenceError$1:
1576
+ return ReferenceError;
1577
+ default:
1578
+ return Error;
1579
+ }
1580
+ }
1581
+ if (message.startsWith('TypeError: ')) {
1582
+ return TypeError;
1583
+ }
1584
+ if (message.startsWith('SyntaxError: ')) {
1585
+ return SyntaxError;
1586
+ }
1587
+ if (message.startsWith('ReferenceError: ')) {
1588
+ return ReferenceError;
1589
+ }
1590
+ return Error;
1341
1591
  };
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;
1592
+ const constructError = (message, type, name) => {
1593
+ const ErrorConstructor = getErrorConstructor(message, type);
1594
+ if (ErrorConstructor === DOMException && name) {
1595
+ return new ErrorConstructor(message, name);
1596
+ }
1597
+ if (ErrorConstructor === Error) {
1598
+ const error = new Error(message);
1599
+ if (name && name !== 'VError') {
1600
+ error.name = name;
1601
+ }
1602
+ return error;
1603
+ }
1604
+ return new ErrorConstructor(message);
1348
1605
  };
1349
-
1350
- const handleClickDisable = async state => {
1351
- return state;
1606
+ const joinLines = lines => {
1607
+ return lines.join(NewLine);
1352
1608
  };
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 {
1609
+ const splitLines = lines => {
1610
+ return lines.split(NewLine);
1611
+ };
1612
+ const getCurrentStack = () => {
1613
+ const currentStack = joinLines(splitLines(new Error().stack || '').slice(2));
1614
+ return currentStack;
1615
+ };
1616
+ const getNewLineIndex = (string, startIndex = undefined) => {
1617
+ return string.indexOf(NewLine, startIndex);
1618
+ };
1619
+ const getParentStack = error => {
1620
+ let parentStack = error.stack || error.data || error.message || '';
1621
+ if (parentStack.startsWith(' at')) {
1622
+ parentStack = error.message + NewLine + parentStack;
1623
+ }
1624
+ return parentStack;
1625
+ };
1626
+ const MethodNotFound = -32601;
1627
+ const Custom = -32001;
1628
+ const restoreJsonRpcError = error => {
1629
+ const currentStack = getCurrentStack();
1630
+ if (error && error instanceof Error) {
1631
+ if (typeof error.stack === 'string') {
1632
+ error.stack = error.stack + NewLine + currentStack;
1633
+ }
1634
+ return error;
1635
+ }
1636
+ if (error && error.code && error.code === MethodNotFound) {
1637
+ const restoredError = new JsonRpcError(error.message);
1638
+ const parentStack = getParentStack(error);
1639
+ restoredError.stack = parentStack + NewLine + currentStack;
1640
+ return restoredError;
1641
+ }
1642
+ if (error && error.message) {
1643
+ const restoredError = constructError(error.message, error.type, error.name);
1644
+ if (error.data) {
1645
+ if (error.data.stack && error.data.type && error.message) {
1646
+ restoredError.stack = error.data.type + ': ' + error.message + NewLine + error.data.stack + NewLine + currentStack;
1647
+ } else if (error.data.stack) {
1648
+ restoredError.stack = error.data.stack;
1649
+ }
1650
+ if (error.data.codeFrame) {
1651
+ // @ts-ignore
1652
+ restoredError.codeFrame = error.data.codeFrame;
1653
+ }
1654
+ if (error.data.code) {
1655
+ // @ts-ignore
1656
+ restoredError.code = error.data.code;
1657
+ }
1658
+ if (error.data.type) {
1659
+ // @ts-ignore
1660
+ restoredError.name = error.data.type;
1661
+ }
1662
+ } else {
1663
+ if (error.stack) {
1664
+ const lowerStack = restoredError.stack || '';
1665
+ // @ts-ignore
1666
+ const indexNewLine = getNewLineIndex(lowerStack);
1667
+ const parentStack = getParentStack(error);
1668
+ // @ts-ignore
1669
+ restoredError.stack = parentStack + lowerStack.slice(indexNewLine);
1670
+ }
1671
+ if (error.codeFrame) {
1672
+ // @ts-ignore
1673
+ restoredError.codeFrame = error.codeFrame;
1674
+ }
1675
+ }
1676
+ return restoredError;
1677
+ }
1678
+ if (typeof error === 'string') {
1679
+ return new Error(`JsonRpc Error: ${error}`);
1680
+ }
1681
+ return new Error(`JsonRpc Error: ${error}`);
1682
+ };
1683
+ const unwrapJsonRpcResult = responseMessage => {
1684
+ if ('error' in responseMessage) {
1685
+ const restoredError = restoreJsonRpcError(responseMessage.error);
1686
+ throw restoredError;
1687
+ }
1688
+ if ('result' in responseMessage) {
1689
+ return responseMessage.result;
1690
+ }
1691
+ throw new JsonRpcError('unexpected response message');
1692
+ };
1693
+ const warn = (...args) => {
1694
+ console.warn(...args);
1695
+ };
1696
+ const resolve = (id, response) => {
1697
+ const fn = get$1(id);
1698
+ if (!fn) {
1699
+ console.log(response);
1700
+ warn(`callback ${id} may already be disposed`);
1701
+ return;
1702
+ }
1703
+ fn(response);
1704
+ remove(id);
1705
+ };
1706
+ const E_COMMAND_NOT_FOUND = 'E_COMMAND_NOT_FOUND';
1707
+ const getErrorType = prettyError => {
1708
+ if (prettyError && prettyError.type) {
1709
+ return prettyError.type;
1710
+ }
1711
+ if (prettyError && prettyError.constructor && prettyError.constructor.name) {
1712
+ return prettyError.constructor.name;
1713
+ }
1714
+ return undefined;
1715
+ };
1716
+ const isAlreadyStack = line => {
1717
+ return line.trim().startsWith('at ');
1718
+ };
1719
+ const getStack = prettyError => {
1720
+ const stackString = prettyError.stack || '';
1721
+ const newLineIndex = stackString.indexOf('\n');
1722
+ if (newLineIndex !== -1 && !isAlreadyStack(stackString.slice(0, newLineIndex))) {
1723
+ return stackString.slice(newLineIndex + 1);
1724
+ }
1725
+ return stackString;
1726
+ };
1727
+ const getErrorProperty = (error, prettyError) => {
1728
+ if (error && error.code === E_COMMAND_NOT_FOUND) {
1729
+ return {
1730
+ code: MethodNotFound,
1731
+ message: error.message,
1732
+ data: error.stack
1733
+ };
1734
+ }
1735
+ return {
1736
+ code: Custom,
1737
+ message: prettyError.message,
1738
+ data: {
1739
+ stack: getStack(prettyError),
1740
+ codeFrame: prettyError.codeFrame,
1741
+ type: getErrorType(prettyError),
1742
+ code: prettyError.code,
1743
+ name: prettyError.name
1744
+ }
1745
+ };
1746
+ };
1747
+ const create$1$1 = (id, error) => {
1748
+ return {
1749
+ jsonrpc: Two,
1360
1750
  id,
1361
- label
1362
- } = command;
1363
- return [{
1364
- type: Code$2,
1365
- value: id
1366
- }, {
1367
- type: Text$1,
1368
- value: label
1369
- }];
1751
+ error
1752
+ };
1370
1753
  };
1754
+ const getErrorResponse = (id, error, preparePrettyError, logError) => {
1755
+ const prettyError = preparePrettyError(error);
1756
+ logError(error, prettyError);
1757
+ const errorProperty = getErrorProperty(error, prettyError);
1758
+ return create$1$1(id, errorProperty);
1759
+ };
1760
+ const create$6 = (message, result) => {
1761
+ return {
1762
+ jsonrpc: Two,
1763
+ id: message.id,
1764
+ result: result ?? null
1765
+ };
1766
+ };
1767
+ const getSuccessResponse = (message, result) => {
1768
+ const resultProperty = result ?? null;
1769
+ return create$6(message, resultProperty);
1770
+ };
1771
+ const getErrorResponseSimple = (id, error) => {
1772
+ return {
1773
+ jsonrpc: Two,
1774
+ id,
1775
+ error: {
1776
+ code: Custom,
1777
+ // @ts-ignore
1778
+ message: error.message,
1779
+ data: error
1780
+ }
1781
+ };
1782
+ };
1783
+ const getResponse = async (message, ipc, execute, preparePrettyError, logError, requiresSocket) => {
1784
+ try {
1785
+ const result = requiresSocket(message.method) ? await execute(message.method, ipc, ...message.params) : await execute(message.method, ...message.params);
1786
+ return getSuccessResponse(message, result);
1787
+ } catch (error) {
1788
+ if (ipc.canUseSimpleErrorResponse) {
1789
+ return getErrorResponseSimple(message.id, error);
1790
+ }
1791
+ return getErrorResponse(message.id, error, preparePrettyError, logError);
1792
+ }
1793
+ };
1794
+ const defaultPreparePrettyError = error => {
1795
+ return error;
1796
+ };
1797
+ const defaultLogError = () => {
1798
+ // ignore
1799
+ };
1800
+ const defaultRequiresSocket = () => {
1801
+ return false;
1802
+ };
1803
+ const defaultResolve = resolve;
1371
1804
 
1372
- const getFeatureDetailsCommand = extension => {
1373
- const commands = extension.commands || [];
1374
- const rows = commands.map(getCommandTableEntry);
1805
+ // TODO maybe remove this in v6 or v7, only accept options object to simplify the code
1806
+ const normalizeParams = args => {
1807
+ if (args.length === 1) {
1808
+ const options = args[0];
1809
+ return {
1810
+ ipc: options.ipc,
1811
+ message: options.message,
1812
+ execute: options.execute,
1813
+ resolve: options.resolve || defaultResolve,
1814
+ preparePrettyError: options.preparePrettyError || defaultPreparePrettyError,
1815
+ logError: options.logError || defaultLogError,
1816
+ requiresSocket: options.requiresSocket || defaultRequiresSocket
1817
+ };
1818
+ }
1375
1819
  return {
1376
- commands: rows
1820
+ ipc: args[0],
1821
+ message: args[1],
1822
+ execute: args[2],
1823
+ resolve: args[3],
1824
+ preparePrettyError: args[4],
1825
+ logError: args[5],
1826
+ requiresSocket: args[6]
1377
1827
  };
1378
1828
  };
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
- }];
1829
+ const handleJsonRpcMessage = async (...args) => {
1830
+ const options = normalizeParams(args);
1831
+ const {
1832
+ message,
1833
+ ipc,
1834
+ execute,
1835
+ resolve,
1836
+ preparePrettyError,
1837
+ logError,
1838
+ requiresSocket
1839
+ } = options;
1840
+ if ('id' in message) {
1841
+ if ('method' in message) {
1842
+ const response = await getResponse(message, ipc, execute, preparePrettyError, logError, requiresSocket);
1843
+ try {
1844
+ ipc.send(response);
1845
+ } catch (error) {
1846
+ const errorResponse = getErrorResponse(message.id, error, preparePrettyError, logError);
1847
+ ipc.send(errorResponse);
1848
+ }
1849
+ return;
1850
+ }
1851
+ resolve(message.id, message);
1852
+ return;
1853
+ }
1854
+ if ('method' in message) {
1855
+ await getResponse(message, ipc, execute, preparePrettyError, logError, requiresSocket);
1856
+ return;
1857
+ }
1858
+ throw new JsonRpcError('unexpected message');
1859
+ };
1860
+ const invokeHelper = async (ipc, method, params, useSendAndTransfer) => {
1861
+ const {
1862
+ message,
1863
+ promise
1864
+ } = create$2$1(method, params);
1865
+ if (useSendAndTransfer && ipc.sendAndTransfer) {
1866
+ ipc.sendAndTransfer(message);
1867
+ } else {
1868
+ ipc.send(message);
1869
+ }
1870
+ const responseMessage = await promise;
1871
+ return unwrapJsonRpcResult(responseMessage);
1872
+ };
1873
+ const send = (transport, method, ...params) => {
1874
+ const message = create$4(method, params);
1875
+ transport.send(message);
1876
+ };
1877
+ const invoke = (ipc, method, ...params) => {
1878
+ return invokeHelper(ipc, method, params, false);
1879
+ };
1880
+ const invokeAndTransfer = (ipc, method, ...params) => {
1881
+ return invokeHelper(ipc, method, params, true);
1882
+ };
1883
+
1884
+ const commands = Object.create(null);
1885
+ const register = commandMap => {
1886
+ Object.assign(commands, commandMap);
1887
+ };
1888
+ const getCommand = key => {
1889
+ return commands[key];
1890
+ };
1891
+ const execute = (command, ...args) => {
1892
+ const fn = getCommand(command);
1893
+ if (!fn) {
1894
+ throw new Error(`command not found ${command}`);
1895
+ }
1896
+ return fn(...args);
1897
+ };
1898
+
1899
+ const createRpc = ipc => {
1900
+ const rpc = {
1901
+ // @ts-ignore
1902
+ ipc,
1903
+ /**
1904
+ * @deprecated
1905
+ */
1906
+ send(method, ...params) {
1907
+ send(ipc, method, ...params);
1908
+ },
1909
+ invoke(method, ...params) {
1910
+ return invoke(ipc, method, ...params);
1911
+ },
1912
+ invokeAndTransfer(method, ...params) {
1913
+ return invokeAndTransfer(ipc, method, ...params);
1914
+ },
1915
+ async dispose() {
1916
+ await ipc?.dispose();
1917
+ }
1918
+ };
1919
+ return rpc;
1920
+ };
1921
+ const requiresSocket = () => {
1922
+ return false;
1923
+ };
1924
+ const preparePrettyError = error => {
1925
+ return error;
1392
1926
  };
1393
-
1394
- const getFeatureDetailsJsonValidation = extension => {
1395
- const validations = extension.jsonValidation || [];
1396
- const rows = validations.map(getJsonValidationTableEntry);
1397
- return {
1398
- jsonValidation: rows
1399
- };
1927
+ const logError = () => {
1928
+ // handled by renderer worker
1400
1929
  };
1401
-
1402
- const getFeatureDetailsProgrammingLanguages = extension => {
1403
- return {
1404
- programmingLanguages: []
1405
- };
1930
+ const handleMessage = event => {
1931
+ const actualRequiresSocket = event?.target?.requiresSocket || requiresSocket;
1932
+ const actualExecute = event?.target?.execute || execute;
1933
+ return handleJsonRpcMessage(event.target, event.data, actualExecute, resolve, preparePrettyError, logError, actualRequiresSocket);
1406
1934
  };
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
- }];
1935
+ const handleIpc = ipc => {
1936
+ if ('addEventListener' in ipc) {
1937
+ ipc.addEventListener('message', handleMessage);
1938
+ } else if ('on' in ipc) {
1939
+ // deprecated
1940
+ ipc.on('message', handleMessage);
1941
+ }
1421
1942
  };
1422
-
1423
- const getFeatureDetailsSettings = extension => {
1424
- const settings = extension.settings || [];
1425
- const rows = settings.map(getSettingsTableEntry);
1426
- return {
1427
- settings: rows
1428
- };
1943
+ const listen$1 = async (module, options) => {
1944
+ const rawIpc = await module.listen(options);
1945
+ if (module.signal) {
1946
+ module.signal(rawIpc);
1947
+ }
1948
+ const ipc = module.wrap(rawIpc);
1949
+ return ipc;
1429
1950
  };
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(' ');
1951
+ const create$5 = async ({
1952
+ commandMap,
1953
+ messagePort
1954
+ }) => {
1955
+ // TODO create a commandMap per rpc instance
1956
+ register(commandMap);
1957
+ const rawIpc = await IpcParentWithMessagePort$1.create({
1958
+ messagePort,
1959
+ isMessagePortOpen: true
1960
+ });
1961
+ const ipc = IpcParentWithMessagePort$1.wrap(rawIpc);
1962
+ handleIpc(ipc);
1963
+ const rpc = createRpc(ipc);
1964
+ messagePort.start();
1965
+ return rpc;
1441
1966
  };
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 => {
1482
- return {
1483
- type: Text,
1484
- text: data,
1485
- childCount: 0
1486
- };
1967
+ const create$3 = async ({
1968
+ commandMap,
1969
+ send
1970
+ }) => {
1971
+ const {
1972
+ port1,
1973
+ port2
1974
+ } = new MessageChannel();
1975
+ await send(port1);
1976
+ return create$5({
1977
+ commandMap,
1978
+ messagePort: port2
1979
+ });
1487
1980
  };
1488
-
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';
1553
-
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';
1567
-
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
- }];
1981
+ const TransferMessagePortRpcParent = {
1982
+ __proto__: null,
1983
+ create: create$3
1577
1984
  };
1578
-
1579
- const rpcs = Object.create(null);
1580
- const set$g = (id, rpc) => {
1581
- rpcs[id] = rpc;
1985
+ const create$2 = async ({
1986
+ commandMap
1987
+ }) => {
1988
+ // TODO create a commandMap per rpc instance
1989
+ register(commandMap);
1990
+ const ipc = await listen$1(IpcChildWithModuleWorkerAndMessagePort$1);
1991
+ handleIpc(ipc);
1992
+ const rpc = createRpc(ipc);
1993
+ return rpc;
1582
1994
  };
1583
- const get = id => {
1584
- return rpcs[id];
1995
+ const WebWorkerRpcClient = {
1996
+ __proto__: null,
1997
+ create: create$2
1585
1998
  };
1586
1999
 
1587
- /* eslint-disable @typescript-eslint/explicit-function-return-type */
1588
-
1589
- const create = rpcId => {
1590
- return {
1591
- // @ts-ignore
1592
- invoke(method, ...params) {
1593
- const rpc = get(rpcId);
1594
- // @ts-ignore
1595
- return rpc.invoke(method, ...params);
2000
+ const create$1 = () => {
2001
+ const states = Object.create(null);
2002
+ return {
2003
+ get(uid) {
2004
+ return states[uid];
1596
2005
  },
1597
- // @ts-ignore
1598
- invokeAndTransfer(method, ...params) {
1599
- const rpc = get(rpcId);
1600
- // @ts-ignore
1601
- return rpc.invokeAndTransfer(method, ...params);
2006
+ set(uid, oldState, newState) {
2007
+ states[uid] = {
2008
+ oldState,
2009
+ newState
2010
+ };
1602
2011
  },
1603
- set(rpc) {
1604
- set$g(rpcId, rpc);
2012
+ dispose(uid) {
2013
+ delete states[uid];
1605
2014
  },
1606
- async dispose() {
1607
- const rpc = get(rpcId);
1608
- await rpc.dispose();
2015
+ getKeys() {
2016
+ return Object.keys(states).map(key => {
2017
+ return Number.parseInt(key);
2018
+ });
2019
+ },
2020
+ clear() {
2021
+ for (const key of Object.keys(states)) {
2022
+ delete states[key];
2023
+ }
2024
+ },
2025
+ wrapCommand(fn) {
2026
+ const wrapped = async (uid, ...args) => {
2027
+ const {
2028
+ newState
2029
+ } = states[uid];
2030
+ const newerState = await fn(newState, ...args);
2031
+ if (newState === newerState) {
2032
+ return;
2033
+ }
2034
+ const latest = states[uid];
2035
+ states[uid] = {
2036
+ oldState: latest.oldState,
2037
+ newState: newerState
2038
+ };
2039
+ };
2040
+ return wrapped;
2041
+ },
2042
+ diff(uid, modules, numbers) {
2043
+ const {
2044
+ oldState,
2045
+ newState
2046
+ } = states[uid];
2047
+ const diffResult = [];
2048
+ for (let i = 0; i < modules.length; i++) {
2049
+ const fn = modules[i];
2050
+ if (!fn(oldState, newState)) {
2051
+ diffResult.push(numbers[i]);
2052
+ }
2053
+ }
2054
+ return diffResult;
1609
2055
  }
1610
2056
  };
1611
2057
  };
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);
2058
+ const terminate = () => {
2059
+ globalThis.close();
1624
2060
  };
1625
- const MarkdownWorker = {
1626
- __proto__: null,
1627
- getVirtualDom: getVirtualDom$1,
1628
- render: render$1,
1629
- set: set$5
2061
+
2062
+ const copyImage = state => {
2063
+ return state;
1630
2064
  };
2065
+
1631
2066
  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);
2067
+ get,
2068
+ set: set$1,
2069
+ dispose: dispose$1,
2070
+ wrapCommand
2071
+ } = create$1();
2072
+
2073
+ const create = (uid, uri, x, y, width, height, platform, assetDir) => {
2074
+ const state = {
2075
+ uid,
2076
+ activationEvents: [],
2077
+ assetDir: assetDir || '',
2078
+ badge: '',
2079
+ baseUrl: '',
2080
+ builtinExtensionsBadgeEnabled: true,
2081
+ categories: [],
2082
+ changelogVirtualDom: [],
2083
+ changelogScrollTop: 0,
2084
+ commands: [],
2085
+ description: '',
2086
+ detailsVirtualDom: [],
2087
+ displaySize: '',
2088
+ entries: [],
2089
+ extension: {},
2090
+ extensionId: '',
2091
+ extensionVersion: '',
2092
+ features: [],
2093
+ featuresVirtualDom: [],
2094
+ folderSize: 0,
2095
+ hasColorTheme: false,
2096
+ iconSrc: '',
2097
+ isBuiltin: false,
2098
+ jsonValidation: [],
2099
+ name: '',
2100
+ platform,
2101
+ programmingLanguages: [],
2102
+ readmeScrollTop: 0,
2103
+ resources: [],
2104
+ scrollSource: 0,
2105
+ scrollToTopButtonEnabled: false,
2106
+ secondEntries: [],
2107
+ selectedFeature: '',
2108
+ selectedTab: '',
2109
+ settings: [],
2110
+ settingsButtonEnabled: false,
2111
+ showAdditionalDetailsBreakpoint: 600,
2112
+ sizeOnDisk: 0,
2113
+ sizeValue: 0,
2114
+ themesMarkdownDom: [],
2115
+ uri,
2116
+ webViews: [],
2117
+ width,
2118
+ focus: 0
2119
+ };
2120
+ set$1(uid, state, state);
1653
2121
  };
1654
- const getExtension$3 = async id => {
1655
- // @ts-ignore
1656
- return invoke$3('ExtensionManagement.getExtension', id);
2122
+
2123
+ const isEqual$2 = (oldState, newState) => {
2124
+ return oldState.focus === newState.focus;
1657
2125
  };
1658
- const openNativeFolder$1 = async uri => {
1659
- // @ts-ignore
1660
- await invoke$3('OpenNativeFolder.openNativeFolder', uri);
2126
+
2127
+ const isEqual$1 = (oldState, newState) => {
2128
+ return oldState.activationEvents === newState.activationEvents && oldState.badge === newState.badge && oldState.categories === newState.categories && oldState.changelogVirtualDom === newState.changelogVirtualDom && oldState.commands === newState.commands && oldState.description === newState.description && oldState.detailsVirtualDom === newState.detailsVirtualDom && oldState.displaySize === newState.displaySize && oldState.extensionId === newState.extensionId && oldState.extensionVersion === newState.extensionVersion && oldState.jsonValidation === newState.jsonValidation && oldState.selectedFeature === newState.selectedFeature && oldState.selectedTab === newState.selectedTab && oldState.settings === newState.settings && oldState.themesMarkdownDom === newState.themesMarkdownDom && oldState.webViews === newState.webViews;
1661
2129
  };
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
2130
 
1673
- const {
1674
- set: set$1,
1675
- getVirtualDom,
1676
- render
1677
- } = MarkdownWorker;
2131
+ const User = 1;
2132
+ const Script = 2;
1678
2133
 
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;
2134
+ const isEqual = (oldState, newState) => {
2135
+ return newState.scrollSource === Script || oldState.readmeScrollTop === newState.readmeScrollTop;
1689
2136
  };
1690
2137
 
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';
2138
+ const RenderFocus = 2;
2139
+ const RenderItems = 3;
2140
+ const RenderScrollTop = 4;
2141
+
2142
+ const modules = [isEqual$1, isEqual$2, isEqual];
2143
+ const numbers = [RenderItems, RenderFocus, RenderScrollTop];
2144
+
2145
+ const diff2 = uid => {
2146
+ const {
2147
+ oldState,
2148
+ newState
2149
+ } = get(uid);
2150
+ const diffResult = [];
2151
+ for (let i = 0; i < modules.length; i++) {
2152
+ const fn = modules[i];
2153
+ if (!fn(oldState, newState)) {
2154
+ diffResult.push(numbers[i]);
1699
2155
  }
1700
2156
  }
1701
- return markdown;
2157
+ return diffResult;
1702
2158
  };
1703
2159
 
1704
- const getColorThemeMarkdown = themes => {
1705
- const heading = 'Color Themes';
1706
- return getThemeItemMarkdown(heading, themes);
1707
- };
1708
- const getIconThemeMarkdown = iconThemes => {
1709
- const heading = 'File Icon Themes';
1710
- return getThemeItemMarkdown(heading, iconThemes);
1711
- };
1712
- const getProductIconThemeMarkdown = iconThemes => {
1713
- const heading = 'Product Icon Themes';
1714
- return getThemeItemMarkdown(heading, iconThemes);
1715
- };
1716
- const getThemeMarkdown = (themes, iconThemes, productIconThemes) => {
1717
- let markdown = '';
1718
- markdown += getColorThemeMarkdown(themes);
1719
- markdown += getIconThemeMarkdown(iconThemes);
1720
- markdown += getProductIconThemeMarkdown(productIconThemes);
1721
- return markdown;
2160
+ const dispose = uid => {
2161
+ dispose$1(uid);
1722
2162
  };
1723
2163
 
1724
- const renderMarkdown = async (markdown, options = {}) => {
1725
- const html = await render(markdown, options);
1726
- return html;
1727
- };
2164
+ const commandIds = ['copyImage', 'getMenuEntries', 'handleClickCategory', 'handleClickDisable', 'handleClickScrollToTop', 'handleClickSettings', 'handleClickSetColorTheme', 'handleClickSize', 'handleClickUninstall', 'handleFeaturesClick', 'handleIconError', 'handleTabsClick', 'handleWheel', 'renderEventListeners', 'resize', 'saveState', 'selectTab', 'terminate'];
1728
2165
 
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
- };
2166
+ const getCommandIds = () => {
2167
+ return commandIds;
1744
2168
  };
1745
2169
 
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
- };
2170
+ const None = 0;
2171
+
2172
+ const getCopyMenuEntry = () => ({
2173
+ id: 'copy',
2174
+ label: copy(),
2175
+ flags: None,
2176
+ command: 'ClipBoard.execCopy'
2177
+ });
2178
+
2179
+ const getImageMenuEntries = props => {
2180
+ if (!props.isImage) {
2181
+ return [];
2182
+ }
2183
+ return [{
2184
+ id: 'openImageInNewTab',
2185
+ label: openImageInNewTab(),
2186
+ flags: None,
2187
+ command: 'Open.openUrl',
2188
+ args: [props.url || '']
2189
+ }, {
2190
+ id: 'saveImageAs',
2191
+ label: saveImageAs(),
2192
+ flags: None,
2193
+ command: 'SaveFileAs.saveFileAs',
2194
+ args: ['image.png', props.url || '']
2195
+ }];
1759
2196
  };
1760
2197
 
1761
- const getWebViews = extension => {
1762
- const rawWebViews = extension.webViews || [];
1763
- return rawWebViews.map(toWebView);
2198
+ const getLinkMenuEntries = props => {
2199
+ if (!props.isLink) {
2200
+ return [];
2201
+ }
2202
+ return [{
2203
+ id: 'openInNewTab',
2204
+ label: openInNewTab(),
2205
+ flags: None,
2206
+ command: 'Open.openUrl',
2207
+ args: [props.url || '']
2208
+ }];
1764
2209
  };
1765
2210
 
1766
- const getFeatureDetailsWebView = extension => {
1767
- const webViews = getWebViews(extension);
1768
- return {
1769
- webViews
1770
- };
2211
+ const getMenuEntries = props => [...getLinkMenuEntries(props), ...getImageMenuEntries(props), getCopyMenuEntry()];
2212
+
2213
+ const handleClickCategory = async (state, categoryId) => {
2214
+ // TODO: Implement category click functionality
2215
+ return state;
1771
2216
  };
1772
2217
 
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
- }
2218
+ const handleClickDisable = async state => {
2219
+ return state;
1790
2220
  };
1791
2221
 
1792
2222
  const selectFeature = async (state, name) => {
@@ -1845,6 +2275,7 @@ const {
1845
2275
  readFile: readFile$1,
1846
2276
  set,
1847
2277
  setColorTheme: setColorTheme$1,
2278
+ uninstallExtension,
1848
2279
  sendMessagePortToMarkdownWorker: sendMessagePortToMarkdownWorker$1
1849
2280
  } = RendererWorker;
1850
2281
 
@@ -1884,6 +2315,10 @@ const handleClickSize = async state => {
1884
2315
  };
1885
2316
 
1886
2317
  const handleClickUninstall = async state => {
2318
+ const {
2319
+ id
2320
+ } = state.extension;
2321
+ await uninstallExtension(id);
1887
2322
  return state;
1888
2323
  };
1889
2324
 
@@ -1999,7 +2434,8 @@ const selectTabFeatures = async state => {
1999
2434
  const {
2000
2435
  extension,
2001
2436
  baseUrl,
2002
- selectedFeature
2437
+ selectedFeature,
2438
+ features
2003
2439
  } = state;
2004
2440
  const actualSelectedFeature = selectedFeature || Theme;
2005
2441
  const fn = getFeatureDetailsHandler(actualSelectedFeature);
@@ -2007,6 +2443,7 @@ const selectTabFeatures = async state => {
2007
2443
  return {
2008
2444
  ...state,
2009
2445
  selectedTab: Features,
2446
+ selectedFeature: features[0].id || '',
2010
2447
  ...partialNewState
2011
2448
  };
2012
2449
  };
@@ -2060,7 +2497,7 @@ const createMarkdownWorkerRpc = async () => {
2060
2497
 
2061
2498
  const initializeMarkdownWorker = async () => {
2062
2499
  const rpc = await createMarkdownWorkerRpc();
2063
- set$1(rpc);
2500
+ set$3(rpc);
2064
2501
  };
2065
2502
 
2066
2503
  const initialize = async () => {
@@ -2068,57 +2505,10 @@ const initialize = async () => {
2068
2505
  // TODO create connection to file system worker
2069
2506
  };
2070
2507
 
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
2508
  const Web = 1;
2080
2509
  const Electron = 2;
2081
2510
  const Remote = 3;
2082
2511
 
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
2512
  const getAllExtensions = async platform => {
2123
2513
  if (platform === Web) {
2124
2514
  return [];
@@ -2148,6 +2538,13 @@ const getExtension = async (id, platform) => {
2148
2538
  }
2149
2539
  };
2150
2540
 
2541
+ class ExtensionNotFoundError extends Error {
2542
+ constructor(extensionId) {
2543
+ super(`extension not found: ${extensionId}`);
2544
+ this.name = 'ExtensionNotFoundError';
2545
+ }
2546
+ }
2547
+
2151
2548
  const getRemoteSrc = uri => {
2152
2549
  const src = `/remote${uri}`;
2153
2550
  return src;
@@ -2281,48 +2678,6 @@ const getExtensionIdFromUri = uri => {
2281
2678
  return id;
2282
2679
  };
2283
2680
 
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
2681
  const getFolderSize = async uri => {
2327
2682
  if (!uri) {
2328
2683
  throw new VError(`uri is required`);
@@ -2374,10 +2729,105 @@ const getViewletSize = width => {
2374
2729
  return Large;
2375
2730
  };
2376
2731
 
2732
+ const isLanguageBasicsExtension = extension => {
2733
+ return extension.name && extension.name.startsWith('Language Basics');
2734
+ };
2735
+
2736
+ const isThemeExtension = extension => {
2737
+ return extension.name && extension.name.endsWith(' Theme');
2738
+ };
2739
+
2740
+ const getIcon = (extension, platform, assetDir) => {
2741
+ if (!extension) {
2742
+ return extensionDefaultIcon(assetDir);
2743
+ }
2744
+ if (!extension.path || !extension.icon) {
2745
+ if (isLanguageBasicsExtension(extension)) {
2746
+ return extensionLanguageBasics(assetDir);
2747
+ }
2748
+ if (isThemeExtension(extension)) {
2749
+ return extensionTheme(assetDir);
2750
+ }
2751
+ return extensionDefaultIcon(assetDir);
2752
+ }
2753
+ if (platform === Remote || platform === Electron) {
2754
+ if (extension.builtin) {
2755
+ return `${assetDir}/extensions/${extension.id}/${extension.icon}`;
2756
+ }
2757
+ return `/remote/${extension.path}/${extension.icon}`; // TODO support windows paths
2758
+ }
2759
+ return '';
2760
+ };
2761
+
2762
+ const getDescription = extension => {
2763
+ if (!extension || !extension.description) {
2764
+ return 'n/a';
2765
+ }
2766
+ return extension.description;
2767
+ };
2768
+
2769
+ const getName = extension => {
2770
+ if (extension && extension.name) {
2771
+ return extension.name;
2772
+ }
2773
+ if (extension && extension.id) {
2774
+ return extension.id;
2775
+ }
2776
+ return 'n/a';
2777
+ };
2778
+
2779
+ const getBadge = (builtin, badgeEnabled) => {
2780
+ if (builtin && badgeEnabled) {
2781
+ return 'builtin';
2782
+ }
2783
+ return '';
2784
+ };
2785
+
2377
2786
  const hasColorThemes = extension => {
2378
2787
  return Boolean(extension && extension.colorThemes && extension.colorThemes.length > 0);
2379
2788
  };
2380
2789
 
2790
+ const loadHeaderContent = (state, platform, extension) => {
2791
+ const {
2792
+ assetDir,
2793
+ builtinExtensionsBadgeEnabled
2794
+ } = state;
2795
+ const iconSrc = getIcon(extension, platform, assetDir);
2796
+ const description = getDescription(extension);
2797
+ const name = getName(extension);
2798
+ const extensionUri = extension.uri || extension.path;
2799
+ const extensionId = extension?.id || 'n/a';
2800
+ const extensionVersion = extension?.version || 'n/a';
2801
+ const hasColorTheme = hasColorThemes(extension);
2802
+ const isBuiltin = extension?.builtin;
2803
+ const badge = getBadge(isBuiltin, builtinExtensionsBadgeEnabled);
2804
+ return {
2805
+ badge,
2806
+ description,
2807
+ extension,
2808
+ extensionId,
2809
+ extensionUri,
2810
+ extensionVersion,
2811
+ hasColorTheme,
2812
+ iconSrc,
2813
+ name
2814
+ };
2815
+ };
2816
+
2817
+ const getSavedChangelogScrollTop = savedState => {
2818
+ if (savedState && typeof savedState === 'object' && 'changelogScrollTop' in savedState && typeof savedState.changelogScrollTop === 'number') {
2819
+ return savedState.changelogScrollTop;
2820
+ }
2821
+ return 0;
2822
+ };
2823
+
2824
+ const getSavedReadmeScrollTop = savedState => {
2825
+ if (savedState && typeof savedState === 'object' && 'readmeScrollTop' in savedState && typeof savedState.readmeScrollTop === 'number') {
2826
+ return savedState.readmeScrollTop;
2827
+ }
2828
+ return 0;
2829
+ };
2830
+
2381
2831
  const getSavedSelectedFeature = savedState => {
2382
2832
  if (savedState && typeof savedState === 'object' && 'selectedFeature' in savedState && typeof savedState.selectedFeature === 'string') {
2383
2833
  return savedState.selectedFeature;
@@ -2395,23 +2845,37 @@ const getSavedSelectedTab = savedState => {
2395
2845
  const restoreState = savedState => {
2396
2846
  const selectedTab = getSavedSelectedTab(savedState);
2397
2847
  const selectedFeature = getSavedSelectedFeature(savedState);
2848
+ const readmeScrollTop = getSavedReadmeScrollTop(savedState);
2849
+ const changelogScrollTop = getSavedChangelogScrollTop(savedState);
2398
2850
  return {
2399
2851
  selectedFeature,
2400
- selectedTab
2852
+ selectedTab,
2853
+ readmeScrollTop,
2854
+ changelogScrollTop
2401
2855
  };
2402
2856
  };
2403
2857
 
2404
2858
  const loadContent = async (state, platform, savedState) => {
2405
2859
  const {
2406
- uri,
2407
2860
  width,
2408
- assetDir
2861
+ uri
2409
2862
  } = state;
2410
2863
  const id = getExtensionIdFromUri(uri);
2411
2864
  const extension = await getExtension(id, platform);
2412
2865
  if (!extension) {
2413
- throw new Error(`extension not found: ${id}`);
2866
+ throw new ExtensionNotFoundError(id);
2414
2867
  }
2868
+ const headerData = loadHeaderContent(state, platform, extension);
2869
+ const {
2870
+ badge,
2871
+ description,
2872
+ extensionId,
2873
+ extensionUri,
2874
+ extensionVersion,
2875
+ hasColorTheme,
2876
+ iconSrc,
2877
+ name
2878
+ } = headerData;
2415
2879
  const readmeContent = await loadReadmeContent(extension.path);
2416
2880
  const baseUrl = getBaseUrl(extension.path, platform);
2417
2881
  const readmeHtml = await renderMarkdown(readmeContent, {
@@ -2420,16 +2884,13 @@ const loadContent = async (state, platform, savedState) => {
2420
2884
  const detailsVirtualDom = await getMarkdownVirtualDom(readmeHtml, {
2421
2885
  scrollToTopEnabled: true
2422
2886
  });
2423
- const iconSrc = getIcon(extension, platform, assetDir);
2424
- const description = getDescription(extension);
2425
- const name = getName(extension);
2426
2887
  const size = getViewletSize(width);
2427
2888
  const {
2428
2889
  selectedFeature,
2429
- selectedTab
2890
+ selectedTab,
2891
+ readmeScrollTop
2430
2892
  } = restoreState(savedState);
2431
- const features = getFeatures(selectedFeature, extension);
2432
- const extensionUri = extension.uri || extension.path;
2893
+ const features = getFeatures(selectedFeature || Theme, extension);
2433
2894
  const folderSize = await getFolderSize(extensionUri);
2434
2895
  const displaySize = getDisplaySize(size);
2435
2896
  const entries = getEntries();
@@ -2438,11 +2899,9 @@ const loadContent = async (state, platform, savedState) => {
2438
2899
  const resources = getResources();
2439
2900
  const sizeValue = getViewletSize(width || 0);
2440
2901
  const isBuiltin = extension?.builtin;
2441
- const hasColorTheme = hasColorThemes(extension);
2442
- const extensionId = extension?.id || 'n/a';
2443
- const extensionVersion = extension?.version || 'n/a';
2444
2902
  return {
2445
2903
  ...state,
2904
+ badge,
2446
2905
  baseUrl,
2447
2906
  categories,
2448
2907
  description,
@@ -2450,20 +2909,21 @@ const loadContent = async (state, platform, savedState) => {
2450
2909
  displaySize,
2451
2910
  entries,
2452
2911
  extension,
2912
+ extensionId,
2913
+ extensionVersion,
2453
2914
  features,
2454
2915
  folderSize,
2455
2916
  hasColorTheme,
2456
2917
  iconSrc,
2457
2918
  isBuiltin,
2458
2919
  name,
2920
+ readmeScrollTop,
2459
2921
  resources,
2922
+ scrollToTopButtonEnabled: true,
2460
2923
  secondEntries,
2461
2924
  selectedTab,
2462
2925
  sizeOnDisk: size,
2463
- sizeValue,
2464
- extensionId,
2465
- extensionVersion,
2466
- scrollToTopButtonEnabled: true
2926
+ sizeValue
2467
2927
  };
2468
2928
  };
2469
2929
 
@@ -2471,13 +2931,6 @@ const loadContent2 = async (state, savedState) => {
2471
2931
  return loadContent(state, state.platform, savedState);
2472
2932
  };
2473
2933
 
2474
- const getBadge = (builtin, badgeEnabled) => {
2475
- if (builtin && badgeEnabled) {
2476
- return 'builtin';
2477
- }
2478
- return '';
2479
- };
2480
-
2481
2934
  const getExtensionDetailButtons = (hasColorTheme, isBuiltin) => {
2482
2935
  const allActions = [{
2483
2936
  label: setColorTheme$3(),
@@ -2542,7 +2995,7 @@ const getCategoriesDom = categories => {
2542
2995
  }, ...categories.flatMap(getCategoryVirtualDom)];
2543
2996
  };
2544
2997
 
2545
- const parentNode$1 = {
2998
+ const parentNode = {
2546
2999
  type: VirtualDomElements.Dt,
2547
3000
  className: MoreInfoEntryKey,
2548
3001
  childCount: 1
@@ -2551,27 +3004,29 @@ const getMoreInfoEntryKeyVirtualDom = item => {
2551
3004
  const {
2552
3005
  key
2553
3006
  } = item;
2554
- return [parentNode$1, text(key)];
3007
+ return [parentNode, text(key)];
2555
3008
  };
2556
3009
 
2557
- const getTag = (onClick, code) => {
3010
+ const getMoreInfoEntryValueClassName = (onClick, code) => {
2558
3011
  if (onClick) {
2559
- return VirtualDomElements.A;
3012
+ return mergeClassNames(MoreInfoEntryValue, Link);
2560
3013
  }
2561
3014
  if (code) {
2562
- return VirtualDomElements.Code;
3015
+ return mergeClassNames(MoreInfoEntryValue, Code$1);
2563
3016
  }
2564
- return VirtualDomElements.Dd;
3017
+ return MoreInfoEntryValue;
2565
3018
  };
2566
- const getClassName = (onClick, code) => {
3019
+
3020
+ const getMoreInfoEntryValueTag = (onClick, code) => {
2567
3021
  if (onClick) {
2568
- return mergeClassNames(MoreInfoEntryValue, Link);
3022
+ return VirtualDomElements.A;
2569
3023
  }
2570
3024
  if (code) {
2571
- return mergeClassNames(MoreInfoEntryValue, Code);
3025
+ return VirtualDomElements.Code;
2572
3026
  }
2573
- return MoreInfoEntryValue;
3027
+ return VirtualDomElements.Dd;
2574
3028
  };
3029
+
2575
3030
  const getMoreInfoEntryValueVirtualDom = item => {
2576
3031
  const {
2577
3032
  value,
@@ -2579,8 +3034,8 @@ const getMoreInfoEntryValueVirtualDom = item => {
2579
3034
  code,
2580
3035
  title
2581
3036
  } = item;
2582
- const type = getTag(onClick, code);
2583
- const className = getClassName(onClick, code);
3037
+ const type = getMoreInfoEntryValueTag(onClick, code);
3038
+ const className = getMoreInfoEntryValueClassName(onClick, code);
2584
3039
  return [{
2585
3040
  type: type,
2586
3041
  className,
@@ -2687,16 +3142,11 @@ const getMarketplaceEntries = () => {
2687
3142
  }];
2688
3143
  };
2689
3144
 
2690
- // import * as GetScrollToTopVirtualDom from '../GetScrollToTopVirtualDom/GetScrollToTopVirtualDom.ts'
2691
-
2692
3145
  const getChildCount = (additionalDetails, scrollToTopEnabled) => {
2693
3146
  let count = 1;
2694
3147
  if (additionalDetails) {
2695
3148
  count++;
2696
3149
  }
2697
- // if (scrollToTopEnabled) {
2698
- // count++
2699
- // }
2700
3150
  return count;
2701
3151
  };
2702
3152
  const getDetailsVirtualDom = (sanitizedReadmeHtml, displaySize, extensionId, extensionVersion, width, extensionUri, scrollToTopButtonEnabled, categories$1, resources$1, showAdditionalDetailsBreakpoint // new parameter, no default
@@ -2714,264 +3164,10 @@ const getDetailsVirtualDom = (sanitizedReadmeHtml, displaySize, extensionId, ext
2714
3164
  className: ExtensionDetailPanel,
2715
3165
  childCount: childCount,
2716
3166
  role: AriaRoles.Panel
2717
- },
2718
- // ...GetScrollToTopVirtualDom.getScrollToTopVirtualDom(scrollToTopButtonEnabled),
2719
- ...sanitizedReadmeHtml, ...getAdditionalDetailsVirtualDom(showAdditionalDetails, firstHeading, entries, secondHeading, secondEntries, thirdHeading, categories$1, fourthHeading, resources$1)];
3167
+ }, ...sanitizedReadmeHtml, ...getAdditionalDetailsVirtualDom(showAdditionalDetails, firstHeading, entries, secondHeading, secondEntries, thirdHeading, categories$1, fourthHeading, resources$1)];
2720
3168
  return dom;
2721
3169
  };
2722
3170
 
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
-
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}`);
2774
- }
2775
- };
2776
-
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);
2818
- return [{
2819
- type: VirtualDomElements.Div,
2820
- className: FeatureContent,
2821
- childCount: 2
2822
- }, ...getFeatureContentHeadingVirtualDom(heading), ...getTableVirtualDom(tableInfo)];
2823
- };
2824
-
2825
- const getJsonValidationTableEntries = rows => {
2826
- return {
2827
- headings: [fileMatch(), schema()],
2828
- rows
2829
- };
2830
- };
2831
-
2832
- const parentNode = {
2833
- type: VirtualDomElements.Div,
2834
- className: FeatureContent,
2835
- childCount: 2
2836
- };
2837
- const getFeatureJsonValidationVirtualDom = jsonValidation$1 => {
2838
- const heading = jsonValidation();
2839
- const tableInfo = getJsonValidationTableEntries(jsonValidation$1);
2840
- return [parentNode, ...getFeatureContentHeadingVirtualDom(heading), ...getTableVirtualDom(tableInfo)];
2841
- };
2842
-
2843
- const getFeatureNotImplementedVirtualDom = () => {
2844
- const heading = 'Not implemented';
2845
- return [{
2846
- type: VirtualDomElements.Div,
2847
- className: FeatureContent,
2848
- childCount: 1
2849
- }, {
2850
- type: VirtualDomElements.H1,
2851
- childCount: 1
2852
- }, text(heading)];
2853
- };
2854
-
2855
- const getFeatureProgrammingLanguagesVirtualDom = () => {
2856
- const heading = programmingLanguages();
2857
- // TODO
2858
- return [{
2859
- type: VirtualDomElements.Div,
2860
- className: FeatureContent,
2861
- childCount: 1
2862
- }, ...getFeatureContentHeadingVirtualDom(heading)];
2863
- };
2864
-
2865
- const getSettingsTableEntries = rows => {
2866
- const textId = id();
2867
- const textLabel = label();
2868
- return {
2869
- headings: [textId, textLabel],
2870
- rows
2871
- };
2872
- };
2873
-
2874
- const getFeatureSettingsVirtualDom = rows => {
2875
- const heading = settings();
2876
- const tableInfo = getSettingsTableEntries(rows);
2877
- return [{
2878
- type: VirtualDomElements.Div,
2879
- className: FeatureContent,
2880
- childCount: 2
2881
- }, ...getFeatureContentHeadingVirtualDom(heading), ...getTableVirtualDom(tableInfo)];
2882
- };
2883
-
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);
2893
- }
2894
- return stack.length;
2895
- };
2896
-
2897
- const getFeatureThemesVirtualDom = themesDom => {
2898
- const childCount = getVirtualDomChildCount(themesDom);
2899
- const heading = theme();
2900
- return [{
2901
- type: VirtualDomElements.Div,
2902
- className: FeatureContent,
2903
- childCount: 2
2904
- }, ...getFeatureContentHeadingVirtualDom(heading), {
2905
- type: VirtualDomElements.Div,
2906
- className: DefaultMarkdown,
2907
- childCount
2908
- }, ...themesDom];
2909
- };
2910
-
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)];
2942
- };
2943
-
2944
- const getFeatureWebViewsVirtualDom = webViews$1 => {
2945
- const heading = webViews();
2946
- 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)];
2954
- };
2955
-
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();
2972
- }
2973
- };
2974
-
2975
3171
  const getFeatureListItemVirtualDom = feature => {
2976
3172
  const {
2977
3173
  label,
@@ -2998,15 +3194,17 @@ const getFeatureListVirtualDom = features => {
2998
3194
  }, ...features.flatMap(getFeatureListItemVirtualDom)];
2999
3195
  };
3000
3196
 
3001
- const getFeaturesVirtualDom = (features, themesDom, selectedFeature, commands, jsonValidation, settings, webViews) => {
3197
+ const getFeaturesVirtualDom = (features, selectedFeature, state) => {
3002
3198
  if (features.length === 0) {
3003
3199
  const none$1 = none();
3004
3200
  return [{
3005
3201
  type: VirtualDomElements.Div,
3006
3202
  className: Features$1,
3007
- childCount: 3
3203
+ childCount: 1
3008
3204
  }, text(none$1)];
3009
3205
  }
3206
+ const fn = getFeatureVirtualDomHandler(selectedFeature);
3207
+ const featureVirtualDom = fn(state);
3010
3208
  return [{
3011
3209
  type: VirtualDomElements.Div,
3012
3210
  className: Features$1,
@@ -3015,15 +3213,15 @@ const getFeaturesVirtualDom = (features, themesDom, selectedFeature, commands, j
3015
3213
  type: VirtualDomElements.Div,
3016
3214
  className: mergeClassNames(Sash, SashVertical),
3017
3215
  childCount: 0
3018
- }, ...getFeatureContentVirtualDom(themesDom, selectedFeature, commands, jsonValidation, settings, webViews)];
3216
+ }, ...featureVirtualDom];
3019
3217
  };
3020
3218
 
3021
- const getExtensionDetailContentVirtualDom = (sanitizedReadmeHtml, themesDom, selectedTab, features, displaySize, extensionId, extensionVersion, selectedFeature, width, scrollToTopButtonEnabled, categories, resources, breakpoint, commands, jsonValidation, settings, webViews, extensionUri, changelogDom) => {
3219
+ const getExtensionDetailContentVirtualDom = (sanitizedReadmeHtml, themesDom, selectedTab, features, displaySize, extensionId, extensionVersion, selectedFeature, width, scrollToTopButtonEnabled, categories, resources, breakpoint, commands, jsonValidation, settings, webViews, extensionUri, changelogDom, activationEvents, state) => {
3022
3220
  switch (selectedTab) {
3023
3221
  case Details:
3024
3222
  return getDetailsVirtualDom(sanitizedReadmeHtml, displaySize, extensionId, extensionVersion, width, extensionUri, scrollToTopButtonEnabled, categories, resources, breakpoint);
3025
3223
  case Features:
3026
- return getFeaturesVirtualDom(features, themesDom, selectedFeature, commands, jsonValidation, settings, webViews);
3224
+ return getFeaturesVirtualDom(state.features, state.selectedFeature, state);
3027
3225
  case Changelog:
3028
3226
  return getChangelogVirtualDom(changelogDom);
3029
3227
  default:
@@ -3129,7 +3327,7 @@ const getTabs = selectedTab => {
3129
3327
  name: Details,
3130
3328
  selected: selectedTab === Details
3131
3329
  }, {
3132
- label: features(),
3330
+ label: features$1(),
3133
3331
  name: Features,
3134
3332
  selected: selectedTab === Features
3135
3333
  }, {
@@ -3192,43 +3390,43 @@ const getExtensionDetailVirtualDom = (newState, selectedTab) => {
3192
3390
  // 3. virtual dom
3193
3391
  // 4. dom
3194
3392
  const {
3195
- displaySize,
3196
- themesMarkdownDom,
3197
- selectedFeature,
3198
- sizeValue,
3199
- isBuiltin,
3393
+ activationEvents,
3200
3394
  categories,
3201
- resources,
3202
- showAdditionalDetailsBreakpoint,
3203
- scrollToTopButtonEnabled,
3204
- hasColorTheme,
3205
- builtinExtensionsBadgeEnabled,
3206
- settingsButtonEnabled,
3207
- name,
3208
- iconSrc,
3395
+ changelogVirtualDom,
3396
+ commands,
3209
3397
  description,
3210
3398
  detailsVirtualDom,
3211
- features,
3399
+ displaySize,
3400
+ extension,
3212
3401
  extensionId,
3213
3402
  extensionVersion,
3214
- commands,
3403
+ features,
3404
+ hasColorTheme,
3405
+ iconSrc,
3406
+ isBuiltin,
3215
3407
  jsonValidation,
3408
+ name,
3409
+ resources,
3410
+ scrollToTopButtonEnabled,
3411
+ selectedFeature,
3216
3412
  settings,
3413
+ settingsButtonEnabled,
3414
+ showAdditionalDetailsBreakpoint,
3415
+ sizeValue,
3416
+ themesMarkdownDom,
3217
3417
  webViews,
3218
- extension,
3219
- changelogVirtualDom
3418
+ badge
3220
3419
  } = newState;
3221
3420
  const extensionUri = extension.uri || extension.path || '';
3222
3421
  const width = newState?.width || 500;
3223
3422
  const tabs = getTabs(selectedTab);
3224
3423
  const sizeClass = getClassNames(sizeValue);
3225
- const buttonDefs = getExtensionDetailButtons(hasColorTheme, isBuiltin);
3226
- const badge = getBadge(isBuiltin, builtinExtensionsBadgeEnabled); // TODO compute in loadContent
3424
+ const buttonDefs = getExtensionDetailButtons(hasColorTheme, isBuiltin); // TODO compute in loadContent
3227
3425
  const dom = [{
3228
3426
  type: VirtualDomElements.Div,
3229
3427
  className: mergeClassNames(Viewlet, ExtensionDetail, sizeClass),
3230
3428
  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)];
3429
+ }, ...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
3430
  return dom;
3233
3431
  };
3234
3432
 
@@ -3242,7 +3440,9 @@ const renderFocus = (oldState, newState) => {
3242
3440
  };
3243
3441
 
3244
3442
  const renderScrollTop = (oldState, newState) => {
3245
- return ['Viewlet.setScrollTop', '', newState.readmeScrollTop];
3443
+ const selector = '.ExtensionDetailPanel .Markdown';
3444
+ const property = 'scrollTop';
3445
+ return ['Viewlet.setProperty', newState.uid, selector, property, newState.readmeScrollTop];
3246
3446
  };
3247
3447
 
3248
3448
  const getRenderer = diffType => {
@@ -3271,8 +3471,8 @@ const render2 = (uid, diffResult) => {
3271
3471
  const {
3272
3472
  oldState,
3273
3473
  newState
3274
- } = get$1(uid);
3275
- set$2(uid, oldState, newState);
3474
+ } = get(uid);
3475
+ set$1(uid, newState, newState);
3276
3476
  const commands = applyRender(oldState, newState, diffResult);
3277
3477
  return commands;
3278
3478
  };
@@ -3288,8 +3488,9 @@ const renderEventListeners = () => {
3288
3488
  name: HandleReadmeContextMenu,
3289
3489
  params: ['handleReadmeContextMenu', 'event.clientX', 'event.clientY', 'event.target.href', 'event.target.src']
3290
3490
  }, {
3291
- name: HandleReadmeWheel,
3292
- params: ['handleWheel', 'event.deltaX', 'event.deltaY']
3491
+ name: HandleReadmeScroll,
3492
+ params: ['handleWheel', 'event.deltaX', 'event.deltaY'],
3493
+ passive: true
3293
3494
  }, {
3294
3495
  name: HandleTabsClick,
3295
3496
  params: ['handleTabsClick', 'event.target.name']
@@ -3304,7 +3505,8 @@ const renderEventListeners = () => {
3304
3505
  params: ['handleClickDisable']
3305
3506
  }, {
3306
3507
  name: HandleClickScrollToTop,
3307
- params: ['handleClickScrollToTop']
3508
+ params: ['handleClickScrollToTop'],
3509
+ preventDefault: true
3308
3510
  }, {
3309
3511
  name: HandleClickSettings,
3310
3512
  params: ['handleClickSettings']
@@ -3327,20 +3529,24 @@ const resize = (state, dimensions) => {
3327
3529
  const saveState = uid => {
3328
3530
  const {
3329
3531
  newState
3330
- } = get$1(uid);
3532
+ } = get(uid);
3331
3533
  const {
3332
3534
  selectedTab,
3333
- selectedFeature
3535
+ selectedFeature,
3536
+ readmeScrollTop,
3537
+ changelogScrollTop
3334
3538
  } = newState;
3335
3539
  return {
3336
3540
  selectedTab,
3337
- selectedFeature
3541
+ selectedFeature,
3542
+ readmeScrollTop,
3543
+ changelogScrollTop
3338
3544
  };
3339
3545
  };
3340
3546
 
3341
3547
  const commandMap = {
3342
3548
  'ExtensionDetail.copyImage': wrapCommand(copyImage),
3343
- 'ExtensionDetail.create': create$1,
3549
+ 'ExtensionDetail.create': create,
3344
3550
  'ExtensionDetail.diff2': diff2,
3345
3551
  'ExtensionDetail.dispose': dispose,
3346
3552
  'ExtensionDetail.getCommandIds': getCommandIds,
@@ -3374,6 +3580,7 @@ const listen = async () => {
3374
3580
  };
3375
3581
 
3376
3582
  const main = async () => {
3583
+ registerAllFeatures();
3377
3584
  await listen();
3378
3585
  };
3379
3586