mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Merge from master
This commit is contained in:
@@ -1,3 +1,10 @@
|
||||
test/**
|
||||
src/**
|
||||
tsconfig.json
|
||||
tsconfig.json
|
||||
out/test/**
|
||||
out/**
|
||||
extension.webpack.config.js
|
||||
cgmanifest.json
|
||||
yarn.lock
|
||||
preview-src/**
|
||||
webpack.config.js
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
// ATTENTION - THIS DIRECTORY CONTAINS THIRD PARTY OPEN SOURCE MATERIALS:
|
||||
[
|
||||
{
|
||||
"name": "chriskempson/tomorrow-theme",
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"repositoryURL": "https://github.com/chriskempson/tomorrow-theme",
|
||||
"licenseDetail": [
|
||||
"Copyright (C) 2013 Chris Kempson",
|
||||
"",
|
||||
"Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,", "and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:",
|
||||
"",
|
||||
"The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.",
|
||||
"",
|
||||
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER", "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "textmate/markdown.tmbundle",
|
||||
"version": "0.0.0",
|
||||
"license": "TextMate Bundle License",
|
||||
"repositoryURL": "https://github.com/textmate/markdown.tmbundle",
|
||||
"licenseDetail": [
|
||||
"Copyright (c) markdown.tmbundle authors",
|
||||
"",
|
||||
"If not otherwise specified (see below), files in this repository fall under the following license:",
|
||||
"",
|
||||
"Permission to copy, use, modify, sell and distribute this",
|
||||
"software is granted. This software is provided \"as is\" without",
|
||||
"express or implied warranty, and with no claim as to its",
|
||||
"suitability for any purpose.",
|
||||
"",
|
||||
"An exception is made for files in readable text which contain their own license information,",
|
||||
"or files where an accompanying file exists (in the same directory) with a \"-license\" suffix added",
|
||||
"to the base-name name of the original file, and an extension of txt, html, or similar. For example",
|
||||
"\"tidy\" is accompanied by \"tidy-license.txt\"."
|
||||
]
|
||||
}]
|
||||
55
extensions/markdown-language-features/cgmanifest.json
Normal file
55
extensions/markdown-language-features/cgmanifest.json
Normal file
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"registrations": [
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"name": "chriskempson/tomorrow-theme",
|
||||
"repositoryUrl": "https://github.com/chriskempson/tomorrow-theme",
|
||||
"commitHash": "0e0d35ac303f99b8aa182091ebeaee81cf2183a0"
|
||||
}
|
||||
},
|
||||
"licenseDetail": [
|
||||
"Copyright (C) 2013 Chris Kempson",
|
||||
"",
|
||||
"Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,",
|
||||
"and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:",
|
||||
"",
|
||||
"The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.",
|
||||
"",
|
||||
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER",
|
||||
"LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
|
||||
],
|
||||
"license": "MIT",
|
||||
"version": "0.0.0"
|
||||
},
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"name": "textmate/markdown.tmbundle",
|
||||
"repositoryUrl": "https://github.com/textmate/markdown.tmbundle",
|
||||
"commitHash": "11cf764606cb2cde54badb5d0e5a0758a8871c4b"
|
||||
}
|
||||
},
|
||||
"licenseDetail": [
|
||||
"Copyright (c) markdown.tmbundle authors",
|
||||
"",
|
||||
"If not otherwise specified (see below), files in this repository fall under the following license:",
|
||||
"",
|
||||
"Permission to copy, use, modify, sell and distribute this",
|
||||
"software is granted. This software is provided \"as is\" without",
|
||||
"express or implied warranty, and with no claim as to its",
|
||||
"suitability for any purpose.",
|
||||
"",
|
||||
"An exception is made for files in readable text which contain their own license information,",
|
||||
"or files where an accompanying file exists (in the same directory) with a \"-license\" suffix added",
|
||||
"to the base-name name of the original file, and an extension of txt, html, or similar. For example",
|
||||
"\"tidy\" is accompanied by \"tidy-license.txt\"."
|
||||
],
|
||||
"license": "TextMate Bundle License",
|
||||
"version": "0.0.0"
|
||||
}
|
||||
],
|
||||
"version": 1
|
||||
}
|
||||
@@ -2,4 +2,19 @@
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
declare module 'markdown-it-named-headers' { }
|
||||
|
||||
//@ts-check
|
||||
|
||||
'use strict';
|
||||
|
||||
const withDefaults = require('../shared.webpack.config');
|
||||
|
||||
module.exports = withDefaults({
|
||||
context: __dirname,
|
||||
resolve: {
|
||||
mainFields: ['module', 'main']
|
||||
},
|
||||
entry: {
|
||||
extension: './src/extension.ts',
|
||||
}
|
||||
});
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 903 B |
@@ -99,13 +99,15 @@ https://raw.githubusercontent.com/isagalaev/highlight.js/master/src/styles/vs201
|
||||
}
|
||||
|
||||
.hljs-addition {
|
||||
background-color: #144212;
|
||||
background-color: var(--vscode-diffEditor-insertedTextBackground, rgba(155, 185, 85, 0.2));
|
||||
color: rgb(155, 185, 85);
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.hljs-deletion {
|
||||
background-color: #600;
|
||||
background: var(--vscode-diffEditor-removedTextBackground, rgba(255, 0, 0, 0.2));
|
||||
color: rgb(255, 0, 0);
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
}
|
||||
@@ -146,12 +148,10 @@ Visual Studio-like style based on original C# coloring by Jason Diamond <jason@d
|
||||
.vscode-light .hljs-literal,
|
||||
.vscode-light .hljs-template-tag,
|
||||
.vscode-light .hljs-template-variable,
|
||||
.vscode-light .hljs-type,
|
||||
.vscode-light .hljs-addition {
|
||||
.vscode-light .hljs-type {
|
||||
color: #a31515;
|
||||
}
|
||||
|
||||
.vscode-light .hljs-deletion,
|
||||
.vscode-light .hljs-selector-attr,
|
||||
.vscode-light .hljs-selector-pseudo,
|
||||
.vscode-light .hljs-meta {
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -6,7 +6,6 @@
|
||||
"icon": "icon.png",
|
||||
"publisher": "vscode",
|
||||
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
|
||||
"enableProposedApi": true,
|
||||
"engines": {
|
||||
"vscode": "^1.20.0"
|
||||
},
|
||||
@@ -262,6 +261,20 @@
|
||||
"description": "%markdown.preview.doubleClickToSwitchToEditor.desc%",
|
||||
"scope": "resource"
|
||||
},
|
||||
"markdown.preview.openMarkdownLinks": {
|
||||
"type": "string",
|
||||
"default": "inPreview",
|
||||
"description": "%configuration.markdown.preview.openMarkdownLinks.description%",
|
||||
"scope": "resource",
|
||||
"enum": [
|
||||
"inPreview",
|
||||
"inEditor"
|
||||
],
|
||||
"enumDescriptions": [
|
||||
"%configuration.markdown.preview.openMarkdownLinks.inPreview%",
|
||||
"%configuration.markdown.preview.openMarkdownLinks.inEditor%"
|
||||
]
|
||||
},
|
||||
"markdown.trace": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
@@ -304,15 +317,14 @@
|
||||
"dependencies": {
|
||||
"highlight.js": "9.12.0",
|
||||
"markdown-it": "^8.4.1",
|
||||
"markdown-it-named-headers": "0.0.4",
|
||||
"vscode-extension-telemetry": "0.0.18",
|
||||
"vscode-nls": "^3.2.4"
|
||||
"vscode-extension-telemetry": "0.1.0",
|
||||
"vscode-nls": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/highlight.js": "9.1.10",
|
||||
"@types/lodash.throttle": "^4.1.3",
|
||||
"@types/markdown-it": "0.0.2",
|
||||
"@types/node": "7.0.43",
|
||||
"@types/node": "^8.10.25",
|
||||
"lodash.throttle": "^4.1.1",
|
||||
"mocha-junit-reporter": "^1.17.0",
|
||||
"mocha-multi-reporters": "^1.1.7",
|
||||
|
||||
@@ -12,14 +12,17 @@
|
||||
"markdown.preview.scrollPreviewWithEditor.desc": "When a markdown editor is scrolled, update the view of the preview.",
|
||||
"markdown.preview.scrollPreviewWithEditorSelection.desc": "[Deprecated] Scrolls the markdown preview to reveal the currently selected line from the editor.",
|
||||
"markdown.preview.scrollPreviewWithEditorSelection.deprecationMessage": "This setting has been replaced by 'markdown.preview.scrollPreviewWithEditor' and no longer has any effect.",
|
||||
"markdown.preview.title" : "Open Preview",
|
||||
"markdown.preview.title": "Open Preview",
|
||||
"markdown.previewFrontMatter.dec": "Sets how YAML front matter should be rendered in the markdown preview. 'hide' removes the front matter. Otherwise, the front matter is treated as markdown content.",
|
||||
"markdown.previewSide.title" : "Open Preview to the Side",
|
||||
"markdown.previewSide.title": "Open Preview to the Side",
|
||||
"markdown.showLockedPreviewToSide.title": "Open Locked Preview to the Side",
|
||||
"markdown.showSource.title" : "Show Source",
|
||||
"markdown.showSource.title": "Show Source",
|
||||
"markdown.styles.dec": "A list of URLs or local paths to CSS style sheets to use from the markdown preview. Relative paths are interpreted relative to the folder open in the explorer. If there is no open folder, they are interpreted relative to the location of the markdown file. All '\\' need to be written as '\\\\'.",
|
||||
"markdown.showPreviewSecuritySelector.title": "Change Preview Security Settings",
|
||||
"markdown.trace.desc": "Enable debug logging for the markdown extension.",
|
||||
"markdown.preview.refresh.title": "Refresh Preview",
|
||||
"markdown.preview.toggleLock.title": "Toggle Preview Locking"
|
||||
}
|
||||
"markdown.preview.toggleLock.title": "Toggle Preview Locking",
|
||||
"configuration.markdown.preview.openMarkdownLinks.description": "How should clicking on links to markdown files be handled in the preview.",
|
||||
"configuration.markdown.preview.openMarkdownLinks.inEditor": "Try to open links in the editor",
|
||||
"configuration.markdown.preview.openMarkdownLinks.inPreview": "Try to open links in the markdown preview"
|
||||
}
|
||||
@@ -57,7 +57,7 @@ export class CspAlerter {
|
||||
notification.setAttribute('role', 'button');
|
||||
notification.setAttribute('aria-label', strings.cspAlertMessageLabel);
|
||||
notification.onclick = () => {
|
||||
this.messaging!.postCommand('markdown.showPreviewSecuritySelector', [settings.source]);
|
||||
this.messaging!.postMessage('showPreviewSecuritySelector', { source: settings.source });
|
||||
};
|
||||
document.body.appendChild(notification);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,10 @@ const messaging = createPosterForVsCode(vscode);
|
||||
window.cspAlerter.setPoster(messaging);
|
||||
window.styleLoadingMonitor.setPoster(messaging);
|
||||
|
||||
window.onload = () => {
|
||||
updateImageSizes();
|
||||
};
|
||||
|
||||
onceDocumentLoaded(() => {
|
||||
if (settings.scrollPreviewWithEditor) {
|
||||
setTimeout(() => {
|
||||
@@ -53,8 +57,32 @@ 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', () => {
|
||||
scrollDisabled = true;
|
||||
updateImageSizes();
|
||||
}, true);
|
||||
|
||||
window.addEventListener('message', event => {
|
||||
@@ -105,7 +133,7 @@ document.addEventListener('click', event => {
|
||||
}
|
||||
if (node.href.startsWith('file://') || node.href.startsWith('vscode-resource:')) {
|
||||
const [path, fragment] = node.href.replace(/^(file:\/\/|vscode-resource:)/i, '').split('#');
|
||||
messaging.postCommand('_markdown.openDocumentLink', [{ path, fragment }]);
|
||||
messaging.postMessage('clickLink', { path, fragment });
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
break;
|
||||
|
||||
@@ -30,7 +30,7 @@ export class StyleLoadingMonitor {
|
||||
}
|
||||
this.finishedLoading = true;
|
||||
if (this.poster) {
|
||||
this.poster.postCommand('_markdown.onPreviewStyleLoadError', [this.unloadedStyles]);
|
||||
this.poster.postMessage('previewStyleLoadError', { unloadedStyles: this.unloadedStyles });
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -38,7 +38,7 @@ export class StyleLoadingMonitor {
|
||||
public setPoster(poster: MessagePoster): void {
|
||||
this.poster = poster;
|
||||
if (this.finishedLoading) {
|
||||
poster.postCommand('_markdown.onPreviewStyleLoadError', [this.unloadedStyles]);
|
||||
poster.postMessage('previewStyleLoadError', { unloadedStyles: this.unloadedStyles });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,12 +10,6 @@ export interface MessagePoster {
|
||||
* Post a message to the markdown extension
|
||||
*/
|
||||
postMessage(type: string, body: object): void;
|
||||
|
||||
|
||||
/**
|
||||
* Post a command to be executed to the markdown extension
|
||||
*/
|
||||
postCommand(command: string, args: any[]): void;
|
||||
}
|
||||
|
||||
export const createPosterForVsCode = (vscode: any) => {
|
||||
@@ -27,9 +21,6 @@ export const createPosterForVsCode = (vscode: any) => {
|
||||
body
|
||||
});
|
||||
}
|
||||
postCommand(command: string, args: any[]) {
|
||||
this.postMessage('command', { command, args });
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -24,13 +24,13 @@ const getCodeLineElements = (() => {
|
||||
let elements: CodeLineElement[];
|
||||
return () => {
|
||||
if (!elements) {
|
||||
elements = Array.prototype.map.call(
|
||||
elements = ([{ element: document.body, line: 0 }]).concat(Array.prototype.map.call(
|
||||
document.getElementsByClassName('code-line'),
|
||||
(element: any) => {
|
||||
const line = +element.getAttribute('data-line');
|
||||
return { element, line };
|
||||
})
|
||||
.filter((x: any) => !isNaN(x.line));
|
||||
.filter((x: any) => !isNaN(x.line)));
|
||||
}
|
||||
return elements;
|
||||
};
|
||||
@@ -49,8 +49,7 @@ export function getElementsForSourceLine(targetLine: number): { previous: CodeLi
|
||||
for (const entry of lines) {
|
||||
if (entry.line === lineNumber) {
|
||||
return { previous: entry, next: undefined };
|
||||
}
|
||||
else if (entry.line > lineNumber) {
|
||||
} else if (entry.line > lineNumber) {
|
||||
return { previous, next: entry };
|
||||
}
|
||||
previous = entry;
|
||||
@@ -89,22 +88,31 @@ export function getLineElementsAtPageOffset(offset: number): { previous: CodeLin
|
||||
* Attempt to reveal the element for a source line in the editor.
|
||||
*/
|
||||
export function scrollToRevealSourceLine(line: number) {
|
||||
const { previous, next } = getElementsForSourceLine(line);
|
||||
if (previous && getSettings().scrollPreviewWithEditor) {
|
||||
let scrollTo = 0;
|
||||
const rect = previous.element.getBoundingClientRect();
|
||||
const previousTop = rect.top;
|
||||
if (next && next.line !== previous.line) {
|
||||
// Between two elements. Go to percentage offset between them.
|
||||
const betweenProgress = (line - previous.line) / (next.line - previous.line);
|
||||
const elementOffset = next.element.getBoundingClientRect().top - previousTop;
|
||||
scrollTo = previousTop + betweenProgress * elementOffset;
|
||||
}
|
||||
else {
|
||||
scrollTo = previousTop;
|
||||
}
|
||||
window.scroll(0, Math.max(1, window.scrollY + scrollTo));
|
||||
if (!getSettings().scrollPreviewWithEditor) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (line <= 0) {
|
||||
window.scroll(window.scrollX, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
const { previous, next } = getElementsForSourceLine(line);
|
||||
if (!previous) {
|
||||
return;
|
||||
}
|
||||
let scrollTo = 0;
|
||||
const rect = previous.element.getBoundingClientRect();
|
||||
const previousTop = rect.top;
|
||||
if (next && next.line !== previous.line) {
|
||||
// Between two elements. Go to percentage offset between them.
|
||||
const betweenProgress = (line - previous.line) / (next.line - previous.line);
|
||||
const elementOffset = next.element.getBoundingClientRect().top - previousTop;
|
||||
scrollTo = previousTop + betweenProgress * elementOffset;
|
||||
} else {
|
||||
scrollTo = previousTop;
|
||||
}
|
||||
window.scroll(window.scrollX, Math.max(1, window.scrollY + scrollTo));
|
||||
}
|
||||
|
||||
export function getEditorLineNumberForPageOffset(offset: number) {
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
export { OpenDocumentLinkCommand } from './openDocumentLink';
|
||||
export { OnPreviewStyleLoadErrorCommand } from './onPreviewStyleLoadError';
|
||||
export { ShowPreviewCommand, ShowPreviewToSideCommand, ShowLockedPreviewToSideCommand } from './showPreview';
|
||||
export { ShowSourceCommand } from './showSource';
|
||||
export { RefreshPreviewCommand } from './refreshPreview';
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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.loadMessageBundle();
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
import { Command } from '../commandManager';
|
||||
|
||||
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(', ')));
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
import { extname } from 'path';
|
||||
|
||||
import { Command } from '../commandManager';
|
||||
import { MarkdownEngine } from '../markdownEngine';
|
||||
@@ -35,7 +35,7 @@ export class OpenDocumentLinkCommand implements Command {
|
||||
public execute(args: OpenDocumentLinkArgs) {
|
||||
const p = decodeURIComponent(args.path);
|
||||
return this.tryOpen(p, args).catch(() => {
|
||||
if (path.extname(p) === '') {
|
||||
if (p && extname(p) === '') {
|
||||
return this.tryOpen(p + '.md', args);
|
||||
}
|
||||
const resource = vscode.Uri.file(p);
|
||||
@@ -47,13 +47,14 @@ export class OpenDocumentLinkCommand implements Command {
|
||||
|
||||
private async tryOpen(path: string, args: OpenDocumentLinkArgs) {
|
||||
const resource = vscode.Uri.file(path);
|
||||
if (vscode.window.activeTextEditor && isMarkdownFile(vscode.window.activeTextEditor.document) && vscode.window.activeTextEditor.document.uri.fsPath === resource.fsPath) {
|
||||
return this.tryRevealLine(vscode.window.activeTextEditor, args.fragment);
|
||||
} else {
|
||||
return vscode.workspace.openTextDocument(resource)
|
||||
.then(vscode.window.showTextDocument)
|
||||
.then(editor => this.tryRevealLine(editor, args.fragment));
|
||||
if (vscode.window.activeTextEditor && isMarkdownFile(vscode.window.activeTextEditor.document)) {
|
||||
if (!path || vscode.window.activeTextEditor.document.uri.fsPath === resource.fsPath) {
|
||||
return this.tryRevealLine(vscode.window.activeTextEditor, args.fragment);
|
||||
}
|
||||
}
|
||||
return vscode.workspace.openTextDocument(resource)
|
||||
.then(vscode.window.showTextDocument)
|
||||
.then(editor => this.tryRevealLine(editor, args.fragment));
|
||||
}
|
||||
|
||||
private async tryRevealLine(editor: vscode.TextEditor, fragment?: string) {
|
||||
@@ -73,3 +74,37 @@ export class OpenDocumentLinkCommand implements Command {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export async function resolveLinkToMarkdownFile(path: string): Promise<vscode.Uri | undefined> {
|
||||
try {
|
||||
const standardLink = await tryResolveLinkToMarkdownFile(path);
|
||||
if (standardLink) {
|
||||
return standardLink;
|
||||
}
|
||||
} catch {
|
||||
// Noop
|
||||
}
|
||||
|
||||
// If no extension, try with `.md` extension
|
||||
if (extname(path) === '') {
|
||||
return tryResolveLinkToMarkdownFile(path + '.md');
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async function tryResolveLinkToMarkdownFile(path: string): Promise<vscode.Uri | undefined> {
|
||||
const resource = vscode.Uri.file(path);
|
||||
|
||||
let document: vscode.TextDocument;
|
||||
try {
|
||||
document = await vscode.workspace.openTextDocument(resource);
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
if (isMarkdownFile(document)) {
|
||||
return document.uri;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
@@ -38,9 +38,10 @@ async function showPreview(
|
||||
return;
|
||||
}
|
||||
|
||||
const resourceColumn = (vscode.window.activeTextEditor && vscode.window.activeTextEditor.viewColumn) || vscode.ViewColumn.One;
|
||||
webviewManager.preview(resource, {
|
||||
resourceColumn: (vscode.window.activeTextEditor && vscode.window.activeTextEditor.viewColumn) || vscode.ViewColumn.One,
|
||||
previewColumn: previewSettings.sideBySide ? vscode.ViewColumn.Beside : vscode.ViewColumn.Active,
|
||||
resourceColumn: resourceColumn,
|
||||
previewColumn: previewSettings.sideBySide ? resourceColumn + 1 : resourceColumn,
|
||||
locked: !!previewSettings.locked
|
||||
});
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
commandManager.register(new commands.RefreshPreviewCommand(previewManager));
|
||||
commandManager.register(new commands.MoveCursorToPositionCommand());
|
||||
commandManager.register(new commands.ShowPreviewSecuritySelectorCommand(previewSecuritySelector, previewManager));
|
||||
commandManager.register(new commands.OnPreviewStyleLoadErrorCommand());
|
||||
commandManager.register(new commands.OpenDocumentLinkCommand(engine));
|
||||
commandManager.register(new commands.ToggleLockCommand(previewManager));
|
||||
// {{SQL CARBON EDIT}}
|
||||
|
||||
@@ -3,34 +3,38 @@
|
||||
* 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 * as vscode from 'vscode';
|
||||
import { OpenDocumentLinkCommand } from '../commands/openDocumentLink';
|
||||
import { getUriForLinkWithKnownExternalScheme } from '../util/links';
|
||||
|
||||
function normalizeLink(
|
||||
document: vscode.TextDocument,
|
||||
link: string,
|
||||
base: string
|
||||
): vscode.Uri {
|
||||
const uri = vscode.Uri.parse(link);
|
||||
if (uri.scheme) {
|
||||
return uri;
|
||||
const externalSchemeUri = getUriForLinkWithKnownExternalScheme(link);
|
||||
if (externalSchemeUri) {
|
||||
return externalSchemeUri;
|
||||
}
|
||||
|
||||
// assume it must be a file
|
||||
let resourcePath = uri.path;
|
||||
if (!uri.path) {
|
||||
// Assume it must be an relative or absolute file path
|
||||
// Use a fake scheme to avoid parse warnings
|
||||
const tempUri = vscode.Uri.parse(`vscode-resource:${link}`);
|
||||
|
||||
let resourcePath = tempUri.path;
|
||||
if (!tempUri.path && document.uri.scheme === 'file') {
|
||||
resourcePath = document.uri.path;
|
||||
} else if (uri.path[0] === '/') {
|
||||
} else if (tempUri.path[0] === '/') {
|
||||
const root = vscode.workspace.getWorkspaceFolder(document.uri);
|
||||
if (root) {
|
||||
resourcePath = path.join(root.uri.fsPath, uri.path);
|
||||
resourcePath = path.join(root.uri.fsPath, tempUri.path);
|
||||
}
|
||||
} else {
|
||||
resourcePath = path.join(base, uri.path);
|
||||
resourcePath = base ? path.join(base, tempUri.path) : tempUri.path;
|
||||
}
|
||||
|
||||
return OpenDocumentLinkCommand.createCommandUri(resourcePath, uri.fragment);
|
||||
return OpenDocumentLinkCommand.createCommandUri(resourcePath, tempUri.fragment);
|
||||
}
|
||||
|
||||
function matchAll(
|
||||
@@ -55,7 +59,7 @@ export default class LinkProvider implements vscode.DocumentLinkProvider {
|
||||
document: vscode.TextDocument,
|
||||
_token: vscode.CancellationToken
|
||||
): vscode.DocumentLink[] {
|
||||
const base = path.dirname(document.uri.fsPath);
|
||||
const base = document.uri.scheme === 'file' ? path.dirname(document.uri.fsPath) : '';
|
||||
const text = document.getText();
|
||||
|
||||
return this.providerInlineLinks(text, document, base)
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Token } from 'markdown-it';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
import { MarkdownEngine } from '../markdownEngine';
|
||||
import { TableOfContentsProvider } from '../tableOfContentsProvider';
|
||||
|
||||
@@ -16,35 +16,83 @@ export default class MarkdownFoldingProvider implements vscode.FoldingRangeProvi
|
||||
private readonly engine: MarkdownEngine
|
||||
) { }
|
||||
|
||||
private async getRegions(document: vscode.TextDocument): Promise<vscode.FoldingRange[]> {
|
||||
|
||||
const isStartRegion = (t: string) => /^\s*<!--\s*#?region\b.*-->/.test(t);
|
||||
const isEndRegion = (t: string) => /^\s*<!--\s*#?endregion\b.*-->/.test(t);
|
||||
|
||||
const isRegionMarker = (token: Token) => token.type === 'html_block' &&
|
||||
(isStartRegion(token.content) || isEndRegion(token.content));
|
||||
|
||||
|
||||
const tokens = await this.engine.parse(document.uri, document.getText());
|
||||
const regionMarkers = tokens.filter(isRegionMarker)
|
||||
.map(token => ({ line: token.map[0], isStart: isStartRegion(token.content) }));
|
||||
|
||||
const nestingStack: { line: number, isStart: boolean }[] = [];
|
||||
return regionMarkers
|
||||
.map(marker => {
|
||||
if (marker.isStart) {
|
||||
nestingStack.push(marker);
|
||||
} else if (nestingStack.length && nestingStack[nestingStack.length - 1].isStart) {
|
||||
return new vscode.FoldingRange(nestingStack.pop()!.line, marker.line, vscode.FoldingRangeKind.Region);
|
||||
} else {
|
||||
// noop: invalid nesting (i.e. [end, start] or [start, end, end])
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.filter((region: vscode.FoldingRange | null): region is vscode.FoldingRange => !!region);
|
||||
}
|
||||
|
||||
public async provideFoldingRanges(
|
||||
document: vscode.TextDocument,
|
||||
_: vscode.FoldingContext,
|
||||
_token: vscode.CancellationToken
|
||||
): Promise<vscode.FoldingRange[]> {
|
||||
const tocProvider = new TableOfContentsProvider(this.engine, document);
|
||||
let toc = await tocProvider.getToc();
|
||||
if (toc.length > rangeLimit) {
|
||||
toc = toc.slice(0, rangeLimit);
|
||||
}
|
||||
|
||||
const foldingRanges = toc.map((entry, startIndex) => {
|
||||
const start = entry.line;
|
||||
let end: number | undefined = undefined;
|
||||
for (let i = startIndex + 1; i < toc.length; ++i) {
|
||||
if (toc[i].level <= entry.level) {
|
||||
end = toc[i].line - 1;
|
||||
if (document.lineAt(end).isEmptyOrWhitespace && end >= start + 1) {
|
||||
end = end - 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new vscode.FoldingRange(
|
||||
start,
|
||||
typeof end === 'number' ? end : document.lineCount - 1);
|
||||
});
|
||||
|
||||
|
||||
return foldingRanges;
|
||||
const foldables = await Promise.all([
|
||||
this.getRegions(document),
|
||||
this.getHeaderFoldingRanges(document),
|
||||
this.getBlockFoldingRanges(document)]);
|
||||
return ([] as vscode.FoldingRange[]).concat.apply([], foldables).slice(0, rangeLimit);
|
||||
}
|
||||
}
|
||||
|
||||
private async getHeaderFoldingRanges(document: vscode.TextDocument) {
|
||||
const tocProvider = new TableOfContentsProvider(this.engine, document);
|
||||
const toc = await tocProvider.getToc();
|
||||
return toc.map(entry => {
|
||||
let endLine = entry.location.range.end.line;
|
||||
if (document.lineAt(endLine).isEmptyOrWhitespace && endLine >= entry.line + 1) {
|
||||
endLine = endLine - 1;
|
||||
}
|
||||
return new vscode.FoldingRange(entry.line, endLine);
|
||||
});
|
||||
}
|
||||
|
||||
private async getBlockFoldingRanges(document: vscode.TextDocument): Promise<vscode.FoldingRange[]> {
|
||||
|
||||
const isFoldableToken = (token: Token) => {
|
||||
switch (token.type) {
|
||||
case 'fence':
|
||||
case 'list_item_open':
|
||||
return token.map[1] > token.map[0];
|
||||
|
||||
case 'html_block':
|
||||
return token.map[1] > token.map[0] + 1;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const tokens = await this.engine.parse(document.uri, document.getText());
|
||||
const multiLineListItems = tokens.filter(isFoldableToken);
|
||||
return multiLineListItems.map(listItem => {
|
||||
const start = listItem.map[0];
|
||||
let end = listItem.map[1] - 1;
|
||||
if (document.lineAt(end).isEmptyOrWhitespace && end >= start + 1) {
|
||||
end = end - 1;
|
||||
}
|
||||
return new vscode.FoldingRange(start, end);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,51 @@ import { getVisibleLine, MarkdownFileTopmostLineMonitor } from '../util/topmostL
|
||||
import { MarkdownPreviewConfigurationManager } from './previewConfig';
|
||||
import { MarkdownContributions } from '../markdownExtensions';
|
||||
import { isMarkdownFile } from '../util/file';
|
||||
import { resolveLinkToMarkdownFile } from '../commands/openDocumentLink';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
interface WebviewMessage {
|
||||
readonly source: string;
|
||||
}
|
||||
|
||||
interface CacheImageSizesMessage extends WebviewMessage {
|
||||
readonly type: 'cacheImageSizes';
|
||||
readonly body: { id: string, width: number, height: number }[];
|
||||
}
|
||||
|
||||
interface RevealLineMessage extends WebviewMessage {
|
||||
readonly type: 'revealLine';
|
||||
readonly body: {
|
||||
readonly line: number;
|
||||
};
|
||||
}
|
||||
|
||||
interface DidClickMessage extends WebviewMessage {
|
||||
readonly type: 'didClick';
|
||||
readonly body: {
|
||||
readonly line: number;
|
||||
};
|
||||
}
|
||||
|
||||
interface ClickLinkMessage extends WebviewMessage {
|
||||
readonly type: 'clickLink';
|
||||
readonly body: {
|
||||
readonly path: string;
|
||||
readonly fragment?: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface ShowPreviewSecuritySelectorMessage extends WebviewMessage {
|
||||
readonly type: 'showPreviewSecuritySelector';
|
||||
}
|
||||
|
||||
interface PreviewStyleLoadErrorMessage extends WebviewMessage {
|
||||
readonly type: 'previewStyleLoadError';
|
||||
readonly body: {
|
||||
readonly unloadedStyles: string[];
|
||||
};
|
||||
}
|
||||
|
||||
export class MarkdownPreview {
|
||||
|
||||
public static viewType = 'markdown.preview';
|
||||
@@ -33,6 +76,7 @@ export class MarkdownPreview {
|
||||
private forceUpdate = false;
|
||||
private isScrolling = false;
|
||||
private _disposed: boolean = false;
|
||||
private imageInfo: { id: string, width: number, height: number }[] = [];
|
||||
|
||||
public static async revive(
|
||||
webview: vscode.WebviewPanel,
|
||||
@@ -117,14 +161,14 @@ export class MarkdownPreview {
|
||||
this._onDidChangeViewStateEmitter.fire(e);
|
||||
}, null, this.disposables);
|
||||
|
||||
this.editor.webview.onDidReceiveMessage(e => {
|
||||
this.editor.webview.onDidReceiveMessage((e: CacheImageSizesMessage | RevealLineMessage | DidClickMessage | ClickLinkMessage | ShowPreviewSecuritySelectorMessage | PreviewStyleLoadErrorMessage) => {
|
||||
if (e.source !== this._resource.toString()) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (e.type) {
|
||||
case 'command':
|
||||
vscode.commands.executeCommand(e.body.command, ...e.body.args);
|
||||
case 'cacheImageSizes':
|
||||
this.onCacheImageSizes(e.body);
|
||||
break;
|
||||
|
||||
case 'revealLine':
|
||||
@@ -135,6 +179,17 @@ export class MarkdownPreview {
|
||||
this.onDidClickPreview(e.body.line);
|
||||
break;
|
||||
|
||||
case 'clickLink':
|
||||
this.onDidClickPreviewLink(e.body.path, e.body.fragment);
|
||||
break;
|
||||
|
||||
case 'showPreviewSecuritySelector':
|
||||
vscode.commands.executeCommand('markdown.showPreviewSecuritySelector', e.source);
|
||||
break;
|
||||
|
||||
case 'previewStyleLoadError':
|
||||
vscode.window.showWarningMessage(localize('onPreviewStyleLoadError', "Could not load 'markdown.styles': {0}", e.body.unloadedStyles.join(', ')));
|
||||
break;
|
||||
}
|
||||
}, null, this.disposables);
|
||||
|
||||
@@ -181,7 +236,8 @@ export class MarkdownPreview {
|
||||
return {
|
||||
resource: this.resource.toString(),
|
||||
locked: this._locked,
|
||||
line: this.line
|
||||
line: this.line,
|
||||
imageInfo: this.imageInfo
|
||||
};
|
||||
}
|
||||
|
||||
@@ -347,7 +403,6 @@ export class MarkdownPreview {
|
||||
): vscode.WebviewOptions {
|
||||
return {
|
||||
enableScripts: true,
|
||||
enableCommandUris: true,
|
||||
localResourceRoots: MarkdownPreview.getLocalResourceRoots(resource, contributions)
|
||||
};
|
||||
}
|
||||
@@ -400,6 +455,24 @@ export class MarkdownPreview {
|
||||
|
||||
vscode.workspace.openTextDocument(this._resource).then(vscode.window.showTextDocument);
|
||||
}
|
||||
|
||||
private async onDidClickPreviewLink(path: string, fragment: string | undefined) {
|
||||
const config = vscode.workspace.getConfiguration('markdown', this.resource);
|
||||
const openLinks = config.get<string>('preview.openMarkdownLinks', 'inPreview');
|
||||
if (openLinks === 'inPreview') {
|
||||
const markdownLink = await resolveLinkToMarkdownFile(path);
|
||||
if (markdownLink) {
|
||||
this.update(markdownLink);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
vscode.commands.executeCommand('_markdown.openDocumentLink', { path, fragment });
|
||||
}
|
||||
|
||||
private async onCacheImageSizes(imageInfo: { id: string, width: number, height: number }[]) {
|
||||
this.imageInfo = imageInfo;
|
||||
}
|
||||
}
|
||||
|
||||
export interface PreviewSettings {
|
||||
|
||||
@@ -79,7 +79,7 @@ export class MarkdownContentProvider {
|
||||
data-strings="${JSON.stringify(previewStrings).replace(/"/g, '"')}"
|
||||
data-state="${JSON.stringify(state || {}).replace(/"/g, '"')}">
|
||||
<script src="${this.extensionResourcePath('pre.js')}" nonce="${nonce}"></script>
|
||||
${this.getStyles(sourceUri, nonce, config)}
|
||||
${this.getStyles(sourceUri, nonce, config, state)}
|
||||
<base href="${markdownDocument.uri.with({ scheme: 'vscode-resource' }).toString(true)}">
|
||||
</head>
|
||||
<body class="vscode-body ${config.scrollBeyondLastLine ? 'scrollBeyondLastLine' : ''} ${config.wordWrap ? 'wordWrap' : ''} ${config.markEditorSelection ? 'showEditorSelection' : ''}">
|
||||
@@ -104,7 +104,7 @@ export class MarkdownContentProvider {
|
||||
// Use href if it is already an URL
|
||||
const hrefUri = vscode.Uri.parse(href);
|
||||
if (['http', 'https'].indexOf(hrefUri.scheme) >= 0) {
|
||||
return hrefUri.toString();
|
||||
return hrefUri.toString(true);
|
||||
}
|
||||
|
||||
// Use href as file URI if it is absolute
|
||||
@@ -131,7 +131,7 @@ export class MarkdownContentProvider {
|
||||
private computeCustomStyleSheetIncludes(resource: vscode.Uri, config: MarkdownPreviewConfiguration): string {
|
||||
if (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">`;
|
||||
return `<link rel="stylesheet" class="code-user-style" data-source="${style.replace(/"/g, '"')}" href="${this.fixHref(resource, style).replace(/"/g, '"')}" type="text/css" media="screen">`;
|
||||
}).join('\n');
|
||||
}
|
||||
return '';
|
||||
@@ -147,14 +147,30 @@ export class MarkdownContentProvider {
|
||||
</style>`;
|
||||
}
|
||||
|
||||
private getStyles(resource: vscode.Uri, nonce: string, config: MarkdownPreviewConfiguration): string {
|
||||
private getImageStabilizerStyles(state?: any) {
|
||||
let ret = '<style>\n';
|
||||
if (state && state.imageInfo) {
|
||||
state.imageInfo.forEach((imgInfo: any) => {
|
||||
ret += `#${imgInfo.id}.loading {
|
||||
height: ${imgInfo.height}px;
|
||||
width: ${imgInfo.width}px;
|
||||
}\n`;
|
||||
});
|
||||
}
|
||||
ret += '</style>\n';
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private getStyles(resource: vscode.Uri, nonce: string, config: MarkdownPreviewConfiguration, state?: any): string {
|
||||
const baseStyles = this.contributions.previewStyles
|
||||
.map(resource => `<link rel="stylesheet" type="text/css" href="${resource.toString()}">`)
|
||||
.join('\n');
|
||||
|
||||
return `${baseStyles}
|
||||
${this.getSettingsOverrideStyles(nonce, config)}
|
||||
${this.computeCustomStyleSheetIncludes(resource, config)}`;
|
||||
${this.computeCustomStyleSheetIncludes(resource, config)}
|
||||
${this.getImageStabilizerStyles(state)}`;
|
||||
}
|
||||
|
||||
private getScripts(nonce: string): string {
|
||||
|
||||
@@ -6,8 +6,10 @@
|
||||
import { MarkdownIt, Token } from 'markdown-it';
|
||||
import * as path from 'path';
|
||||
import * as vscode from 'vscode';
|
||||
import * as crypto from 'crypto';
|
||||
import { MarkdownContributions } from './markdownExtensions';
|
||||
import { Slugifier } from './slugify';
|
||||
import { getUriForLinkWithKnownExternalScheme } from './util/links';
|
||||
|
||||
const FrontMatterRegex = /^---\s*[^]*?(-{3}|\.{3})\s*/;
|
||||
|
||||
@@ -15,8 +17,8 @@ export class MarkdownEngine {
|
||||
private md?: MarkdownIt;
|
||||
|
||||
private firstLine?: number;
|
||||
|
||||
private currentDocument?: vscode.Uri;
|
||||
private _slugCount = new Map<string, number>();
|
||||
|
||||
public constructor(
|
||||
private readonly extensionPreviewResourceProvider: MarkdownContributions,
|
||||
@@ -34,14 +36,19 @@ export class MarkdownEngine {
|
||||
private async getEngine(resource: vscode.Uri): Promise<MarkdownIt> {
|
||||
if (!this.md) {
|
||||
const hljs = await import('highlight.js');
|
||||
const mdnh = await import('markdown-it-named-headers');
|
||||
this.md = (await import('markdown-it'))({
|
||||
html: true,
|
||||
highlight: (str: string, lang: string) => {
|
||||
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 && lang.toLocaleLowerCase() === 'json5') {
|
||||
lang = 'json';
|
||||
}
|
||||
if (lang && lang.toLocaleLowerCase() === 'c#') {
|
||||
lang = 'cs';
|
||||
}
|
||||
if (lang && hljs.getLanguage(lang)) {
|
||||
try {
|
||||
return `<div>${hljs.highlight(lang, str, true).value}</div>`;
|
||||
@@ -49,8 +56,6 @@ export class MarkdownEngine {
|
||||
}
|
||||
return `<code><div>${this.md!.utils.escapeHtml(str)}</div></code>`;
|
||||
}
|
||||
}).use(mdnh, {
|
||||
slugify: (header: string) => this.slugifier.fromHeading(header).value
|
||||
});
|
||||
|
||||
for (const plugin of this.extensionPreviewResourceProvider.markdownItPlugins) {
|
||||
@@ -61,10 +66,12 @@ export class MarkdownEngine {
|
||||
this.addLineNumberRenderer(this.md, renderName);
|
||||
}
|
||||
|
||||
this.addImageStabilizer(this.md);
|
||||
this.addFencedRenderer(this.md);
|
||||
|
||||
this.addLinkNormalizer(this.md);
|
||||
this.addLinkValidator(this.md);
|
||||
this.addNamedHeaders(this.md);
|
||||
}
|
||||
|
||||
const config = vscode.workspace.getConfiguration('markdown', resource);
|
||||
@@ -101,18 +108,24 @@ export class MarkdownEngine {
|
||||
}
|
||||
this.currentDocument = document;
|
||||
this.firstLine = offset;
|
||||
this._slugCount = new Map<string, number>();
|
||||
|
||||
const engine = await this.getEngine(document);
|
||||
return engine.render(text);
|
||||
}
|
||||
|
||||
public async parse(document: vscode.Uri, source: string): Promise<Token[]> {
|
||||
const UNICODE_NEWLINE_REGEX = /\u2028|\u2029/g;
|
||||
const { text, offset } = this.stripFrontmatter(source);
|
||||
this.currentDocument = document;
|
||||
this._slugCount = new Map<string, number>();
|
||||
|
||||
const engine = await this.getEngine(document);
|
||||
|
||||
return engine.parse(text, {}).map(token => {
|
||||
return engine.parse(text.replace(UNICODE_NEWLINE_REGEX, ''), {}).map(token => {
|
||||
if (token.map) {
|
||||
token.map[0] += offset;
|
||||
token.map[1] += offset;
|
||||
}
|
||||
return token;
|
||||
});
|
||||
@@ -135,6 +148,28 @@ export class MarkdownEngine {
|
||||
};
|
||||
}
|
||||
|
||||
private addImageStabilizer(md: any): void {
|
||||
const original = md.renderer.rules.image;
|
||||
md.renderer.rules.image = (tokens: any, idx: number, options: any, env: any, self: any) => {
|
||||
const token = tokens[idx];
|
||||
token.attrJoin('class', 'loading');
|
||||
|
||||
const src = token.attrGet('src');
|
||||
if (src) {
|
||||
const hash = crypto.createHash('sha256');
|
||||
hash.update(src);
|
||||
const imgHash = hash.digest('hex');
|
||||
token.attrSet('id', `image-hash-${imgHash}`);
|
||||
}
|
||||
|
||||
if (original) {
|
||||
return original(tokens, idx, options, env, self);
|
||||
} else {
|
||||
return self.renderToken(tokens, idx, options, env, self);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private addFencedRenderer(md: any): void {
|
||||
const original = md.renderer.rules['fenced'];
|
||||
md.renderer.rules['fenced'] = (tokens: any, idx: number, options: any, env: any, self: any) => {
|
||||
@@ -151,8 +186,18 @@ export class MarkdownEngine {
|
||||
const normalizeLink = md.normalizeLink;
|
||||
md.normalizeLink = (link: string) => {
|
||||
try {
|
||||
let uri = vscode.Uri.parse(link);
|
||||
if (!uri.scheme && uri.path) {
|
||||
const externalSchemeUri = getUriForLinkWithKnownExternalScheme(link);
|
||||
if (externalSchemeUri) {
|
||||
// set true to skip encoding
|
||||
return normalizeLink(externalSchemeUri.toString(true));
|
||||
}
|
||||
|
||||
|
||||
// Assume it must be an relative or absolute file path
|
||||
// Use a fake scheme to avoid parse warnings
|
||||
let uri = vscode.Uri.parse(`vscode-resource:${link}`);
|
||||
|
||||
if (uri.path) {
|
||||
// Assume it must be a file
|
||||
const fragment = uri.fragment;
|
||||
if (uri.path[0] === '/') {
|
||||
@@ -170,10 +215,8 @@ export class MarkdownEngine {
|
||||
});
|
||||
}
|
||||
return normalizeLink(uri.with({ scheme: 'vscode-resource' }).toString(true));
|
||||
} else if (!uri.scheme && !uri.path && uri.fragment) {
|
||||
return normalizeLink(uri.with({
|
||||
fragment: this.slugifier.fromHeading(uri.fragment).value
|
||||
}).toString(true));
|
||||
} else if (!uri.path && uri.fragment) {
|
||||
return `#${this.slugifier.fromHeading(uri.fragment).value}`;
|
||||
}
|
||||
} catch (e) {
|
||||
// noop
|
||||
@@ -189,4 +232,29 @@ export class MarkdownEngine {
|
||||
return validateLink(link) || link.indexOf('file:') === 0;
|
||||
};
|
||||
}
|
||||
|
||||
private addNamedHeaders(md: any): void {
|
||||
const original = md.renderer.rules.heading_open;
|
||||
md.renderer.rules.heading_open = (tokens: any, idx: number, options: any, env: any, self: any) => {
|
||||
const title = tokens[idx + 1].children.reduce((acc: string, t: any) => acc + t.content, '');
|
||||
let slug = this.slugifier.fromHeading(title);
|
||||
|
||||
if (this._slugCount.has(slug.value)) {
|
||||
const count = this._slugCount.get(slug.value)!;
|
||||
this._slugCount.set(slug.value, count + 1);
|
||||
slug = this.slugifier.fromHeading(slug.value + '-' + (count + 1));
|
||||
} else {
|
||||
this._slugCount.set(slug.value, 0);
|
||||
}
|
||||
|
||||
tokens[idx].attrs = tokens[idx].attrs || [];
|
||||
tokens[idx].attrs.push(['id', slug.value]);
|
||||
|
||||
if (original) {
|
||||
return original(tokens, idx, options, env, self);
|
||||
} else {
|
||||
return self.renderToken(tokens, idx, options, env, self);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import * as nls from 'vscode-nls';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
export enum MarkdownPreviewSecurityLevel {
|
||||
export const enum MarkdownPreviewSecurityLevel {
|
||||
Strict = 0,
|
||||
AllowInsecureContent = 1,
|
||||
AllowScriptsAndAllContent = 2,
|
||||
|
||||
@@ -23,7 +23,7 @@ export const githubSlugifier: Slugifier = new class implements Slugifier {
|
||||
heading.trim()
|
||||
.toLowerCase()
|
||||
.replace(/\s+/g, '-') // Replace whitespace with -
|
||||
.replace(/[\]\[\!\'\#\$\%\&\'\(\)\*\+\,\.\/\:\;\<\=\>\?\@\\\^\_\{\|\}\~\`。,、;:?!…—·ˉ¨‘’“”々~‖∶"'`|〃〔〕〈〉《》「」『』.〖〗【】()[]{}]/g, '') // Remove known puctuators
|
||||
.replace(/[\]\[\!\'\#\$\%\&\'\(\)\*\+\,\.\/\:\;\<\=\>\?\@\\\^\_\{\|\}\~\`。,、;:?!…—·ˉ¨‘’“”々~‖∶"'`|〃〔〕〈〉《》「」『』.〖〗【】()[]{}]/g, '') // Remove known punctuators
|
||||
.replace(/^\-+/, '') // Remove leading -
|
||||
.replace(/\-+$/, '') // Remove trailing -
|
||||
);
|
||||
|
||||
@@ -17,6 +17,7 @@ export interface TocEntry {
|
||||
|
||||
export interface SkinnyTextDocument {
|
||||
readonly uri: vscode.Uri;
|
||||
readonly lineCount: number;
|
||||
getText(): string;
|
||||
lineAt(line: number): vscode.TextLine;
|
||||
}
|
||||
@@ -50,18 +51,48 @@ export class TableOfContentsProvider {
|
||||
const toc: TocEntry[] = [];
|
||||
const tokens = await this.engine.parse(document.uri, document.getText());
|
||||
|
||||
const slugCount = new Map<string, number>();
|
||||
|
||||
for (const heading of tokens.filter(token => token.type === 'heading_open')) {
|
||||
const lineNumber = heading.map[0];
|
||||
const line = document.lineAt(lineNumber);
|
||||
|
||||
let slug = githubSlugifier.fromHeading(line.text);
|
||||
if (slugCount.has(slug.value)) {
|
||||
const count = slugCount.get(slug.value)!;
|
||||
slugCount.set(slug.value, count + 1);
|
||||
slug = githubSlugifier.fromHeading(slug.value + '-' + (count + 1));
|
||||
} else {
|
||||
slugCount.set(slug.value, 0);
|
||||
}
|
||||
|
||||
toc.push({
|
||||
slug: githubSlugifier.fromHeading(line.text),
|
||||
slug,
|
||||
text: TableOfContentsProvider.getHeaderText(line.text),
|
||||
level: TableOfContentsProvider.getHeaderLevel(heading.markup),
|
||||
line: lineNumber,
|
||||
location: new vscode.Location(document.uri, line.range)
|
||||
});
|
||||
}
|
||||
return toc;
|
||||
|
||||
// Get full range of section
|
||||
return toc.map((entry, startIndex): TocEntry => {
|
||||
let end: number | undefined = undefined;
|
||||
for (let i = startIndex + 1; i < toc.length; ++i) {
|
||||
if (toc[i].level <= entry.level) {
|
||||
end = toc[i].line - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
const endLine = typeof end === 'number' ? end : document.lineCount - 1;
|
||||
return {
|
||||
...entry,
|
||||
location: new vscode.Location(document.uri,
|
||||
new vscode.Range(
|
||||
entry.location.range.start,
|
||||
new vscode.Position(endLine, document.lineAt(endLine).range.end.character)))
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private static getHeaderLevel(markup: string): number {
|
||||
|
||||
@@ -10,7 +10,7 @@ import LinkProvider from '../features/documentLinkProvider';
|
||||
import { InMemoryDocument } from './inMemoryDocument';
|
||||
|
||||
|
||||
const testFileName = vscode.Uri.parse('test.md');
|
||||
const testFileName = vscode.Uri.file('test.md');
|
||||
|
||||
const noopToken = new class implements vscode.CancellationToken {
|
||||
private _onCancellationRequestedEmitter = new vscode.EventEmitter<void>();
|
||||
|
||||
@@ -11,7 +11,7 @@ import { InMemoryDocument } from './inMemoryDocument';
|
||||
import { createNewMarkdownEngine } from './engine';
|
||||
|
||||
|
||||
const testFileName = vscode.Uri.parse('test.md');
|
||||
const testFileName = vscode.Uri.file('test.md');
|
||||
|
||||
|
||||
function getSymbolsForFile(fileContents: string) {
|
||||
@@ -82,5 +82,16 @@ suite('markdown.DocumentSymbolProvider', () => {
|
||||
assert.strictEqual(symbols[0].children[0].name, '### h2');
|
||||
assert.strictEqual(symbols[0].children[1].name, '## h3');
|
||||
});
|
||||
|
||||
test('Should handle line separator in file. Issue #63749', async () => {
|
||||
const symbols = await getSymbolsForFile(`# A
|
||||
- foo
|
||||
|
||||
# B
|
||||
- bar`);
|
||||
assert.strictEqual(symbols.length, 2);
|
||||
assert.strictEqual(symbols[0].name, '# A');
|
||||
assert.strictEqual(symbols[1].name, '# B');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import MarkdownFoldingProvider from '../features/foldingProvider';
|
||||
import { InMemoryDocument } from './inMemoryDocument';
|
||||
import { createNewMarkdownEngine } from './engine';
|
||||
|
||||
const testFileName = vscode.Uri.parse('test.md');
|
||||
const testFileName = vscode.Uri.file('test.md');
|
||||
|
||||
suite('markdown.FoldingProvider', () => {
|
||||
test('Should not return anything for empty document', async () => {
|
||||
@@ -78,6 +78,103 @@ y`);
|
||||
assert.strictEqual(firstFold.end, 2);
|
||||
});
|
||||
|
||||
test('Should fold nested <!-- #region --> markers', async () => {
|
||||
const folds = await getFoldsForDocument(`a
|
||||
<!-- #region -->
|
||||
b
|
||||
<!-- #region hello!-->
|
||||
b.a
|
||||
<!-- #endregion -->
|
||||
b
|
||||
<!-- #region: foo! -->
|
||||
b.b
|
||||
<!-- #endregion: foo -->
|
||||
b
|
||||
<!-- #endregion -->
|
||||
a`);
|
||||
assert.strictEqual(folds.length, 3);
|
||||
const [outer, first, second] = folds.sort((a, b) => a.start - b.start);
|
||||
|
||||
assert.strictEqual(outer.start, 1);
|
||||
assert.strictEqual(outer.end, 11);
|
||||
assert.strictEqual(first.start, 3);
|
||||
assert.strictEqual(first.end, 5);
|
||||
assert.strictEqual(second.start, 7);
|
||||
assert.strictEqual(second.end, 9);
|
||||
});
|
||||
|
||||
test('Should fold from list to end of document', async () => {
|
||||
const folds = await getFoldsForDocument(`a
|
||||
- b
|
||||
c
|
||||
d`);
|
||||
assert.strictEqual(folds.length, 1);
|
||||
const firstFold = folds[0];
|
||||
assert.strictEqual(firstFold.start, 1);
|
||||
assert.strictEqual(firstFold.end, 3);
|
||||
});
|
||||
|
||||
test('lists folds should span multiple lines of content', async () => {
|
||||
const folds = await getFoldsForDocument(`a
|
||||
- This list item\n spans multiple\n lines.`);
|
||||
assert.strictEqual(folds.length, 1);
|
||||
const firstFold = folds[0];
|
||||
assert.strictEqual(firstFold.start, 1);
|
||||
assert.strictEqual(firstFold.end, 3);
|
||||
});
|
||||
|
||||
test('List should leave single blankline before new element', async () => {
|
||||
const folds = await getFoldsForDocument(`- a
|
||||
a
|
||||
|
||||
|
||||
b`);
|
||||
assert.strictEqual(folds.length, 1);
|
||||
const firstFold = folds[0];
|
||||
assert.strictEqual(firstFold.start, 0);
|
||||
assert.strictEqual(firstFold.end, 3);
|
||||
});
|
||||
|
||||
test('Should fold fenced code blocks', async () => {
|
||||
const folds = await getFoldsForDocument(`~~~ts
|
||||
a
|
||||
~~~
|
||||
b`);
|
||||
assert.strictEqual(folds.length, 1);
|
||||
const firstFold = folds[0];
|
||||
assert.strictEqual(firstFold.start, 0);
|
||||
assert.strictEqual(firstFold.end, 2);
|
||||
});
|
||||
|
||||
test('Should fold fenced code blocks with yaml front matter', async () => {
|
||||
const folds = await getFoldsForDocument(`---
|
||||
title: bla
|
||||
---
|
||||
|
||||
~~~ts
|
||||
a
|
||||
~~~
|
||||
|
||||
a
|
||||
a
|
||||
b
|
||||
a`);
|
||||
assert.strictEqual(folds.length, 1);
|
||||
const firstFold = folds[0];
|
||||
assert.strictEqual(firstFold.start, 4);
|
||||
assert.strictEqual(firstFold.end, 6);
|
||||
});
|
||||
|
||||
test('Should fold html blocks', async () => {
|
||||
const folds = await getFoldsForDocument(`x
|
||||
<div>
|
||||
fa
|
||||
</div>`);
|
||||
assert.strictEqual(folds.length, 1);
|
||||
const firstFold = folds[0];
|
||||
assert.strictEqual(firstFold.start, 1);
|
||||
assert.strictEqual(firstFold.end, 3);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import { TableOfContentsProvider } from '../tableOfContentsProvider';
|
||||
import { InMemoryDocument } from './inMemoryDocument';
|
||||
import { createNewMarkdownEngine } from './engine';
|
||||
|
||||
const testFileName = vscode.Uri.parse('test.md');
|
||||
const testFileName = vscode.Uri.file('test.md');
|
||||
|
||||
suite('markdown.TableOfContentsProvider', () => {
|
||||
test('Lookup should not return anything for empty document', async () => {
|
||||
@@ -106,4 +106,25 @@ suite('markdown.TableOfContentsProvider', () => {
|
||||
assert.strictEqual((await provider.lookup('Заголовок-header-3'))!.line, 4);
|
||||
assert.strictEqual((await provider.lookup('Заголовок'))!.line, 5);
|
||||
});
|
||||
|
||||
test('Lookup should support suffixes for repeated headers', async () => {
|
||||
const doc = new InMemoryDocument(testFileName, `# a\n# a\n## a`);
|
||||
const provider = new TableOfContentsProvider(createNewMarkdownEngine(), doc);
|
||||
|
||||
{
|
||||
const entry = await provider.lookup('a');
|
||||
assert.ok(entry);
|
||||
assert.strictEqual(entry!.line, 0);
|
||||
}
|
||||
{
|
||||
const entry = await provider.lookup('a-1');
|
||||
assert.ok(entry);
|
||||
assert.strictEqual(entry!.line, 1);
|
||||
}
|
||||
{
|
||||
const entry = await provider.lookup('a-2');
|
||||
assert.ok(entry);
|
||||
assert.strictEqual(entry!.line, 2);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -22,7 +22,7 @@ suite('markdown.WorkspaceSymbolProvider', () => {
|
||||
});
|
||||
|
||||
test('Should return symbols from workspace with one markdown file', async () => {
|
||||
const testFileName = vscode.Uri.parse('test.md');
|
||||
const testFileName = vscode.Uri.file('test.md');
|
||||
|
||||
const provider = new MarkdownWorkspaceSymbolProvider(symbolProvider, new InMemoryWorkspaceMarkdownDocumentProvider([
|
||||
new InMemoryDocument(testFileName, `# header1\nabc\n## header2`)
|
||||
@@ -49,7 +49,7 @@ suite('markdown.WorkspaceSymbolProvider', () => {
|
||||
});
|
||||
|
||||
test('Should update results when markdown file changes symbols', async () => {
|
||||
const testFileName = vscode.Uri.parse('test.md');
|
||||
const testFileName = vscode.Uri.file('test.md');
|
||||
|
||||
const workspaceFileProvider = new InMemoryWorkspaceMarkdownDocumentProvider([
|
||||
new InMemoryDocument(testFileName, `# header1`)
|
||||
@@ -68,7 +68,7 @@ suite('markdown.WorkspaceSymbolProvider', () => {
|
||||
});
|
||||
|
||||
test('Should remove results when file is deleted', async () => {
|
||||
const testFileName = vscode.Uri.parse('test.md');
|
||||
const testFileName = vscode.Uri.file('test.md');
|
||||
|
||||
const workspaceFileProvider = new InMemoryWorkspaceMarkdownDocumentProvider([
|
||||
new InMemoryDocument(testFileName, `# header1`)
|
||||
@@ -84,7 +84,7 @@ suite('markdown.WorkspaceSymbolProvider', () => {
|
||||
});
|
||||
|
||||
test('Should update results when markdown file is created', async () => {
|
||||
const testFileName = vscode.Uri.parse('test.md');
|
||||
const testFileName = vscode.Uri.file('test.md');
|
||||
|
||||
const workspaceFileProvider = new InMemoryWorkspaceMarkdownDocumentProvider([
|
||||
new InMemoryDocument(testFileName, `# header1`)
|
||||
@@ -94,7 +94,7 @@ suite('markdown.WorkspaceSymbolProvider', () => {
|
||||
assert.strictEqual((await provider.provideWorkspaceSymbols('')).length, 1);
|
||||
|
||||
// Creat file
|
||||
workspaceFileProvider.createDocument(new InMemoryDocument(vscode.Uri.parse('test2.md'), `# new header\nabc\n## header2`));
|
||||
workspaceFileProvider.createDocument(new InMemoryDocument(vscode.Uri.file('test2.md'), `# new header\nabc\n## header2`));
|
||||
const newSymbols = await provider.provideWorkspaceSymbols('');
|
||||
assert.strictEqual(newSymbols.length, 3);
|
||||
});
|
||||
@@ -105,7 +105,7 @@ class InMemoryWorkspaceMarkdownDocumentProvider implements WorkspaceMarkdownDocu
|
||||
private readonly _documents = new Map<string, vscode.TextDocument>();
|
||||
|
||||
constructor(documents: vscode.TextDocument[]) {
|
||||
for( const doc of documents) {
|
||||
for (const doc of documents) {
|
||||
this._documents.set(doc.fileName, doc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,5 +4,4 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
/// <reference path='../../../../src/vs/vscode.d.ts'/>
|
||||
/// <reference path='../../../../src/vs/vscode.proposed.d.ts'/>
|
||||
/// <reference types='@types/node'/>
|
||||
|
||||
18
extensions/markdown-language-features/src/util/links.ts
Normal file
18
extensions/markdown-language-features/src/util/links.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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';
|
||||
|
||||
const knownSchemes = ['http:', 'https:', 'file:', 'mailto:', 'data:', 'vscode-resource:'];
|
||||
|
||||
export function getUriForLinkWithKnownExternalScheme(
|
||||
link: string,
|
||||
): vscode.Uri | undefined {
|
||||
if (knownSchemes.some(knownScheme => link.toLowerCase().startsWith(knownScheme))) {
|
||||
return vscode.Uri.parse(link);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
@@ -1,20 +1,13 @@
|
||||
{
|
||||
"extends": "../shared.tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es2017",
|
||||
"outDir": "./out",
|
||||
"experimentalDecorators": true,
|
||||
"lib": [
|
||||
"es6",
|
||||
"es2015.promise",
|
||||
"dom"
|
||||
],
|
||||
"outDir": "./out",
|
||||
"sourceMap": true,
|
||||
"noImplicitAny": true,
|
||||
"noImplicitReturns": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"strict": true,
|
||||
"alwaysStrict": true
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
|
||||
@@ -29,10 +29,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-0.0.2.tgz#5d9ad19e6e6508cdd2f2596df86fd0aade598660"
|
||||
integrity sha1-XZrRnm5lCM3S8llt+G/Qqt5ZhmA=
|
||||
|
||||
"@types/node@7.0.43":
|
||||
version "7.0.43"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.43.tgz#a187e08495a075f200ca946079c914e1a5fe962c"
|
||||
integrity sha512-7scYwwfHNppXvH/9JzakbVxk0o0QUILVk1Lv64GRaxwPuGpnF1QBiwdvhDpLcymb8BpomQL3KYoWKq3wUdDMhQ==
|
||||
"@types/node@^8.10.25":
|
||||
version "8.10.25"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.25.tgz#801fe4e39372cef18f268db880a5fbfcf71adc7e"
|
||||
integrity sha512-WXvAXaknB0c2cJ7N44e1kUrVu5K90mSfPPaT5XxfuSMxEWva86EYIwxUZM3jNZ2P1CIC9e2z4WJqpAF69PQxeA==
|
||||
|
||||
abbrev@1:
|
||||
version "1.1.1"
|
||||
@@ -159,10 +159,10 @@ anymatch@^2.0.0:
|
||||
micromatch "^3.1.4"
|
||||
normalize-path "^2.1.1"
|
||||
|
||||
applicationinsights@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.1.tgz#53446b830fe8d5d619eee2a278b31d3d25030927"
|
||||
integrity sha1-U0Rrgw/o1dYZ7uKieLMdPSUDCSc=
|
||||
applicationinsights@1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.6.tgz#bc201810de91cea910dab34e8ad35ecde488edeb"
|
||||
integrity sha512-VQT3kBpJVPw5fCO5n+WUeSx0VHjxFtD7znYbILBlVgOS9/cMDuGFmV2Br3ObzFyZUDGNbEfW36fD1y2/vAiCKw==
|
||||
dependencies:
|
||||
diagnostic-channel "0.2.0"
|
||||
diagnostic-channel-publishers "0.2.1"
|
||||
@@ -3895,13 +3895,6 @@ map-visit@^1.0.0:
|
||||
dependencies:
|
||||
object-visit "^1.0.0"
|
||||
|
||||
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"
|
||||
integrity sha1-gu/CgyQkCmsed7mq5QF3HV81HB8=
|
||||
dependencies:
|
||||
string "^3.0.1"
|
||||
|
||||
markdown-it@^8.4.1:
|
||||
version "8.4.1"
|
||||
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.1.tgz#206fe59b0e4e1b78a7c73250af9b34a4ad0aaf44"
|
||||
@@ -5711,11 +5704,6 @@ string-width@^2.0.0, string-width@^2.1.0:
|
||||
is-fullwidth-code-point "^2.0.0"
|
||||
strip-ansi "^4.0.0"
|
||||
|
||||
string@^3.0.1:
|
||||
version "3.3.1"
|
||||
resolved "https://registry.yarnpkg.com/string/-/string-3.3.1.tgz#8d2757ec1c0e6c526796fbb6b14036a4098398b7"
|
||||
integrity sha1-jSdX7BwObFJnlvu2sUA2pAmDmLc=
|
||||
|
||||
string_decoder@^1.0.0, string_decoder@~1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab"
|
||||
@@ -6320,17 +6308,17 @@ vm-browserify@0.0.4:
|
||||
dependencies:
|
||||
indexof "0.0.1"
|
||||
|
||||
vscode-extension-telemetry@0.0.18:
|
||||
version "0.0.18"
|
||||
resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.18.tgz#602ba20d8c71453aa34533a291e7638f6e5c0327"
|
||||
integrity sha512-Vw3Sr+dZwl+c6PlsUwrTtCOJkgrmvS3OUVDQGcmpXWAgq9xGq6as0K4pUx+aGqTjzLAESmWSrs6HlJm6J6Khcg==
|
||||
vscode-extension-telemetry@0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.1.0.tgz#3cdcb61d03829966bd04b5f11471a1e40d6abaad"
|
||||
integrity sha512-WVCnP+uLxlqB6UD98yQNV47mR5Rf79LFxpuZhSPhEf0Sb4tPZed3a63n003/dchhOwyCTCBuNN4n8XKJkLEI1Q==
|
||||
dependencies:
|
||||
applicationinsights "1.0.1"
|
||||
applicationinsights "1.0.6"
|
||||
|
||||
vscode-nls@^3.2.4:
|
||||
version "3.2.4"
|
||||
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.4.tgz#2166b4183c8aea884d20727f5449e62be69fd398"
|
||||
integrity sha512-FTjdqa4jDDoBjJqr36O8lmmZf/55kQ2w4ZY/+GL6K92fq765BqO3aYw21atnXUno/P04V5DWagNl4ybDIndJsw==
|
||||
vscode-nls@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.0.0.tgz#4001c8a6caba5cedb23a9c5ce1090395c0e44002"
|
||||
integrity sha512-qCfdzcH+0LgQnBpZA53bA32kzp9rpq/f66Som577ObeuDlFIrtbEJ+A/+CCxjIh4G8dpJYNCKIsxpRAHIfsbNw==
|
||||
|
||||
vscode@^1.1.10:
|
||||
version "1.1.10"
|
||||
|
||||
Reference in New Issue
Block a user