diff --git a/extensions/markdown-language-features/package.json b/extensions/markdown-language-features/package.json index 8c65847f4df..2e13c9aaa38 100644 --- a/extensions/markdown-language-features/package.json +++ b/extensions/markdown-language-features/package.json @@ -181,16 +181,6 @@ "description": "%markdown.styles.dec%", "scope": "resource" }, - "markdown.previewFrontMatter": { - "type": "string", - "enum": [ - "hide", - "show" - ], - "default": "hide", - "description": "%markdown.previewFrontMatter.dec%", - "scope": "resource" - }, "markdown.preview.breaks": { "type": "boolean", "default": false, @@ -307,6 +297,7 @@ "dependencies": { "highlight.js": "9.13.1", "markdown-it": "^8.4.2", + "markdown-it-front-matter": "^0.1.2", "vscode-extension-telemetry": "0.1.0", "vscode-nls": "^4.0.0" }, diff --git a/extensions/markdown-language-features/package.nls.json b/extensions/markdown-language-features/package.nls.json index ca3d7226f58..7841caff810 100644 --- a/extensions/markdown-language-features/package.nls.json +++ b/extensions/markdown-language-features/package.nls.json @@ -13,7 +13,6 @@ "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.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.showLockedPreviewToSide.title": "Open Locked Preview to the Side", "markdown.showSource.title": "Show Source", diff --git a/extensions/markdown-language-features/src/features/previewConfig.ts b/extensions/markdown-language-features/src/features/previewConfig.ts index d660bf10793..ed09a9ce46e 100644 --- a/extensions/markdown-language-features/src/features/previewConfig.ts +++ b/extensions/markdown-language-features/src/features/previewConfig.ts @@ -12,7 +12,6 @@ export class MarkdownPreviewConfiguration { public readonly scrollBeyondLastLine: boolean; public readonly wordWrap: boolean; - public readonly previewFrontMatter: string; public readonly lineBreaks: boolean; public readonly doubleClickToSwitchToEditor: boolean; public readonly scrollEditorWithPreview: boolean; @@ -36,7 +35,6 @@ export class MarkdownPreviewConfiguration { this.wordWrap = markdownEditorConfig['editor.wordWrap'] !== 'off'; } - this.previewFrontMatter = markdownConfig.get('previewFrontMatter', 'hide'); this.scrollPreviewWithEditor = !!markdownConfig.get('preview.scrollPreviewWithEditor', true); this.scrollEditorWithPreview = !!markdownConfig.get('preview.scrollEditorWithPreview', true); this.lineBreaks = !!markdownConfig.get('preview.breaks', false); diff --git a/extensions/markdown-language-features/src/features/previewContentProvider.ts b/extensions/markdown-language-features/src/features/previewContentProvider.ts index 403fc9249d8..c5efa00ac3c 100644 --- a/extensions/markdown-language-features/src/features/previewContentProvider.ts +++ b/extensions/markdown-language-features/src/features/previewContentProvider.ts @@ -68,7 +68,7 @@ export class MarkdownContentProvider { const nonce = new Date().getTime() + '' + new Date().getMilliseconds(); const csp = this.getCspForResource(sourceUri, nonce); - const body = await this.engine.render(markdownDocument, config.previewFrontMatter === 'hide'); + const body = await this.engine.render(markdownDocument); return ` diff --git a/extensions/markdown-language-features/src/markdownEngine.ts b/extensions/markdown-language-features/src/markdownEngine.ts index c77358048bf..9195507a620 100644 --- a/extensions/markdown-language-features/src/markdownEngine.ts +++ b/extensions/markdown-language-features/src/markdownEngine.ts @@ -12,13 +12,11 @@ import { Slugifier } from './slugify'; import { SkinnyTextDocument } from './tableOfContentsProvider'; import { getUriForLinkWithKnownExternalScheme } from './util/links'; -const FrontMatterRegex = /^---\s*[^]*?(-{3}|\.{3})\s*/; const UNICODE_NEWLINE_REGEX = /\u2028|\u2029/g; export class MarkdownEngine { private md?: MarkdownIt; - private firstLine?: number; private currentDocument?: vscode.Uri; private _slugCount = new Map(); private _cache?: { @@ -69,6 +67,21 @@ export class MarkdownEngine { this.usePlugin(await plugin); } + const frontMatterPlugin = require('markdown-it-front-matter'); + // Extract rules from front matter plugin and apply at a lower precedence + let fontMatterRule: any; + frontMatterPlugin({ + block: { + ruler: { + before: (_id: any, _id2: any, rule: any) => { fontMatterRule = rule; } + } + } + }, () => { /* noop */ }); + + this.md.block.ruler.before('fence', 'front_matter', fontMatterRule, { + alt: ['paragraph', 'reference', 'blockquote', 'list'] + }); + for (const renderName of ['paragraph_open', 'heading_open', 'image', 'code_block', 'fence', 'blockquote_open', 'list_item_open']) { this.addLineNumberRenderer(this.md, renderName); } @@ -89,20 +102,7 @@ export class MarkdownEngine { return this.md; } - private stripFrontmatter(text: string): { frontMatter?: string, body: string, lineOffset: number } { - let offset = 0; - const frontMatterMatch = FrontMatterRegex.exec(text); - let frontMatter: string | undefined; - if (frontMatterMatch) { - frontMatter = frontMatterMatch[0]; - offset = frontMatter.split(/\r\n|\n|\r/g).length - 1; - text = text.substr(frontMatter.length); - } - return { frontMatter, body: text, lineOffset: offset }; - } - private tokenize(document: SkinnyTextDocument, engine: MarkdownIt): Token[] { - const { body: text, lineOffset: offset } = this.stripFrontmatter(document.getText()); const uri = document.uri; if (this._cache && this._cache.document.toString() === uri.toString() @@ -113,15 +113,9 @@ export class MarkdownEngine { this.currentDocument = document.uri; this._slugCount = new Map(); - this.firstLine = offset; - const tokens = engine.parse(text.replace(UNICODE_NEWLINE_REGEX, ''), {}).map(token => { - if (token.map) { - token.map[0] += offset; - token.map[1] += offset; - } - return token; - }); + const text = document.getText(); + const tokens = engine.parse(text.replace(UNICODE_NEWLINE_REGEX, ''), {}); this._cache = { tokens, document: uri, @@ -130,10 +124,9 @@ export class MarkdownEngine { return tokens; } - public async render(document: SkinnyTextDocument, _stripFrontmatter: boolean): Promise { + public async render(document: SkinnyTextDocument): Promise { const engine = await this.getEngine(document.uri); - const html = engine.renderer.render(this.tokenize(document, engine), this.md, {}); - return html; + return engine.renderer.render(this.tokenize(document, engine), engine, {}); } public async parse(document: SkinnyTextDocument): Promise { @@ -146,7 +139,7 @@ export class MarkdownEngine { md.renderer.rules[ruleName] = (tokens: any, idx: number, options: any, env: any, self: any) => { const token = tokens[idx]; if (token.map && token.map.length) { - token.attrSet('data-line', this.firstLine + token.map[0]); + token.attrSet('data-line', token.map[0]); token.attrJoin('class', 'code-line'); } diff --git a/extensions/markdown-language-features/yarn.lock b/extensions/markdown-language-features/yarn.lock index 071b5b8e161..af3977a75cc 100644 --- a/extensions/markdown-language-features/yarn.lock +++ b/extensions/markdown-language-features/yarn.lock @@ -3895,6 +3895,11 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" +markdown-it-front-matter@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/markdown-it-front-matter/-/markdown-it-front-matter-0.1.2.tgz#e50bf56e77e6a4f5ac4ffa894d4d45ccd9896b20" + integrity sha1-5Qv1bnfmpPWsT/qJTU1FzNmJayA= + markdown-it@^8.4.2: version "8.4.2" resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.2.tgz#386f98998dc15a37722aa7722084f4020bdd9b54"