mirror of
https://github.com/microsoft/vscode.git
synced 2026-02-26 12:44:05 +00:00
Splits the preview part of the markdown preview from the dynamic preview management part of things. Static preview swap to preview the active markdown file and don't scroll sync with any other markdown files
199 lines
4.9 KiB
TypeScript
199 lines
4.9 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
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 throttle = require('lodash.throttle');
|
|
|
|
declare let acquireVsCodeApi: any;
|
|
|
|
let scrollDisabled = true;
|
|
const marker = new ActiveLineMarker();
|
|
const settings = getSettings();
|
|
|
|
const vscode = acquireVsCodeApi();
|
|
|
|
const state = { ...vscode.getState(), ...getData<any>('data-state') };
|
|
// Make sure to sync VS Code state here
|
|
vscode.setState(state);
|
|
|
|
const messaging = createPosterForVsCode(vscode);
|
|
|
|
window.cspAlerter.setPoster(messaging);
|
|
window.styleLoadingMonitor.setPoster(messaging);
|
|
|
|
window.onload = () => {
|
|
updateImageSizes();
|
|
};
|
|
|
|
onceDocumentLoaded(() => {
|
|
const scrollProgress = state.scrollProgress;
|
|
|
|
if (typeof scrollProgress === 'number' && !settings.fragment) {
|
|
setImmediate(() => {
|
|
scrollDisabled = true;
|
|
window.scrollTo(0, scrollProgress * document.body.clientHeight);
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (settings.scrollPreviewWithEditor) {
|
|
setImmediate(() => {
|
|
// Try to scroll to fragment if available
|
|
if (settings.fragment) {
|
|
state.fragment = undefined;
|
|
vscode.setState(state);
|
|
|
|
const element = getLineElementForFragment(settings.fragment);
|
|
if (element) {
|
|
scrollDisabled = true;
|
|
scrollToRevealSourceLine(element.line);
|
|
}
|
|
} else {
|
|
if (!isNaN(settings.line!)) {
|
|
scrollDisabled = true;
|
|
scrollToRevealSourceLine(settings.line!);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
const onUpdateView = (() => {
|
|
const doScroll = throttle((line: number) => {
|
|
scrollDisabled = true;
|
|
scrollToRevealSourceLine(line);
|
|
}, 50);
|
|
|
|
return (line: number) => {
|
|
if (!isNaN(line)) {
|
|
state.line = line;
|
|
|
|
doScroll(line);
|
|
}
|
|
};
|
|
})();
|
|
|
|
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', () => {
|
|
scrollDisabled = true;
|
|
updateScrollProgress();
|
|
updateImageSizes();
|
|
}, true);
|
|
|
|
window.addEventListener('message', event => {
|
|
if (event.data.source !== settings.source) {
|
|
return;
|
|
}
|
|
|
|
switch (event.data.type) {
|
|
case 'onDidChangeTextEditorSelection':
|
|
marker.onDidChangeTextEditorSelection(event.data.line);
|
|
break;
|
|
|
|
case 'updateView':
|
|
onUpdateView(event.data.line);
|
|
break;
|
|
}
|
|
}, false);
|
|
|
|
document.addEventListener('dblclick', event => {
|
|
if (!settings.doubleClickToSwitchToEditor) {
|
|
return;
|
|
}
|
|
|
|
// Ignore clicks on links
|
|
for (let node = event.target as HTMLElement; node; node = node.parentNode as HTMLElement) {
|
|
if (node.tagName === 'A') {
|
|
return;
|
|
}
|
|
}
|
|
|
|
const offset = event.pageY;
|
|
const line = getEditorLineNumberForPageOffset(offset);
|
|
if (typeof line === 'number' && !isNaN(line)) {
|
|
messaging.postMessage('didClick', { line: Math.floor(line) });
|
|
}
|
|
});
|
|
|
|
const passThroughLinkSchemes = ['http:', 'https:', 'mailto:', 'vscode:', 'vscode-insiders:'];
|
|
|
|
document.addEventListener('click', event => {
|
|
if (!event) {
|
|
return;
|
|
}
|
|
|
|
let node: any = event.target;
|
|
while (node) {
|
|
if (node.tagName && node.tagName === 'A' && node.href) {
|
|
if (node.getAttribute('href').startsWith('#')) {
|
|
return;
|
|
}
|
|
|
|
// Pass through known schemes
|
|
if (passThroughLinkSchemes.some(scheme => node.href.startsWith(scheme))) {
|
|
return;
|
|
}
|
|
|
|
const hrefText = node.getAttribute('data-href') || node.getAttribute('href');
|
|
|
|
// If original link doesn't look like a url, delegate back to VS Code to resolve
|
|
if (!/^[a-z\-]+:/i.test(hrefText)) {
|
|
messaging.postMessage('openLink', { href: hrefText });
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
return;
|
|
}
|
|
|
|
return;
|
|
}
|
|
node = node.parentNode;
|
|
}
|
|
}, true);
|
|
|
|
window.addEventListener('scroll', throttle(() => {
|
|
updateScrollProgress();
|
|
|
|
if (scrollDisabled) {
|
|
scrollDisabled = false;
|
|
} else {
|
|
const line = getEditorLineNumberForPageOffset(window.scrollY);
|
|
if (typeof line === 'number' && !isNaN(line)) {
|
|
messaging.postMessage('revealLine', { line });
|
|
}
|
|
}
|
|
}, 50));
|
|
|
|
function updateScrollProgress() {
|
|
state.scrollProgress = window.scrollY / document.body.clientHeight;
|
|
vscode.setState(state);
|
|
}
|
|
|