mirror of https://github.com/microsoft/vscode.git
Use morphdom to reduce number of full page updates to md preview
This should help improve scroll sync and also reduce the number of times we go out to the network if images are in the preview
This commit is contained in:
parent
b2494d777f
commit
8f672cac62
|
@ -356,6 +356,7 @@
|
|||
"highlight.js": "^10.4.1",
|
||||
"markdown-it": "^12.2.0",
|
||||
"markdown-it-front-matter": "^0.2.1",
|
||||
"morphdom": "^2.6.1",
|
||||
"vscode-extension-telemetry": "0.4.2",
|
||||
"vscode-nls": "^5.0.0"
|
||||
},
|
||||
|
|
|
@ -7,8 +7,8 @@ import { getElementsForSourceLine } from './scroll-sync';
|
|||
export class ActiveLineMarker {
|
||||
private _current: any;
|
||||
|
||||
onDidChangeTextEditorSelection(line: number) {
|
||||
const { previous } = getElementsForSourceLine(line);
|
||||
onDidChangeTextEditorSelection(line: number, documentVersion: number) {
|
||||
const { previous } = getElementsForSourceLine(line, documentVersion);
|
||||
this._update(previous && previous.element);
|
||||
}
|
||||
|
||||
|
@ -31,4 +31,4 @@ export class ActiveLineMarker {
|
|||
}
|
||||
element.className += ' code-active-line';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { MessagePoster } from './messaging';
|
||||
import { getSettings } from './settings';
|
||||
import { SettingsManager } from './settings';
|
||||
import { getStrings } from './strings';
|
||||
|
||||
/**
|
||||
|
@ -16,7 +16,9 @@ export class CspAlerter {
|
|||
|
||||
private messaging?: MessagePoster;
|
||||
|
||||
constructor() {
|
||||
constructor(
|
||||
private readonly settingsManager: SettingsManager,
|
||||
) {
|
||||
document.addEventListener('securitypolicyviolation', () => {
|
||||
this.onCspWarning();
|
||||
});
|
||||
|
@ -42,7 +44,7 @@ export class CspAlerter {
|
|||
|
||||
private showCspWarning() {
|
||||
const strings = getStrings();
|
||||
const settings = getSettings();
|
||||
const settings = this.settingsManager.settings;
|
||||
|
||||
if (this.didShow || settings.disableSecurityWarnings || !this.messaging) {
|
||||
return;
|
||||
|
|
|
@ -7,12 +7,14 @@ import { ActiveLineMarker } from './activeLineMarker';
|
|||
import { onceDocumentLoaded } from './events';
|
||||
import { createPosterForVsCode } from './messaging';
|
||||
import { getEditorLineNumberForPageOffset, scrollToRevealSourceLine, getLineElementForFragment } from './scroll-sync';
|
||||
import { getSettings, getData } from './settings';
|
||||
import { SettingsManager, getData } from './settings';
|
||||
import throttle = require('lodash.throttle');
|
||||
import morphdom from 'morphdom';
|
||||
|
||||
let documentVersion = 0;
|
||||
let scrollDisabledCount = 0;
|
||||
const marker = new ActiveLineMarker();
|
||||
const settings = getSettings();
|
||||
const settings = new SettingsManager();
|
||||
|
||||
const vscode = acquireVsCodeApi();
|
||||
|
||||
|
@ -26,15 +28,11 @@ const state = {
|
|||
// Make sure to sync VS Code state here
|
||||
vscode.setState(state);
|
||||
|
||||
const messaging = createPosterForVsCode(vscode);
|
||||
const messaging = createPosterForVsCode(vscode, settings);
|
||||
|
||||
window.cspAlerter.setPoster(messaging);
|
||||
window.styleLoadingMonitor.setPoster(messaging);
|
||||
|
||||
window.onload = () => {
|
||||
updateImageSizes();
|
||||
};
|
||||
|
||||
|
||||
function doAfterImagesLoaded(cb: () => void) {
|
||||
const imgElements = document.getElementsByTagName('img');
|
||||
|
@ -58,7 +56,7 @@ function doAfterImagesLoaded(cb: () => void) {
|
|||
onceDocumentLoaded(() => {
|
||||
const scrollProgress = state.scrollProgress;
|
||||
|
||||
if (typeof scrollProgress === 'number' && !settings.fragment) {
|
||||
if (typeof scrollProgress === 'number' && !settings.settings.fragment) {
|
||||
doAfterImagesLoaded(() => {
|
||||
scrollDisabledCount += 1;
|
||||
window.scrollTo(0, scrollProgress * document.body.clientHeight);
|
||||
|
@ -66,22 +64,22 @@ onceDocumentLoaded(() => {
|
|||
return;
|
||||
}
|
||||
|
||||
if (settings.scrollPreviewWithEditor) {
|
||||
if (settings.settings.scrollPreviewWithEditor) {
|
||||
doAfterImagesLoaded(() => {
|
||||
// Try to scroll to fragment if available
|
||||
if (settings.fragment) {
|
||||
if (settings.settings.fragment) {
|
||||
state.fragment = undefined;
|
||||
vscode.setState(state);
|
||||
|
||||
const element = getLineElementForFragment(settings.fragment);
|
||||
const element = getLineElementForFragment(settings.settings.fragment, documentVersion);
|
||||
if (element) {
|
||||
scrollDisabledCount += 1;
|
||||
scrollToRevealSourceLine(element.line);
|
||||
scrollToRevealSourceLine(element.line, documentVersion, settings);
|
||||
}
|
||||
} else {
|
||||
if (!isNaN(settings.line!)) {
|
||||
if (!isNaN(settings.settings.line!)) {
|
||||
scrollDisabledCount += 1;
|
||||
scrollToRevealSourceLine(settings.line!);
|
||||
scrollToRevealSourceLine(settings.settings.line!, documentVersion, settings);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -91,7 +89,7 @@ onceDocumentLoaded(() => {
|
|||
const onUpdateView = (() => {
|
||||
const doScroll = throttle((line: number) => {
|
||||
scrollDisabledCount += 1;
|
||||
doAfterImagesLoaded(() => scrollToRevealSourceLine(line));
|
||||
doAfterImagesLoaded(() => scrollToRevealSourceLine(line, documentVersion, settings));
|
||||
}, 50);
|
||||
|
||||
return (line: number) => {
|
||||
|
@ -103,53 +101,36 @@ const onUpdateView = (() => {
|
|||
};
|
||||
})();
|
||||
|
||||
let updateImageSizes = throttle(() => {
|
||||
const imageInfo: { id: string, height: number, width: number; }[] = [];
|
||||
let images = document.getElementsByTagName('img');
|
||||
if (images) {
|
||||
let i;
|
||||
for (i = 0; i < images.length; i++) {
|
||||
const img = images[i];
|
||||
|
||||
if (img.classList.contains('loading')) {
|
||||
img.classList.remove('loading');
|
||||
}
|
||||
|
||||
imageInfo.push({
|
||||
id: img.id,
|
||||
height: img.height,
|
||||
width: img.width
|
||||
});
|
||||
}
|
||||
|
||||
messaging.postMessage('cacheImageSizes', imageInfo);
|
||||
}
|
||||
}, 50);
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
scrollDisabledCount += 1;
|
||||
updateScrollProgress();
|
||||
updateImageSizes();
|
||||
}, true);
|
||||
|
||||
window.addEventListener('message', event => {
|
||||
if (event.data.source !== settings.source) {
|
||||
if (settings.settings && event.data.source !== settings.settings.source) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.data.type) {
|
||||
case 'onDidChangeTextEditorSelection':
|
||||
marker.onDidChangeTextEditorSelection(event.data.line);
|
||||
marker.onDidChangeTextEditorSelection(event.data.line, documentVersion);
|
||||
break;
|
||||
|
||||
case 'updateView':
|
||||
onUpdateView(event.data.line);
|
||||
break;
|
||||
|
||||
case 'updateContent':
|
||||
const root = document.querySelector('.markdown-body')!;
|
||||
morphdom(root, event.data.content);
|
||||
++documentVersion;
|
||||
break;
|
||||
}
|
||||
}, false);
|
||||
|
||||
document.addEventListener('dblclick', event => {
|
||||
if (!settings.doubleClickToSwitchToEditor) {
|
||||
if (!settings.settings.doubleClickToSwitchToEditor) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -161,7 +142,7 @@ document.addEventListener('dblclick', event => {
|
|||
}
|
||||
|
||||
const offset = event.pageY;
|
||||
const line = getEditorLineNumberForPageOffset(offset);
|
||||
const line = getEditorLineNumberForPageOffset(offset, documentVersion, settings);
|
||||
if (typeof line === 'number' && !isNaN(line)) {
|
||||
messaging.postMessage('didClick', { line: Math.floor(line) });
|
||||
}
|
||||
|
@ -210,7 +191,7 @@ window.addEventListener('scroll', throttle(() => {
|
|||
if (scrollDisabledCount > 0) {
|
||||
scrollDisabledCount -= 1;
|
||||
} else {
|
||||
const line = getEditorLineNumberForPageOffset(window.scrollY);
|
||||
const line = getEditorLineNumberForPageOffset(window.scrollY, documentVersion, settings);
|
||||
if (typeof line === 'number' && !isNaN(line)) {
|
||||
messaging.postMessage('revealLine', { line });
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { getSettings } from './settings';
|
||||
import { SettingsManager } from './settings';
|
||||
|
||||
export interface MessagePoster {
|
||||
/**
|
||||
|
@ -12,12 +12,12 @@ export interface MessagePoster {
|
|||
postMessage(type: string, body: object): void;
|
||||
}
|
||||
|
||||
export const createPosterForVsCode = (vscode: any) => {
|
||||
export const createPosterForVsCode = (vscode: any, settingsManager: SettingsManager) => {
|
||||
return new class implements MessagePoster {
|
||||
postMessage(type: string, body: object): void {
|
||||
vscode.postMessage({
|
||||
type,
|
||||
source: getSettings().source,
|
||||
source: settingsManager.settings!.source,
|
||||
body
|
||||
});
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
import { CspAlerter } from './csp';
|
||||
import { StyleLoadingMonitor } from './loading';
|
||||
import { SettingsManager } from './settings';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
|
@ -13,5 +14,5 @@ declare global {
|
|||
}
|
||||
}
|
||||
|
||||
window.cspAlerter = new CspAlerter();
|
||||
window.styleLoadingMonitor = new StyleLoadingMonitor();
|
||||
window.cspAlerter = new CspAlerter(new SettingsManager());
|
||||
window.styleLoadingMonitor = new StyleLoadingMonitor();
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { getSettings } from './settings';
|
||||
import { SettingsManager } from './settings';
|
||||
|
||||
const codeLineClass = 'code-line';
|
||||
|
||||
|
@ -11,8 +11,8 @@ function clamp(min: number, max: number, value: number) {
|
|||
return Math.min(max, Math.max(min, value));
|
||||
}
|
||||
|
||||
function clampLine(line: number) {
|
||||
return clamp(0, getSettings().lineCount - 1, line);
|
||||
function clampLine(line: number, lineCount: number) {
|
||||
return clamp(0, lineCount - 1, line);
|
||||
}
|
||||
|
||||
|
||||
|
@ -22,10 +22,12 @@ export interface CodeLineElement {
|
|||
}
|
||||
|
||||
const getCodeLineElements = (() => {
|
||||
let elements: CodeLineElement[];
|
||||
return () => {
|
||||
if (!elements) {
|
||||
elements = [{ element: document.body, line: 0 }];
|
||||
let cachedElements: CodeLineElement[] | undefined;
|
||||
let cachedVersion = -1;
|
||||
return (documentVersion: number) => {
|
||||
if (!cachedElements || documentVersion !== cachedVersion) {
|
||||
cachedVersion = documentVersion;
|
||||
cachedElements = [{ element: document.body, line: 0 }];
|
||||
for (const element of document.getElementsByClassName(codeLineClass)) {
|
||||
const line = +element.getAttribute('data-line')!;
|
||||
if (isNaN(line)) {
|
||||
|
@ -35,13 +37,13 @@ const getCodeLineElements = (() => {
|
|||
if (element.tagName === 'CODE' && element.parentElement && element.parentElement.tagName === 'PRE') {
|
||||
// Fenched code blocks are a special case since the `code-line` can only be marked on
|
||||
// the `<code>` element and not the parent `<pre>` element.
|
||||
elements.push({ element: element.parentElement as HTMLElement, line });
|
||||
cachedElements.push({ element: element.parentElement as HTMLElement, line });
|
||||
} else {
|
||||
elements.push({ element: element as HTMLElement, line });
|
||||
cachedElements.push({ element: element as HTMLElement, line });
|
||||
}
|
||||
}
|
||||
}
|
||||
return elements;
|
||||
return cachedElements;
|
||||
};
|
||||
})();
|
||||
|
||||
|
@ -51,9 +53,9 @@ const getCodeLineElements = (() => {
|
|||
* If an exact match, returns a single element. If the line is between elements,
|
||||
* returns the element prior to and the element after the given line.
|
||||
*/
|
||||
export function getElementsForSourceLine(targetLine: number): { previous: CodeLineElement; next?: CodeLineElement; } {
|
||||
export function getElementsForSourceLine(targetLine: number, documentVersion: number): { previous: CodeLineElement; next?: CodeLineElement; } {
|
||||
const lineNumber = Math.floor(targetLine);
|
||||
const lines = getCodeLineElements();
|
||||
const lines = getCodeLineElements(documentVersion);
|
||||
let previous = lines[0] || null;
|
||||
for (const entry of lines) {
|
||||
if (entry.line === lineNumber) {
|
||||
|
@ -69,8 +71,8 @@ export function getElementsForSourceLine(targetLine: number): { previous: CodeLi
|
|||
/**
|
||||
* Find the html elements that are at a specific pixel offset on the page.
|
||||
*/
|
||||
export function getLineElementsAtPageOffset(offset: number): { previous: CodeLineElement; next?: CodeLineElement; } {
|
||||
const lines = getCodeLineElements();
|
||||
export function getLineElementsAtPageOffset(offset: number, documentVersion: number): { previous: CodeLineElement; next?: CodeLineElement; } {
|
||||
const lines = getCodeLineElements(documentVersion);
|
||||
const position = offset - window.scrollY;
|
||||
let lo = -1;
|
||||
let hi = lines.length - 1;
|
||||
|
@ -117,8 +119,8 @@ function getElementBounds({ element }: CodeLineElement): { top: number, height:
|
|||
/**
|
||||
* Attempt to reveal the element for a source line in the editor.
|
||||
*/
|
||||
export function scrollToRevealSourceLine(line: number) {
|
||||
if (!getSettings().scrollPreviewWithEditor) {
|
||||
export function scrollToRevealSourceLine(line: number, documentVersion: number, settingsManager: SettingsManager) {
|
||||
if (!settingsManager.settings?.scrollPreviewWithEditor) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -127,7 +129,7 @@ export function scrollToRevealSourceLine(line: number) {
|
|||
return;
|
||||
}
|
||||
|
||||
const { previous, next } = getElementsForSourceLine(line);
|
||||
const { previous, next } = getElementsForSourceLine(line, documentVersion);
|
||||
if (!previous) {
|
||||
return;
|
||||
}
|
||||
|
@ -147,19 +149,20 @@ export function scrollToRevealSourceLine(line: number) {
|
|||
window.scroll(window.scrollX, Math.max(1, window.scrollY + scrollTo));
|
||||
}
|
||||
|
||||
export function getEditorLineNumberForPageOffset(offset: number) {
|
||||
const { previous, next } = getLineElementsAtPageOffset(offset);
|
||||
export function getEditorLineNumberForPageOffset(offset: number, documentVersion: number, settingsManager: SettingsManager) {
|
||||
const lineCount = settingsManager.settings?.lineCount ?? 0;
|
||||
const { previous, next } = getLineElementsAtPageOffset(offset, documentVersion);
|
||||
if (previous) {
|
||||
const previousBounds = getElementBounds(previous);
|
||||
const offsetFromPrevious = (offset - window.scrollY - previousBounds.top);
|
||||
if (next) {
|
||||
const progressBetweenElements = offsetFromPrevious / (getElementBounds(next).top - previousBounds.top);
|
||||
const line = previous.line + progressBetweenElements * (next.line - previous.line);
|
||||
return clampLine(line);
|
||||
return clampLine(line, lineCount);
|
||||
} else {
|
||||
const progressWithinElement = offsetFromPrevious / (previousBounds.height);
|
||||
const line = previous.line + progressWithinElement;
|
||||
return clampLine(line);
|
||||
return clampLine(line, lineCount);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -168,8 +171,8 @@ export function getEditorLineNumberForPageOffset(offset: number) {
|
|||
/**
|
||||
* Try to find the html element by using a fragment id
|
||||
*/
|
||||
export function getLineElementForFragment(fragment: string): CodeLineElement | undefined {
|
||||
return getCodeLineElements().find((element) => {
|
||||
export function getLineElementForFragment(fragment: string, documentVersion: number): CodeLineElement | undefined {
|
||||
return getCodeLineElements(documentVersion).find((element) => {
|
||||
return element.element.id === fragment;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -15,8 +15,6 @@ export interface PreviewSettings {
|
|||
readonly webviewResourceRoot: string;
|
||||
}
|
||||
|
||||
let cachedSettings: PreviewSettings | undefined = undefined;
|
||||
|
||||
export function getData<T = {}>(key: string): T {
|
||||
const element = document.getElementById('vscode-markdown-preview-data');
|
||||
if (element) {
|
||||
|
@ -29,15 +27,14 @@ export function getData<T = {}>(key: string): T {
|
|||
throw new Error(`Could not load data for ${key}`);
|
||||
}
|
||||
|
||||
export function getSettings(): PreviewSettings {
|
||||
if (cachedSettings) {
|
||||
return cachedSettings;
|
||||
export class SettingsManager {
|
||||
private _settings: PreviewSettings = getData('data-settings');
|
||||
|
||||
public get settings(): PreviewSettings {
|
||||
return this._settings;
|
||||
}
|
||||
|
||||
cachedSettings = getData('data-settings');
|
||||
if (cachedSettings) {
|
||||
return cachedSettings;
|
||||
public updateSettings(newSettings: PreviewSettings) {
|
||||
this._settings = newSettings;
|
||||
}
|
||||
|
||||
throw new Error('Could not load settings');
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
"compilerOptions": {
|
||||
"outDir": "./dist/",
|
||||
"jsx": "react",
|
||||
"esModuleInterop": true,
|
||||
"lib": [
|
||||
"es2018",
|
||||
"DOM",
|
||||
|
|
|
@ -16,7 +16,7 @@ import { WebviewResourceProvider } from '../util/resources';
|
|||
import { getVisibleLine, LastScrollLocation, TopmostLineMonitor } from '../util/topmostLineMonitor';
|
||||
import { urlToUri } from '../util/url';
|
||||
import { MarkdownPreviewConfigurationManager } from './previewConfig';
|
||||
import { MarkdownContentProvider, MarkdownContentProviderOutput } from './previewContentProvider';
|
||||
import { MarkdownContentProvider } from './previewContentProvider';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
|
@ -63,7 +63,7 @@ interface PreviewStyleLoadErrorMessage extends WebviewMessage {
|
|||
|
||||
export class PreviewDocumentVersion {
|
||||
|
||||
private readonly resource: vscode.Uri;
|
||||
public readonly resource: vscode.Uri;
|
||||
private readonly version: number;
|
||||
|
||||
public constructor(document: vscode.TextDocument) {
|
||||
|
@ -314,13 +314,18 @@ class MarkdownPreview extends Disposable implements WebviewResourceProvider {
|
|||
return;
|
||||
}
|
||||
|
||||
const shouldReloadPage = !this.currentVersion || this.currentVersion.resource.toString() !== pendingVersion.resource.toString();
|
||||
this.currentVersion = pendingVersion;
|
||||
const content = await this._contentProvider.provideTextDocumentContent(document, this, this._previewConfigurations, this.line, this.state);
|
||||
|
||||
const content = await (shouldReloadPage
|
||||
? this._contentProvider.provideTextDocumentContent(document, this, this._previewConfigurations, this.line, this.state)
|
||||
: this._contentProvider.markdownBody(document, this));
|
||||
|
||||
// Another call to `doUpdate` may have happened.
|
||||
// Make sure we are still updating for the correct document
|
||||
if (this.currentVersion?.equals(pendingVersion)) {
|
||||
this.setContent(content);
|
||||
this.updateWebviewContent(content.html, shouldReloadPage);
|
||||
this.updateImageWatchers(content.containingImages);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -366,7 +371,7 @@ class MarkdownPreview extends Disposable implements WebviewResourceProvider {
|
|||
this._webviewPanel.webview.html = this._contentProvider.provideFileNotFoundContent(this._resource);
|
||||
}
|
||||
|
||||
private setContent(content: MarkdownContentProviderOutput): void {
|
||||
private updateWebviewContent(html: string, reloadPage: boolean): void {
|
||||
if (this._disposed) {
|
||||
return;
|
||||
}
|
||||
|
@ -377,9 +382,19 @@ class MarkdownPreview extends Disposable implements WebviewResourceProvider {
|
|||
this._webviewPanel.iconPath = this.iconPath;
|
||||
this._webviewPanel.webview.options = this.getWebviewOptions();
|
||||
|
||||
this._webviewPanel.webview.html = content.html;
|
||||
if (reloadPage) {
|
||||
this._webviewPanel.webview.html = html;
|
||||
} else {
|
||||
this._webviewPanel.webview.postMessage({
|
||||
type: 'updateContent',
|
||||
content: html,
|
||||
source: this._resource.toString(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const srcs = new Set(content.containingImages.map(img => img.src));
|
||||
private updateImageWatchers(containingImages: { src: string }[]) {
|
||||
const srcs = new Set(containingImages.map(img => img.src));
|
||||
|
||||
// Delete stale file watchers.
|
||||
for (const [src, watcher] of [...this._fileWatchersBySrc]) {
|
||||
|
|
|
@ -81,7 +81,7 @@ export class MarkdownContentProvider {
|
|||
const nonce = getNonce();
|
||||
const csp = this.getCsp(resourceProvider, sourceUri, nonce);
|
||||
|
||||
const body = await this.engine.render(markdownDocument, resourceProvider);
|
||||
const body = await this.markdownBody(markdownDocument, resourceProvider);
|
||||
const html = `<!DOCTYPE html>
|
||||
<html style="${escapeAttribute(this.getSettingsOverrideStyles(config))}">
|
||||
<head>
|
||||
|
@ -97,7 +97,6 @@ export class MarkdownContentProvider {
|
|||
</head>
|
||||
<body class="vscode-body ${config.scrollBeyondLastLine ? 'scrollBeyondLastLine' : ''} ${config.wordWrap ? 'wordWrap' : ''} ${config.markEditorSelection ? 'showEditorSelection' : ''}">
|
||||
${body.html}
|
||||
<div class="code-line" data-line="${markdownDocument.lineCount}"></div>
|
||||
${this.getScripts(resourceProvider, nonce)}
|
||||
</body>
|
||||
</html>`;
|
||||
|
@ -107,6 +106,18 @@ export class MarkdownContentProvider {
|
|||
};
|
||||
}
|
||||
|
||||
public async markdownBody(
|
||||
markdownDocument: vscode.TextDocument,
|
||||
resourceProvider: WebviewResourceProvider,
|
||||
): Promise<MarkdownContentProviderOutput> {
|
||||
const rendered = await this.engine.render(markdownDocument, resourceProvider);
|
||||
const html = `<div class="markdown-body">${rendered.html}<div class="code-line" data-line="${markdownDocument.lineCount}"></div></div>`;
|
||||
return {
|
||||
html,
|
||||
containingImages: rendered.containingImages
|
||||
};
|
||||
}
|
||||
|
||||
public provideFileNotFoundContent(
|
||||
resource: vscode.Uri,
|
||||
): string {
|
||||
|
|
|
@ -107,6 +107,11 @@ mdurl@^1.0.1:
|
|||
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
|
||||
integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=
|
||||
|
||||
morphdom@^2.6.1:
|
||||
version "2.6.1"
|
||||
resolved "https://registry.yarnpkg.com/morphdom/-/morphdom-2.6.1.tgz#e868e24f989fa3183004b159aed643e628b4306e"
|
||||
integrity sha512-Y8YRbAEP3eKykroIBWrjcfMw7mmwJfjhqdpSvoqinu8Y702nAwikpXcNFDiIkyvfCLxLM9Wu95RZqo4a9jFBaA==
|
||||
|
||||
uc.micro@^1.0.1, uc.micro@^1.0.5:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac"
|
||||
|
|
Loading…
Reference in New Issue