mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Initial VS Code 1.19 source merge (#571)
* Initial 1.19 xcopy * Fix yarn build * Fix numerous build breaks * Next batch of build break fixes * More build break fixes * Runtime breaks * Additional post merge fixes * Fix windows setup file * Fix test failures. * Update license header blocks to refer to source eula
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
test/**
|
||||
src/**
|
||||
tsconfig.json
|
||||
npm-shrinkwrap.json
|
||||
tsconfig.json
|
||||
@@ -12,7 +12,7 @@
|
||||
let didShow = false;
|
||||
|
||||
const showCspWarning = () => {
|
||||
if (didShow) {
|
||||
if (didShow || settings.disableSecurityWarnings) {
|
||||
return;
|
||||
}
|
||||
didShow = true;
|
||||
|
||||
@@ -317,8 +317,8 @@
|
||||
"devDependencies": {
|
||||
"@types/highlight.js": "9.1.10",
|
||||
"@types/markdown-it": "0.0.2",
|
||||
"@types/node": "8.0.33",
|
||||
"@types/node": "7.0.43",
|
||||
"gulp-rename": "^1.2.2",
|
||||
"gulp-replace": "^0.5.4"
|
||||
}
|
||||
}
|
||||
}
|
||||
36
extensions/markdown/src/commandManager.ts
Normal file
36
extensions/markdown/src/commandManager.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
export interface Command {
|
||||
readonly id: string;
|
||||
|
||||
execute(...args: any[]): void;
|
||||
}
|
||||
|
||||
export class CommandManager {
|
||||
private readonly commands = new Map<string, vscode.Disposable>();
|
||||
|
||||
public dispose() {
|
||||
for (const registration of this.commands.values()) {
|
||||
registration.dispose();
|
||||
}
|
||||
this.commands.clear();
|
||||
}
|
||||
|
||||
public register<T extends Command>(command: T): T {
|
||||
this.registerCommand(command.id, command.execute, command);
|
||||
return command;
|
||||
}
|
||||
|
||||
private registerCommand(id: string, impl: (...args: any[]) => void, thisArg?: any) {
|
||||
if (this.commands.has(id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.commands.set(id, vscode.commands.registerCommand(id, impl, thisArg));
|
||||
}
|
||||
}
|
||||
291
extensions/markdown/src/commands.ts
Normal file
291
extensions/markdown/src/commands.ts
Normal file
@@ -0,0 +1,291 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vscode-nls';
|
||||
const localize = nls.config(process.env.VSCODE_NLS_CONFIG)();
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
|
||||
import { Command } from './commandManager';
|
||||
import { ExtensionContentSecurityPolicyArbiter, PreviewSecuritySelector } from './security';
|
||||
import { getMarkdownUri, MDDocumentContentProvider, isMarkdownFile } from './features/previewContentProvider';
|
||||
import { Logger } from './logger';
|
||||
import { TableOfContentsProvider } from './tableOfContentsProvider';
|
||||
import { MarkdownEngine } from './markdownEngine';
|
||||
import { TelemetryReporter } from './telemetryReporter';
|
||||
|
||||
|
||||
function getViewColumn(sideBySide: boolean): vscode.ViewColumn | undefined {
|
||||
const active = vscode.window.activeTextEditor;
|
||||
if (!active) {
|
||||
return vscode.ViewColumn.One;
|
||||
}
|
||||
|
||||
if (!sideBySide) {
|
||||
return active.viewColumn;
|
||||
}
|
||||
|
||||
switch (active.viewColumn) {
|
||||
case vscode.ViewColumn.One:
|
||||
return vscode.ViewColumn.Two;
|
||||
case vscode.ViewColumn.Two:
|
||||
return vscode.ViewColumn.Three;
|
||||
}
|
||||
|
||||
return active.viewColumn;
|
||||
}
|
||||
|
||||
function showPreview(
|
||||
cspArbiter: ExtensionContentSecurityPolicyArbiter,
|
||||
telemetryReporter: TelemetryReporter,
|
||||
uri?: vscode.Uri,
|
||||
sideBySide: boolean = false,
|
||||
) {
|
||||
let resource = uri;
|
||||
if (!(resource instanceof vscode.Uri)) {
|
||||
if (vscode.window.activeTextEditor) {
|
||||
// we are relaxed and don't check for markdown files
|
||||
resource = vscode.window.activeTextEditor.document.uri;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(resource instanceof vscode.Uri)) {
|
||||
if (!vscode.window.activeTextEditor) {
|
||||
// this is most likely toggling the preview
|
||||
return vscode.commands.executeCommand('markdown.showSource');
|
||||
}
|
||||
// nothing found that could be shown or toggled
|
||||
return;
|
||||
}
|
||||
|
||||
const thenable = vscode.commands.executeCommand('vscode.previewHtml',
|
||||
getMarkdownUri(resource),
|
||||
getViewColumn(sideBySide),
|
||||
localize('previewTitle', 'Preview {0}', path.basename(resource.fsPath)),
|
||||
{
|
||||
allowScripts: true,
|
||||
allowSvgs: cspArbiter.shouldAllowSvgsForResource(resource)
|
||||
});
|
||||
|
||||
telemetryReporter.sendTelemetryEvent('openPreview', {
|
||||
where: sideBySide ? 'sideBySide' : 'inPlace',
|
||||
how: (uri instanceof vscode.Uri) ? 'action' : 'pallete'
|
||||
});
|
||||
|
||||
return thenable;
|
||||
}
|
||||
|
||||
export class ShowPreviewCommand implements Command {
|
||||
public readonly id = 'markdown.showPreview';
|
||||
|
||||
public constructor(
|
||||
private readonly cspArbiter: ExtensionContentSecurityPolicyArbiter,
|
||||
private readonly telemetryReporter: TelemetryReporter
|
||||
) { }
|
||||
|
||||
public execute(uri?: vscode.Uri) {
|
||||
showPreview(this.cspArbiter, this.telemetryReporter, uri, false);
|
||||
}
|
||||
}
|
||||
|
||||
export class ShowPreviewToSideCommand implements Command {
|
||||
public readonly id = 'markdown.showPreviewToSide';
|
||||
|
||||
public constructor(
|
||||
private readonly cspArbiter: ExtensionContentSecurityPolicyArbiter,
|
||||
private readonly telemetryReporter: TelemetryReporter
|
||||
) { }
|
||||
|
||||
public execute(uri?: vscode.Uri) {
|
||||
showPreview(this.cspArbiter, this.telemetryReporter, uri, true);
|
||||
}
|
||||
}
|
||||
|
||||
export class ShowSourceCommand implements Command {
|
||||
public readonly id = 'markdown.showSource';
|
||||
|
||||
public execute(mdUri?: vscode.Uri) {
|
||||
if (!mdUri) {
|
||||
return vscode.commands.executeCommand('workbench.action.navigateBack');
|
||||
}
|
||||
|
||||
const docUri = vscode.Uri.parse(mdUri.query);
|
||||
for (const editor of vscode.window.visibleTextEditors) {
|
||||
if (editor.document.uri.scheme === docUri.scheme && editor.document.uri.toString() === docUri.toString()) {
|
||||
return vscode.window.showTextDocument(editor.document, editor.viewColumn);
|
||||
}
|
||||
}
|
||||
|
||||
return vscode.workspace.openTextDocument(docUri)
|
||||
.then(vscode.window.showTextDocument);
|
||||
}
|
||||
}
|
||||
|
||||
export class RefreshPreviewCommand implements Command {
|
||||
public readonly id = 'markdown.refreshPreview';
|
||||
|
||||
public constructor(
|
||||
private readonly contentProvider: MDDocumentContentProvider
|
||||
) { }
|
||||
|
||||
public execute(resource: string | undefined) {
|
||||
if (resource) {
|
||||
const source = vscode.Uri.parse(resource);
|
||||
this.contentProvider.update(source);
|
||||
} else if (vscode.window.activeTextEditor && isMarkdownFile(vscode.window.activeTextEditor.document)) {
|
||||
this.contentProvider.update(getMarkdownUri(vscode.window.activeTextEditor.document.uri));
|
||||
} else {
|
||||
// update all generated md documents
|
||||
for (const document of vscode.workspace.textDocuments) {
|
||||
if (document.uri.scheme === 'markdown') {
|
||||
this.contentProvider.update(document.uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class ShowPreviewSecuritySelectorCommand implements Command {
|
||||
public readonly id = 'markdown.showPreviewSecuritySelector';
|
||||
|
||||
public constructor(
|
||||
private readonly previewSecuritySelector: PreviewSecuritySelector
|
||||
) { }
|
||||
|
||||
public execute(resource: string | undefined) {
|
||||
if (resource) {
|
||||
const source = vscode.Uri.parse(resource).query;
|
||||
this.previewSecuritySelector.showSecutitySelectorForResource(vscode.Uri.parse(source));
|
||||
} else {
|
||||
if (vscode.window.activeTextEditor && vscode.window.activeTextEditor.document.languageId === 'markdown') {
|
||||
this.previewSecuritySelector.showSecutitySelectorForResource(vscode.window.activeTextEditor.document.uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class RevealLineCommand implements Command {
|
||||
public readonly id = '_markdown.revealLine';
|
||||
|
||||
public constructor(
|
||||
private logger: Logger
|
||||
) { }
|
||||
|
||||
public execute(uri: string, line: number) {
|
||||
const sourceUri = vscode.Uri.parse(decodeURIComponent(uri));
|
||||
this.logger.log('revealLine', { uri, sourceUri: sourceUri.toString(), line });
|
||||
|
||||
vscode.window.visibleTextEditors
|
||||
.filter(editor => isMarkdownFile(editor.document) && editor.document.uri.toString() === sourceUri.toString())
|
||||
.forEach(editor => {
|
||||
const sourceLine = Math.floor(line);
|
||||
const fraction = line - sourceLine;
|
||||
const text = editor.document.lineAt(sourceLine).text;
|
||||
const start = Math.floor(fraction * text.length);
|
||||
editor.revealRange(
|
||||
new vscode.Range(sourceLine, start, sourceLine + 1, 0),
|
||||
vscode.TextEditorRevealType.AtTop);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class DidClickCommand implements Command {
|
||||
public readonly id = '_markdown.didClick';
|
||||
|
||||
public execute(uri: string, line: number) {
|
||||
const sourceUri = vscode.Uri.parse(decodeURIComponent(uri));
|
||||
return vscode.workspace.openTextDocument(sourceUri)
|
||||
.then(document => vscode.window.showTextDocument(document))
|
||||
.then(editor =>
|
||||
vscode.commands.executeCommand('revealLine', { lineNumber: Math.floor(line), at: 'center' })
|
||||
.then(() => editor))
|
||||
.then(editor => {
|
||||
if (editor) {
|
||||
editor.selection = new vscode.Selection(
|
||||
new vscode.Position(Math.floor(line), 0),
|
||||
new vscode.Position(Math.floor(line), 0));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class MoveCursorToPositionCommand implements Command {
|
||||
public readonly id = '_markdown.moveCursorToPosition';
|
||||
|
||||
public execute(line: number, character: number) {
|
||||
if (!vscode.window.activeTextEditor) {
|
||||
return;
|
||||
}
|
||||
const position = new vscode.Position(line, character);
|
||||
const selection = new vscode.Selection(position, position);
|
||||
vscode.window.activeTextEditor.revealRange(selection);
|
||||
vscode.window.activeTextEditor.selection = selection;
|
||||
}
|
||||
}
|
||||
|
||||
export class OnPreviewStyleLoadErrorCommand implements Command {
|
||||
public readonly id = '_markdown.onPreviewStyleLoadError';
|
||||
|
||||
public execute(resources: string[]) {
|
||||
vscode.window.showWarningMessage(localize('onPreviewStyleLoadError', "Could not load 'markdown.styles': {0}", resources.join(', ')));
|
||||
}
|
||||
}
|
||||
|
||||
export interface OpenDocumentLinkArgs {
|
||||
path: string;
|
||||
fragment: string;
|
||||
}
|
||||
|
||||
export class OpenDocumentLinkCommand implements Command {
|
||||
private static readonly id = '_markdown.openDocumentLink';
|
||||
public readonly id = OpenDocumentLinkCommand.id;
|
||||
|
||||
public static createCommandUri(
|
||||
path: string,
|
||||
fragment: string
|
||||
): vscode.Uri {
|
||||
return vscode.Uri.parse(`command:${OpenDocumentLinkCommand.id}?${encodeURIComponent(JSON.stringify({ path, fragment }))}`);
|
||||
}
|
||||
|
||||
public constructor(
|
||||
private readonly engine: MarkdownEngine
|
||||
) { }
|
||||
|
||||
public execute(args: OpenDocumentLinkArgs) {
|
||||
const tryRevealLine = async (editor: vscode.TextEditor) => {
|
||||
if (editor && args.fragment) {
|
||||
const toc = new TableOfContentsProvider(this.engine, editor.document);
|
||||
const line = await toc.lookup(args.fragment);
|
||||
if (!isNaN(line)) {
|
||||
return editor.revealRange(
|
||||
new vscode.Range(line, 0, line, 0),
|
||||
vscode.TextEditorRevealType.AtTop);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const tryOpen = async (path: string) => {
|
||||
if (vscode.window.activeTextEditor && isMarkdownFile(vscode.window.activeTextEditor.document) && vscode.window.activeTextEditor.document.uri.fsPath === path) {
|
||||
return tryRevealLine(vscode.window.activeTextEditor);
|
||||
} else {
|
||||
const resource = vscode.Uri.file(path);
|
||||
return vscode.workspace.openTextDocument(resource)
|
||||
.then(vscode.window.showTextDocument)
|
||||
.then(tryRevealLine);
|
||||
}
|
||||
};
|
||||
|
||||
return tryOpen(args.path).catch(() => {
|
||||
if (path.extname(args.path) === '') {
|
||||
return tryOpen(args.path + '.md');
|
||||
}
|
||||
const resource = vscode.Uri.file(args.path);
|
||||
return Promise.resolve(void 0)
|
||||
.then(() => vscode.commands.executeCommand('vscode.open', resource))
|
||||
.then(() => void 0);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -3,200 +3,52 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as nls from 'vscode-nls';
|
||||
const localize = nls.config(process.env.VSCODE_NLS_CONFIG)();
|
||||
import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
import TelemetryReporter from 'vscode-extension-telemetry';
|
||||
|
||||
import { MarkdownEngine } from './markdownEngine';
|
||||
import LinkProvider from './documentLinkProvider';
|
||||
import MDDocumentSymbolProvider from './documentSymbolProvider';
|
||||
import { ExtensionContentSecurityPolicyArbiter, PreviewSecuritySelector } from './security';
|
||||
import { MDDocumentContentProvider, getMarkdownUri, isMarkdownFile } from './previewContentProvider';
|
||||
import { TableOfContentsProvider } from './tableOfContentsProvider';
|
||||
import { Logger } from './logger';
|
||||
import { CommandManager } from './commandManager';
|
||||
import * as commands from './commands';
|
||||
import { loadDefaultTelemetryReporter } from './telemetryReporter';
|
||||
import { loadMarkdownExtensions } from './markdownExtensions';
|
||||
import LinkProvider from './features/documentLinkProvider';
|
||||
import MDDocumentSymbolProvider from './features/documentSymbolProvider';
|
||||
import { MDDocumentContentProvider, getMarkdownUri, isMarkdownFile } from './features/previewContentProvider';
|
||||
|
||||
interface IPackageInfo {
|
||||
name: string;
|
||||
version: string;
|
||||
aiKey: string;
|
||||
}
|
||||
|
||||
interface OpenDocumentLinkArgs {
|
||||
path: string;
|
||||
fragment: string;
|
||||
}
|
||||
|
||||
const resolveExtensionResources = (extension: vscode.Extension<any>, stylePath: string): vscode.Uri => {
|
||||
const resource = vscode.Uri.parse(stylePath);
|
||||
if (resource.scheme) {
|
||||
return resource;
|
||||
}
|
||||
return vscode.Uri.file(path.join(extension.extensionPath, stylePath));
|
||||
};
|
||||
|
||||
var telemetryReporter: TelemetryReporter | null;
|
||||
|
||||
export function activate(context: vscode.ExtensionContext) {
|
||||
const packageInfo = getPackageInfo();
|
||||
telemetryReporter = packageInfo && new TelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey);
|
||||
if (telemetryReporter) {
|
||||
context.subscriptions.push(telemetryReporter);
|
||||
}
|
||||
const telemetryReporter = loadDefaultTelemetryReporter();
|
||||
context.subscriptions.push(telemetryReporter);
|
||||
|
||||
const cspArbiter = new ExtensionContentSecurityPolicyArbiter(context.globalState);
|
||||
const cspArbiter = new ExtensionContentSecurityPolicyArbiter(context.globalState, context.workspaceState);
|
||||
const engine = new MarkdownEngine();
|
||||
|
||||
const logger = new Logger();
|
||||
|
||||
const selector = 'markdown';
|
||||
|
||||
const contentProvider = new MDDocumentContentProvider(engine, context, cspArbiter, logger);
|
||||
const contentProviderRegistration = vscode.workspace.registerTextDocumentContentProvider('markdown', contentProvider);
|
||||
context.subscriptions.push(vscode.workspace.registerTextDocumentContentProvider(selector, contentProvider));
|
||||
|
||||
loadMarkdownExtensions(contentProvider, engine);
|
||||
|
||||
context.subscriptions.push(vscode.languages.registerDocumentSymbolProvider(selector, new MDDocumentSymbolProvider(engine)));
|
||||
context.subscriptions.push(vscode.languages.registerDocumentLinkProvider(selector, new LinkProvider()));
|
||||
|
||||
const previewSecuritySelector = new PreviewSecuritySelector(cspArbiter, contentProvider);
|
||||
|
||||
for (const extension of vscode.extensions.all) {
|
||||
const contributes = extension.packageJSON && extension.packageJSON.contributes;
|
||||
if (!contributes) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const styles = contributes['markdown.previewStyles'];
|
||||
if (styles && Array.isArray(styles)) {
|
||||
for (const style of styles) {
|
||||
try {
|
||||
contentProvider.addStyle(resolveExtensionResources(extension, style));
|
||||
} catch (e) {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const scripts = contributes['markdown.previewScripts'];
|
||||
if (scripts && Array.isArray(scripts)) {
|
||||
for (const script of scripts) {
|
||||
try {
|
||||
contentProvider.addScript(resolveExtensionResources(extension, script));
|
||||
} catch (e) {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (contributes['markdown.markdownItPlugins']) {
|
||||
extension.activate().then(() => {
|
||||
if (extension.exports && extension.exports.extendMarkdownIt) {
|
||||
engine.addPlugin((md: any) => extension.exports.extendMarkdownIt(md));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const symbolsProvider = new MDDocumentSymbolProvider(engine);
|
||||
const symbolsProviderRegistration = vscode.languages.registerDocumentSymbolProvider({ language: 'markdown' }, symbolsProvider);
|
||||
context.subscriptions.push(contentProviderRegistration, symbolsProviderRegistration);
|
||||
|
||||
context.subscriptions.push(vscode.languages.registerDocumentLinkProvider('markdown', new LinkProvider()));
|
||||
|
||||
context.subscriptions.push(vscode.commands.registerCommand('markdown.showPreview', (uri) => showPreview(cspArbiter, uri, false)));
|
||||
context.subscriptions.push(vscode.commands.registerCommand('markdown.showPreviewToSide', uri => showPreview(cspArbiter, uri, true)));
|
||||
context.subscriptions.push(vscode.commands.registerCommand('markdown.showSource', showSource));
|
||||
|
||||
context.subscriptions.push(vscode.commands.registerCommand('_markdown.moveCursorToPosition', (line: number, character: number) => {
|
||||
if (!vscode.window.activeTextEditor) {
|
||||
return;
|
||||
}
|
||||
const position = new vscode.Position(line, character);
|
||||
const selection = new vscode.Selection(position, position);
|
||||
vscode.window.activeTextEditor.revealRange(selection);
|
||||
vscode.window.activeTextEditor.selection = selection;
|
||||
}));
|
||||
|
||||
context.subscriptions.push(vscode.commands.registerCommand('_markdown.revealLine', (uri, line) => {
|
||||
const sourceUri = vscode.Uri.parse(decodeURIComponent(uri));
|
||||
logger.log('revealLine', { uri, sourceUri: sourceUri.toString(), line });
|
||||
|
||||
vscode.window.visibleTextEditors
|
||||
.filter(editor => isMarkdownFile(editor.document) && editor.document.uri.toString() === sourceUri.toString())
|
||||
.forEach(editor => {
|
||||
const sourceLine = Math.floor(line);
|
||||
const fraction = line - sourceLine;
|
||||
const text = editor.document.lineAt(sourceLine).text;
|
||||
const start = Math.floor(fraction * text.length);
|
||||
editor.revealRange(
|
||||
new vscode.Range(sourceLine, start, sourceLine + 1, 0),
|
||||
vscode.TextEditorRevealType.AtTop);
|
||||
});
|
||||
}));
|
||||
|
||||
context.subscriptions.push(vscode.commands.registerCommand('_markdown.didClick', (uri: string, line) => {
|
||||
const sourceUri = vscode.Uri.parse(decodeURIComponent(uri));
|
||||
return vscode.workspace.openTextDocument(sourceUri)
|
||||
.then(document => vscode.window.showTextDocument(document))
|
||||
.then(editor =>
|
||||
vscode.commands.executeCommand('revealLine', { lineNumber: Math.floor(line), at: 'center' })
|
||||
.then(() => editor))
|
||||
.then(editor => {
|
||||
if (editor) {
|
||||
editor.selection = new vscode.Selection(
|
||||
new vscode.Position(Math.floor(line), 0),
|
||||
new vscode.Position(Math.floor(line), 0));
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
context.subscriptions.push(vscode.commands.registerCommand('_markdown.openDocumentLink', (args: OpenDocumentLinkArgs) => {
|
||||
const tryRevealLine = async (editor: vscode.TextEditor) => {
|
||||
if (editor && args.fragment) {
|
||||
const toc = new TableOfContentsProvider(engine, editor.document);
|
||||
const line = await toc.lookup(args.fragment);
|
||||
if (!isNaN(line)) {
|
||||
return editor.revealRange(
|
||||
new vscode.Range(line, 0, line, 0),
|
||||
vscode.TextEditorRevealType.AtTop);
|
||||
}
|
||||
}
|
||||
};
|
||||
if (vscode.window.activeTextEditor && isMarkdownFile(vscode.window.activeTextEditor.document) && vscode.window.activeTextEditor.document.uri.fsPath === args.path) {
|
||||
return tryRevealLine(vscode.window.activeTextEditor);
|
||||
} else {
|
||||
const resource = vscode.Uri.file(args.path);
|
||||
return vscode.workspace.openTextDocument(resource)
|
||||
.then(vscode.window.showTextDocument)
|
||||
.then(tryRevealLine, _ => vscode.commands.executeCommand('vscode.open', resource));
|
||||
}
|
||||
}));
|
||||
|
||||
context.subscriptions.push(vscode.commands.registerCommand('markdown.showPreviewSecuritySelector', (resource: string | undefined) => {
|
||||
if (resource) {
|
||||
const source = vscode.Uri.parse(resource).query;
|
||||
previewSecuritySelector.showSecutitySelectorForResource(vscode.Uri.parse(source));
|
||||
} else {
|
||||
if (vscode.window.activeTextEditor && vscode.window.activeTextEditor.document.languageId === 'markdown') {
|
||||
previewSecuritySelector.showSecutitySelectorForResource(vscode.window.activeTextEditor.document.uri);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
context.subscriptions.push(vscode.commands.registerCommand('markdown.refreshPreview', (resource: string | undefined) => {
|
||||
if (resource) {
|
||||
const source = vscode.Uri.parse(resource);
|
||||
contentProvider.update(source);
|
||||
} else if (vscode.window.activeTextEditor && isMarkdownFile(vscode.window.activeTextEditor.document)) {
|
||||
contentProvider.update(getMarkdownUri(vscode.window.activeTextEditor.document.uri));
|
||||
} else {
|
||||
// update all generated md documents
|
||||
for (const document of vscode.workspace.textDocuments) {
|
||||
if (document.uri.scheme === 'markdown') {
|
||||
contentProvider.update(document.uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
context.subscriptions.push(vscode.commands.registerCommand('_markdown.onPreviewStyleLoadError', (resources: string[]) => {
|
||||
vscode.window.showWarningMessage(localize('onPreviewStyleLoadError', "Could not load 'markdown.styles': {0}", resources.join(', ')));
|
||||
}));
|
||||
const commandManager = new CommandManager();
|
||||
context.subscriptions.push(commandManager);
|
||||
commandManager.register(new commands.ShowPreviewCommand(cspArbiter, telemetryReporter));
|
||||
commandManager.register(new commands.ShowPreviewToSideCommand(cspArbiter, telemetryReporter));
|
||||
commandManager.register(new commands.ShowSourceCommand());
|
||||
commandManager.register(new commands.RefreshPreviewCommand(contentProvider));
|
||||
commandManager.register(new commands.RevealLineCommand(logger));
|
||||
commandManager.register(new commands.MoveCursorToPositionCommand());
|
||||
commandManager.register(new commands.ShowPreviewSecuritySelectorCommand(previewSecuritySelector));
|
||||
commandManager.register(new commands.OnPreviewStyleLoadErrorCommand());
|
||||
commandManager.register(new commands.DidClickCommand());
|
||||
commandManager.register(new commands.OpenDocumentLinkCommand(engine));
|
||||
|
||||
context.subscriptions.push(vscode.workspace.onDidSaveTextDocument(document => {
|
||||
if (isMarkdownFile(document)) {
|
||||
@@ -230,95 +82,3 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
function showPreview(cspArbiter: ExtensionContentSecurityPolicyArbiter, uri?: vscode.Uri, sideBySide: boolean = false) {
|
||||
let resource = uri;
|
||||
if (!(resource instanceof vscode.Uri)) {
|
||||
if (vscode.window.activeTextEditor) {
|
||||
// we are relaxed and don't check for markdown files
|
||||
resource = vscode.window.activeTextEditor.document.uri;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(resource instanceof vscode.Uri)) {
|
||||
if (!vscode.window.activeTextEditor) {
|
||||
// this is most likely toggling the preview
|
||||
return vscode.commands.executeCommand('markdown.showSource');
|
||||
}
|
||||
// nothing found that could be shown or toggled
|
||||
return;
|
||||
}
|
||||
|
||||
const thenable = vscode.commands.executeCommand('vscode.previewHtml',
|
||||
getMarkdownUri(resource),
|
||||
getViewColumn(sideBySide),
|
||||
localize('previewTitle', 'Preview {0}', path.basename(resource.fsPath)),
|
||||
{
|
||||
allowScripts: true,
|
||||
allowSvgs: cspArbiter.shouldAllowSvgsForResource(resource)
|
||||
});
|
||||
|
||||
if (telemetryReporter) {
|
||||
/* __GDPR__
|
||||
"openPreview" : {
|
||||
"where" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"how": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
}
|
||||
*/
|
||||
telemetryReporter.sendTelemetryEvent('openPreview', {
|
||||
where: sideBySide ? 'sideBySide' : 'inPlace',
|
||||
how: (uri instanceof vscode.Uri) ? 'action' : 'pallete'
|
||||
});
|
||||
}
|
||||
|
||||
return thenable;
|
||||
}
|
||||
|
||||
function getViewColumn(sideBySide: boolean): vscode.ViewColumn | undefined {
|
||||
const active = vscode.window.activeTextEditor;
|
||||
if (!active) {
|
||||
return vscode.ViewColumn.One;
|
||||
}
|
||||
|
||||
if (!sideBySide) {
|
||||
return active.viewColumn;
|
||||
}
|
||||
|
||||
switch (active.viewColumn) {
|
||||
case vscode.ViewColumn.One:
|
||||
return vscode.ViewColumn.Two;
|
||||
case vscode.ViewColumn.Two:
|
||||
return vscode.ViewColumn.Three;
|
||||
}
|
||||
|
||||
return active.viewColumn;
|
||||
}
|
||||
|
||||
function showSource(mdUri: vscode.Uri) {
|
||||
if (!mdUri) {
|
||||
return vscode.commands.executeCommand('workbench.action.navigateBack');
|
||||
}
|
||||
|
||||
const docUri = vscode.Uri.parse(mdUri.query);
|
||||
for (const editor of vscode.window.visibleTextEditors) {
|
||||
if (editor.document.uri.scheme === docUri.scheme && editor.document.uri.toString() === docUri.toString()) {
|
||||
return vscode.window.showTextDocument(editor.document, editor.viewColumn);
|
||||
}
|
||||
}
|
||||
|
||||
return vscode.workspace.openTextDocument(docUri)
|
||||
.then(vscode.window.showTextDocument);
|
||||
}
|
||||
|
||||
function getPackageInfo(): IPackageInfo | null {
|
||||
const extention = vscode.extensions.getExtension('Microsoft.vscode-markdown');
|
||||
if (extention && extention.packageJSON) {
|
||||
return {
|
||||
name: extention.packageJSON.name,
|
||||
version: extention.packageJSON.version,
|
||||
aiKey: extention.packageJSON.aiKey
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
160
extensions/markdown/src/features/documentLinkProvider.ts
Normal file
160
extensions/markdown/src/features/documentLinkProvider.ts
Normal file
@@ -0,0 +1,160 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
import { OpenDocumentLinkCommand } from '../commands';
|
||||
|
||||
function normalizeLink(
|
||||
document: vscode.TextDocument,
|
||||
link: string,
|
||||
base: string
|
||||
): vscode.Uri {
|
||||
const uri = vscode.Uri.parse(link);
|
||||
if (uri.scheme) {
|
||||
return uri;
|
||||
}
|
||||
|
||||
// assume it must be a file
|
||||
let resourcePath = uri.path;
|
||||
if (!uri.path) {
|
||||
resourcePath = document.uri.path;
|
||||
} else if (uri.path[0] === '/') {
|
||||
const root = vscode.workspace.getWorkspaceFolder(document.uri);
|
||||
if (root) {
|
||||
resourcePath = path.join(root.uri.fsPath, uri.path);
|
||||
}
|
||||
} else {
|
||||
resourcePath = path.join(base, uri.path);
|
||||
}
|
||||
|
||||
return OpenDocumentLinkCommand.createCommandUri(resourcePath, uri.fragment);
|
||||
}
|
||||
|
||||
function matchAll(
|
||||
pattern: RegExp,
|
||||
text: string
|
||||
): Array<RegExpMatchArray> {
|
||||
const out: RegExpMatchArray[] = [];
|
||||
pattern.lastIndex = 0;
|
||||
let match: RegExpMatchArray | null;
|
||||
while ((match = pattern.exec(text))) {
|
||||
out.push(match);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
export default class LinkProvider implements vscode.DocumentLinkProvider {
|
||||
private readonly linkPattern = /(\[[^\]]*\]\(\s*?)(((((?=.*\)\)+)|(?=.*\)\]+))[^\s\)]+?)|([^\s]+?)))\)/g;
|
||||
private readonly referenceLinkPattern = /(\[([^\]]+)\]\[\s*?)([^\s\]]*?)\]/g;
|
||||
private readonly definitionPattern = /^([\t ]*\[([^\]]+)\]:\s*)(\S+)/gm;
|
||||
|
||||
public provideDocumentLinks(
|
||||
document: vscode.TextDocument,
|
||||
_token: vscode.CancellationToken
|
||||
): vscode.DocumentLink[] {
|
||||
const base = path.dirname(document.uri.fsPath);
|
||||
const text = document.getText();
|
||||
|
||||
return this.providerInlineLinks(text, document, base)
|
||||
.concat(this.provideReferenceLinks(text, document, base));
|
||||
}
|
||||
|
||||
private providerInlineLinks(
|
||||
text: string,
|
||||
document: vscode.TextDocument,
|
||||
base: string
|
||||
): vscode.DocumentLink[] {
|
||||
const results: vscode.DocumentLink[] = [];
|
||||
for (const match of matchAll(this.linkPattern, text)) {
|
||||
const pre = match[1];
|
||||
const link = match[2];
|
||||
const offset = (match.index || 0) + pre.length;
|
||||
const linkStart = document.positionAt(offset);
|
||||
const linkEnd = document.positionAt(offset + link.length);
|
||||
try {
|
||||
results.push(new vscode.DocumentLink(
|
||||
new vscode.Range(linkStart, linkEnd),
|
||||
normalizeLink(document, link, base)));
|
||||
} catch (e) {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private provideReferenceLinks(
|
||||
text: string,
|
||||
document: vscode.TextDocument,
|
||||
base: string
|
||||
): vscode.DocumentLink[] {
|
||||
const results: vscode.DocumentLink[] = [];
|
||||
|
||||
const definitions = this.getDefinitions(text, document);
|
||||
for (const match of matchAll(this.referenceLinkPattern, text)) {
|
||||
let linkStart: vscode.Position;
|
||||
let linkEnd: vscode.Position;
|
||||
let reference = match[3];
|
||||
if (reference) { // [text][ref]
|
||||
const pre = match[1];
|
||||
const offset = (match.index || 0) + pre.length;
|
||||
linkStart = document.positionAt(offset);
|
||||
linkEnd = document.positionAt(offset + reference.length);
|
||||
} else if (match[2]) { // [ref][]
|
||||
reference = match[2];
|
||||
const offset = (match.index || 0) + 1;
|
||||
linkStart = document.positionAt(offset);
|
||||
linkEnd = document.positionAt(offset + match[2].length);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
const link = definitions.get(reference);
|
||||
if (link) {
|
||||
results.push(new vscode.DocumentLink(
|
||||
new vscode.Range(linkStart, linkEnd),
|
||||
vscode.Uri.parse(`command:_markdown.moveCursorToPosition?${encodeURIComponent(JSON.stringify([link.linkRange.start.line, link.linkRange.start.character]))}`)));
|
||||
}
|
||||
} catch (e) {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
|
||||
for (const definition of Array.from(definitions.values())) {
|
||||
try {
|
||||
results.push(new vscode.DocumentLink(
|
||||
definition.linkRange,
|
||||
normalizeLink(document, definition.link, base)));
|
||||
} catch (e) {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private getDefinitions(text: string, document: vscode.TextDocument) {
|
||||
const out = new Map<string, { link: string, linkRange: vscode.Range }>();
|
||||
for (const match of matchAll(this.definitionPattern, text)) {
|
||||
const pre = match[1];
|
||||
const reference = match[2];
|
||||
const link = match[3].trim();
|
||||
|
||||
const offset = (match.index || 0) + pre.length;
|
||||
const linkStart = document.positionAt(offset);
|
||||
const linkEnd = document.positionAt(offset + link.length);
|
||||
|
||||
out.set(reference, {
|
||||
link: link,
|
||||
linkRange: new vscode.Range(linkStart, linkEnd)
|
||||
});
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
25
extensions/markdown/src/features/documentSymbolProvider.ts
Normal file
25
extensions/markdown/src/features/documentSymbolProvider.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
import { MarkdownEngine } from '../markdownEngine';
|
||||
import { TableOfContentsProvider } from '../tableOfContentsProvider';
|
||||
|
||||
export default class MDDocumentSymbolProvider implements vscode.DocumentSymbolProvider {
|
||||
|
||||
constructor(
|
||||
private engine: MarkdownEngine
|
||||
) { }
|
||||
|
||||
public async provideDocumentSymbols(document: vscode.TextDocument): Promise<vscode.SymbolInformation[]> {
|
||||
const toc = await new TableOfContentsProvider(this.engine, document).getToc();
|
||||
return toc.map(entry => {
|
||||
return new vscode.SymbolInformation('#'.repeat(entry.level) + ' ' + entry.text, vscode.SymbolKind.Namespace, '', entry.location);
|
||||
});
|
||||
}
|
||||
}
|
||||
318
extensions/markdown/src/features/previewContentProvider.ts
Normal file
318
extensions/markdown/src/features/previewContentProvider.ts
Normal file
@@ -0,0 +1,318 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
import { MarkdownEngine } from '../markdownEngine';
|
||||
|
||||
import * as nls from 'vscode-nls';
|
||||
import { Logger } from '../logger';
|
||||
import { ContentSecurityPolicyArbiter, MarkdownPreviewSecurityLevel } from '../security';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
const previewStrings = {
|
||||
cspAlertMessageText: localize('preview.securityMessage.text', 'Some content has been disabled in this document'),
|
||||
cspAlertMessageTitle: localize('preview.securityMessage.title', 'Potentially unsafe or insecure content has been disabled in the markdown preview. Change the Markdown preview security setting to allow insecure content or enable scripts'),
|
||||
cspAlertMessageLabel: localize('preview.securityMessage.label', 'Content Disabled Security Warning')
|
||||
};
|
||||
|
||||
export function isMarkdownFile(document: vscode.TextDocument) {
|
||||
return document.languageId === 'markdown'
|
||||
&& document.uri.scheme !== 'markdown'; // prevent processing of own documents
|
||||
}
|
||||
|
||||
export function getMarkdownUri(uri: vscode.Uri) {
|
||||
if (uri.scheme === 'markdown') {
|
||||
return uri;
|
||||
}
|
||||
|
||||
return uri.with({
|
||||
scheme: 'markdown',
|
||||
path: uri.path + '.rendered',
|
||||
query: uri.toString()
|
||||
});
|
||||
}
|
||||
|
||||
class MarkdownPreviewConfig {
|
||||
public static getConfigForResource(resource: vscode.Uri) {
|
||||
return new MarkdownPreviewConfig(resource);
|
||||
}
|
||||
|
||||
public readonly scrollBeyondLastLine: boolean;
|
||||
public readonly wordWrap: boolean;
|
||||
public readonly previewFrontMatter: string;
|
||||
public readonly lineBreaks: boolean;
|
||||
public readonly doubleClickToSwitchToEditor: boolean;
|
||||
public readonly scrollEditorWithPreview: boolean;
|
||||
public readonly scrollPreviewWithEditorSelection: boolean;
|
||||
public readonly markEditorSelection: boolean;
|
||||
|
||||
public readonly lineHeight: number;
|
||||
public readonly fontSize: number;
|
||||
public readonly fontFamily: string | undefined;
|
||||
public readonly styles: string[];
|
||||
|
||||
private constructor(resource: vscode.Uri) {
|
||||
const editorConfig = vscode.workspace.getConfiguration('editor', resource);
|
||||
const markdownConfig = vscode.workspace.getConfiguration('markdown', resource);
|
||||
const markdownEditorConfig = vscode.workspace.getConfiguration('[markdown]');
|
||||
|
||||
this.scrollBeyondLastLine = editorConfig.get<boolean>('scrollBeyondLastLine', false);
|
||||
|
||||
this.wordWrap = editorConfig.get<string>('wordWrap', 'off') !== 'off';
|
||||
if (markdownEditorConfig && markdownEditorConfig['editor.wordWrap']) {
|
||||
this.wordWrap = markdownEditorConfig['editor.wordWrap'] !== 'off';
|
||||
}
|
||||
|
||||
this.previewFrontMatter = markdownConfig.get<string>('previewFrontMatter', 'hide');
|
||||
this.scrollPreviewWithEditorSelection = !!markdownConfig.get<boolean>('preview.scrollPreviewWithEditorSelection', true);
|
||||
this.scrollEditorWithPreview = !!markdownConfig.get<boolean>('preview.scrollEditorWithPreview', true);
|
||||
this.lineBreaks = !!markdownConfig.get<boolean>('preview.breaks', false);
|
||||
this.doubleClickToSwitchToEditor = !!markdownConfig.get<boolean>('preview.doubleClickToSwitchToEditor', true);
|
||||
this.markEditorSelection = !!markdownConfig.get<boolean>('preview.markEditorSelection', true);
|
||||
|
||||
this.fontFamily = markdownConfig.get<string | undefined>('preview.fontFamily', undefined);
|
||||
this.fontSize = Math.max(8, +markdownConfig.get<number>('preview.fontSize', NaN));
|
||||
this.lineHeight = Math.max(0.6, +markdownConfig.get<number>('preview.lineHeight', NaN));
|
||||
|
||||
this.styles = markdownConfig.get<string[]>('styles', []);
|
||||
}
|
||||
|
||||
public isEqualTo(otherConfig: MarkdownPreviewConfig) {
|
||||
for (let key in this) {
|
||||
if (this.hasOwnProperty(key) && key !== 'styles') {
|
||||
if (this[key] !== otherConfig[key]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check styles
|
||||
if (this.styles.length !== otherConfig.styles.length) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < this.styles.length; ++i) {
|
||||
if (this.styles[i] !== otherConfig.styles[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
class PreviewConfigManager {
|
||||
private previewConfigurationsForWorkspaces = new Map<string, MarkdownPreviewConfig>();
|
||||
|
||||
public loadAndCacheConfiguration(
|
||||
resource: vscode.Uri
|
||||
) {
|
||||
const config = MarkdownPreviewConfig.getConfigForResource(resource);
|
||||
this.previewConfigurationsForWorkspaces.set(this.getKey(resource), config);
|
||||
return config;
|
||||
}
|
||||
|
||||
public shouldUpdateConfiguration(
|
||||
resource: vscode.Uri
|
||||
): boolean {
|
||||
const key = this.getKey(resource);
|
||||
const currentConfig = this.previewConfigurationsForWorkspaces.get(key);
|
||||
const newConfig = MarkdownPreviewConfig.getConfigForResource(resource);
|
||||
return (!currentConfig || !currentConfig.isEqualTo(newConfig));
|
||||
}
|
||||
|
||||
private getKey(
|
||||
resource: vscode.Uri
|
||||
): string {
|
||||
const folder = vscode.workspace.getWorkspaceFolder(resource);
|
||||
if (!folder) {
|
||||
return '';
|
||||
}
|
||||
return folder.uri.toString();
|
||||
}
|
||||
}
|
||||
|
||||
export class MDDocumentContentProvider implements vscode.TextDocumentContentProvider {
|
||||
private _onDidChange = new vscode.EventEmitter<vscode.Uri>();
|
||||
private _waiting: boolean = false;
|
||||
private previewConfigurations = new PreviewConfigManager();
|
||||
|
||||
private extraStyles: Array<vscode.Uri> = [];
|
||||
private extraScripts: Array<vscode.Uri> = [];
|
||||
|
||||
constructor(
|
||||
private engine: MarkdownEngine,
|
||||
private context: vscode.ExtensionContext,
|
||||
private cspArbiter: ContentSecurityPolicyArbiter,
|
||||
private logger: Logger
|
||||
) { }
|
||||
|
||||
public addScript(resource: vscode.Uri): void {
|
||||
this.extraScripts.push(resource);
|
||||
}
|
||||
|
||||
public addStyle(resource: vscode.Uri): void {
|
||||
this.extraStyles.push(resource);
|
||||
}
|
||||
|
||||
private getMediaPath(mediaFile: string): string {
|
||||
return vscode.Uri.file(this.context.asAbsolutePath(path.join('media', mediaFile))).toString();
|
||||
}
|
||||
|
||||
private fixHref(resource: vscode.Uri, href: string): string {
|
||||
if (!href) {
|
||||
return href;
|
||||
}
|
||||
|
||||
// Use href if it is already an URL
|
||||
const hrefUri = vscode.Uri.parse(href);
|
||||
if (['file', 'http', 'https'].indexOf(hrefUri.scheme) >= 0) {
|
||||
return hrefUri.toString();
|
||||
}
|
||||
|
||||
// Use href as file URI if it is absolute
|
||||
if (path.isAbsolute(href)) {
|
||||
return vscode.Uri.file(href).toString();
|
||||
}
|
||||
|
||||
// use a workspace relative path if there is a workspace
|
||||
let root = vscode.workspace.getWorkspaceFolder(resource);
|
||||
if (root) {
|
||||
return vscode.Uri.file(path.join(root.uri.fsPath, href)).toString();
|
||||
}
|
||||
|
||||
// otherwise look relative to the markdown file
|
||||
return vscode.Uri.file(path.join(path.dirname(resource.fsPath), href)).toString();
|
||||
}
|
||||
|
||||
private computeCustomStyleSheetIncludes(resource: vscode.Uri, config: MarkdownPreviewConfig): string {
|
||||
if (config.styles && Array.isArray(config.styles)) {
|
||||
return config.styles.map(style => {
|
||||
return `<link rel="stylesheet" class="code-user-style" data-source="${style.replace(/"/g, '"')}" href="${this.fixHref(resource, style)}" type="text/css" media="screen">`;
|
||||
}).join('\n');
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
private getSettingsOverrideStyles(nonce: string, config: MarkdownPreviewConfig): string {
|
||||
return `<style nonce="${nonce}">
|
||||
body {
|
||||
${config.fontFamily ? `font-family: ${config.fontFamily};` : ''}
|
||||
${isNaN(config.fontSize) ? '' : `font-size: ${config.fontSize}px;`}
|
||||
${isNaN(config.lineHeight) ? '' : `line-height: ${config.lineHeight};`}
|
||||
}
|
||||
</style>`;
|
||||
}
|
||||
|
||||
private getStyles(resource: vscode.Uri, nonce: string, config: MarkdownPreviewConfig): string {
|
||||
const baseStyles = [
|
||||
this.getMediaPath('markdown.css'),
|
||||
this.getMediaPath('tomorrow.css')
|
||||
].concat(this.extraStyles.map(resource => resource.toString()));
|
||||
|
||||
return `${baseStyles.map(href => `<link rel="stylesheet" type="text/css" href="${href}">`).join('\n')}
|
||||
${this.getSettingsOverrideStyles(nonce, config)}
|
||||
${this.computeCustomStyleSheetIncludes(resource, config)}`;
|
||||
}
|
||||
|
||||
private getScripts(nonce: string): string {
|
||||
const scripts = [this.getMediaPath('main.js')].concat(this.extraScripts.map(resource => resource.toString()));
|
||||
return scripts
|
||||
.map(source => `<script async src="${source}" nonce="${nonce}" charset="UTF-8"></script>`)
|
||||
.join('\n');
|
||||
}
|
||||
|
||||
public async provideTextDocumentContent(uri: vscode.Uri): Promise<string> {
|
||||
const sourceUri = vscode.Uri.parse(uri.query);
|
||||
|
||||
let initialLine: number | undefined = undefined;
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
if (editor && editor.document.uri.toString() === sourceUri.toString()) {
|
||||
initialLine = editor.selection.active.line;
|
||||
}
|
||||
|
||||
const document = await vscode.workspace.openTextDocument(sourceUri);
|
||||
const config = this.previewConfigurations.loadAndCacheConfiguration(sourceUri);
|
||||
|
||||
const initialData = {
|
||||
previewUri: uri.toString(),
|
||||
source: sourceUri.toString(),
|
||||
line: initialLine,
|
||||
scrollPreviewWithEditorSelection: config.scrollPreviewWithEditorSelection,
|
||||
scrollEditorWithPreview: config.scrollEditorWithPreview,
|
||||
doubleClickToSwitchToEditor: config.doubleClickToSwitchToEditor,
|
||||
disableSecurityWarnings: this.cspArbiter.shouldDisableSecurityWarnings()
|
||||
};
|
||||
|
||||
this.logger.log('provideTextDocumentContent', initialData);
|
||||
|
||||
// Content Security Policy
|
||||
const nonce = new Date().getTime() + '' + new Date().getMilliseconds();
|
||||
const csp = this.getCspForResource(sourceUri, nonce);
|
||||
|
||||
const body = await this.engine.render(sourceUri, config.previewFrontMatter === 'hide', document.getText());
|
||||
return `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
|
||||
${csp}
|
||||
<meta id="vscode-markdown-preview-data" data-settings="${JSON.stringify(initialData).replace(/"/g, '"')}" data-strings="${JSON.stringify(previewStrings).replace(/"/g, '"')}">
|
||||
<script src="${this.getMediaPath('csp.js')}" nonce="${nonce}"></script>
|
||||
<script src="${this.getMediaPath('loading.js')}" nonce="${nonce}"></script>
|
||||
${this.getStyles(sourceUri, nonce, config)}
|
||||
<base href="${document.uri.toString(true)}">
|
||||
</head>
|
||||
<body class="vscode-body ${config.scrollBeyondLastLine ? 'scrollBeyondLastLine' : ''} ${config.wordWrap ? 'wordWrap' : ''} ${config.markEditorSelection ? 'showEditorSelection' : ''}">
|
||||
${body}
|
||||
<div class="code-line" data-line="${document.lineCount}"></div>
|
||||
${this.getScripts(nonce)}
|
||||
</body>
|
||||
</html>`;
|
||||
}
|
||||
|
||||
public updateConfiguration() {
|
||||
// update all generated md documents
|
||||
for (const document of vscode.workspace.textDocuments) {
|
||||
if (document.uri.scheme === 'markdown') {
|
||||
const sourceUri = vscode.Uri.parse(document.uri.query);
|
||||
if (this.previewConfigurations.shouldUpdateConfiguration(sourceUri)) {
|
||||
this.update(document.uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get onDidChange(): vscode.Event<vscode.Uri> {
|
||||
return this._onDidChange.event;
|
||||
}
|
||||
|
||||
public update(uri: vscode.Uri) {
|
||||
if (!this._waiting) {
|
||||
this._waiting = true;
|
||||
setTimeout(() => {
|
||||
this._waiting = false;
|
||||
this._onDidChange.fire(uri);
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
|
||||
private getCspForResource(resource: vscode.Uri, nonce: string): string {
|
||||
switch (this.cspArbiter.getSecurityLevelForResource(resource)) {
|
||||
case MarkdownPreviewSecurityLevel.AllowInsecureContent:
|
||||
return `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' http: https: data:; media-src 'self' http: https: data:; script-src 'nonce-${nonce}'; style-src 'self' 'unsafe-inline' http: https: data:; font-src 'self' http: https: data:;">`;
|
||||
|
||||
case MarkdownPreviewSecurityLevel.AllowScriptsAndAllContent:
|
||||
return '';
|
||||
|
||||
case MarkdownPreviewSecurityLevel.Strict:
|
||||
default:
|
||||
return `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' https: data:; media-src 'self' https: data:; script-src 'nonce-${nonce}'; style-src 'self' 'unsafe-inline' https: data:; font-src 'self' https: data:;">`;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,10 @@ export class MarkdownEngine {
|
||||
this.md = (await import('markdown-it'))({
|
||||
html: true,
|
||||
highlight: (str: string, lang: string) => {
|
||||
// Workaround for highlight not supporting tsx: https://github.com/isagalaev/highlight.js/issues/1155
|
||||
if (lang && ['tsx', 'typescriptreact'].indexOf(lang.toLocaleLowerCase()) >= 0) {
|
||||
lang = 'jsx';
|
||||
}
|
||||
if (lang && hljs.getLanguage(lang)) {
|
||||
try {
|
||||
return `<pre class="hljs"><code><div>${hljs.highlight(lang, str, true).value}</div></code></pre>`;
|
||||
|
||||
86
extensions/markdown/src/markdownExtensions.ts
Normal file
86
extensions/markdown/src/markdownExtensions.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
|
||||
import { MDDocumentContentProvider } from './features/previewContentProvider';
|
||||
import { MarkdownEngine } from './markdownEngine';
|
||||
|
||||
const resolveExtensionResources = (extension: vscode.Extension<any>, stylePath: string): vscode.Uri => {
|
||||
const resource = vscode.Uri.parse(stylePath);
|
||||
if (resource.scheme) {
|
||||
return resource;
|
||||
}
|
||||
return vscode.Uri.file(path.join(extension.extensionPath, stylePath));
|
||||
};
|
||||
|
||||
|
||||
export function loadMarkdownExtensions(
|
||||
contentProvider: MDDocumentContentProvider,
|
||||
engine: MarkdownEngine
|
||||
) {
|
||||
for (const extension of vscode.extensions.all) {
|
||||
const contributes = extension.packageJSON && extension.packageJSON.contributes;
|
||||
if (!contributes) {
|
||||
continue;
|
||||
}
|
||||
|
||||
tryLoadPreviewStyles(contributes, contentProvider, extension);
|
||||
tryLoadPreviewScripts(contributes, contentProvider, extension);
|
||||
tryLoadMarkdownItPlugins(contributes, extension, engine);
|
||||
}
|
||||
}
|
||||
|
||||
function tryLoadMarkdownItPlugins(
|
||||
contributes: any,
|
||||
extension: vscode.Extension<any>,
|
||||
engine: MarkdownEngine
|
||||
) {
|
||||
if (contributes['markdown.markdownItPlugins']) {
|
||||
extension.activate().then(() => {
|
||||
if (extension.exports && extension.exports.extendMarkdownIt) {
|
||||
engine.addPlugin((md: any) => extension.exports.extendMarkdownIt(md));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function tryLoadPreviewScripts(
|
||||
contributes: any,
|
||||
contentProvider: MDDocumentContentProvider,
|
||||
extension: vscode.Extension<any>
|
||||
) {
|
||||
const scripts = contributes['markdown.previewScripts'];
|
||||
if (scripts && Array.isArray(scripts)) {
|
||||
for (const script of scripts) {
|
||||
try {
|
||||
contentProvider.addScript(resolveExtensionResources(extension, script));
|
||||
}
|
||||
catch (e) {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function tryLoadPreviewStyles(
|
||||
contributes: any,
|
||||
contentProvider: MDDocumentContentProvider,
|
||||
extension: vscode.Extension<any>
|
||||
) {
|
||||
const styles = contributes['markdown.previewStyles'];
|
||||
if (styles && Array.isArray(styles)) {
|
||||
for (const style of styles) {
|
||||
try {
|
||||
contentProvider.addStyle(resolveExtensionResources(extension, style));
|
||||
}
|
||||
catch (e) {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
import { getMarkdownUri, MDDocumentContentProvider } from './previewContentProvider';
|
||||
import { getMarkdownUri, MDDocumentContentProvider } from './features/previewContentProvider';
|
||||
|
||||
import * as nls from 'vscode-nls';
|
||||
|
||||
@@ -24,14 +24,20 @@ export interface ContentSecurityPolicyArbiter {
|
||||
setSecurityLevelForResource(resource: vscode.Uri, level: MarkdownPreviewSecurityLevel): Thenable<void>;
|
||||
|
||||
shouldAllowSvgsForResource(resource: vscode.Uri): void;
|
||||
|
||||
shouldDisableSecurityWarnings(): boolean;
|
||||
|
||||
setShouldDisableSecurityWarning(shouldShow: boolean): Thenable<void>;
|
||||
}
|
||||
|
||||
export class ExtensionContentSecurityPolicyArbiter implements ContentSecurityPolicyArbiter {
|
||||
private readonly old_trusted_workspace_key = 'trusted_preview_workspace:';
|
||||
private readonly security_level_key = 'preview_security_level:';
|
||||
private readonly should_disable_security_warning_key = 'preview_should_show_security_warning:';
|
||||
|
||||
constructor(
|
||||
private globalState: vscode.Memento
|
||||
private globalState: vscode.Memento,
|
||||
private workspaceState: vscode.Memento
|
||||
) { }
|
||||
|
||||
public getSecurityLevelForResource(resource: vscode.Uri): MarkdownPreviewSecurityLevel {
|
||||
@@ -57,6 +63,14 @@ export class ExtensionContentSecurityPolicyArbiter implements ContentSecurityPol
|
||||
return securityLevel === MarkdownPreviewSecurityLevel.AllowInsecureContent || securityLevel === MarkdownPreviewSecurityLevel.AllowScriptsAndAllContent;
|
||||
}
|
||||
|
||||
public shouldDisableSecurityWarnings(): boolean {
|
||||
return this.workspaceState.get<boolean>(this.should_disable_security_warning_key, false);
|
||||
}
|
||||
|
||||
public setShouldDisableSecurityWarning(disabled: boolean): Thenable<void> {
|
||||
return this.workspaceState.update(this.should_disable_security_warning_key, disabled);
|
||||
}
|
||||
|
||||
private getRoot(resource: vscode.Uri): vscode.Uri {
|
||||
if (vscode.workspace.workspaceFolders) {
|
||||
const folderForResource = vscode.workspace.getWorkspaceFolder(resource);
|
||||
@@ -82,7 +96,7 @@ export class PreviewSecuritySelector {
|
||||
|
||||
public async showSecutitySelectorForResource(resource: vscode.Uri): Promise<void> {
|
||||
interface PreviewSecurityPickItem extends vscode.QuickPickItem {
|
||||
type: 'moreinfo' | MarkdownPreviewSecurityLevel;
|
||||
type: 'moreinfo' | 'toggle' | MarkdownPreviewSecurityLevel;
|
||||
}
|
||||
|
||||
function markActiveWhen(when: boolean): string {
|
||||
@@ -108,7 +122,13 @@ export class PreviewSecuritySelector {
|
||||
type: 'moreinfo',
|
||||
label: localize('moreInfo.title', 'More Information'),
|
||||
description: ''
|
||||
}
|
||||
}, {
|
||||
type: 'toggle',
|
||||
label: this.cspArbiter.shouldDisableSecurityWarnings()
|
||||
? localize('enableSecurityWarning.title', "Enable preview security warnings in this workspace")
|
||||
: localize('disableSecurityWarning.title', "Disable preview security warning in this workspace"),
|
||||
description: localize('toggleSecurityWarning.description', 'Does not effect the content security level')
|
||||
},
|
||||
], {
|
||||
placeHolder: localize(
|
||||
'preview.showPreviewSecuritySelector.title',
|
||||
@@ -124,9 +144,14 @@ export class PreviewSecuritySelector {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.cspArbiter.setSecurityLevelForResource(resource, selection.type);
|
||||
|
||||
const sourceUri = getMarkdownUri(resource);
|
||||
if (selection.type === 'toggle') {
|
||||
this.cspArbiter.setShouldDisableSecurityWarning(!this.cspArbiter.shouldDisableSecurityWarnings());
|
||||
this.contentProvider.update(sourceUri);
|
||||
return;
|
||||
}
|
||||
|
||||
await this.cspArbiter.setSecurityLevelForResource(resource, selection.type);
|
||||
|
||||
await vscode.commands.executeCommand('_workbench.htmlPreview.updateOptions',
|
||||
sourceUri,
|
||||
|
||||
60
extensions/markdown/src/telemetryReporter.ts
Normal file
60
extensions/markdown/src/telemetryReporter.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as vscode from 'vscode';
|
||||
import { default as VSCodeTelemetryReporter } from 'vscode-extension-telemetry';
|
||||
|
||||
interface IPackageInfo {
|
||||
name: string;
|
||||
version: string;
|
||||
aiKey: string;
|
||||
}
|
||||
|
||||
export interface TelemetryReporter {
|
||||
dispose(): void;
|
||||
sendTelemetryEvent(eventName: string, properties?: {
|
||||
[key: string]: string;
|
||||
}): void;
|
||||
}
|
||||
|
||||
const nullReporter = new class NullTelemetryReporter implements TelemetryReporter {
|
||||
sendTelemetryEvent() { /** noop */ }
|
||||
dispose() { /** noop */ }
|
||||
};
|
||||
|
||||
class ExtensionReporter implements TelemetryReporter {
|
||||
private readonly _reporter: VSCodeTelemetryReporter;
|
||||
|
||||
constructor(
|
||||
packageInfo: IPackageInfo
|
||||
) {
|
||||
this._reporter = new VSCodeTelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey);
|
||||
}
|
||||
sendTelemetryEvent(eventName: string, properties?: {
|
||||
[key: string]: string;
|
||||
}) {
|
||||
this._reporter.sendTelemetryEvent(eventName, properties);
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this._reporter.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
export function loadDefaultTelemetryReporter(): TelemetryReporter {
|
||||
const packageInfo = getPackageInfo();
|
||||
return packageInfo ? new ExtensionReporter(packageInfo) : nullReporter;
|
||||
}
|
||||
|
||||
function getPackageInfo(): IPackageInfo | null {
|
||||
const extention = vscode.extensions.getExtension('Microsoft.vscode-markdown');
|
||||
if (extention && extention.packageJSON) {
|
||||
return {
|
||||
name: extention.packageJSON.name,
|
||||
version: extention.packageJSON.version,
|
||||
aiKey: extention.packageJSON.aiKey
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -478,7 +478,7 @@
|
||||
<key>list_paragraph</key>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>(^|\G)(?=\S)(?![*+-]\s|[0-9]+\.\s)</string>
|
||||
<string>(^|\G)(?=\S)(?![*+->]\s|[0-9]+\.\s)</string>
|
||||
<key>name</key>
|
||||
<string>meta.paragraph.markdown</string>
|
||||
<key>patterns</key>
|
||||
@@ -497,7 +497,7 @@
|
||||
</dict>
|
||||
</array>
|
||||
<key>while</key>
|
||||
<string>(^|\G)(?!\s*$|#|[ ]{0,3}([-*_][ ]{2,}){3,}[ \t]*$\n?|>|[ ]{0,3}[*+-]|[ ]{0,3}[0-9]+\.)</string>
|
||||
<string>(^|\G)(?!\s*$|#|[ ]{0,3}([-*_>][ ]{2,}){3,}[ \t]*$\n?|[ ]{0,3}[*+->]|[ ]{0,3}[0-9]+\.)</string>
|
||||
</dict>
|
||||
<key>lists</key>
|
||||
<dict>
|
||||
@@ -3191,11 +3191,16 @@
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.markdown</string>
|
||||
</dict>
|
||||
<key>10</key>
|
||||
<key>9</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>string.other.link.description.title.markdown</string>
|
||||
</dict>
|
||||
<key>10</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.markdown</string>
|
||||
</dict>
|
||||
<key>11</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
@@ -3204,12 +3209,12 @@
|
||||
<key>12</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.markdown</string>
|
||||
<string>string.other.link.description.title.markdown</string>
|
||||
</dict>
|
||||
<key>13</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>string.other.link.description.title.markdown</string>
|
||||
<string>punctuation.definition.string.markdown</string>
|
||||
</dict>
|
||||
<key>14</key>
|
||||
<dict>
|
||||
@@ -3217,11 +3222,6 @@
|
||||
<string>punctuation.definition.string.markdown</string>
|
||||
</dict>
|
||||
<key>15</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.markdown</string>
|
||||
</dict>
|
||||
<key>16</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.metadata.markdown</string>
|
||||
@@ -3239,24 +3239,19 @@
|
||||
<key>5</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>invalid.illegal.whitespace.markdown</string>
|
||||
<string>punctuation.definition.metadata.markdown</string>
|
||||
</dict>
|
||||
<key>6</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.metadata.markdown</string>
|
||||
<string>punctuation.definition.link.markdown</string>
|
||||
</dict>
|
||||
<key>7</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.link.markdown</string>
|
||||
</dict>
|
||||
<key>8</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>markup.underline.link.image.markdown</string>
|
||||
</dict>
|
||||
<key>9</key>
|
||||
<key>8</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.link.markdown</string>
|
||||
@@ -3266,7 +3261,6 @@
|
||||
<string>(?x:
|
||||
(\!\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])
|
||||
# Match the link text.
|
||||
([ ])? # Space not allowed
|
||||
(\() # Opening paren for url
|
||||
(<?)(\S+?)(>?) # The url
|
||||
[ \t]* # Optional whitespace
|
||||
@@ -3503,37 +3497,37 @@
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.markdown</string>
|
||||
</dict>
|
||||
<key>10</key>
|
||||
<key>9</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>string.other.link.description.title.markdown</string>
|
||||
</dict>
|
||||
<key>10</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.markdown</string>
|
||||
</dict>
|
||||
<key>11</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.markdown</string>
|
||||
<string>punctuation.definition.string.end.markdown</string>
|
||||
</dict>
|
||||
<key>12</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.end.markdown</string>
|
||||
<string>string.other.link.description.title.markdown</string>
|
||||
</dict>
|
||||
<key>13</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>string.other.link.description.title.markdown</string>
|
||||
<string>punctuation.definition.string.begin.markdown</string>
|
||||
</dict>
|
||||
<key>14</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.markdown</string>
|
||||
</dict>
|
||||
<key>15</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.end.markdown</string>
|
||||
</dict>
|
||||
<key>16</key>
|
||||
<key>15</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.metadata.markdown</string>
|
||||
@@ -3551,24 +3545,19 @@
|
||||
<key>5</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>invalid.illegal.whitespace.markdown</string>
|
||||
<string>punctuation.definition.metadata.markdown</string>
|
||||
</dict>
|
||||
<key>6</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.metadata.markdown</string>
|
||||
<string>punctuation.definition.link.markdown</string>
|
||||
</dict>
|
||||
<key>7</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.link.markdown</string>
|
||||
</dict>
|
||||
<key>8</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>markup.underline.link.markdown</string>
|
||||
</dict>
|
||||
<key>9</key>
|
||||
<key>8</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.link.markdown</string>
|
||||
@@ -3578,7 +3567,6 @@
|
||||
<string>(?x:
|
||||
(\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])
|
||||
# Match the link text.
|
||||
([ ])? # Space not allowed
|
||||
(\() # Opening paren for url
|
||||
(<?)(.*?)(>?) # The url
|
||||
[ \t]* # Optional whitespace
|
||||
|
||||
@@ -303,7 +303,7 @@
|
||||
<key>list_paragraph</key>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>(^|\G)(?=\S)(?![*+-]\s|[0-9]+\.\s)</string>
|
||||
<string>(^|\G)(?=\S)(?![*+->]\s|[0-9]+\.\s)</string>
|
||||
<key>name</key>
|
||||
<string>meta.paragraph.markdown</string>
|
||||
<key>patterns</key>
|
||||
@@ -322,7 +322,7 @@
|
||||
</dict>
|
||||
</array>
|
||||
<key>while</key>
|
||||
<string>(^|\G)(?!\s*$|#|[ ]{0,3}([-*_][ ]{2,}){3,}[ \t]*$\n?|>|[ ]{0,3}[*+-]|[ ]{0,3}[0-9]+\.)</string>
|
||||
<string>(^|\G)(?!\s*$|#|[ ]{0,3}([-*_>][ ]{2,}){3,}[ \t]*$\n?|[ ]{0,3}[*+->]|[ ]{0,3}[0-9]+\.)</string>
|
||||
</dict>
|
||||
<key>lists</key>
|
||||
<dict>
|
||||
@@ -681,11 +681,16 @@
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.markdown</string>
|
||||
</dict>
|
||||
<key>10</key>
|
||||
<key>9</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>string.other.link.description.title.markdown</string>
|
||||
</dict>
|
||||
<key>10</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.markdown</string>
|
||||
</dict>
|
||||
<key>11</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
@@ -694,12 +699,12 @@
|
||||
<key>12</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.markdown</string>
|
||||
<string>string.other.link.description.title.markdown</string>
|
||||
</dict>
|
||||
<key>13</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>string.other.link.description.title.markdown</string>
|
||||
<string>punctuation.definition.string.markdown</string>
|
||||
</dict>
|
||||
<key>14</key>
|
||||
<dict>
|
||||
@@ -707,11 +712,6 @@
|
||||
<string>punctuation.definition.string.markdown</string>
|
||||
</dict>
|
||||
<key>15</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.markdown</string>
|
||||
</dict>
|
||||
<key>16</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.metadata.markdown</string>
|
||||
@@ -729,24 +729,19 @@
|
||||
<key>5</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>invalid.illegal.whitespace.markdown</string>
|
||||
<string>punctuation.definition.metadata.markdown</string>
|
||||
</dict>
|
||||
<key>6</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.metadata.markdown</string>
|
||||
<string>punctuation.definition.link.markdown</string>
|
||||
</dict>
|
||||
<key>7</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.link.markdown</string>
|
||||
</dict>
|
||||
<key>8</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>markup.underline.link.image.markdown</string>
|
||||
</dict>
|
||||
<key>9</key>
|
||||
<key>8</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.link.markdown</string>
|
||||
@@ -756,7 +751,6 @@
|
||||
<string>(?x:
|
||||
(\!\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])
|
||||
# Match the link text.
|
||||
([ ])? # Space not allowed
|
||||
(\() # Opening paren for url
|
||||
(<?)(\S+?)(>?) # The url
|
||||
[ \t]* # Optional whitespace
|
||||
@@ -993,37 +987,37 @@
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.markdown</string>
|
||||
</dict>
|
||||
<key>10</key>
|
||||
<key>9</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>string.other.link.description.title.markdown</string>
|
||||
</dict>
|
||||
<key>10</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.markdown</string>
|
||||
</dict>
|
||||
<key>11</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.markdown</string>
|
||||
<string>punctuation.definition.string.end.markdown</string>
|
||||
</dict>
|
||||
<key>12</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.end.markdown</string>
|
||||
<string>string.other.link.description.title.markdown</string>
|
||||
</dict>
|
||||
<key>13</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>string.other.link.description.title.markdown</string>
|
||||
<string>punctuation.definition.string.begin.markdown</string>
|
||||
</dict>
|
||||
<key>14</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.markdown</string>
|
||||
</dict>
|
||||
<key>15</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.end.markdown</string>
|
||||
</dict>
|
||||
<key>16</key>
|
||||
<key>15</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.metadata.markdown</string>
|
||||
@@ -1041,24 +1035,19 @@
|
||||
<key>5</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>invalid.illegal.whitespace.markdown</string>
|
||||
<string>punctuation.definition.metadata.markdown</string>
|
||||
</dict>
|
||||
<key>6</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.metadata.markdown</string>
|
||||
<string>punctuation.definition.link.markdown</string>
|
||||
</dict>
|
||||
<key>7</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.link.markdown</string>
|
||||
</dict>
|
||||
<key>8</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>markup.underline.link.markdown</string>
|
||||
</dict>
|
||||
<key>9</key>
|
||||
<key>8</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.link.markdown</string>
|
||||
@@ -1068,7 +1057,6 @@
|
||||
<string>(?x:
|
||||
(\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])
|
||||
# Match the link text.
|
||||
([ ])? # Space not allowed
|
||||
(\() # Opening paren for url
|
||||
(<?)(.*?)(>?) # The url
|
||||
[ \t]* # Optional whitespace
|
||||
|
||||
@@ -47,6 +47,7 @@ in_words_are ignored.
|
||||
>> And, they can be nested
|
||||
|
||||
1. A numbered list
|
||||
> Block quotes in list
|
||||
2. Which is numbered
|
||||
3. With periods and a space
|
||||
|
||||
|
||||
@@ -1792,6 +1792,50 @@
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " ",
|
||||
"t": "text.html.markdown markup.list.numbered.markdown",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": ">",
|
||||
"t": "text.html.markdown markup.list.numbered.markdown markup.quote.markdown beginning.punctuation.definition.quote.markdown",
|
||||
"r": {
|
||||
"dark_plus": "beginning.punctuation.definition.quote.markdown: #608B4E",
|
||||
"light_plus": "beginning.punctuation.definition.quote.markdown: #0451A5",
|
||||
"dark_vs": "beginning.punctuation.definition.quote.markdown: #608B4E",
|
||||
"light_vs": "beginning.punctuation.definition.quote.markdown: #0451A5",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " ",
|
||||
"t": "text.html.markdown markup.list.numbered.markdown markup.quote.markdown",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "Block quotes in list",
|
||||
"t": "text.html.markdown markup.list.numbered.markdown markup.quote.markdown meta.paragraph.markdown",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "2.",
|
||||
"t": "text.html.markdown markup.list.numbered.markdown beginning.punctuation.definition.list.markdown",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"target": "es2017",
|
||||
"lib": [
|
||||
"es6",
|
||||
"es2015.promise",
|
||||
@@ -9,11 +9,11 @@
|
||||
],
|
||||
"outDir": "./out",
|
||||
"sourceMap": true,
|
||||
"strictNullChecks": true,
|
||||
"noImplicitAny": true,
|
||||
"noImplicitReturns": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true
|
||||
"noUnusedParameters": true,
|
||||
"strict": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
|
||||
171
extensions/markdown/yarn.lock
Normal file
171
extensions/markdown/yarn.lock
Normal file
@@ -0,0 +1,171 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@types/highlight.js@9.1.10":
|
||||
version "9.1.10"
|
||||
resolved "https://registry.yarnpkg.com/@types/highlight.js/-/highlight.js-9.1.10.tgz#b621f809cd9573b80992b90cffc5788208e3069c"
|
||||
|
||||
"@types/markdown-it@0.0.2":
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-0.0.2.tgz#5d9ad19e6e6508cdd2f2596df86fd0aade598660"
|
||||
|
||||
"@types/node@7.0.43":
|
||||
version "7.0.43"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.43.tgz#a187e08495a075f200ca946079c914e1a5fe962c"
|
||||
|
||||
applicationinsights@0.18.0:
|
||||
version "0.18.0"
|
||||
resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-0.18.0.tgz#162ebb48a383408bc4de44db32b417307f45bbc1"
|
||||
|
||||
argparse@^1.0.7:
|
||||
version "1.0.9"
|
||||
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86"
|
||||
dependencies:
|
||||
sprintf-js "~1.0.2"
|
||||
|
||||
binaryextensions@~1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/binaryextensions/-/binaryextensions-1.0.1.tgz#1e637488b35b58bda5f4774bf96a5212a8c90755"
|
||||
|
||||
core-util-is@~1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||
|
||||
entities@~1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0"
|
||||
|
||||
escape-string-regexp@^1.0.3:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||
|
||||
gulp-rename@^1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/gulp-rename/-/gulp-rename-1.2.2.tgz#3ad4428763f05e2764dec1c67d868db275687817"
|
||||
|
||||
gulp-replace@^0.5.4:
|
||||
version "0.5.4"
|
||||
resolved "https://registry.yarnpkg.com/gulp-replace/-/gulp-replace-0.5.4.tgz#69a67914bbd13c562bff14f504a403796aa0daa9"
|
||||
dependencies:
|
||||
istextorbinary "1.0.2"
|
||||
readable-stream "^2.0.1"
|
||||
replacestream "^4.0.0"
|
||||
|
||||
highlight.js@9.5.0:
|
||||
version "9.5.0"
|
||||
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.5.0.tgz#46ae51b9db00f70052bcdf196cd404757b6582ae"
|
||||
|
||||
inherits@~2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
|
||||
|
||||
isarray@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
|
||||
|
||||
istextorbinary@1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/istextorbinary/-/istextorbinary-1.0.2.tgz#ace19354d1a9a0173efeb1084ce0f87b0ad7decf"
|
||||
dependencies:
|
||||
binaryextensions "~1.0.0"
|
||||
textextensions "~1.0.0"
|
||||
|
||||
linkify-it@^2.0.0:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.0.3.tgz#d94a4648f9b1c179d64fa97291268bdb6ce9434f"
|
||||
dependencies:
|
||||
uc.micro "^1.0.1"
|
||||
|
||||
markdown-it-named-headers@0.0.4:
|
||||
version "0.0.4"
|
||||
resolved "https://registry.yarnpkg.com/markdown-it-named-headers/-/markdown-it-named-headers-0.0.4.tgz#82efc28324240a6b1e77b9aae501771d5f351c1f"
|
||||
dependencies:
|
||||
string "^3.0.1"
|
||||
|
||||
markdown-it@^8.4.0:
|
||||
version "8.4.0"
|
||||
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.0.tgz#e2400881bf171f7018ed1bd9da441dac8af6306d"
|
||||
dependencies:
|
||||
argparse "^1.0.7"
|
||||
entities "~1.1.1"
|
||||
linkify-it "^2.0.0"
|
||||
mdurl "^1.0.1"
|
||||
uc.micro "^1.0.3"
|
||||
|
||||
mdurl@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
|
||||
|
||||
object-assign@^4.0.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
|
||||
process-nextick-args@~1.0.6:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
|
||||
|
||||
readable-stream@^2.0.1, readable-stream@^2.0.2:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c"
|
||||
dependencies:
|
||||
core-util-is "~1.0.0"
|
||||
inherits "~2.0.3"
|
||||
isarray "~1.0.0"
|
||||
process-nextick-args "~1.0.6"
|
||||
safe-buffer "~5.1.1"
|
||||
string_decoder "~1.0.3"
|
||||
util-deprecate "~1.0.1"
|
||||
|
||||
replacestream@^4.0.0:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/replacestream/-/replacestream-4.0.2.tgz#0c4140707e4f0323f50de044851708cf58bc37bd"
|
||||
dependencies:
|
||||
escape-string-regexp "^1.0.3"
|
||||
object-assign "^4.0.1"
|
||||
readable-stream "^2.0.2"
|
||||
|
||||
safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
|
||||
|
||||
sprintf-js@~1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
||||
|
||||
string@^3.0.1:
|
||||
version "3.3.1"
|
||||
resolved "https://registry.yarnpkg.com/string/-/string-3.3.1.tgz#8d2757ec1c0e6c526796fbb6b14036a4098398b7"
|
||||
|
||||
string_decoder@~1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab"
|
||||
dependencies:
|
||||
safe-buffer "~5.1.0"
|
||||
|
||||
textextensions@~1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/textextensions/-/textextensions-1.0.2.tgz#65486393ee1f2bb039a60cbba05b0b68bd9501d2"
|
||||
|
||||
uc.micro@^1.0.1, uc.micro@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.3.tgz#7ed50d5e0f9a9fb0a573379259f2a77458d50192"
|
||||
|
||||
util-deprecate@~1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
|
||||
vscode-extension-telemetry@0.0.8:
|
||||
version "0.0.8"
|
||||
resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.8.tgz#2261bff986b6690a6f1f746a45ac5bd1f85d29e0"
|
||||
dependencies:
|
||||
applicationinsights "0.18.0"
|
||||
winreg "1.2.3"
|
||||
|
||||
vscode-nls@2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-2.0.2.tgz#808522380844b8ad153499af5c3b03921aea02da"
|
||||
|
||||
winreg@1.2.3:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/winreg/-/winreg-1.2.3.tgz#93ad116b2696da87d58f7265a8fcea5254a965d5"
|
||||
Reference in New Issue
Block a user