Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import * as uri from 'vscode-uri';
import { OpenDocumentLinkCommand } from '../commands/openDocumentLink';
import { ILogger } from '../logging';
import { IMdParser } from '../markdownEngine';
import { ITextDocument } from '../types/textDocument';
import { getLine, ITextDocument } from '../types/textDocument';
import { coalesce } from '../util/arrays';
import { noopToken } from '../util/cancellation';
import { Disposable } from '../util/dispose';
Expand Down Expand Up @@ -422,9 +422,9 @@ export class MdLinkComputer {
reference = match[5];
const offset = ((match.index ?? 0) + match[1].length) + 1;
hrefStart = document.positionAt(offset);
const line = document.lineAt(hrefStart.line);
const line = getLine(document, hrefStart.line);
// See if link looks like a checkbox
const checkboxMatch = line.text.match(/^\s*[\-\*]\s*\[x\]/i);
const checkboxMatch = line.match(/^\s*[\-\*]\s*\[x\]/i);
if (checkboxMatch && hrefStart.character <= checkboxMatch[0].length) {
continue;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import type Token = require('markdown-it/lib/token');
import * as vscode from 'vscode';
import { IMdParser } from '../markdownEngine';
import { MdTableOfContentsProvider } from '../tableOfContents';
import { ITextDocument } from '../types/textDocument';
import { getLine, ITextDocument } from '../types/textDocument';
import { isEmptyOrWhitespace } from '../util/string';

const rangeLimit = 5000;

Expand Down Expand Up @@ -59,7 +60,7 @@ export class MdFoldingProvider implements vscode.FoldingRangeProvider {
const toc = await this.tocProvide.getForDocument(document);
return toc.entries.map(entry => {
let endLine = entry.sectionLocation.range.end.line;
if (document.lineAt(endLine).isEmptyOrWhitespace && endLine >= entry.line + 1) {
if (isEmptyOrWhitespace(getLine(document, endLine)) && endLine >= entry.line + 1) {
endLine = endLine - 1;
}
return new vscode.FoldingRange(entry.line, endLine);
Expand All @@ -72,7 +73,7 @@ export class MdFoldingProvider implements vscode.FoldingRangeProvider {
return multiLineListItems.map(listItem => {
const start = listItem.map[0];
let end = listItem.map[1] - 1;
if (document.lineAt(end).isEmptyOrWhitespace && end >= start + 1) {
if (isEmptyOrWhitespace(getLine(document, end)) && end >= start + 1) {
end = end - 1;
}
return new vscode.FoldingRange(start, end, this.getFoldingRangeKind(listItem));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { dirname, resolve } from 'path';
import * as vscode from 'vscode';
import { IMdParser } from '../markdownEngine';
import { TableOfContents } from '../tableOfContents';
import { ITextDocument } from '../types/textDocument';
import { getLine, ITextDocument } from '../types/textDocument';
import { resolveUriToMarkdownFile } from '../util/openDocumentLink';
import { Schemes } from '../util/schemes';
import { IMdWorkspace } from '../workspace';
Expand Down Expand Up @@ -167,7 +167,7 @@ export class MdVsCodePathCompletionProvider implements vscode.CompletionItemProv
private readonly definitionPattern = /^\s*\[[\w\-]+\]:\s*([^\s]*)$/m;

private getPathCompletionContext(document: ITextDocument, position: vscode.Position): CompletionContext | undefined {
const line = document.lineAt(position.line).text;
const line = getLine(document, position.line);

const linePrefixText = line.slice(0, position.character);
const lineSuffixText = line.slice(position.character);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import Token = require('markdown-it/lib/token');
import * as vscode from 'vscode';
import { IMdParser } from '../markdownEngine';
import { MdTableOfContentsProvider, TocEntry } from '../tableOfContents';
import { ITextDocument } from '../types/textDocument';
import { getLine, ITextDocument } from '../types/textDocument';
import { isEmptyOrWhitespace } from '../util/string';

interface MarkdownItTokenWithMap extends Token {
map: [number, number];
Expand Down Expand Up @@ -111,14 +112,14 @@ function createBlockRange(block: MarkdownItTokenWithMap, document: ITextDocument
if (block.type === 'fence') {
return createFencedRange(block, cursorLine, document, parent);
} else {
let startLine = document.lineAt(block.map[0]).isEmptyOrWhitespace ? block.map[0] + 1 : block.map[0];
let startLine = isEmptyOrWhitespace(getLine(document, block.map[0])) ? block.map[0] + 1 : block.map[0];
let endLine = startLine === block.map[1] ? block.map[1] : block.map[1] - 1;
if (block.type === 'paragraph_open' && block.map[1] - block.map[0] === 2) {
startLine = endLine = cursorLine;
} else if (isList(block) && document.lineAt(endLine).isEmptyOrWhitespace) {
} else if (isList(block) && isEmptyOrWhitespace(getLine(document, endLine))) {
endLine = endLine - 1;
}
const range = new vscode.Range(startLine, 0, endLine, document.lineAt(endLine).text?.length ?? 0);
const range = new vscode.Range(startLine, 0, endLine, getLine(document, endLine).length);
if (parent?.range.contains(range) && !parent.range.isEqual(range)) {
return new vscode.SelectionRange(range, parent);
} else if (parent?.range.isEqual(range)) {
Expand All @@ -130,7 +131,7 @@ function createBlockRange(block: MarkdownItTokenWithMap, document: ITextDocument
}

function createInlineRange(document: ITextDocument, cursorPosition: vscode.Position, parent?: vscode.SelectionRange): vscode.SelectionRange | undefined {
const lineText = document.lineAt(cursorPosition.line).text;
const lineText = getLine(document, cursorPosition.line);
const boldSelection = createBoldRange(lineText, cursorPosition.character, cursorPosition.line, parent);
const italicSelection = createOtherInlineRange(lineText, cursorPosition.character, cursorPosition.line, true, parent);
let comboSelection: vscode.SelectionRange | undefined;
Expand All @@ -150,8 +151,8 @@ function createFencedRange(token: MarkdownItTokenWithMap, cursorLine: number, do
const startLine = token.map[0];
const endLine = token.map[1] - 1;
const onFenceLine = cursorLine === startLine || cursorLine === endLine;
const fenceRange = new vscode.Range(startLine, 0, endLine, document.lineAt(endLine).text.length);
const contentRange = endLine - startLine > 2 && !onFenceLine ? new vscode.Range(startLine + 1, 0, endLine - 1, document.lineAt(endLine - 1).text.length) : undefined;
const fenceRange = new vscode.Range(startLine, 0, endLine, getLine(document, endLine).length);
const contentRange = endLine - startLine > 2 && !onFenceLine ? new vscode.Range(startLine + 1, 0, endLine - 1, getLine(document, endLine - 1).length) : undefined;
if (contentRange) {
return new vscode.SelectionRange(contentRange, new vscode.SelectionRange(fenceRange, parent));
} else {
Expand Down Expand Up @@ -242,7 +243,7 @@ function getFirstChildHeader(document: ITextDocument, header?: TocEntry, toc?: r
const children = toc.filter(t => header.sectionLocation.range.contains(t.sectionLocation.range) && t.sectionLocation.range.start.line > header.sectionLocation.range.start.line).sort((t1, t2) => t1.line - t2.line);
if (children.length > 0) {
childRange = children[0].sectionLocation.range.start;
const lineText = document.lineAt(childRange.line - 1).text;
const lineText = getLine(document, childRange.line - 1);
return childRange ? childRange.translate(-1, lineText.length) : undefined;
}
}
Expand Down
14 changes: 7 additions & 7 deletions extensions/markdown-language-features/src/tableOfContents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import * as vscode from 'vscode';
import { ILogger } from './logging';
import { IMdParser } from './markdownEngine';
import { githubSlugifier, Slug, Slugifier } from './slugify';
import { ITextDocument } from './types/textDocument';
import { getLine, ITextDocument } from './types/textDocument';
import { Disposable } from './util/dispose';
import { isMarkdownFile } from './util/file';
import { Schemes } from './util/schemes';
Expand Down Expand Up @@ -108,9 +108,9 @@ export class TableOfContents {
}

const lineNumber = heading.map[0];
const line = document.lineAt(lineNumber);
const line = getLine(document, lineNumber);

let slug = parser.slugifier.fromHeading(line.text);
let slug = parser.slugifier.fromHeading(line);
const existingSlugEntry = existingSlugEntries.get(slug.value);
if (existingSlugEntry) {
++existingSlugEntry.count;
Expand All @@ -120,14 +120,14 @@ export class TableOfContents {
}

const headerLocation = new vscode.Location(document.uri,
new vscode.Range(lineNumber, 0, lineNumber, line.text.length));
new vscode.Range(lineNumber, 0, lineNumber, line.length));

const headerTextLocation = new vscode.Location(document.uri,
new vscode.Range(lineNumber, line.text.match(/^#+\s*/)?.[0].length ?? 0, lineNumber, line.text.length - (line.text.match(/\s*#*$/)?.[0].length ?? 0)));
new vscode.Range(lineNumber, line.match(/^#+\s*/)?.[0].length ?? 0, lineNumber, line.length - (line.match(/\s*#*$/)?.[0].length ?? 0)));

toc.push({
slug,
text: TableOfContents.getHeaderText(line.text),
text: TableOfContents.getHeaderText(line),
level: TableOfContents.getHeaderLevel(heading.markup),
line: lineNumber,
sectionLocation: headerLocation, // Populated in next steps
Expand All @@ -151,7 +151,7 @@ export class TableOfContents {
sectionLocation: new vscode.Location(document.uri,
new vscode.Range(
entry.sectionLocation.range.start,
new vscode.Position(endLine, document.lineAt(endLine).text.length)))
new vscode.Position(endLine, getLine(document, endLine).length)))
};
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { nulLogger } from './nulLogging';
import { assertRangeEqual, joinLines, workspacePath } from './util';


suite.only('Markdown: MdLinkComputer', () => {
suite('Markdown: MdLinkComputer', () => {

function getLinksForFile(fileContents: string): Promise<MdLink[]> {
const doc = new InMemoryDocument(workspacePath('x.md'), fileContents);
Expand Down
15 changes: 5 additions & 10 deletions extensions/markdown-language-features/src/types/textDocument.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import type * as vscode from 'vscode';

/**
* Minimal version of {@link vscode.TextLine}.
*/
export interface ITextLine {
readonly text: string;
readonly isEmptyOrWhitespace: boolean;
}
import * as vscode from 'vscode';

/**
* Minimal version of {@link vscode.TextDocument}.
Expand All @@ -22,6 +14,9 @@ export interface ITextDocument {
readonly lineCount: number;

getText(range?: vscode.Range): string;
lineAt(line: number): ITextLine;
positionAt(offset: number): vscode.Position;
}

export function getLine(doc: ITextDocument, line: number): string {
return doc.getText(new vscode.Range(line, 0, line, Number.MAX_VALUE)).replace(/\r?\n$/, '');
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@

import * as vscode from 'vscode';
import { TextDocument } from 'vscode-languageserver-textdocument';
import { ITextDocument, ITextLine } from '../types/textDocument';
import { ITextDocument } from '../types/textDocument';

export class InMemoryDocument implements ITextDocument {

private readonly _doc: TextDocument;

private lines: ITextLine[] | undefined;

constructor(
public readonly uri: vscode.Uri, contents: string,
public readonly version = 0,
Expand All @@ -25,16 +23,6 @@ export class InMemoryDocument implements ITextDocument {
return this._doc.lineCount;
}

lineAt(index: any): ITextLine {
if (!this.lines) {
this.lines = this._doc.getText().split(/\r?\n/).map(text => ({
text,
get isEmptyOrWhitespace() { return /^\s*$/.test(text); }
}));
}
return this.lines[index];
}

positionAt(offset: number): vscode.Position {
const pos = this._doc.positionAt(offset);
return new vscode.Position(pos.line, pos.character);
Expand Down
8 changes: 8 additions & 0 deletions extensions/markdown-language-features/src/util/string.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

export function isEmptyOrWhitespace(str: string): boolean {
return /^\s*$/.test(str);
}