src/vs/workbench/contrib/update/common/updateInfoParser.ts

205 LOC · 203 covered · 2 uncovered · 39 ranges · 28 concepts · 22 introducers · 20 tests

File neighbourhood

The centred file is linked to every concept that introduces one of its ranges, every test that runs code from the file, and the gray connector concepts standing between those tests and the file's own introducer concepts. Undirected links join concepts to every file where they introduce source and concepts to the tests they introduce; arrows show specialization between the displayed concepts and bridge only concepts omitted from this view. Concept colors match the source ranges below; connector concepts have no source color and are shown in gray.

Focused file, its introducer and connector concepts, their introduced files, and tests that run code from the file

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the related-file, concept, and source links on this page.

Focused file, its introducer and connector concepts, their introduced files, and tests that run code from the fileupdateInfoParser.ts ×1 · 2 introduced LOCupdateInfoParser.ts ×1updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput block frontmatter with buttons|occurrence=1, updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput block frontmatter with no body|occurrence=1 · 0 introduced LOCupdateInfoParser.test|ti…updateInfoParser.ts ×1 · 2 introduced LOCupdateInfoParser.ts ×1updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput ignores invalid style values|occurrence=1, updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput JSON envelope with markdown and buttons|occurrence=1 · 0 introduced LOCupdateInfoParser.test|ti…updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput block frontmatter with bannerImageUrl, badge, title, and features|occurrence=1 · 0 introduced LOCupdateInfoParser.test|ti…updateInfoParser.ts ×1 · 2 introduced LOCupdateInfoParser.ts ×1updateInfoParser.ts ×1 · 1 introduced LOCupdateInfoParser.ts ×1updateInfoParser.ts ×1 · 2 introduced LOCupdateInfoParser.ts ×1updateInfoParser.ts ×2 · 4 introduced LOCupdateInfoParser.ts ×2updateInfoParser.ts ×3 · 16 introduced LOCupdateInfoParser.ts ×3updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput ignores non-string feature icon|occurrence=1, updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput JSON envelope with bannerImageUrl, badge, title, and features|occurrence=1 · 0 introduced LOCupdateInfoParser.test|ti…updateInfoParser.ts ×4 · 11 introduced LOCupdateInfoParser.ts ×4updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput JSON envelope without buttons|occurrence=1, updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput ignores non-string bannerImageUrl, badge, and title|occurrence=1 · 0 introduced LOCupdateInfoParser.test|ti…updateInfoParser.ts ×1 · 2 introduced LOCupdateInfoParser.ts ×1updateInfoParser.ts ×1 · 3 introduced LOCupdateInfoParser.ts ×1updateInfoParser.ts ×1 · 2 introduced LOCupdateInfoParser.ts ×1updateInfoParser.ts ×1 · 2 introduced LOCupdateInfoParser.ts ×1updateInfoParser.ts ×1 · 2 introduced LOCupdateInfoParser.ts ×1updateInfoParser.ts ×1 · 2 introduced LOCupdateInfoParser.ts ×1updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput strips BOM prefix|occurrence=1, updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput plain markdown returns as-is with no buttons|occurrence=1, +1 · 0 introduced LOCupdateInfoParser.test|ti…updateInfoParser.ts ×2 · 6 introduced LOCupdateInfoParser.ts ×2updateInfoParser.ts ×5 · 20 introduced LOCupdateInfoParser.ts ×5updateInfoParser.ts ×1 · 3 introduced LOCupdateInfoParser.ts ×1updateInfoParser.ts ×1 · 2 introduced LOCupdateInfoParser.ts ×1updateInfoParser.ts ×1 · 2 introduced LOCupdateInfoParser.ts ×1updateInfoParser.ts ×2 · 4 introduced LOCupdateInfoParser.ts ×2updateInfoParser.ts ×1 · 4 introduced LOCupdateInfoParser.ts ×1updateInfoParser.ts ×6 · 109 introduced LOCupdateInfoParser.ts ×6updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput JSON envelope with bannerImageUrl, badge, title, and features|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/contrib/update/test/common/updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput JSON envelope with bannerImageUrl, badge, title, and features|occurrence=1updateInfoParser.test|ti…updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput JSON envelope with invalid JSON falls back to plain markdown|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/contrib/update/test/common/updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput JSON envelope with invalid JSON falls back to plain markdown|occurrence=1updateInfoParser.test|ti…updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput JSON envelope with markdown and buttons|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/contrib/update/test/common/updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput JSON envelope with markdown and buttons|occurrence=1updateInfoParser.test|ti…updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput JSON envelope without buttons|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/contrib/update/test/common/updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput JSON envelope without buttons|occurrence=1updateInfoParser.test|ti…updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput JSON envelope without markdown property falls back to plain markdown|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/contrib/update/test/common/updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput JSON envelope without markdown property falls back to plain markdown|occurrence=1updateInfoParser.test|ti…updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput block frontmatter with bannerImageUrl, badge, title, and features|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/contrib/update/test/common/updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput block frontmatter with bannerImageUrl, badge, title, and features|occurrence=1updateInfoParser.test|ti…updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput block frontmatter with buttons|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/contrib/update/test/common/updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput block frontmatter with buttons|occurrence=1updateInfoParser.test|ti…updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput block frontmatter with no body|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/contrib/update/test/common/updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput block frontmatter with no body|occurrence=1updateInfoParser.test|ti…updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput caps features at 5 entries and skips invalid ones|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/contrib/update/test/common/updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput caps features at 5 entries and skips invalid ones|occurrence=1updateInfoParser.test|ti…updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput frontmatter with invalid JSON falls back to full text|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/contrib/update/test/common/updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput frontmatter with invalid JSON falls back to full text|occurrence=1updateInfoParser.test|ti…updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput ignores invalid style values|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/contrib/update/test/common/updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput ignores invalid style values|occurrence=1updateInfoParser.test|ti…updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput ignores non-string bannerImageUrl, badge, and title|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/contrib/update/test/common/updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput ignores non-string bannerImageUrl, badge, and title|occurrence=1updateInfoParser.test|ti…updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput ignores non-string feature icon|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/contrib/update/test/common/updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput ignores non-string feature icon|occurrence=1updateInfoParser.test|ti…updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput inline frontmatter handles nested JSON with braces|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/contrib/update/test/common/updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput inline frontmatter handles nested JSON with braces|occurrence=1updateInfoParser.test|ti…updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput inline frontmatter with buttons|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/contrib/update/test/common/updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput inline frontmatter with buttons|occurrence=1updateInfoParser.test|ti…updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput plain markdown returns as-is with no buttons|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/contrib/update/test/common/updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput plain markdown returns as-is with no buttons|occurrence=1updateInfoParser.test|ti…updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput returns undefined buttons when all buttons are invalid|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/contrib/update/test/common/updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput returns undefined buttons when all buttons are invalid|occurrence=1updateInfoParser.test|ti…updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput returns undefined features when all features are invalid|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/contrib/update/test/common/updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput returns undefined features when all features are invalid|occurrence=1updateInfoParser.test|ti…updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput skips buttons with missing required properties|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/contrib/update/test/common/updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput skips buttons with missing required properties|occurrence=1updateInfoParser.test|ti…updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput strips BOM prefix|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/contrib/update/test/common/updateInfoParser.test|title=updateInfoParser parseUpdateInfoInput strips BOM prefix|occurrence=1updateInfoParser.test|ti…Focused file · src/vs/workbench/contrib/update/common/updateInfoParser.ts · 205 LOCcommon/updateInfoParser.…

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the related-file, concept, and source links on this page while the interactive map is unavailable.

1 > /*--------------------------------------------------------------------------------------------- updateInfoParser.ts ×6
2 > * Copyright (c) Microsoft Corporation. All rights reserved.
3 > * Licensed under the MIT License. See License.txt in the project root for license information.
4 > *--------------------------------------------------------------------------------------------*/
5 >
6 > import { hasKey, Mutable } from '../../../../base/common/types.js';
7 >
8 > const MAX_FEATURES = 5;
9 >
10 > export type UpdateInfoButtonStyle = 'primary' | 'secondary';
11 >
12 > export interface IUpdateInfoButton {
13 > readonly label: string;
14 > readonly commandId: string;
15 > readonly args?: unknown[];
16 > readonly style?: UpdateInfoButtonStyle;
17 > }
18 >
19 > export interface IUpdateInfoFeature {
20 > /**
21 > * Optional Codicon icon identifier (e.g. `$(sparkle)` or `$(lightbulb)`) displayed
22 > * alongside the feature title.
23 > */
24 > readonly icon?: string;
25 > /** Short title for the feature highlight. */
26 > readonly title: string;
27 > /** One-line description of the feature. */
28 > readonly description: string;
29 > }
30 >
31 > export interface IParsedUpdateInfoInput {
32 > /** Markdown body rendered in the update-info widget. */
33 > readonly markdown: string;
34 > /** Optional action buttons shown below the markdown content. */
35 > readonly buttons?: IUpdateInfoButton[];
36 > /**
37 > * Optional URL for a banner/hero image shown at the top of the widget.
38 > * Must be an `https://` URL; non-HTTPS URLs are ignored.
39 > */
40 > readonly bannerImageUrl?: string;
41 > /** Optional short badge label (e.g. `"New"`) displayed on the widget. */
42 > readonly badge?: string;
43 > /** Optional heading title rendered above the markdown body. */
44 > readonly title?: string;
45 > /**
46 > * Optional list of feature highlights. At most {@link MAX_FEATURES} entries
47 > * (currently 5) are displayed; any additional entries are silently dropped.
48 > */
49 > readonly features?: IUpdateInfoFeature[];
50 > }
51 >
52 > /**
53 > * Parses optional metadata from update info input.
54 > *
55 > * Supported formats:
56 > *
57 > * **JSON envelope** - a single JSON object with `markdown` and optional fields:
58 > * ```json
59 > * {
60 > * "markdown": "$(info) **Feature**<br>Description...",
61 > * "title": "What's New",
62 > * "badge": "New",
63 > * "bannerImageUrl": "https://example.com/banner.png",
64 > * "buttons": [
65 > * { "label": "Release Notes", "commandId": "update.showCurrentReleaseNotes", "style": "secondary" },
66 > * { "label": "Open Sessions", "commandId": "workbench.action.chat.open", "style": "primary" }
67 > * ],
68 > * "features": [
69 > * { "icon": "$(sparkle)", "title": "Feature", "description": "Short description" }
70 > * ]
71 > * }
72 > * ```
73 > *
74 > * **Block frontmatter** - YAML-style `---` delimiters wrapping a JSON metadata block:
75 > * ```
76 > * ---
77 > * { "buttons": [...], "features": [...] }
78 > * ---
79 > * $(info) **Feature**<br>Description...
80 > * ```
81 > *
82 > * **Inline frontmatter** - metadata on a single `---` line:
83 > * ```
84 > * --- { "buttons": [...] } ---
85 > * $(info) **Feature**<br>Description...
86 > * ```
87 > *
88 > * At most 5 feature entries are retained; any additional ones are silently dropped.
89 > */
90 > export function parseUpdateInfoInput(text: string): IParsedUpdateInfoInput {
91 > const normalized = text.replace(/^\uFEFF/, '');
92 > return tryParseUpdateInfoEnvelope(normalized) ?? parseUpdateInfoFrontmatter(normalized);
93 > }
94 >
95 > function tryParseUpdateInfoEnvelope(text: string): IParsedUpdateInfoInput | undefined {
96 > const trimmed = text.trim();
97 > if (!trimmed.startsWith('{') || !trimmed.endsWith('}')) {
98 > return undefined; updateInfoParser.ts ×1
99 > }
101 > try {
102 > const value = JSON.parse(trimmed) as { markdown?: string; buttons?: unknown; bannerImageUrl?: unknown; badge?: unknown; title?: unknown; features?: unknown };
103 > if (typeof value.markdown !== 'string') {
104 > return undefined; updateInfoParser.ts ×1
105 > }
107 > return buildParsedInput(value.markdown, value);
108 > } catch {
109 return undefined;
110 }
112 >
113 > function buildParsedInput(markdown: string, meta: { buttons?: unknown; bannerImageUrl?: unknown; badge?: unknown; title?: unknown; features?: unknown }): IParsedUpdateInfoInput { updateInfoParser.ts ×5
114 > const result: Mutable<IParsedUpdateInfoInput> = {
115 > markdown,
116 > buttons: parseUpdateInfoButtons(meta.buttons),
117 > };
118 > if (typeof meta.bannerImageUrl === 'string') { result.bannerImageUrl = meta.bannerImageUrl; }
119 > if (typeof meta.badge === 'string') { result.badge = meta.badge; }
120 > if (typeof meta.title === 'string') { result.title = meta.title; }
121 > const features = parseUpdateInfoFeatures(meta.features);
122 > if (features) { result.features = features; }
123 > return result;
124 > }
126 > function parseUpdateInfoFrontmatter(text: string): IParsedUpdateInfoInput { updateInfoParser.ts ×2
127 > const blockMatch = text.match(/^---[ \t]*\r?\n(?<json>[\s\S]*?)\r?\n---[ \t]*(?:\r?\n(?<body>[\s\S]*))?$/);
128 > if (blockMatch?.groups) {
129 > return parseUpdateInfoFrontmatterMatch(text, blockMatch.groups['json'], blockMatch.groups['body'] ?? ''); updateInfoParser.ts ×1
130 > }
132 > const inlineMatch = text.match(/^---[ \t]*(?<json>\{.*\})[ \t]*---[ \t]*(?<body>[\s\S]*)$/);
133 > if (inlineMatch?.groups) { updateInfoParser.ts ×2
134 > return parseUpdateInfoFrontmatterMatch(text, inlineMatch.groups['json'], inlineMatch.groups['body']); updateInfoParser.ts ×1
135 > }
137 > return { markdown: text };
138 > }
140 > function parseUpdateInfoFrontmatterMatch(text: string, jsonText: string, markdown: string): IParsedUpdateInfoInput { updateInfoParser.ts ×2
141 > try {
142 > const meta = JSON.parse(jsonText) as { buttons?: unknown; bannerImageUrl?: unknown; badge?: unknown; title?: unknown; features?: unknown };
143 > return buildParsedInput(markdown, meta);
144 > } catch {
145 > return { markdown: text }; updateInfoParser.ts ×1
146 > }
149 > function parseUpdateInfoButtons(buttons: unknown): IUpdateInfoButton[] | undefined { updateInfoParser.ts ×5
150 > if (!Array.isArray(buttons)) {
151 > return undefined; updateInfoParser.ts ×1
152 > }
154 > const parsedButtons: IUpdateInfoButton[] = [];
155 > for (const button of buttons) {
156 > if (typeof button !== 'object' || button === null) {
157 > continue; updateInfoParser.ts ×1
158 > }
160 > if (!hasKey(button, { label: true, commandId: true }) || typeof button.label !== 'string' || typeof button.commandId !== 'string') {
161 > continue; updateInfoParser.ts ×1
162 > }
164 > const style = hasKey(button, { style: true }) && (button.style === 'primary' || button.style === 'secondary') ? button.style : undefined; updateInfoParser.ts ×3
165 > const args = hasKey(button, { args: true }) && Array.isArray(button.args) ? button.args : undefined;
166 > parsedButtons.push({
167 > label: button.label,
168 > commandId: button.commandId,
169 > args,
170 > style,
171 > });
172 > }
173 >
174 > return parsedButtons.length ? parsedButtons : undefined; updateInfoParser.ts ×5
175 > }
177 > /**
178 > * Parses an array of feature-highlight objects from raw update-info metadata.
179 > * Only the first {@link MAX_FEATURES} valid entries are returned; the rest are
180 > * discarded. Each entry must have at minimum a `title` and `description` string.
181 > * The optional `icon` field accepts a Codicon identifier (e.g. `$(sparkle)`).
182 > */
183 > function parseUpdateInfoFeatures(features: unknown): IUpdateInfoFeature[] | undefined { updateInfoParser.ts ×5
184 > if (!Array.isArray(features)) {
185 > return undefined; updateInfoParser.ts ×1
186 > }
188 > const parsed: IUpdateInfoFeature[] = [];
189 > for (const feature of features) {
190 > if (typeof feature !== 'object' || feature === null) {
191 > continue; updateInfoParser.ts ×2
192 > }
193 > const candidate = feature as { title?: unknown; description?: unknown; icon?: unknown }; updateInfoParser.ts ×4
194 > if (typeof candidate.title !== 'string' || typeof candidate.description !== 'string') {
195 > continue; updateInfoParser.ts ×2
196 > }
197 > const icon = typeof candidate.icon === 'string' ? candidate.icon : undefined; updateInfoParser.ts ×4
198 > parsed.push({ icon, title: candidate.title, description: candidate.description });
199 > if (parsed.length >= MAX_FEATURES) {
201 > }
203 >
204 > return parsed.length ? parsed : undefined; updateInfoParser.ts ×5
205 > }