@codingame/monaco-vscode-update-service-override 31.0.0 → 32.0.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.
@@ -63,7 +63,7 @@ let UpdateTooltip = class UpdateTooltip extends Disposable {
63
63
  this.messageNode = append(this.domNode, $(".state-message"));
64
64
  this.buttonBar = append(this.domNode, $(".button-bar"));
65
65
  this.releaseNotesButton = append(this.buttonBar, $("button.release-notes-button"));
66
- this.releaseNotesButton.textContent = ( localize(15015, "Release Notes"));
66
+ this.releaseNotesButton.textContent = ( localize(15320, "Release Notes"));
67
67
  this._register(addDisposableListener(this.releaseNotesButton, "click", () => {
68
68
  if (this.releaseNotesVersion) {
69
69
  this.runCommandAndClose(ShowCurrentReleaseNotesActionId, this.releaseNotesVersion);
@@ -82,7 +82,7 @@ let UpdateTooltip = class UpdateTooltip extends Disposable {
82
82
  const productVersion = this.productService.version;
83
83
  if (productVersion) {
84
84
  const currentCommitId = this.productService.commit?.substring(0, 7);
85
- this.currentVersionNode.textContent = currentCommitId ? ( localize(15016, "Current Version: {0} ({1})", productVersion, currentCommitId)) : ( localize(15017, "Current Version: {0}", productVersion));
85
+ this.currentVersionNode.textContent = currentCommitId ? ( localize(15321, "Current Version: {0} ({1})", productVersion, currentCommitId)) : ( localize(15322, "Current Version: {0}", productVersion));
86
86
  this.currentVersionCopyValue.value = currentCommitId ? `${productVersion} (${this.productService.commit})` : productVersion;
87
87
  this.currentVersionNode.parentElement.style.display = "";
88
88
  } else {
@@ -138,46 +138,46 @@ let UpdateTooltip = class UpdateTooltip extends Disposable {
138
138
  }
139
139
  }
140
140
  renderUninitialized() {
141
- this.renderTitleAndInfo(( localize(15018, "Initializing")));
142
- this.renderMessage(( localize(15019, "Initializing update service...")));
141
+ this.renderTitleAndInfo(( localize(15323, "Initializing")));
142
+ this.renderMessage(( localize(15324, "Initializing update service...")));
143
143
  }
144
144
  renderDisabled(
145
145
  {
146
146
  reason
147
147
  }
148
148
  ) {
149
- this.renderTitleAndInfo(( localize(15020, "Updates Disabled")));
149
+ this.renderTitleAndInfo(( localize(15325, "Updates Disabled")));
150
150
  switch (reason) {
151
151
  case DisablementReason.NotBuilt:
152
- this.renderMessage(( localize(15021, "Updates are not available for this build.")), Codicon.info);
152
+ this.renderMessage(( localize(15326, "Updates are not available for this build.")), Codicon.info);
153
153
  break;
154
154
  case DisablementReason.DisabledByEnvironment:
155
- this.renderMessage(( localize(15022, "Updates are disabled by the --disable-updates command line flag.")), Codicon.warning);
155
+ this.renderMessage(( localize(15327, "Updates are disabled by the --disable-updates command line flag.")), Codicon.warning);
156
156
  break;
157
157
  case DisablementReason.ManuallyDisabled:
158
158
  this.renderMessage(( localize(
159
- 15023,
159
+ 15328,
160
160
  "Updates are manually disabled. Change the \"update.mode\" setting to enable."
161
161
  )), Codicon.warning);
162
162
  break;
163
163
  case DisablementReason.Policy:
164
- this.renderMessage(( localize(15024, "Updates are disabled by organization policy.")), Codicon.info);
164
+ this.renderMessage(( localize(15329, "Updates are disabled by organization policy.")), Codicon.info);
165
165
  break;
166
166
  case DisablementReason.MissingConfiguration:
167
- this.renderMessage(( localize(15025, "Updates are disabled because no update URL is configured.")), Codicon.info);
167
+ this.renderMessage(( localize(15330, "Updates are disabled because no update URL is configured.")), Codicon.info);
168
168
  break;
169
169
  case DisablementReason.InvalidConfiguration:
170
- this.renderMessage(( localize(15026, "Updates are disabled because the update URL is invalid.")), Codicon.error);
170
+ this.renderMessage(( localize(15331, "Updates are disabled because the update URL is invalid.")), Codicon.error);
171
171
  break;
172
172
  case DisablementReason.RunningAsAdmin:
173
173
  this.renderMessage(( localize(
174
- 15027,
174
+ 15332,
175
175
  "Updates are not available when running a user install of {0} as administrator.",
176
176
  this.productService.nameShort
177
177
  )), Codicon.warning);
178
178
  break;
179
179
  default:
180
- this.renderMessage(( localize(15028, "Updates are disabled.")), Codicon.warning);
180
+ this.renderMessage(( localize(15333, "Updates are disabled.")), Codicon.warning);
181
181
  break;
182
182
  }
183
183
  }
@@ -188,55 +188,55 @@ let UpdateTooltip = class UpdateTooltip extends Disposable {
188
188
  }
189
189
  ) {
190
190
  if (error) {
191
- this.renderTitleAndInfo(( localize(15029, "Update Error")));
191
+ this.renderTitleAndInfo(( localize(15334, "Update Error")));
192
192
  this.renderMessage(error, Codicon.error);
193
193
  return;
194
194
  }
195
195
  if (notAvailable) {
196
- this.renderTitleAndInfo(( localize(15030, "No Update Available")));
197
- this.renderMessage(( localize(15031, "There are no updates currently available.")), Codicon.info);
196
+ this.renderTitleAndInfo(( localize(15335, "No Update Available")));
197
+ this.renderMessage(( localize(15336, "There are no updates currently available.")), Codicon.info);
198
198
  return;
199
199
  }
200
- this.renderTitleAndInfo(( localize(15032, "Up to Date")));
200
+ this.renderTitleAndInfo(( localize(15337, "Up to Date")));
201
201
  switch (this.configurationService.getValue("update.mode")) {
202
202
  case "none":
203
- this.renderMessage(( localize(15033, "Automatic updates are disabled.")), Codicon.warning);
203
+ this.renderMessage(( localize(15338, "Automatic updates are disabled.")), Codicon.warning);
204
204
  break;
205
205
  case "manual":
206
206
  this.renderMessage(( localize(
207
- 15034,
207
+ 15339,
208
208
  "Automatic updates will be checked but not installed automatically."
209
209
  )));
210
210
  break;
211
211
  case "start":
212
- this.renderMessage(( localize(15035, "Updates will be applied on restart.")));
212
+ this.renderMessage(( localize(15340, "Updates will be applied on restart.")));
213
213
  break;
214
214
  case "default":
215
215
  if (this.meteredConnectionService.isConnectionMetered) {
216
216
  this.renderMessage(( localize(
217
- 15036,
217
+ 15341,
218
218
  "Automatic updates are paused because the network connection is metered."
219
219
  )), Codicon.radioTower);
220
220
  } else {
221
- this.renderMessage(( localize(15037, "Automatic updates are enabled. Happy Coding!")), Codicon.smiley);
221
+ this.renderMessage(( localize(15342, "Automatic updates are enabled. Happy Coding!")), Codicon.smiley);
222
222
  }
223
223
  break;
224
224
  }
225
225
  }
226
226
  renderCheckingForUpdates() {
227
- this.renderTitleAndInfo(( localize(15038, "Checking for Updates")));
228
- this.renderMessage(( localize(15039, "Checking for updates, please wait...")));
227
+ this.renderTitleAndInfo(( localize(15343, "Checking for Updates")));
228
+ this.renderMessage(( localize(15344, "Checking for updates, please wait...")));
229
229
  }
230
230
  renderAvailableForDownload(
231
231
  {
232
232
  update
233
233
  }
234
234
  ) {
235
- this.renderTitleAndInfo(( localize(15040, "Update Available")), update);
236
- this.renderActionButton(( localize(15041, "Download")), "update.downloadNow");
235
+ this.renderTitleAndInfo(( localize(15345, "Update Available")), update);
236
+ this.renderActionButton(( localize(15346, "Download")), "update.downloadNow");
237
237
  }
238
238
  renderDownloading(state) {
239
- this.renderTitleAndInfo(( localize(15042, "Downloading Update")), state.update);
239
+ this.renderTitleAndInfo(( localize(15347, "Downloading Update")), state.update);
240
240
  const {
241
241
  downloadedBytes,
242
242
  totalBytes
@@ -249,15 +249,15 @@ let UpdateTooltip = class UpdateTooltip extends Disposable {
249
249
  this.progressContainer.style.display = "";
250
250
  const speed = computeDownloadSpeed(state);
251
251
  if (speed !== undefined && speed > 0) {
252
- this.speedInfoNode.textContent = ( localize(15043, "{0}/s", formatBytes(speed)));
252
+ this.speedInfoNode.textContent = ( localize(15348, "{0}/s", formatBytes(speed)));
253
253
  }
254
254
  const timeRemaining = computeDownloadTimeRemaining(state);
255
255
  if (timeRemaining !== undefined && timeRemaining > 0) {
256
- this.timeRemainingNode.textContent = `~${formatTimeRemaining(timeRemaining)} ${( localize(15044, "remaining"))}`;
256
+ this.timeRemainingNode.textContent = `~${formatTimeRemaining(timeRemaining)} ${( localize(15349, "remaining"))}`;
257
257
  }
258
258
  this.downloadStatsContainer.style.display = "";
259
259
  } else {
260
- this.renderMessage(( localize(15045, "Downloading update, please wait...")));
260
+ this.renderMessage(( localize(15350, "Downloading update, please wait...")));
261
261
  }
262
262
  }
263
263
  renderDownloaded(
@@ -265,8 +265,8 @@ let UpdateTooltip = class UpdateTooltip extends Disposable {
265
265
  update
266
266
  }
267
267
  ) {
268
- this.renderTitleAndInfo(( localize(15046, "Update is Ready to Install")), update);
269
- this.renderActionButton(( localize(15047, "Install")), "update.install");
268
+ this.renderTitleAndInfo(( localize(15351, "Update is Ready to Install")), update);
269
+ this.renderActionButton(( localize(15352, "Install")), "update.install");
270
270
  }
271
271
  renderUpdating(
272
272
  {
@@ -275,7 +275,7 @@ let UpdateTooltip = class UpdateTooltip extends Disposable {
275
275
  maxProgress
276
276
  }
277
277
  ) {
278
- this.renderTitleAndInfo(( localize(15048, "Installing Update")), update);
278
+ this.renderTitleAndInfo(( localize(15353, "Installing Update")), update);
279
279
  const percentage = computeProgressPercent(currentProgress, maxProgress);
280
280
  if (percentage !== undefined) {
281
281
  this.progressFill.style.width = `${percentage}%`;
@@ -283,7 +283,7 @@ let UpdateTooltip = class UpdateTooltip extends Disposable {
283
283
  this.progressSizeNode.textContent = "";
284
284
  this.progressContainer.style.display = "";
285
285
  } else {
286
- this.renderMessage(( localize(15049, "Installing update, please wait...")));
286
+ this.renderMessage(( localize(15354, "Installing update, please wait...")));
287
287
  }
288
288
  }
289
289
  renderReady(
@@ -292,10 +292,10 @@ let UpdateTooltip = class UpdateTooltip extends Disposable {
292
292
  }
293
293
  ) {
294
294
  if (this.configurationService.getValue("update.mode") === "manual") {
295
- this.renderTitleAndInfo(( localize(15050, "Update Installed")), update);
296
- this.renderActionButton(( localize(15051, "Restart")), "update.restart");
295
+ this.renderTitleAndInfo(( localize(15355, "Update Installed")), update);
296
+ this.renderActionButton(( localize(15356, "Restart")), "update.restart");
297
297
  } else {
298
- this.renderTitleAndInfo(( localize(15052, "Restart to Update")), update);
298
+ this.renderTitleAndInfo(( localize(15357, "Restart to Update")), update);
299
299
  }
300
300
  }
301
301
  renderOverwriting(
@@ -303,23 +303,23 @@ let UpdateTooltip = class UpdateTooltip extends Disposable {
303
303
  update
304
304
  }
305
305
  ) {
306
- this.renderTitleAndInfo(( localize(15053, "Downloading Newer Update")), update);
307
- this.renderMessage(( localize(15054, "A newer update was released. Downloading, please wait...")));
306
+ this.renderTitleAndInfo(( localize(15358, "Downloading Newer Update")), update);
307
+ this.renderMessage(( localize(15359, "A newer update was released. Downloading, please wait...")));
308
308
  }
309
309
  renderRestarting(
310
310
  {
311
311
  update
312
312
  }
313
313
  ) {
314
- this.renderTitleAndInfo(( localize(15055, "Restarting {0}", this.productService.nameShort)), update);
315
- this.renderMessage(( localize(15056, "Restarting to update, please wait...")));
314
+ this.renderTitleAndInfo(( localize(15360, "Restarting {0}", this.productService.nameShort)), update);
315
+ this.renderMessage(( localize(15361, "Restarting to update, please wait...")));
316
316
  }
317
317
  renderTitleAndInfo(title, update) {
318
318
  this.titleNode.textContent = title;
319
319
  const version = update?.productVersion;
320
320
  if (version) {
321
321
  const updateCommitId = update.version?.substring(0, 7);
322
- this.latestVersionNode.textContent = updateCommitId ? ( localize(15057, "Latest Version: {0} ({1})", version, updateCommitId)) : ( localize(15058, "Latest Version: {0}", version));
322
+ this.latestVersionNode.textContent = updateCommitId ? ( localize(15362, "Latest Version: {0} ({1})", version, updateCommitId)) : ( localize(15363, "Latest Version: {0}", version));
323
323
  this.latestVersionCopyValue.value = updateCommitId ? `${version} (${update.version})` : version;
324
324
  this.latestVersionNode.parentElement.style.display = "";
325
325
  } else {
@@ -327,7 +327,7 @@ let UpdateTooltip = class UpdateTooltip extends Disposable {
327
327
  }
328
328
  const releaseDate = update?.timestamp ?? tryParseDate(this.productService.date);
329
329
  if (typeof releaseDate === "number" && releaseDate > 0) {
330
- this.releaseDateNode.textContent = ( localize(15059, "Released {0}", formatDate(releaseDate)));
330
+ this.releaseDateNode.textContent = ( localize(15364, "Released {0}", formatDate(releaseDate)));
331
331
  this.releaseDateNode.style.display = "";
332
332
  } else {
333
333
  this.releaseDateNode.style.display = "none";
@@ -360,7 +360,7 @@ let UpdateTooltip = class UpdateTooltip extends Disposable {
360
360
  const copyButton = append(row, $("a.copy-version-button"));
361
361
  copyButton.setAttribute("role", "button");
362
362
  copyButton.setAttribute("tabindex", "0");
363
- const title = ( localize(15060, "Copy"));
363
+ const title = ( localize(15365, "Copy"));
364
364
  copyButton.title = title;
365
365
  copyButton.setAttribute("aria-label", title);
366
366
  const copyIcon = append(copyButton, $(".copy-icon"));
@@ -5,22 +5,55 @@ export interface IUpdateInfoButton {
5
5
  readonly args?: unknown[];
6
6
  readonly style?: UpdateInfoButtonStyle;
7
7
  }
8
+ export interface IUpdateInfoFeature {
9
+ /**
10
+ * Optional Codicon icon identifier (e.g. `$(sparkle)` or `$(lightbulb)`) displayed
11
+ * alongside the feature title.
12
+ */
13
+ readonly icon?: string;
14
+ /** Short title for the feature highlight. */
15
+ readonly title: string;
16
+ /** One-line description of the feature. */
17
+ readonly description: string;
18
+ }
8
19
  export interface IParsedUpdateInfoInput {
20
+ /** Markdown body rendered in the update-info widget. */
9
21
  readonly markdown: string;
22
+ /** Optional action buttons shown below the markdown content. */
10
23
  readonly buttons?: IUpdateInfoButton[];
24
+ /**
25
+ * Optional URL for a banner/hero image shown at the top of the widget.
26
+ * Must be an `https://` URL; non-HTTPS URLs are ignored.
27
+ */
28
+ readonly bannerImageUrl?: string;
29
+ /** Optional short badge label (e.g. `"New"`) displayed on the widget. */
30
+ readonly badge?: string;
31
+ /** Optional heading title rendered above the markdown body. */
32
+ readonly title?: string;
33
+ /**
34
+ * Optional list of feature highlights. At most {@link MAX_FEATURES} entries
35
+ * (currently 5) are displayed; any additional entries are silently dropped.
36
+ */
37
+ readonly features?: IUpdateInfoFeature[];
11
38
  }
12
39
  /**
13
40
  * Parses optional metadata from update info input.
14
41
  *
15
42
  * Supported formats:
16
43
  *
17
- * **JSON envelope** - a single JSON object with `markdown` and optional `buttons`:
44
+ * **JSON envelope** - a single JSON object with `markdown` and optional fields:
18
45
  * ```json
19
46
  * {
20
47
  * "markdown": "$(info) **Feature**<br>Description...",
48
+ * "title": "What's New",
49
+ * "badge": "New",
50
+ * "bannerImageUrl": "https://example.com/banner.png",
21
51
  * "buttons": [
22
52
  * { "label": "Release Notes", "commandId": "update.showCurrentReleaseNotes", "style": "secondary" },
23
53
  * { "label": "Open Sessions", "commandId": "workbench.action.chat.open", "style": "primary" }
54
+ * ],
55
+ * "features": [
56
+ * { "icon": "$(sparkle)", "title": "Feature", "description": "Short description" }
24
57
  * ]
25
58
  * }
26
59
  * ```
@@ -28,7 +61,7 @@ export interface IParsedUpdateInfoInput {
28
61
  * **Block frontmatter** - YAML-style `---` delimiters wrapping a JSON metadata block:
29
62
  * ```
30
63
  * ---
31
- * { "buttons": [...] }
64
+ * { "buttons": [...], "features": [...] }
32
65
  * ---
33
66
  * $(info) **Feature**<br>Description...
34
67
  * ```
@@ -38,5 +71,7 @@ export interface IParsedUpdateInfoInput {
38
71
  * --- { "buttons": [...] } ---
39
72
  * $(info) **Feature**<br>Description...
40
73
  * ```
74
+ *
75
+ * At most 5 feature entries are retained; any additional ones are silently dropped.
41
76
  */
42
77
  export declare function parseUpdateInfoInput(text: string): IParsedUpdateInfoInput;
@@ -1,6 +1,7 @@
1
1
 
2
2
  import { hasKey } from '@codingame/monaco-vscode-api/vscode/vs/base/common/types';
3
3
 
4
+ const MAX_FEATURES = 5;
4
5
  function parseUpdateInfoInput(text) {
5
6
  const normalized = text.replace(/^\uFEFF/, '');
6
7
  return tryParseUpdateInfoEnvelope(normalized) ?? parseUpdateInfoFrontmatter(normalized);
@@ -15,15 +16,32 @@ function tryParseUpdateInfoEnvelope(text) {
15
16
  if (typeof value.markdown !== 'string') {
16
17
  return undefined;
17
18
  }
18
- return {
19
- markdown: value.markdown,
20
- buttons: parseUpdateInfoButtons(value.buttons),
21
- };
19
+ return buildParsedInput(value.markdown, value);
22
20
  }
23
21
  catch {
24
22
  return undefined;
25
23
  }
26
24
  }
25
+ function buildParsedInput(markdown, meta) {
26
+ const result = {
27
+ markdown,
28
+ buttons: parseUpdateInfoButtons(meta.buttons),
29
+ };
30
+ if (typeof meta.bannerImageUrl === 'string') {
31
+ result.bannerImageUrl = meta.bannerImageUrl;
32
+ }
33
+ if (typeof meta.badge === 'string') {
34
+ result.badge = meta.badge;
35
+ }
36
+ if (typeof meta.title === 'string') {
37
+ result.title = meta.title;
38
+ }
39
+ const features = parseUpdateInfoFeatures(meta.features);
40
+ if (features) {
41
+ result.features = features;
42
+ }
43
+ return result;
44
+ }
27
45
  function parseUpdateInfoFrontmatter(text) {
28
46
  const blockMatch = text.match(/^---[ \t]*\r?\n(?<json>[\s\S]*?)\r?\n---[ \t]*(?:\r?\n(?<body>[\s\S]*))?$/);
29
47
  if (blockMatch?.groups) {
@@ -38,10 +56,7 @@ function parseUpdateInfoFrontmatter(text) {
38
56
  function parseUpdateInfoFrontmatterMatch(text, jsonText, markdown) {
39
57
  try {
40
58
  const meta = JSON.parse(jsonText);
41
- return {
42
- markdown,
43
- buttons: parseUpdateInfoButtons(meta.buttons),
44
- };
59
+ return buildParsedInput(markdown, meta);
45
60
  }
46
61
  catch {
47
62
  return { markdown: text };
@@ -70,5 +85,26 @@ function parseUpdateInfoButtons(buttons) {
70
85
  }
71
86
  return parsedButtons.length ? parsedButtons : undefined;
72
87
  }
88
+ function parseUpdateInfoFeatures(features) {
89
+ if (!Array.isArray(features)) {
90
+ return undefined;
91
+ }
92
+ const parsed = [];
93
+ for (const feature of features) {
94
+ if (typeof feature !== 'object' || feature === null) {
95
+ continue;
96
+ }
97
+ const candidate = feature;
98
+ if (typeof candidate.title !== 'string' || typeof candidate.description !== 'string') {
99
+ continue;
100
+ }
101
+ const icon = typeof candidate.icon === 'string' ? candidate.icon : undefined;
102
+ parsed.push({ icon, title: candidate.title, description: candidate.description });
103
+ if (parsed.length >= MAX_FEATURES) {
104
+ break;
105
+ }
106
+ }
107
+ return parsed.length ? parsed : undefined;
108
+ }
73
109
 
74
110
  export { parseUpdateInfoInput };
@@ -54,31 +54,31 @@ function formatTimeRemaining(seconds) {
54
54
  if (hours >= 1) {
55
55
  const formattedHours = formatDecimal(hours);
56
56
  if (formattedHours === "1") {
57
- return localize(15061, "{0} hour", formattedHours);
57
+ return localize(15366, "{0} hour", formattedHours);
58
58
  } else {
59
- return localize(15062, "{0} hours", formattedHours);
59
+ return localize(15367, "{0} hours", formattedHours);
60
60
  }
61
61
  }
62
62
  const minutes = Math.floor(seconds / 60);
63
63
  if (minutes >= 1) {
64
- return localize(15063, "{0} min", minutes);
64
+ return localize(15368, "{0} min", minutes);
65
65
  }
66
- return localize(15064, "{0}s", seconds);
66
+ return localize(15369, "{0}s", seconds);
67
67
  }
68
68
  function formatBytes(bytes) {
69
69
  if (bytes < 1024) {
70
- return localize(15065, "{0} B", bytes);
70
+ return localize(15370, "{0} B", bytes);
71
71
  }
72
72
  const kb = bytes / 1024;
73
73
  if (kb < 1024) {
74
- return localize(15066, "{0} KB", formatDecimal(kb));
74
+ return localize(15371, "{0} KB", formatDecimal(kb));
75
75
  }
76
76
  const mb = kb / 1024;
77
77
  if (mb < 1024) {
78
- return localize(15067, "{0} MB", formatDecimal(mb));
78
+ return localize(15372, "{0} MB", formatDecimal(mb));
79
79
  }
80
80
  const gb = mb / 1024;
81
- return localize(15068, "{0} GB", formatDecimal(gb));
81
+ return localize(15373, "{0} GB", formatDecimal(gb));
82
82
  }
83
83
  function tryParseDate(date) {
84
84
  if (date === undefined) {