@theia/core 1.75.0-next.12 → 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 +14 -14
- package/lib/browser/catalog.json +41 -7
- package/lib/browser/markdown-rendering/markdown-link-handler.d.ts +11 -0
- package/lib/browser/markdown-rendering/markdown-link-handler.d.ts.map +1 -1
- package/lib/browser/markdown-rendering/markdown-link-handler.js +23 -1
- package/lib/browser/markdown-rendering/markdown-link-handler.js.map +1 -1
- package/lib/browser/markdown-rendering/markdown-renderer.d.ts +11 -0
- package/lib/browser/markdown-rendering/markdown-renderer.d.ts.map +1 -1
- package/lib/browser/markdown-rendering/markdown-renderer.js +41 -0
- package/lib/browser/markdown-rendering/markdown-renderer.js.map +1 -1
- package/lib/browser/markdown-rendering/markdown-renderer.spec.d.ts +2 -0
- package/lib/browser/markdown-rendering/markdown-renderer.spec.d.ts.map +1 -0
- package/lib/browser/markdown-rendering/markdown-renderer.spec.js +79 -0
- package/lib/browser/markdown-rendering/markdown-renderer.spec.js.map +1 -0
- package/package.json +19 -19
- package/src/browser/markdown-rendering/markdown-link-handler.ts +23 -1
- package/src/browser/markdown-rendering/markdown-renderer.spec.ts +88 -0
- package/src/browser/markdown-rendering/markdown-renderer.ts +43 -0
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.
|
|
79
|
-
- `@lumino/commands` (from [`@lumino/commands@^2.3.
|
|
80
|
-
- `@lumino/coreutils` (from [`@lumino/coreutils@^2.2.
|
|
81
|
-
- `@lumino/domutils` (from [`@lumino/domutils@^2.0.
|
|
82
|
-
- `@lumino/dragdrop` (from [`@lumino/dragdrop@^2.1.
|
|
83
|
-
- `@lumino/messaging` (from [`@lumino/messaging@^2.0.
|
|
84
|
-
- `@lumino/properties` (from [`@lumino/properties@^2.0.
|
|
85
|
-
- `@lumino/signaling` (from [`@lumino/signaling@^2.1.
|
|
86
|
-
- `@lumino/virtualdom` (from [`@lumino/virtualdom@^2.0.
|
|
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.
|
|
103
|
-
- `dompurify` (from [`dompurify@^3.4.
|
|
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.
|
|
109
|
-
- `markdown-it-emoji` (from [`markdown-it-emoji@^3.
|
|
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.
|
|
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
|
package/lib/browser/catalog.json
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
"$schema": "https://www.schemastore.org/schema-catalog.json",
|
|
3
3
|
"version": 1,
|
|
4
4
|
"schemas": [
|
|
5
|
+
{
|
|
6
|
+
"name": "glslint config",
|
|
7
|
+
"description": "glslint project config and shader-dialect preset (glslint.toml): ecosystem detection, #pragma expansion, shared-library and injected-define declarations",
|
|
8
|
+
"fileMatch": ["glslint.toml"],
|
|
9
|
+
"url": "https://raw.githubusercontent.com/johncarmack1984/glslint/main/schema/glslint.schema.json"
|
|
10
|
+
},
|
|
5
11
|
{
|
|
6
12
|
"name": "Mermaid config",
|
|
7
13
|
"description": "Configuration for Mermaid diagrams and charts",
|
|
@@ -2530,6 +2536,15 @@
|
|
|
2530
2536
|
"fileMatch": ["**/scenarios/*/*.yaml"],
|
|
2531
2537
|
"url": "https://raw.githubusercontent.com/crowdsecurity/crowdsec-yaml-schemas/main/scenario_schema.yaml"
|
|
2532
2538
|
},
|
|
2539
|
+
{
|
|
2540
|
+
"name": "crucible",
|
|
2541
|
+
"description": "Settings for the crucible coding agent",
|
|
2542
|
+
"fileMatch": [
|
|
2543
|
+
"**/.crucible/config.json",
|
|
2544
|
+
"**/.crucible/config.local.json"
|
|
2545
|
+
],
|
|
2546
|
+
"url": "https://www.schemastore.org/crucible-code-schema.json"
|
|
2547
|
+
},
|
|
2533
2548
|
{
|
|
2534
2549
|
"name": "cypress.json",
|
|
2535
2550
|
"description": "Cypress.io test runner configuration file",
|
|
@@ -4598,6 +4613,14 @@
|
|
|
4598
4613
|
"fileMatch": ["*.patch", "*.patch.json", "*.patch.yml", "*.patch.yaml"],
|
|
4599
4614
|
"url": "https://www.schemastore.org/json-patch.json"
|
|
4600
4615
|
},
|
|
4616
|
+
{
|
|
4617
|
+
"name": "Jsontron",
|
|
4618
|
+
"description": "Jsontron vocabulary: rules and assert keywords using jq expressions for cross-field validation",
|
|
4619
|
+
"url": "https://www.schemastore.org/jsontron-0.1.json",
|
|
4620
|
+
"versions": {
|
|
4621
|
+
"0.1": "https://www.schemastore.org/jsontron-0.1.json"
|
|
4622
|
+
}
|
|
4623
|
+
},
|
|
4601
4624
|
{
|
|
4602
4625
|
"name": "jsconfig.json",
|
|
4603
4626
|
"description": "JavaScript project configuration file",
|
|
@@ -6590,10 +6613,10 @@
|
|
|
6590
6613
|
"url": "https://www.schemastore.org/replit.json"
|
|
6591
6614
|
},
|
|
6592
6615
|
{
|
|
6593
|
-
"name": "
|
|
6594
|
-
"description": "Declarative GitHub repository settings applied by the
|
|
6616
|
+
"name": "github-settings-as-code",
|
|
6617
|
+
"description": "Declarative GitHub repository settings applied by the github-settings-as-code action; accepts Probot Settings app files as-is. Documentation: https://github.com/Vivswan/github-settings-as-code",
|
|
6595
6618
|
"fileMatch": ["**/.github/settings.yml"],
|
|
6596
|
-
"url": "https://raw.githubusercontent.com/Vivswan/
|
|
6619
|
+
"url": "https://raw.githubusercontent.com/Vivswan/github-settings-as-code/main/lib/settings.schema.json"
|
|
6597
6620
|
},
|
|
6598
6621
|
{
|
|
6599
6622
|
"name": "reposets Configuration",
|
|
@@ -7890,7 +7913,7 @@
|
|
|
7890
7913
|
"venvironment.json",
|
|
7891
7914
|
"*.venvironment.json"
|
|
7892
7915
|
],
|
|
7893
|
-
"url": "https://www.schemastore.org/venvironment-schema-v5.
|
|
7916
|
+
"url": "https://www.schemastore.org/venvironment-schema-v5.1.0.json",
|
|
7894
7917
|
"versions": {
|
|
7895
7918
|
"1.0.0": "https://www.schemastore.org/venvironment-schema-v1.0.0.json",
|
|
7896
7919
|
"1.1.0": "https://www.schemastore.org/venvironment-schema-v1.1.0.json",
|
|
@@ -7904,7 +7927,8 @@
|
|
|
7904
7927
|
"4.0.0": "https://www.schemastore.org/venvironment-schema-v4.0.0.json",
|
|
7905
7928
|
"4.1.0": "https://www.schemastore.org/venvironment-schema-v4.1.0.json",
|
|
7906
7929
|
"4.2.0": "https://www.schemastore.org/venvironment-schema-v4.2.0.json",
|
|
7907
|
-
"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"
|
|
7908
7932
|
}
|
|
7909
7933
|
},
|
|
7910
7934
|
{
|
|
@@ -7918,10 +7942,11 @@
|
|
|
7918
7942
|
"venvplus.json",
|
|
7919
7943
|
"*.venvplus.json"
|
|
7920
7944
|
],
|
|
7921
|
-
"url": "https://www.schemastore.org/venvplus-schema-v1.
|
|
7945
|
+
"url": "https://www.schemastore.org/venvplus-schema-v1.2.0.json",
|
|
7922
7946
|
"versions": {
|
|
7923
7947
|
"1.0.0": "https://www.schemastore.org/venvplus-schema-v1.0.0.json",
|
|
7924
|
-
"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"
|
|
7925
7950
|
}
|
|
7926
7951
|
},
|
|
7927
7952
|
{
|
|
@@ -10970,6 +10995,15 @@
|
|
|
10970
10995
|
"description": "Configuration for preview servers in Claude Code Desktop",
|
|
10971
10996
|
"fileMatch": ["**/.claude/launch.json"],
|
|
10972
10997
|
"url": "https://www.schemastore.org/claude-code-launch.json"
|
|
10998
|
+
},
|
|
10999
|
+
{
|
|
11000
|
+
"name": "ArchSmith diagram IR",
|
|
11001
|
+
"description": "Intermediate representation consumed by ArchSmith to validate and render architecture diagrams",
|
|
11002
|
+
"fileMatch": ["*.archsmith.json"],
|
|
11003
|
+
"url": "https://ayeshlk.github.io/archsmith/schema/latest/diagram-schema.json",
|
|
11004
|
+
"versions": {
|
|
11005
|
+
"0.3.0": "https://ayeshlk.github.io/archsmith/schema/0.3.0/diagram-schema.json"
|
|
11006
|
+
}
|
|
10973
11007
|
}
|
|
10974
11008
|
]
|
|
10975
11009
|
}
|
|
@@ -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
|
|
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(() =>
|
|
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
|
|
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;
|
|
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 `` 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;
|
|
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 @@
|
|
|
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('');
|
|
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('');
|
|
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('');
|
|
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('');
|
|
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('');
|
|
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.
|
|
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.
|
|
10
|
-
"@lumino/commands": "^2.3.
|
|
11
|
-
"@lumino/coreutils": "^2.2.
|
|
12
|
-
"@lumino/domutils": "^2.0.
|
|
13
|
-
"@lumino/dragdrop": "^2.1.
|
|
14
|
-
"@lumino/messaging": "^2.0.
|
|
15
|
-
"@lumino/properties": "^2.0.
|
|
16
|
-
"@lumino/signaling": "^2.1.
|
|
17
|
-
"@lumino/virtualdom": "^2.0.
|
|
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.
|
|
20
|
-
"@theia/application-package": "1.75.0-next.
|
|
21
|
-
"@theia/request": "1.75.0-next.
|
|
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.
|
|
36
|
+
"body-parser": "^1.20.6",
|
|
37
37
|
"cookie": "^1.1.1",
|
|
38
|
-
"dompurify": "^3.4.
|
|
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.
|
|
56
|
-
"markdown-it-emoji": "^3.
|
|
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.
|
|
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": "
|
|
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(() =>
|
|
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('');
|
|
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('');
|
|
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('');
|
|
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('');
|
|
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('');
|
|
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 `` 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
|
}
|