@theia/core 1.75.0-next.14 → 1.75.0-next.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -75,15 +75,15 @@ export class SomeClass {
75
75
  - `electron` (from [`electron@42.3.0`](https://www.npmjs.com/package/electron/v/42.3.0))
76
76
  - `electron-store` (from [`electron-store@^8.2.0`](https://www.npmjs.com/package/electron-store))
77
77
  - `@theia/core/shared/...`
78
- - `@lumino/algorithm` (from [`@lumino/algorithm@^2.0.4`](https://www.npmjs.com/package/@lumino/algorithm))
79
- - `@lumino/commands` (from [`@lumino/commands@^2.3.3`](https://www.npmjs.com/package/@lumino/commands))
80
- - `@lumino/coreutils` (from [`@lumino/coreutils@^2.2.2`](https://www.npmjs.com/package/@lumino/coreutils))
81
- - `@lumino/domutils` (from [`@lumino/domutils@^2.0.4`](https://www.npmjs.com/package/@lumino/domutils))
82
- - `@lumino/dragdrop` (from [`@lumino/dragdrop@^2.1.8`](https://www.npmjs.com/package/@lumino/dragdrop))
83
- - `@lumino/messaging` (from [`@lumino/messaging@^2.0.4`](https://www.npmjs.com/package/@lumino/messaging))
84
- - `@lumino/properties` (from [`@lumino/properties@^2.0.4`](https://www.npmjs.com/package/@lumino/properties))
85
- - `@lumino/signaling` (from [`@lumino/signaling@^2.1.5`](https://www.npmjs.com/package/@lumino/signaling))
86
- - `@lumino/virtualdom` (from [`@lumino/virtualdom@^2.0.4`](https://www.npmjs.com/package/@lumino/virtualdom))
78
+ - `@lumino/algorithm` (from [`@lumino/algorithm@^2.0.5`](https://www.npmjs.com/package/@lumino/algorithm))
79
+ - `@lumino/commands` (from [`@lumino/commands@^2.3.4`](https://www.npmjs.com/package/@lumino/commands))
80
+ - `@lumino/coreutils` (from [`@lumino/coreutils@^2.2.3`](https://www.npmjs.com/package/@lumino/coreutils))
81
+ - `@lumino/domutils` (from [`@lumino/domutils@^2.0.5`](https://www.npmjs.com/package/@lumino/domutils))
82
+ - `@lumino/dragdrop` (from [`@lumino/dragdrop@^2.1.9`](https://www.npmjs.com/package/@lumino/dragdrop))
83
+ - `@lumino/messaging` (from [`@lumino/messaging@^2.0.5`](https://www.npmjs.com/package/@lumino/messaging))
84
+ - `@lumino/properties` (from [`@lumino/properties@^2.0.5`](https://www.npmjs.com/package/@lumino/properties))
85
+ - `@lumino/signaling` (from [`@lumino/signaling@^2.1.6`](https://www.npmjs.com/package/@lumino/signaling))
86
+ - `@lumino/virtualdom` (from [`@lumino/virtualdom@^2.0.5`](https://www.npmjs.com/package/@lumino/virtualdom))
87
87
  - `@lumino/widgets` (from [`@lumino/widgets@2.7.5`](https://www.npmjs.com/package/@lumino/widgets/v/2.7.5))
88
88
  - `@theia/application-package` (from [`@theia/application-package@1.74.0`](https://www.npmjs.com/package/@theia/application-package/v/1.74.0))
89
89
  - `@theia/application-package/lib/api` (from [`@theia/application-package@1.74.0`](https://www.npmjs.com/package/@theia/application-package/v/1.74.0))
@@ -99,16 +99,16 @@ export class SomeClass {
99
99
  - `react-virtuoso` (from [`react-virtuoso@^2.19.1`](https://www.npmjs.com/package/react-virtuoso))
100
100
  - `vscode-languageserver-protocol` (from [`vscode-languageserver-protocol@3.17.5`](https://www.npmjs.com/package/vscode-languageserver-protocol/v/3.17.5))
101
101
  - `vscode-uri` (from [`vscode-uri@3.0.8`](https://www.npmjs.com/package/vscode-uri/v/3.0.8))
102
- - `@parcel/watcher` (from [`@parcel/watcher@^2.5.6`](https://www.npmjs.com/package/@parcel/watcher))
103
- - `dompurify` (from [`dompurify@^3.4.11`](https://www.npmjs.com/package/dompurify))
102
+ - `@parcel/watcher` (from [`@parcel/watcher@^2.6.0`](https://www.npmjs.com/package/@parcel/watcher))
103
+ - `dompurify` (from [`dompurify@^3.4.13`](https://www.npmjs.com/package/dompurify))
104
104
  - `express` (from [`express@^4.22.2`](https://www.npmjs.com/package/express))
105
105
  - `lodash.debounce` (from [`lodash.debounce@^4.0.8`](https://www.npmjs.com/package/lodash.debounce))
106
106
  - `lodash.throttle` (from [`lodash.throttle@^4.1.1`](https://www.npmjs.com/package/lodash.throttle))
107
107
  - `markdown-it` (from [`markdown-it@^14.3.0`](https://www.npmjs.com/package/markdown-it))
108
- - `markdown-it-anchor` (from [`markdown-it-anchor@^9.2.0`](https://www.npmjs.com/package/markdown-it-anchor))
109
- - `markdown-it-emoji` (from [`markdown-it-emoji@^3.0.0`](https://www.npmjs.com/package/markdown-it-emoji))
108
+ - `markdown-it-anchor` (from [`markdown-it-anchor@^9.2.1`](https://www.npmjs.com/package/markdown-it-anchor))
109
+ - `markdown-it-emoji` (from [`markdown-it-emoji@^3.1.0`](https://www.npmjs.com/package/markdown-it-emoji))
110
110
  - `react` (from [`react@^18.3.1 || ^19.0.0`](https://www.npmjs.com/package/react))
111
- - `ws` (from [`ws@^8.21.0`](https://www.npmjs.com/package/ws))
111
+ - `ws` (from [`ws@^8.21.3`](https://www.npmjs.com/package/ws))
112
112
  - `yargs` (from [`yargs@^17.7.3`](https://www.npmjs.com/package/yargs))
113
113
 
114
114
  ## Logging Configuration
@@ -7913,7 +7913,7 @@
7913
7913
  "venvironment.json",
7914
7914
  "*.venvironment.json"
7915
7915
  ],
7916
- "url": "https://www.schemastore.org/venvironment-schema-v5.0.0.json",
7916
+ "url": "https://www.schemastore.org/venvironment-schema-v5.1.0.json",
7917
7917
  "versions": {
7918
7918
  "1.0.0": "https://www.schemastore.org/venvironment-schema-v1.0.0.json",
7919
7919
  "1.1.0": "https://www.schemastore.org/venvironment-schema-v1.1.0.json",
@@ -7927,7 +7927,8 @@
7927
7927
  "4.0.0": "https://www.schemastore.org/venvironment-schema-v4.0.0.json",
7928
7928
  "4.1.0": "https://www.schemastore.org/venvironment-schema-v4.1.0.json",
7929
7929
  "4.2.0": "https://www.schemastore.org/venvironment-schema-v4.2.0.json",
7930
- "5.0.0": "https://www.schemastore.org/venvironment-schema-v5.0.0.json"
7930
+ "5.0.0": "https://www.schemastore.org/venvironment-schema-v5.0.0.json",
7931
+ "5.1.0": "https://www.schemastore.org/venvironment-schema-v5.1.0.json"
7931
7932
  }
7932
7933
  },
7933
7934
  {
@@ -7941,10 +7942,11 @@
7941
7942
  "venvplus.json",
7942
7943
  "*.venvplus.json"
7943
7944
  ],
7944
- "url": "https://www.schemastore.org/venvplus-schema-v1.1.0.json",
7945
+ "url": "https://www.schemastore.org/venvplus-schema-v1.2.0.json",
7945
7946
  "versions": {
7946
7947
  "1.0.0": "https://www.schemastore.org/venvplus-schema-v1.0.0.json",
7947
- "1.1.0": "https://www.schemastore.org/venvplus-schema-v1.1.0.json"
7948
+ "1.1.0": "https://www.schemastore.org/venvplus-schema-v1.1.0.json",
7949
+ "1.2.0": "https://www.schemastore.org/venvplus-schema-v1.2.0.json"
7948
7950
  }
7949
7951
  },
7950
7952
  {
@@ -1,6 +1,15 @@
1
1
  import { Disposable } from '../../common';
2
2
  import { MarkdownString } from '../../common/markdown-rendering/markdown-string';
3
3
  import { OpenerService } from '../opener-service';
4
+ /**
5
+ * Marks an element whose markdown links are already routed through an {@link OpenerService}.
6
+ *
7
+ * Renderers that install their own link handling declare it with {@link markMarkdownLinksWired},
8
+ * so that {@link wireMarkdownLinkHandler} does not add a second handler and open every link twice.
9
+ */
10
+ export declare const MARKDOWN_LINKS_WIRED_ATTRIBUTE = "data-theia-markdown-links-wired";
11
+ /** Declares that the element's markdown links are already routed through an {@link OpenerService}. */
12
+ export declare function markMarkdownLinksWired(root: HTMLElement): void;
4
13
  /**
5
14
  * Wires up anchor clicks inside a rendered markdown element so that they are routed
6
15
  * through the {@link OpenerService} instead of relying on default browser navigation.
@@ -9,6 +18,8 @@ import { OpenerService } from '../opener-service';
9
18
  * Also sets the `title` attribute on each anchor to its `href` (when no title is set)
10
19
  * so users can hover to see the link target.
11
20
  *
21
+ * Does nothing if the element's links are already wired, see {@link markMarkdownLinksWired}.
22
+ *
12
23
  * @returns a {@link Disposable} that removes the click listener.
13
24
  */
14
25
  export declare function wireMarkdownLinkHandler(root: HTMLElement, source: MarkdownString, openerService: OpenerService): Disposable;
@@ -1 +1 @@
1
- {"version":3,"file":"markdown-link-handler.d.ts","sourceRoot":"","sources":["../../../src/browser/markdown-rendering/markdown-link-handler.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,iDAAiD,CAAC;AAEjF,OAAO,EAAQ,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAExD;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACnC,IAAI,EAAE,WAAW,EACjB,MAAM,EAAE,cAAc,EACtB,aAAa,EAAE,aAAa,GAC7B,UAAU,CAyBZ"}
1
+ {"version":3,"file":"markdown-link-handler.d.ts","sourceRoot":"","sources":["../../../src/browser/markdown-rendering/markdown-link-handler.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,iDAAiD,CAAC;AAEjF,OAAO,EAAQ,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAExD;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,oCAAoC,CAAC;AAEhF,sGAAsG;AACtG,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAE9D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CACnC,IAAI,EAAE,WAAW,EACjB,MAAM,EAAE,cAAc,EACtB,aAAa,EAAE,aAAa,GAC7B,UAAU,CAgCZ"}
@@ -15,11 +15,24 @@
15
15
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
16
16
  // *****************************************************************************
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.MARKDOWN_LINKS_WIRED_ATTRIBUTE = void 0;
19
+ exports.markMarkdownLinksWired = markMarkdownLinksWired;
18
20
  exports.wireMarkdownLinkHandler = wireMarkdownLinkHandler;
19
21
  const common_1 = require("../../common");
20
22
  const markdown_string_1 = require("../../common/markdown-rendering/markdown-string");
21
23
  const uri_1 = require("../../common/uri");
22
24
  const opener_service_1 = require("../opener-service");
25
+ /**
26
+ * Marks an element whose markdown links are already routed through an {@link OpenerService}.
27
+ *
28
+ * Renderers that install their own link handling declare it with {@link markMarkdownLinksWired},
29
+ * so that {@link wireMarkdownLinkHandler} does not add a second handler and open every link twice.
30
+ */
31
+ exports.MARKDOWN_LINKS_WIRED_ATTRIBUTE = 'data-theia-markdown-links-wired';
32
+ /** Declares that the element's markdown links are already routed through an {@link OpenerService}. */
33
+ function markMarkdownLinksWired(root) {
34
+ root.setAttribute(exports.MARKDOWN_LINKS_WIRED_ATTRIBUTE, 'true');
35
+ }
23
36
  /**
24
37
  * Wires up anchor clicks inside a rendered markdown element so that they are routed
25
38
  * through the {@link OpenerService} instead of relying on default browser navigation.
@@ -28,9 +41,15 @@ const opener_service_1 = require("../opener-service");
28
41
  * Also sets the `title` attribute on each anchor to its `href` (when no title is set)
29
42
  * so users can hover to see the link target.
30
43
  *
44
+ * Does nothing if the element's links are already wired, see {@link markMarkdownLinksWired}.
45
+ *
31
46
  * @returns a {@link Disposable} that removes the click listener.
32
47
  */
33
48
  function wireMarkdownLinkHandler(root, source, openerService) {
49
+ if (root.hasAttribute(exports.MARKDOWN_LINKS_WIRED_ATTRIBUTE)) {
50
+ return common_1.Disposable.NULL;
51
+ }
52
+ markMarkdownLinksWired(root);
34
53
  for (const anchor of root.querySelectorAll('a')) {
35
54
  const href = anchor.getAttribute('href');
36
55
  if (href && !anchor.hasAttribute('title')) {
@@ -55,6 +74,9 @@ function wireMarkdownLinkHandler(root, source, openerService) {
55
74
  }
56
75
  };
57
76
  root.addEventListener('click', handleClick);
58
- return common_1.Disposable.create(() => root.removeEventListener('click', handleClick));
77
+ return common_1.Disposable.create(() => {
78
+ root.removeEventListener('click', handleClick);
79
+ root.removeAttribute(exports.MARKDOWN_LINKS_WIRED_ATTRIBUTE);
80
+ });
59
81
  }
60
82
  //# sourceMappingURL=markdown-link-handler.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"markdown-link-handler.js","sourceRoot":"","sources":["../../../src/browser/markdown-rendering/markdown-link-handler.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,+CAA+C;AAC/C,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;;AAiBhF,0DA6BC;AA5CD,yCAA0C;AAC1C,qFAAiF;AACjF,0CAAmC;AACnC,sDAAwD;AAExD;;;;;;;;;GASG;AACH,SAAgB,uBAAuB,CACnC,IAAiB,EACjB,MAAsB,EACtB,aAA4B;IAE5B,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,GAAG,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC;YACxC,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACvC,CAAC;IACL,CAAC;IACD,MAAM,WAAW,GAAG,KAAK,EAAE,KAAiB,EAAE,EAAE;QAC5C,MAAM,IAAI,GAAI,KAAK,CAAC,MAA6B,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;QACtF,IAAI,CAAC,IAAI,EAAE,CAAC;YACR,OAAO;QACX,CAAC;QACD,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,IAAI,aAAG,CAAC,IAAI,CAAC,CAAC;QAC1B,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,gCAAc,CAAC,gBAAgB,CAAC,MAAM,CAAC,SAAS,EAAE,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC;YACtG,OAAO;QACX,CAAC;QACD,IAAI,CAAC;YACD,MAAM,IAAA,qBAAI,EAAC,aAAa,EAAE,GAAG,CAAC,CAAC;QACnC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,OAAO,CAAC,KAAK,CAAC,mBAAmB,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAC5D,CAAC;IACL,CAAC,CAAC;IACF,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IAC5C,OAAO,mBAAU,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC;AACnF,CAAC"}
1
+ {"version":3,"file":"markdown-link-handler.js","sourceRoot":"","sources":["../../../src/browser/markdown-rendering/markdown-link-handler.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,+CAA+C;AAC/C,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;;;AAgBhF,wDAEC;AAcD,0DAoCC;AAlED,yCAA0C;AAC1C,qFAAiF;AACjF,0CAAmC;AACnC,sDAAwD;AAExD;;;;;GAKG;AACU,QAAA,8BAA8B,GAAG,iCAAiC,CAAC;AAEhF,sGAAsG;AACtG,SAAgB,sBAAsB,CAAC,IAAiB;IACpD,IAAI,CAAC,YAAY,CAAC,sCAA8B,EAAE,MAAM,CAAC,CAAC;AAC9D,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAgB,uBAAuB,CACnC,IAAiB,EACjB,MAAsB,EACtB,aAA4B;IAE5B,IAAI,IAAI,CAAC,YAAY,CAAC,sCAA8B,CAAC,EAAE,CAAC;QACpD,OAAO,mBAAU,CAAC,IAAI,CAAC;IAC3B,CAAC;IACD,sBAAsB,CAAC,IAAI,CAAC,CAAC;IAC7B,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,GAAG,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC;YACxC,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACvC,CAAC;IACL,CAAC;IACD,MAAM,WAAW,GAAG,KAAK,EAAE,KAAiB,EAAE,EAAE;QAC5C,MAAM,IAAI,GAAI,KAAK,CAAC,MAA6B,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;QACtF,IAAI,CAAC,IAAI,EAAE,CAAC;YACR,OAAO;QACX,CAAC;QACD,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,IAAI,aAAG,CAAC,IAAI,CAAC,CAAC;QAC1B,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,gCAAc,CAAC,gBAAgB,CAAC,MAAM,CAAC,SAAS,EAAE,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC;YACtG,OAAO;QACX,CAAC;QACD,IAAI,CAAC;YACD,MAAM,IAAA,qBAAI,EAAC,aAAa,EAAE,GAAG,CAAC,CAAC;QACnC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,OAAO,CAAC,KAAK,CAAC,mBAAmB,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAC5D,CAAC;IACL,CAAC,CAAC;IACF,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IAC5C,OAAO,mBAAU,CAAC,MAAM,CAAC,GAAG,EAAE;QAC1B,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;QAC/C,IAAI,CAAC,eAAe,CAAC,sCAA8B,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -41,5 +41,16 @@ export declare class MarkdownRendererImpl implements MarkdownRenderer {
41
41
  protected init(): void;
42
42
  render(markdown: MarkdownString | undefined, options?: MarkdownRenderOptions): MarkdownRenderResult;
43
43
  protected markdownItPlugin(): void;
44
+ /**
45
+ * Parses the `width=W,height=H` parameter list of an image's sizing suffix.
46
+ *
47
+ * @returns the recognized dimensions, or `undefined` if the suffix is not a well-formed
48
+ * parameter list — in which case it is left as part of the `src`, since it may be a literal
49
+ * `|` in the URL.
50
+ */
51
+ protected parseImageDimensions(params: string): {
52
+ width?: string;
53
+ height?: string;
54
+ } | undefined;
44
55
  }
45
56
  //# sourceMappingURL=markdown-renderer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"markdown-renderer.d.ts","sourceRoot":"","sources":["../../../src/browser/markdown-rendering/markdown-renderer.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,UAAU,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,cAAc,EAAE,MAAM,iDAAiD,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAI9C,MAAM,WAAW,oBAAoB;IACjC,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,UAAU,GAAG,aAAa,KAAK,IAAI,CAAC;IACxE,QAAQ,CAAC,WAAW,EAAE,eAAe,CAAC;CACzC;AAED,MAAM,WAAW,0BAA0B;IACvC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,aAAa,CAAC,EAAE,oBAAoB,CAAC;IAC9C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CACzC;AAMD,MAAM,WAAW,oBAAqB,SAAQ,UAAU;IACpD,OAAO,EAAE,WAAW,CAAC;CACxB;AAED,MAAM,WAAW,qBAAsB,SAAQ,0BAA0B;IACrE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IACzF,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,IAAI,CAAC;CAC7C;AAID,uFAAuF;AACvF,eAAO,MAAM,gBAAgB,eAA6B,CAAC;AAC3D,MAAM,WAAW,gBAAgB;IAC7B,MAAM,CAAC,QAAQ,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,qBAAqB,EAAE,UAAU,CAAC,EAAE,WAAW,GAAG,oBAAoB,CAAC;CACrH;AAED;;;GAGG;AACH,eAAO,MAAM,oBAAoB,eAAiC,CAAC;AAEnE,2DAA2D;AAC3D,eAAO,MAAM,uBAAuB,eAAoC,CAAC;AACzE,MAAM,WAAW,uBAAuB;IACpC,IAAI,gBAAgB,CAAC;CACxB;AAED,qBACa,oBAAqB,YAAW,gBAAgB;IACpC,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IACjE,SAAS,CAAC,QAAQ,CAAC,UAAU,aAA0C;IACvE,SAAS,CAAC,aAAa,EAAE,UAAU,GAAG,SAAS,CAAC;IAGhD,SAAS,CAAC,IAAI,IAAI,IAAI;IAItB,MAAM,CAAC,QAAQ,EAAE,cAAc,GAAG,SAAS,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,oBAAoB;IAWnG,SAAS,CAAC,gBAAgB,IAAI,IAAI;CAWrC"}
1
+ {"version":3,"file":"markdown-renderer.d.ts","sourceRoot":"","sources":["../../../src/browser/markdown-rendering/markdown-renderer.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,UAAU,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,cAAc,EAAE,MAAM,iDAAiD,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAI9C,MAAM,WAAW,oBAAoB;IACjC,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,UAAU,GAAG,aAAa,KAAK,IAAI,CAAC;IACxE,QAAQ,CAAC,WAAW,EAAE,eAAe,CAAC;CACzC;AAED,MAAM,WAAW,0BAA0B;IACvC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,aAAa,CAAC,EAAE,oBAAoB,CAAC;IAC9C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CACzC;AAMD,MAAM,WAAW,oBAAqB,SAAQ,UAAU;IACpD,OAAO,EAAE,WAAW,CAAC;CACxB;AAED,MAAM,WAAW,qBAAsB,SAAQ,0BAA0B;IACrE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IACzF,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,IAAI,CAAC;CAC7C;AAID,uFAAuF;AACvF,eAAO,MAAM,gBAAgB,eAA6B,CAAC;AAC3D,MAAM,WAAW,gBAAgB;IAC7B,MAAM,CAAC,QAAQ,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,qBAAqB,EAAE,UAAU,CAAC,EAAE,WAAW,GAAG,oBAAoB,CAAC;CACrH;AAED;;;GAGG;AACH,eAAO,MAAM,oBAAoB,eAAiC,CAAC;AAEnE,2DAA2D;AAC3D,eAAO,MAAM,uBAAuB,eAAoC,CAAC;AACzE,MAAM,WAAW,uBAAuB;IACpC,IAAI,gBAAgB,CAAC;CACxB;AAED,qBACa,oBAAqB,YAAW,gBAAgB;IACpC,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IACjE,SAAS,CAAC,QAAQ,CAAC,UAAU,aAA0C;IACvE,SAAS,CAAC,aAAa,EAAE,UAAU,GAAG,SAAS,CAAC;IAGhD,SAAS,CAAC,IAAI,IAAI,IAAI;IAItB,MAAM,CAAC,QAAQ,EAAE,cAAc,GAAG,SAAS,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,oBAAoB;IAWnG,SAAS,CAAC,gBAAgB,IAAI,IAAI;IAoClC;;;;;;OAMG;IACH,SAAS,CAAC,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS;CAWlG"}
@@ -60,6 +60,47 @@ let MarkdownRendererImpl = class MarkdownRendererImpl {
60
60
  return `<i class="${(0, widgets_1.codicon)(chunk.name)} ${chunk.animation ? `fa-${chunk.animation}` : ''} icon-inline"></i>`;
61
61
  }).join('');
62
62
  };
63
+ // Support VS Code's `![alt](src|width=W,height=H)` image sizing syntax, which markdown-it
64
+ // would otherwise fold into the `src` attribute, yielding a broken image.
65
+ const renderImage = this.markdownIt.renderer.rules.image;
66
+ this.markdownIt.renderer.rules.image = (tokens, idx, options, env, self) => {
67
+ const token = tokens[idx];
68
+ const srcIndex = token.attrIndex('src');
69
+ if (srcIndex >= 0 && token.attrs) {
70
+ const src = token.attrs[srcIndex][1];
71
+ // markdown-it percent-encodes the link destination, so the separator may have
72
+ // become `%7C` by the time the token reaches the renderer.
73
+ const separator = /(?:\||%7c)(?![\s\S]*(?:\||%7c))/i.exec(src);
74
+ if (separator) {
75
+ const dimensions = this.parseImageDimensions(src.substring(separator.index + separator[0].length));
76
+ if (dimensions) {
77
+ token.attrs[srcIndex][1] = src.substring(0, separator.index);
78
+ for (const [name, value] of Object.entries(dimensions)) {
79
+ token.attrSet(name, value);
80
+ }
81
+ }
82
+ }
83
+ }
84
+ return renderImage ? renderImage(tokens, idx, options, env, self) : self.renderToken(tokens, idx, options);
85
+ };
86
+ }
87
+ /**
88
+ * Parses the `width=W,height=H` parameter list of an image's sizing suffix.
89
+ *
90
+ * @returns the recognized dimensions, or `undefined` if the suffix is not a well-formed
91
+ * parameter list — in which case it is left as part of the `src`, since it may be a literal
92
+ * `|` in the URL.
93
+ */
94
+ parseImageDimensions(params) {
95
+ const dimensions = {};
96
+ for (const param of params.split(',')) {
97
+ const match = /^\s*(width|height)\s*=\s*(\d+)\s*$/.exec(param);
98
+ if (!match) {
99
+ return undefined;
100
+ }
101
+ dimensions[match[1]] = match[2];
102
+ }
103
+ return Object.keys(dimensions).length > 0 ? dimensions : undefined;
63
104
  }
64
105
  };
65
106
  exports.MarkdownRendererImpl = MarkdownRendererImpl;
@@ -1 +1 @@
1
- {"version":3,"file":"markdown-renderer.js","sourceRoot":"","sources":["../../../src/browser/markdown-rendering/markdown-renderer.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,0CAA0C;AAC1C,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;;;;AAEhF,uCAAuC;AACvC,yCAA8D;AAC9D,0CAA0C;AAC1C,qDAAqD;AAGrD,kDAA8C;AAC9C,wCAAqC;AA4BrC,aAAa;AAEb,uFAAuF;AAC1E,QAAA,gBAAgB,GAAG,MAAM,CAAC,kBAAkB,CAAC,CAAC;AAK3D;;;GAGG;AACU,QAAA,oBAAoB,GAAG,MAAM,CAAC,sBAAsB,CAAC,CAAC;AAEnE,2DAA2D;AAC9C,QAAA,uBAAuB,GAAG,MAAM,CAAC,yBAAyB,CAAC,CAAC;AAMlE,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;IAA1B;QAEgB,eAAU,GAAG,UAAU,EAAE,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IA8B3E,CAAC;IA1Ba,IAAI;QACV,IAAI,CAAC,gBAAgB,EAAE,CAAC;IAC5B,CAAC;IAED,MAAM,CAAC,QAAoC,EAAE,OAA+B;QACxE,MAAM,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC3C,IAAI,QAAQ,EAAE,CAAC;YACX,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YACpD,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE;gBACtC,uBAAuB,EAAE,IAAI,CAAC,wDAAwD;aACzF,CAAC,CAAC;QACP,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;IACjD,CAAC;IAES,gBAAgB;QACtB,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE;YAClD,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;YACpC,OAAO,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;gBAC/C,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;oBAC5B,OAAO,KAAK,CAAC;gBACjB,CAAC;gBACD,OAAO,aAAa,IAAA,iBAAO,EAAC,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,oBAAoB,CAAC;YAClH,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChB,CAAC,CAAC;IACN,CAAC;CACJ,CAAA;AAhCY,oDAAoB;AACW;IAAvC,IAAA,kBAAM,EAAC,0BAAW,CAAC;sCAAiC,0BAAW;yDAAC;AAKvD;IADT,IAAA,yBAAa,GAAE;;;;gDAGf;+BARQ,oBAAoB;IADhC,IAAA,sBAAU,GAAE;GACA,oBAAoB,CAgChC"}
1
+ {"version":3,"file":"markdown-renderer.js","sourceRoot":"","sources":["../../../src/browser/markdown-rendering/markdown-renderer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=markdown-renderer.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown-renderer.spec.d.ts","sourceRoot":"","sources":["../../../src/browser/markdown-rendering/markdown-renderer.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ // *****************************************************************************
3
+ // Copyright (C) 2026 Safi Seid-Ahmad, K2view and others.
4
+ //
5
+ // This program and the accompanying materials are made available under the
6
+ // terms of the Eclipse Public License v. 2.0 which is available at
7
+ // http://www.eclipse.org/legal/epl-2.0.
8
+ //
9
+ // This Source Code may also be made available under the following Secondary
10
+ // Licenses when the conditions for such availability set forth in the Eclipse
11
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
12
+ // with the GNU Classpath Exception which is available at
13
+ // https://www.gnu.org/software/classpath/license.html.
14
+ //
15
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
16
+ // *****************************************************************************
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ const jsdom_1 = require("../test/jsdom");
19
+ const disableJSDOM = (0, jsdom_1.enableJSDOM)();
20
+ const inversify_1 = require("inversify");
21
+ const chai_1 = require("chai");
22
+ const common_1 = require("../../common");
23
+ const markdown_string_1 = require("../../common/markdown-rendering/markdown-string");
24
+ const label_parser_1 = require("../label-parser");
25
+ const markdown_renderer_1 = require("./markdown-renderer");
26
+ disableJSDOM();
27
+ describe('MarkdownRendererImpl', () => {
28
+ let restoreJSDOM;
29
+ let renderer;
30
+ before(() => {
31
+ restoreJSDOM = (0, jsdom_1.enableJSDOM)();
32
+ const container = new inversify_1.Container();
33
+ container.bind(label_parser_1.LabelParser).toSelf().inSingletonScope();
34
+ container.bind(common_1.CommandService).toConstantValue({
35
+ executeCommand: () => Promise.resolve(undefined)
36
+ });
37
+ container.bind(markdown_renderer_1.MarkdownRendererImpl).toSelf().inSingletonScope();
38
+ container.bind(markdown_renderer_1.MarkdownRenderer).toService(markdown_renderer_1.MarkdownRendererImpl);
39
+ renderer = container.get(markdown_renderer_1.MarkdownRenderer);
40
+ });
41
+ after(() => {
42
+ restoreJSDOM();
43
+ });
44
+ function renderImage(markdown) {
45
+ const { element } = renderer.render(new markdown_string_1.MarkdownStringImpl(markdown));
46
+ const image = element.querySelector('img');
47
+ (0, chai_1.expect)(image, `image rendered for '${markdown}'`).to.not.be.null;
48
+ return image;
49
+ }
50
+ it('applies the width and height of an image sizing suffix', () => {
51
+ const image = renderImage('![Jane](https://avatars.example.com/u/1|width=20,height=20)');
52
+ (0, chai_1.expect)(image.getAttribute('src')).to.equal('https://avatars.example.com/u/1');
53
+ (0, chai_1.expect)(image.getAttribute('width')).to.equal('20');
54
+ (0, chai_1.expect)(image.getAttribute('height')).to.equal('20');
55
+ });
56
+ it('applies a suffix that sets only one dimension', () => {
57
+ const image = renderImage('![Jane](https://avatars.example.com/u/1|width=20)');
58
+ (0, chai_1.expect)(image.getAttribute('src')).to.equal('https://avatars.example.com/u/1');
59
+ (0, chai_1.expect)(image.getAttribute('width')).to.equal('20');
60
+ (0, chai_1.expect)(image.hasAttribute('height')).to.be.false;
61
+ });
62
+ // markdown-it percent-encodes the link destination, so a pipe it keeps shows up as `%7C`.
63
+ it('keeps a literal pipe that is not a well-formed sizing suffix', () => {
64
+ const image = renderImage('![Jane](https://avatars.example.com/u/1|v=2)');
65
+ (0, chai_1.expect)(image.getAttribute('src')).to.equal('https://avatars.example.com/u/1%7Cv=2');
66
+ (0, chai_1.expect)(image.hasAttribute('width')).to.be.false;
67
+ });
68
+ it('ignores a non-numeric dimension', () => {
69
+ const image = renderImage('![Jane](https://avatars.example.com/u/1|width=20px)');
70
+ (0, chai_1.expect)(image.getAttribute('src')).to.equal('https://avatars.example.com/u/1%7Cwidth=20px');
71
+ (0, chai_1.expect)(image.hasAttribute('width')).to.be.false;
72
+ });
73
+ it('renders an image without a suffix unchanged', () => {
74
+ const image = renderImage('![Jane](https://avatars.example.com/u/1)');
75
+ (0, chai_1.expect)(image.getAttribute('src')).to.equal('https://avatars.example.com/u/1');
76
+ (0, chai_1.expect)(image.hasAttribute('width')).to.be.false;
77
+ });
78
+ });
79
+ //# sourceMappingURL=markdown-renderer.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown-renderer.spec.js","sourceRoot":"","sources":["../../../src/browser/markdown-rendering/markdown-renderer.spec.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,24 +1,24 @@
1
1
  {
2
2
  "name": "@theia/core",
3
- "version": "1.75.0-next.14+28da106c2",
3
+ "version": "1.75.0-next.18+30844b588",
4
4
  "description": "Theia is a cloud & desktop IDE framework implemented in TypeScript.",
5
5
  "main": "lib/common/index.js",
6
6
  "typings": "lib/common/index.d.ts",
7
7
  "dependencies": {
8
8
  "@babel/runtime": "^7.29.7",
9
- "@lumino/algorithm": "^2.0.4",
10
- "@lumino/commands": "^2.3.3",
11
- "@lumino/coreutils": "^2.2.2",
12
- "@lumino/domutils": "^2.0.4",
13
- "@lumino/dragdrop": "^2.1.8",
14
- "@lumino/messaging": "^2.0.4",
15
- "@lumino/properties": "^2.0.4",
16
- "@lumino/signaling": "^2.1.5",
17
- "@lumino/virtualdom": "^2.0.4",
9
+ "@lumino/algorithm": "^2.0.5",
10
+ "@lumino/commands": "^2.3.4",
11
+ "@lumino/coreutils": "^2.2.3",
12
+ "@lumino/domutils": "^2.0.5",
13
+ "@lumino/dragdrop": "^2.1.9",
14
+ "@lumino/messaging": "^2.0.5",
15
+ "@lumino/properties": "^2.0.5",
16
+ "@lumino/signaling": "^2.1.6",
17
+ "@lumino/virtualdom": "^2.0.5",
18
18
  "@lumino/widgets": "2.7.5",
19
- "@parcel/watcher": "^2.5.6",
20
- "@theia/application-package": "1.75.0-next.14+28da106c2",
21
- "@theia/request": "1.75.0-next.14+28da106c2",
19
+ "@parcel/watcher": "^2.6.0",
20
+ "@theia/application-package": "1.75.0-next.18+30844b588",
21
+ "@theia/request": "1.75.0-next.18+30844b588",
22
22
  "@types/body-parser": "^1.19.6",
23
23
  "@types/express": "^4.17.25",
24
24
  "@types/fs-extra": "^4.0.15",
@@ -33,9 +33,9 @@
33
33
  "@vscode/codicons": "0.0.45",
34
34
  "ajv": "^6.15.0",
35
35
  "async-mutex": "^0.4.1",
36
- "body-parser": "^1.20.5",
36
+ "body-parser": "^1.20.6",
37
37
  "cookie": "^1.1.1",
38
- "dompurify": "^3.4.11",
38
+ "dompurify": "^3.4.13",
39
39
  "drivelist": "^12.0.2",
40
40
  "express": "^4.22.2",
41
41
  "fast-json-stable-stringify": "^2.1.0",
@@ -52,8 +52,8 @@
52
52
  "lodash.debounce": "^4.0.8",
53
53
  "lodash.throttle": "^4.1.1",
54
54
  "markdown-it": "^14.3.0",
55
- "markdown-it-anchor": "^9.2.0",
56
- "markdown-it-emoji": "^3.0.0",
55
+ "markdown-it-anchor": "^9.2.1",
56
+ "markdown-it-emoji": "^3.1.0",
57
57
  "msgpackr": "^1.12.1",
58
58
  "p-debounce": "^2.1.0",
59
59
  "perfect-scrollbar": "1.5.5",
@@ -68,7 +68,7 @@
68
68
  "uuid": "^11.1.1",
69
69
  "vscode-languageserver-protocol": "3.17.5",
70
70
  "vscode-uri": "3.0.8",
71
- "ws": "^8.21.0",
71
+ "ws": "^8.21.3",
72
72
  "yargs": "^17.7.3"
73
73
  },
74
74
  "peerDependencies": {
@@ -230,5 +230,5 @@
230
230
  "nyc": {
231
231
  "extends": "../../configs/nyc.json"
232
232
  },
233
- "gitHead": "28da106c2541b3bfecf676b60d655774809e4b6b"
233
+ "gitHead": "30844b5882ba6902a8b3fd96991780b5c6ef12cc"
234
234
  }
@@ -19,6 +19,19 @@ import { MarkdownString } from '../../common/markdown-rendering/markdown-string'
19
19
  import URI from '../../common/uri';
20
20
  import { open, OpenerService } from '../opener-service';
21
21
 
22
+ /**
23
+ * Marks an element whose markdown links are already routed through an {@link OpenerService}.
24
+ *
25
+ * Renderers that install their own link handling declare it with {@link markMarkdownLinksWired},
26
+ * so that {@link wireMarkdownLinkHandler} does not add a second handler and open every link twice.
27
+ */
28
+ export const MARKDOWN_LINKS_WIRED_ATTRIBUTE = 'data-theia-markdown-links-wired';
29
+
30
+ /** Declares that the element's markdown links are already routed through an {@link OpenerService}. */
31
+ export function markMarkdownLinksWired(root: HTMLElement): void {
32
+ root.setAttribute(MARKDOWN_LINKS_WIRED_ATTRIBUTE, 'true');
33
+ }
34
+
22
35
  /**
23
36
  * Wires up anchor clicks inside a rendered markdown element so that they are routed
24
37
  * through the {@link OpenerService} instead of relying on default browser navigation.
@@ -27,6 +40,8 @@ import { open, OpenerService } from '../opener-service';
27
40
  * Also sets the `title` attribute on each anchor to its `href` (when no title is set)
28
41
  * so users can hover to see the link target.
29
42
  *
43
+ * Does nothing if the element's links are already wired, see {@link markMarkdownLinksWired}.
44
+ *
30
45
  * @returns a {@link Disposable} that removes the click listener.
31
46
  */
32
47
  export function wireMarkdownLinkHandler(
@@ -34,6 +49,10 @@ export function wireMarkdownLinkHandler(
34
49
  source: MarkdownString,
35
50
  openerService: OpenerService
36
51
  ): Disposable {
52
+ if (root.hasAttribute(MARKDOWN_LINKS_WIRED_ATTRIBUTE)) {
53
+ return Disposable.NULL;
54
+ }
55
+ markMarkdownLinksWired(root);
37
56
  for (const anchor of root.querySelectorAll('a')) {
38
57
  const href = anchor.getAttribute('href');
39
58
  if (href && !anchor.hasAttribute('title')) {
@@ -57,5 +76,8 @@ export function wireMarkdownLinkHandler(
57
76
  }
58
77
  };
59
78
  root.addEventListener('click', handleClick);
60
- return Disposable.create(() => root.removeEventListener('click', handleClick));
79
+ return Disposable.create(() => {
80
+ root.removeEventListener('click', handleClick);
81
+ root.removeAttribute(MARKDOWN_LINKS_WIRED_ATTRIBUTE);
82
+ });
61
83
  }
@@ -0,0 +1,88 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2026 Safi Seid-Ahmad, K2view and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { enableJSDOM } from '../test/jsdom';
18
+ const disableJSDOM = enableJSDOM();
19
+
20
+ import { Container } from 'inversify';
21
+ import { expect } from 'chai';
22
+ import { CommandService } from '../../common';
23
+ import { MarkdownStringImpl } from '../../common/markdown-rendering/markdown-string';
24
+ import { LabelParser } from '../label-parser';
25
+ import { MarkdownRenderer, MarkdownRendererImpl } from './markdown-renderer';
26
+
27
+ disableJSDOM();
28
+
29
+ describe('MarkdownRendererImpl', () => {
30
+ let restoreJSDOM: () => void;
31
+ let renderer: MarkdownRenderer;
32
+
33
+ before(() => {
34
+ restoreJSDOM = enableJSDOM();
35
+ const container = new Container();
36
+ container.bind(LabelParser).toSelf().inSingletonScope();
37
+ container.bind(CommandService).toConstantValue({
38
+ executeCommand: <T>(): Promise<T | undefined> => Promise.resolve(undefined)
39
+ });
40
+ container.bind(MarkdownRendererImpl).toSelf().inSingletonScope();
41
+ container.bind(MarkdownRenderer).toService(MarkdownRendererImpl);
42
+ renderer = container.get<MarkdownRenderer>(MarkdownRenderer);
43
+ });
44
+
45
+ after(() => {
46
+ restoreJSDOM();
47
+ });
48
+
49
+ function renderImage(markdown: string): HTMLImageElement {
50
+ const { element } = renderer.render(new MarkdownStringImpl(markdown));
51
+ const image = element.querySelector('img');
52
+ expect(image, `image rendered for '${markdown}'`).to.not.be.null;
53
+ return image!;
54
+ }
55
+
56
+ it('applies the width and height of an image sizing suffix', () => {
57
+ const image = renderImage('![Jane](https://avatars.example.com/u/1|width=20,height=20)');
58
+ expect(image.getAttribute('src')).to.equal('https://avatars.example.com/u/1');
59
+ expect(image.getAttribute('width')).to.equal('20');
60
+ expect(image.getAttribute('height')).to.equal('20');
61
+ });
62
+
63
+ it('applies a suffix that sets only one dimension', () => {
64
+ const image = renderImage('![Jane](https://avatars.example.com/u/1|width=20)');
65
+ expect(image.getAttribute('src')).to.equal('https://avatars.example.com/u/1');
66
+ expect(image.getAttribute('width')).to.equal('20');
67
+ expect(image.hasAttribute('height')).to.be.false;
68
+ });
69
+
70
+ // markdown-it percent-encodes the link destination, so a pipe it keeps shows up as `%7C`.
71
+ it('keeps a literal pipe that is not a well-formed sizing suffix', () => {
72
+ const image = renderImage('![Jane](https://avatars.example.com/u/1|v=2)');
73
+ expect(image.getAttribute('src')).to.equal('https://avatars.example.com/u/1%7Cv=2');
74
+ expect(image.hasAttribute('width')).to.be.false;
75
+ });
76
+
77
+ it('ignores a non-numeric dimension', () => {
78
+ const image = renderImage('![Jane](https://avatars.example.com/u/1|width=20px)');
79
+ expect(image.getAttribute('src')).to.equal('https://avatars.example.com/u/1%7Cwidth=20px');
80
+ expect(image.hasAttribute('width')).to.be.false;
81
+ });
82
+
83
+ it('renders an image without a suffix unchanged', () => {
84
+ const image = renderImage('![Jane](https://avatars.example.com/u/1)');
85
+ expect(image.getAttribute('src')).to.equal('https://avatars.example.com/u/1');
86
+ expect(image.hasAttribute('width')).to.be.false;
87
+ });
88
+ });
@@ -101,5 +101,48 @@ export class MarkdownRendererImpl implements MarkdownRenderer {
101
101
  return `<i class="${codicon(chunk.name)} ${chunk.animation ? `fa-${chunk.animation}` : ''} icon-inline"></i>`;
102
102
  }).join('');
103
103
  };
104
+
105
+ // Support VS Code's `![alt](src|width=W,height=H)` image sizing syntax, which markdown-it
106
+ // would otherwise fold into the `src` attribute, yielding a broken image.
107
+ const renderImage = this.markdownIt.renderer.rules.image;
108
+ this.markdownIt.renderer.rules.image = (tokens, idx, options, env, self) => {
109
+ const token = tokens[idx];
110
+ const srcIndex = token.attrIndex('src');
111
+ if (srcIndex >= 0 && token.attrs) {
112
+ const src = token.attrs[srcIndex][1];
113
+ // markdown-it percent-encodes the link destination, so the separator may have
114
+ // become `%7C` by the time the token reaches the renderer.
115
+ const separator = /(?:\||%7c)(?![\s\S]*(?:\||%7c))/i.exec(src);
116
+ if (separator) {
117
+ const dimensions = this.parseImageDimensions(src.substring(separator.index + separator[0].length));
118
+ if (dimensions) {
119
+ token.attrs[srcIndex][1] = src.substring(0, separator.index);
120
+ for (const [name, value] of Object.entries(dimensions)) {
121
+ token.attrSet(name, value);
122
+ }
123
+ }
124
+ }
125
+ }
126
+ return renderImage ? renderImage(tokens, idx, options, env, self) : self.renderToken(tokens, idx, options);
127
+ };
128
+ }
129
+
130
+ /**
131
+ * Parses the `width=W,height=H` parameter list of an image's sizing suffix.
132
+ *
133
+ * @returns the recognized dimensions, or `undefined` if the suffix is not a well-formed
134
+ * parameter list — in which case it is left as part of the `src`, since it may be a literal
135
+ * `|` in the URL.
136
+ */
137
+ protected parseImageDimensions(params: string): { width?: string, height?: string } | undefined {
138
+ const dimensions: { width?: string, height?: string } = {};
139
+ for (const param of params.split(',')) {
140
+ const match = /^\s*(width|height)\s*=\s*(\d+)\s*$/.exec(param);
141
+ if (!match) {
142
+ return undefined;
143
+ }
144
+ dimensions[match[1] as 'width' | 'height'] = match[2];
145
+ }
146
+ return Object.keys(dimensions).length > 0 ? dimensions : undefined;
104
147
  }
105
148
  }