@theia/preview 1.45.1 → 1.46.0-next.72

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.
Files changed (42) hide show
  1. package/README.md +45 -45
  2. package/lib/browser/index.d.ts +3 -3
  3. package/lib/browser/index.js +29 -29
  4. package/lib/browser/markdown/index.d.ts +1 -1
  5. package/lib/browser/markdown/index.js +28 -28
  6. package/lib/browser/markdown/markdown-preview-handler.d.ts +28 -28
  7. package/lib/browser/markdown/markdown-preview-handler.js +301 -301
  8. package/lib/browser/markdown/markdown-preview-handler.spec.d.ts +1 -1
  9. package/lib/browser/markdown/markdown-preview-handler.spec.js +193 -193
  10. package/lib/browser/preview-contribution.d.ts +50 -50
  11. package/lib/browser/preview-contribution.js +262 -262
  12. package/lib/browser/preview-frontend-module.d.ts +5 -5
  13. package/lib/browser/preview-frontend-module.js +52 -52
  14. package/lib/browser/preview-handler.d.ts +104 -104
  15. package/lib/browser/preview-handler.js +76 -76
  16. package/lib/browser/preview-link-normalizer.d.ts +7 -7
  17. package/lib/browser/preview-link-normalizer.js +54 -54
  18. package/lib/browser/preview-preferences.d.ts +11 -11
  19. package/lib/browser/preview-preferences.js +46 -46
  20. package/lib/browser/preview-uri.d.ts +8 -8
  21. package/lib/browser/preview-uri.js +47 -47
  22. package/lib/browser/preview-widget.d.ts +54 -54
  23. package/lib/browser/preview-widget.js +261 -261
  24. package/lib/package.spec.js +25 -25
  25. package/package.json +7 -7
  26. package/src/browser/index.ts +19 -19
  27. package/src/browser/markdown/index.ts +17 -17
  28. package/src/browser/markdown/markdown-preview-handler.spec.ts +228 -228
  29. package/src/browser/markdown/markdown-preview-handler.ts +309 -309
  30. package/src/browser/markdown/style/index.css +18 -18
  31. package/src/browser/markdown/style/markdown.css +203 -203
  32. package/src/browser/markdown/style/tomorrow.css +105 -105
  33. package/src/browser/preview-contribution.ts +276 -276
  34. package/src/browser/preview-frontend-module.ts +57 -57
  35. package/src/browser/preview-handler.ts +141 -141
  36. package/src/browser/preview-link-normalizer.ts +40 -40
  37. package/src/browser/preview-preferences.ts +58 -58
  38. package/src/browser/preview-uri.ts +43 -43
  39. package/src/browser/preview-widget.ts +277 -277
  40. package/src/browser/style/index.css +17 -17
  41. package/src/browser/style/preview-widget.css +29 -29
  42. package/src/package.spec.ts +29 -29
@@ -1,302 +1,302 @@
1
- "use strict";
2
- // *****************************************************************************
3
- // Copyright (C) 2018 TypeFox 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
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
18
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
19
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
20
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
21
- return c > 3 && r && Object.defineProperty(target, key, r), r;
22
- };
23
- var __metadata = (this && this.__metadata) || function (k, v) {
24
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
25
- };
26
- Object.defineProperty(exports, "__esModule", { value: true });
27
- exports.MarkdownPreviewHandler = void 0;
28
- const inversify_1 = require("@theia/core/shared/inversify");
29
- const uri_1 = require("@theia/core/lib/common/uri");
30
- const browser_1 = require("@theia/core/lib/browser");
31
- const common_1 = require("@theia/core/lib/common");
32
- const path_1 = require("@theia/core/lib/common/path");
33
- const hljs = require("highlight.js");
34
- const markdownit = require("@theia/core/shared/markdown-it");
35
- const anchor = require("markdown-it-anchor");
36
- const DOMPurify = require("@theia/core/shared/dompurify");
37
- const preview_uri_1 = require("../preview-uri");
38
- const preview_handler_1 = require("../preview-handler");
39
- const preview_link_normalizer_1 = require("../preview-link-normalizer");
40
- let MarkdownPreviewHandler = class MarkdownPreviewHandler {
41
- constructor() {
42
- this.iconClass = 'markdown-icon file-icon';
43
- this.contentClass = 'markdown-preview';
44
- }
45
- canHandle(uri) {
46
- return uri.scheme === 'file'
47
- && (uri.path.ext.toLowerCase() === '.md' ||
48
- uri.path.ext.toLowerCase() === '.markdown') ? 500 : 0;
49
- }
50
- renderContent(params) {
51
- const content = params.content;
52
- const renderedContent = this.getEngine().render(content, params);
53
- const contentElement = document.createElement('div');
54
- contentElement.classList.add(this.contentClass);
55
- contentElement.innerHTML = DOMPurify.sanitize(renderedContent);
56
- this.addLinkClickedListener(contentElement, params);
57
- return contentElement;
58
- }
59
- addLinkClickedListener(contentElement, params) {
60
- contentElement.addEventListener('click', (event) => {
61
- const candidate = (event.target || event.srcElement);
62
- const link = this.findLink(candidate, contentElement);
63
- if (link) {
64
- event.preventDefault();
65
- if (link.startsWith('#')) {
66
- this.revealFragment(contentElement, link);
67
- }
68
- else {
69
- const preview = !(common_1.isOSX ? event.metaKey : event.ctrlKey);
70
- const uri = this.resolveUri(link, params.originUri, preview);
71
- this.openLink(uri, params.originUri);
72
- }
73
- }
74
- });
75
- }
76
- findLink(element, container) {
77
- let candidate = element;
78
- while (candidate.tagName !== 'A') {
79
- if (candidate === container) {
80
- return;
81
- }
82
- candidate = candidate.parentElement;
83
- if (!candidate) {
84
- return;
85
- }
86
- }
87
- return candidate.getAttribute('href') || undefined;
88
- }
89
- async openLink(uri, originUri) {
90
- const opener = await this.openerService.getOpener(uri);
91
- opener.open(uri, { originUri });
92
- }
93
- resolveUri(link, uri, preview) {
94
- const linkURI = new uri_1.default(link);
95
- // URIs are always absolute, check link as a path whether it is relative
96
- if (!new path_1.Path(link).isAbsolute && linkURI.scheme === uri.scheme &&
97
- (!linkURI.authority || linkURI.authority === uri.authority)) {
98
- // get a relative path from URI by trimming leading `/`
99
- const relativePath = linkURI.path.toString().substring(1);
100
- const resolvedUri = uri.parent.resolve(relativePath).withFragment(linkURI.fragment).withQuery(linkURI.query);
101
- return preview ? preview_uri_1.PreviewUri.encode(resolvedUri) : resolvedUri;
102
- }
103
- return linkURI;
104
- }
105
- revealFragment(contentElement, fragment) {
106
- const elementToReveal = this.findElementForFragment(contentElement, fragment);
107
- if (!elementToReveal) {
108
- return;
109
- }
110
- elementToReveal.scrollIntoView();
111
- }
112
- findElementForFragment(content, link) {
113
- const fragment = link.startsWith('#') ? link.substring(1) : link;
114
- const filter = {
115
- acceptNode: (node) => {
116
- if (node instanceof HTMLHeadingElement) {
117
- if (node.tagName.toLowerCase().startsWith('h') && node.id === fragment) {
118
- return NodeFilter.FILTER_ACCEPT;
119
- }
120
- return NodeFilter.FILTER_SKIP;
121
- }
122
- return NodeFilter.FILTER_SKIP;
123
- }
124
- };
125
- const treeWalker = document.createTreeWalker(content, NodeFilter.SHOW_ELEMENT, filter);
126
- if (treeWalker.nextNode()) {
127
- const element = treeWalker.currentNode;
128
- return element;
129
- }
130
- return undefined;
131
- }
132
- findElementForSourceLine(content, sourceLine) {
133
- const markedElements = content.getElementsByClassName('line');
134
- let matchedElement;
135
- for (let i = 0; i < markedElements.length; i++) {
136
- const element = markedElements[i];
137
- const line = Number.parseInt(element.getAttribute('data-line') || '0');
138
- if (line > sourceLine) {
139
- break;
140
- }
141
- matchedElement = element;
142
- }
143
- return matchedElement;
144
- }
145
- getSourceLineForOffset(content, offset) {
146
- const lineElements = this.getLineElementsAtOffset(content, offset);
147
- if (lineElements.length < 1) {
148
- return undefined;
149
- }
150
- const firstLineNumber = this.getLineNumberFromAttribute(lineElements[0]);
151
- if (firstLineNumber === undefined) {
152
- return undefined;
153
- }
154
- if (lineElements.length === 1) {
155
- return firstLineNumber;
156
- }
157
- const secondLineNumber = this.getLineNumberFromAttribute(lineElements[1]);
158
- if (secondLineNumber === undefined) {
159
- return firstLineNumber;
160
- }
161
- const y1 = lineElements[0].offsetTop;
162
- const y2 = lineElements[1].offsetTop;
163
- const dY = (offset - y1) / (y2 - y1);
164
- const dL = (secondLineNumber - firstLineNumber) * dY;
165
- const line = firstLineNumber + Math.floor(dL);
166
- return line;
167
- }
168
- /**
169
- * returns two significant line elements for the given offset.
170
- */
171
- getLineElementsAtOffset(content, offset) {
172
- let skipNext = false;
173
- const filter = {
174
- acceptNode: (node) => {
175
- if (node instanceof HTMLElement) {
176
- if (node.classList.contains('line')) {
177
- if (skipNext) {
178
- return NodeFilter.FILTER_SKIP;
179
- }
180
- if (node.offsetTop > offset) {
181
- skipNext = true;
182
- }
183
- return NodeFilter.FILTER_ACCEPT;
184
- }
185
- return NodeFilter.FILTER_SKIP;
186
- }
187
- return NodeFilter.FILTER_REJECT;
188
- }
189
- };
190
- const treeWalker = document.createTreeWalker(content, NodeFilter.SHOW_ELEMENT, filter);
191
- const lineElements = [];
192
- while (treeWalker.nextNode()) {
193
- const element = treeWalker.currentNode;
194
- lineElements.push(element);
195
- }
196
- return lineElements.slice(-2);
197
- }
198
- getLineNumberFromAttribute(element) {
199
- const attribute = element.getAttribute('data-line');
200
- return attribute ? Number.parseInt(attribute) : undefined;
201
- }
202
- getEngine() {
203
- if (!this.engine) {
204
- const engine = this.engine = markdownit({
205
- html: true,
206
- linkify: true,
207
- highlight: (str, lang) => {
208
- if (lang && hljs.getLanguage(lang)) {
209
- try {
210
- return '<pre class="hljs"><code><div>' + hljs.highlight(lang, str, true).value + '</div></code></pre>';
211
- }
212
- catch { }
213
- }
214
- return '<pre class="hljs"><code><div>' + engine.utils.escapeHtml(str) + '</div></code></pre>';
215
- }
216
- });
217
- const renderers = ['heading_open', 'paragraph_open', 'list_item_open', 'blockquote_open', 'code_block', 'image', 'fence'];
218
- for (const renderer of renderers) {
219
- const originalRenderer = engine.renderer.rules[renderer];
220
- engine.renderer.rules[renderer] = (tokens, index, options, env, self) => {
221
- const token = tokens[index];
222
- if (token.map) {
223
- const line = token.map[0];
224
- token.attrJoin('class', 'line');
225
- token.attrSet('data-line', line.toString());
226
- }
227
- return (originalRenderer)
228
- // tslint:disable-next-line:no-void-expression
229
- ? originalRenderer(tokens, index, options, env, self)
230
- : self.renderToken(tokens, index, options);
231
- };
232
- }
233
- const originalImageRenderer = engine.renderer.rules.image;
234
- if (originalImageRenderer) {
235
- engine.renderer.rules.image = (tokens, index, options, env, self) => {
236
- if (preview_handler_1.RenderContentParams.is(env)) {
237
- const documentUri = env.originUri;
238
- const token = tokens[index];
239
- if (token.attrs) {
240
- const srcAttr = token.attrs.find(a => a[0] === 'src');
241
- if (srcAttr) {
242
- const href = srcAttr[1];
243
- srcAttr[1] = this.linkNormalizer.normalizeLink(documentUri, href);
244
- }
245
- }
246
- }
247
- return originalImageRenderer(tokens, index, options, env, self);
248
- };
249
- }
250
- const domParser = new DOMParser();
251
- const parseDOM = (html) => domParser.parseFromString(html, 'text/html').getElementsByTagName('body')[0];
252
- const modifyDOM = (body, tag, procedure) => {
253
- const elements = body.getElementsByTagName(tag);
254
- for (let i = 0; i < elements.length; i++) {
255
- const element = elements.item(i);
256
- if (element) {
257
- procedure(element);
258
- }
259
- }
260
- };
261
- const normalizeAllImgSrcInHTML = (html, normalizeLink) => {
262
- const body = parseDOM(html);
263
- modifyDOM(body, 'img', img => {
264
- const src = img.getAttributeNode('src');
265
- if (src) {
266
- src.nodeValue = normalizeLink(src.nodeValue || '');
267
- }
268
- });
269
- return body.innerHTML;
270
- };
271
- for (const name of ['html_block', 'html_inline']) {
272
- const originalRenderer = engine.renderer.rules[name];
273
- if (originalRenderer) {
274
- engine.renderer.rules[name] = (tokens, index, options, env, self) => {
275
- const currentToken = tokens[index];
276
- const content = currentToken.content;
277
- if (content.includes('<img') && preview_handler_1.RenderContentParams.is(env)) {
278
- const documentUri = env.originUri;
279
- currentToken.content = normalizeAllImgSrcInHTML(content, link => this.linkNormalizer.normalizeLink(documentUri, link));
280
- }
281
- return originalRenderer(tokens, index, options, env, self);
282
- };
283
- }
284
- }
285
- anchor(engine, {});
286
- }
287
- return this.engine;
288
- }
289
- };
290
- __decorate([
291
- (0, inversify_1.inject)(browser_1.OpenerService),
292
- __metadata("design:type", Object)
293
- ], MarkdownPreviewHandler.prototype, "openerService", void 0);
294
- __decorate([
295
- (0, inversify_1.inject)(preview_link_normalizer_1.PreviewLinkNormalizer),
296
- __metadata("design:type", preview_link_normalizer_1.PreviewLinkNormalizer)
297
- ], MarkdownPreviewHandler.prototype, "linkNormalizer", void 0);
298
- MarkdownPreviewHandler = __decorate([
299
- (0, inversify_1.injectable)()
300
- ], MarkdownPreviewHandler);
301
- exports.MarkdownPreviewHandler = MarkdownPreviewHandler;
1
+ "use strict";
2
+ // *****************************************************************************
3
+ // Copyright (C) 2018 TypeFox 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
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
18
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
19
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
20
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
21
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
22
+ };
23
+ var __metadata = (this && this.__metadata) || function (k, v) {
24
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
25
+ };
26
+ Object.defineProperty(exports, "__esModule", { value: true });
27
+ exports.MarkdownPreviewHandler = void 0;
28
+ const inversify_1 = require("@theia/core/shared/inversify");
29
+ const uri_1 = require("@theia/core/lib/common/uri");
30
+ const browser_1 = require("@theia/core/lib/browser");
31
+ const common_1 = require("@theia/core/lib/common");
32
+ const path_1 = require("@theia/core/lib/common/path");
33
+ const hljs = require("highlight.js");
34
+ const markdownit = require("@theia/core/shared/markdown-it");
35
+ const anchor = require("markdown-it-anchor");
36
+ const DOMPurify = require("@theia/core/shared/dompurify");
37
+ const preview_uri_1 = require("../preview-uri");
38
+ const preview_handler_1 = require("../preview-handler");
39
+ const preview_link_normalizer_1 = require("../preview-link-normalizer");
40
+ let MarkdownPreviewHandler = class MarkdownPreviewHandler {
41
+ constructor() {
42
+ this.iconClass = 'markdown-icon file-icon';
43
+ this.contentClass = 'markdown-preview';
44
+ }
45
+ canHandle(uri) {
46
+ return uri.scheme === 'file'
47
+ && (uri.path.ext.toLowerCase() === '.md' ||
48
+ uri.path.ext.toLowerCase() === '.markdown') ? 500 : 0;
49
+ }
50
+ renderContent(params) {
51
+ const content = params.content;
52
+ const renderedContent = this.getEngine().render(content, params);
53
+ const contentElement = document.createElement('div');
54
+ contentElement.classList.add(this.contentClass);
55
+ contentElement.innerHTML = DOMPurify.sanitize(renderedContent);
56
+ this.addLinkClickedListener(contentElement, params);
57
+ return contentElement;
58
+ }
59
+ addLinkClickedListener(contentElement, params) {
60
+ contentElement.addEventListener('click', (event) => {
61
+ const candidate = (event.target || event.srcElement);
62
+ const link = this.findLink(candidate, contentElement);
63
+ if (link) {
64
+ event.preventDefault();
65
+ if (link.startsWith('#')) {
66
+ this.revealFragment(contentElement, link);
67
+ }
68
+ else {
69
+ const preview = !(common_1.isOSX ? event.metaKey : event.ctrlKey);
70
+ const uri = this.resolveUri(link, params.originUri, preview);
71
+ this.openLink(uri, params.originUri);
72
+ }
73
+ }
74
+ });
75
+ }
76
+ findLink(element, container) {
77
+ let candidate = element;
78
+ while (candidate.tagName !== 'A') {
79
+ if (candidate === container) {
80
+ return;
81
+ }
82
+ candidate = candidate.parentElement;
83
+ if (!candidate) {
84
+ return;
85
+ }
86
+ }
87
+ return candidate.getAttribute('href') || undefined;
88
+ }
89
+ async openLink(uri, originUri) {
90
+ const opener = await this.openerService.getOpener(uri);
91
+ opener.open(uri, { originUri });
92
+ }
93
+ resolveUri(link, uri, preview) {
94
+ const linkURI = new uri_1.default(link);
95
+ // URIs are always absolute, check link as a path whether it is relative
96
+ if (!new path_1.Path(link).isAbsolute && linkURI.scheme === uri.scheme &&
97
+ (!linkURI.authority || linkURI.authority === uri.authority)) {
98
+ // get a relative path from URI by trimming leading `/`
99
+ const relativePath = linkURI.path.toString().substring(1);
100
+ const resolvedUri = uri.parent.resolve(relativePath).withFragment(linkURI.fragment).withQuery(linkURI.query);
101
+ return preview ? preview_uri_1.PreviewUri.encode(resolvedUri) : resolvedUri;
102
+ }
103
+ return linkURI;
104
+ }
105
+ revealFragment(contentElement, fragment) {
106
+ const elementToReveal = this.findElementForFragment(contentElement, fragment);
107
+ if (!elementToReveal) {
108
+ return;
109
+ }
110
+ elementToReveal.scrollIntoView();
111
+ }
112
+ findElementForFragment(content, link) {
113
+ const fragment = link.startsWith('#') ? link.substring(1) : link;
114
+ const filter = {
115
+ acceptNode: (node) => {
116
+ if (node instanceof HTMLHeadingElement) {
117
+ if (node.tagName.toLowerCase().startsWith('h') && node.id === fragment) {
118
+ return NodeFilter.FILTER_ACCEPT;
119
+ }
120
+ return NodeFilter.FILTER_SKIP;
121
+ }
122
+ return NodeFilter.FILTER_SKIP;
123
+ }
124
+ };
125
+ const treeWalker = document.createTreeWalker(content, NodeFilter.SHOW_ELEMENT, filter);
126
+ if (treeWalker.nextNode()) {
127
+ const element = treeWalker.currentNode;
128
+ return element;
129
+ }
130
+ return undefined;
131
+ }
132
+ findElementForSourceLine(content, sourceLine) {
133
+ const markedElements = content.getElementsByClassName('line');
134
+ let matchedElement;
135
+ for (let i = 0; i < markedElements.length; i++) {
136
+ const element = markedElements[i];
137
+ const line = Number.parseInt(element.getAttribute('data-line') || '0');
138
+ if (line > sourceLine) {
139
+ break;
140
+ }
141
+ matchedElement = element;
142
+ }
143
+ return matchedElement;
144
+ }
145
+ getSourceLineForOffset(content, offset) {
146
+ const lineElements = this.getLineElementsAtOffset(content, offset);
147
+ if (lineElements.length < 1) {
148
+ return undefined;
149
+ }
150
+ const firstLineNumber = this.getLineNumberFromAttribute(lineElements[0]);
151
+ if (firstLineNumber === undefined) {
152
+ return undefined;
153
+ }
154
+ if (lineElements.length === 1) {
155
+ return firstLineNumber;
156
+ }
157
+ const secondLineNumber = this.getLineNumberFromAttribute(lineElements[1]);
158
+ if (secondLineNumber === undefined) {
159
+ return firstLineNumber;
160
+ }
161
+ const y1 = lineElements[0].offsetTop;
162
+ const y2 = lineElements[1].offsetTop;
163
+ const dY = (offset - y1) / (y2 - y1);
164
+ const dL = (secondLineNumber - firstLineNumber) * dY;
165
+ const line = firstLineNumber + Math.floor(dL);
166
+ return line;
167
+ }
168
+ /**
169
+ * returns two significant line elements for the given offset.
170
+ */
171
+ getLineElementsAtOffset(content, offset) {
172
+ let skipNext = false;
173
+ const filter = {
174
+ acceptNode: (node) => {
175
+ if (node instanceof HTMLElement) {
176
+ if (node.classList.contains('line')) {
177
+ if (skipNext) {
178
+ return NodeFilter.FILTER_SKIP;
179
+ }
180
+ if (node.offsetTop > offset) {
181
+ skipNext = true;
182
+ }
183
+ return NodeFilter.FILTER_ACCEPT;
184
+ }
185
+ return NodeFilter.FILTER_SKIP;
186
+ }
187
+ return NodeFilter.FILTER_REJECT;
188
+ }
189
+ };
190
+ const treeWalker = document.createTreeWalker(content, NodeFilter.SHOW_ELEMENT, filter);
191
+ const lineElements = [];
192
+ while (treeWalker.nextNode()) {
193
+ const element = treeWalker.currentNode;
194
+ lineElements.push(element);
195
+ }
196
+ return lineElements.slice(-2);
197
+ }
198
+ getLineNumberFromAttribute(element) {
199
+ const attribute = element.getAttribute('data-line');
200
+ return attribute ? Number.parseInt(attribute) : undefined;
201
+ }
202
+ getEngine() {
203
+ if (!this.engine) {
204
+ const engine = this.engine = markdownit({
205
+ html: true,
206
+ linkify: true,
207
+ highlight: (str, lang) => {
208
+ if (lang && hljs.getLanguage(lang)) {
209
+ try {
210
+ return '<pre class="hljs"><code><div>' + hljs.highlight(lang, str, true).value + '</div></code></pre>';
211
+ }
212
+ catch { }
213
+ }
214
+ return '<pre class="hljs"><code><div>' + engine.utils.escapeHtml(str) + '</div></code></pre>';
215
+ }
216
+ });
217
+ const renderers = ['heading_open', 'paragraph_open', 'list_item_open', 'blockquote_open', 'code_block', 'image', 'fence'];
218
+ for (const renderer of renderers) {
219
+ const originalRenderer = engine.renderer.rules[renderer];
220
+ engine.renderer.rules[renderer] = (tokens, index, options, env, self) => {
221
+ const token = tokens[index];
222
+ if (token.map) {
223
+ const line = token.map[0];
224
+ token.attrJoin('class', 'line');
225
+ token.attrSet('data-line', line.toString());
226
+ }
227
+ return (originalRenderer)
228
+ // tslint:disable-next-line:no-void-expression
229
+ ? originalRenderer(tokens, index, options, env, self)
230
+ : self.renderToken(tokens, index, options);
231
+ };
232
+ }
233
+ const originalImageRenderer = engine.renderer.rules.image;
234
+ if (originalImageRenderer) {
235
+ engine.renderer.rules.image = (tokens, index, options, env, self) => {
236
+ if (preview_handler_1.RenderContentParams.is(env)) {
237
+ const documentUri = env.originUri;
238
+ const token = tokens[index];
239
+ if (token.attrs) {
240
+ const srcAttr = token.attrs.find(a => a[0] === 'src');
241
+ if (srcAttr) {
242
+ const href = srcAttr[1];
243
+ srcAttr[1] = this.linkNormalizer.normalizeLink(documentUri, href);
244
+ }
245
+ }
246
+ }
247
+ return originalImageRenderer(tokens, index, options, env, self);
248
+ };
249
+ }
250
+ const domParser = new DOMParser();
251
+ const parseDOM = (html) => domParser.parseFromString(html, 'text/html').getElementsByTagName('body')[0];
252
+ const modifyDOM = (body, tag, procedure) => {
253
+ const elements = body.getElementsByTagName(tag);
254
+ for (let i = 0; i < elements.length; i++) {
255
+ const element = elements.item(i);
256
+ if (element) {
257
+ procedure(element);
258
+ }
259
+ }
260
+ };
261
+ const normalizeAllImgSrcInHTML = (html, normalizeLink) => {
262
+ const body = parseDOM(html);
263
+ modifyDOM(body, 'img', img => {
264
+ const src = img.getAttributeNode('src');
265
+ if (src) {
266
+ src.nodeValue = normalizeLink(src.nodeValue || '');
267
+ }
268
+ });
269
+ return body.innerHTML;
270
+ };
271
+ for (const name of ['html_block', 'html_inline']) {
272
+ const originalRenderer = engine.renderer.rules[name];
273
+ if (originalRenderer) {
274
+ engine.renderer.rules[name] = (tokens, index, options, env, self) => {
275
+ const currentToken = tokens[index];
276
+ const content = currentToken.content;
277
+ if (content.includes('<img') && preview_handler_1.RenderContentParams.is(env)) {
278
+ const documentUri = env.originUri;
279
+ currentToken.content = normalizeAllImgSrcInHTML(content, link => this.linkNormalizer.normalizeLink(documentUri, link));
280
+ }
281
+ return originalRenderer(tokens, index, options, env, self);
282
+ };
283
+ }
284
+ }
285
+ anchor(engine, {});
286
+ }
287
+ return this.engine;
288
+ }
289
+ };
290
+ __decorate([
291
+ (0, inversify_1.inject)(browser_1.OpenerService),
292
+ __metadata("design:type", Object)
293
+ ], MarkdownPreviewHandler.prototype, "openerService", void 0);
294
+ __decorate([
295
+ (0, inversify_1.inject)(preview_link_normalizer_1.PreviewLinkNormalizer),
296
+ __metadata("design:type", preview_link_normalizer_1.PreviewLinkNormalizer)
297
+ ], MarkdownPreviewHandler.prototype, "linkNormalizer", void 0);
298
+ MarkdownPreviewHandler = __decorate([
299
+ (0, inversify_1.injectable)()
300
+ ], MarkdownPreviewHandler);
301
+ exports.MarkdownPreviewHandler = MarkdownPreviewHandler;
302
302
  //# sourceMappingURL=markdown-preview-handler.js.map
@@ -1,2 +1,2 @@
1
- export {};
1
+ export {};
2
2
  //# sourceMappingURL=markdown-preview-handler.spec.d.ts.map