Merge commit 'be3e8236086165e5e45a5a10783823874b3f3ebd' as 'lib/vscode'
This commit is contained in:
@ -0,0 +1,22 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
export function equals<T>(one: ReadonlyArray<T>, other: ReadonlyArray<T>, itemEquals: (a: T, b: T) => boolean = (a, b) => a === b): boolean {
|
||||
if (one.length !== other.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0, len = one.length; i < len; i++) {
|
||||
if (!itemEquals(one[i], other[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export function flatten<T>(arr: ReadonlyArray<T>[]): T[] {
|
||||
return ([] as T[]).concat.apply([], arr);
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
export function disposeAll(disposables: vscode.Disposable[]) {
|
||||
while (disposables.length) {
|
||||
const item = disposables.pop();
|
||||
if (item) {
|
||||
item.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class Disposable {
|
||||
private _isDisposed = false;
|
||||
|
||||
protected _disposables: vscode.Disposable[] = [];
|
||||
|
||||
public dispose(): any {
|
||||
if (this._isDisposed) {
|
||||
return;
|
||||
}
|
||||
this._isDisposed = true;
|
||||
disposeAll(this._disposables);
|
||||
}
|
||||
|
||||
protected _register<T extends vscode.Disposable>(value: T): T {
|
||||
if (this._isDisposed) {
|
||||
value.dispose();
|
||||
} else {
|
||||
this._disposables.push(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
protected get isDisposed() {
|
||||
return this._isDisposed;
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
export function isMarkdownFile(document: vscode.TextDocument) {
|
||||
return document.languageId === 'markdown';
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Return a hash value for an object.
|
||||
*/
|
||||
export function hash(obj: any, hashVal = 0): number {
|
||||
switch (typeof obj) {
|
||||
case 'object':
|
||||
if (obj === null) {
|
||||
return numberHash(349, hashVal);
|
||||
} else if (Array.isArray(obj)) {
|
||||
return arrayHash(obj, hashVal);
|
||||
}
|
||||
return objectHash(obj, hashVal);
|
||||
case 'string':
|
||||
return stringHash(obj, hashVal);
|
||||
case 'boolean':
|
||||
return booleanHash(obj, hashVal);
|
||||
case 'number':
|
||||
return numberHash(obj, hashVal);
|
||||
case 'undefined':
|
||||
return 937 * 31;
|
||||
default:
|
||||
return numberHash(obj, 617);
|
||||
}
|
||||
}
|
||||
|
||||
function numberHash(val: number, initialHashVal: number): number {
|
||||
return (((initialHashVal << 5) - initialHashVal) + val) | 0; // hashVal * 31 + ch, keep as int32
|
||||
}
|
||||
|
||||
function booleanHash(b: boolean, initialHashVal: number): number {
|
||||
return numberHash(b ? 433 : 863, initialHashVal);
|
||||
}
|
||||
|
||||
function stringHash(s: string, hashVal: number) {
|
||||
hashVal = numberHash(149417, hashVal);
|
||||
for (let i = 0, length = s.length; i < length; i++) {
|
||||
hashVal = numberHash(s.charCodeAt(i), hashVal);
|
||||
}
|
||||
return hashVal;
|
||||
}
|
||||
|
||||
function arrayHash(arr: any[], initialHashVal: number): number {
|
||||
initialHashVal = numberHash(104579, initialHashVal);
|
||||
return arr.reduce((hashVal, item) => hash(item, hashVal), initialHashVal);
|
||||
}
|
||||
|
||||
function objectHash(obj: any, initialHashVal: number): number {
|
||||
initialHashVal = numberHash(181387, initialHashVal);
|
||||
return Object.keys(obj).sort().reduce((hashVal, key) => {
|
||||
hashVal = stringHash(key, hashVal);
|
||||
return hash(obj[key], hashVal);
|
||||
}, initialHashVal);
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
export interface Lazy<T> {
|
||||
readonly value: T;
|
||||
readonly hasValue: boolean;
|
||||
map<R>(f: (x: T) => R): Lazy<R>;
|
||||
}
|
||||
|
||||
class LazyValue<T> implements Lazy<T> {
|
||||
private _hasValue: boolean = false;
|
||||
private _value?: T;
|
||||
|
||||
constructor(
|
||||
private readonly _getValue: () => T
|
||||
) { }
|
||||
|
||||
get value(): T {
|
||||
if (!this._hasValue) {
|
||||
this._hasValue = true;
|
||||
this._value = this._getValue();
|
||||
}
|
||||
return this._value!;
|
||||
}
|
||||
|
||||
get hasValue(): boolean {
|
||||
return this._hasValue;
|
||||
}
|
||||
|
||||
public map<R>(f: (x: T) => R): Lazy<R> {
|
||||
return new LazyValue(() => f(this.value));
|
||||
}
|
||||
}
|
||||
|
||||
export function lazy<T>(getValue: () => T): Lazy<T> {
|
||||
return new LazyValue<T>(getValue);
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
export const Schemes = {
|
||||
http: 'http:',
|
||||
https: 'https:',
|
||||
file: 'file:',
|
||||
untitled: 'untitled',
|
||||
mailto: 'mailto:',
|
||||
data: 'data:',
|
||||
vscode: 'vscode:',
|
||||
'vscode-insiders': 'vscode-insiders:',
|
||||
'vscode-resource': 'vscode-resource:',
|
||||
};
|
||||
|
||||
const knownSchemes = [
|
||||
...Object.values(Schemes),
|
||||
`${vscode.env.uriScheme}:`
|
||||
];
|
||||
|
||||
export function getUriForLinkWithKnownExternalScheme(link: string): vscode.Uri | undefined {
|
||||
if (knownSchemes.some(knownScheme => isOfScheme(knownScheme, link))) {
|
||||
return vscode.Uri.parse(link);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function isOfScheme(scheme: string, link: string): boolean {
|
||||
return link.toLowerCase().startsWith(scheme);
|
||||
}
|
||||
|
||||
export const MarkdownFileExtensions: readonly string[] = [
|
||||
'.md',
|
||||
'.mkd',
|
||||
'.mdwn',
|
||||
'.mdown',
|
||||
'.markdown',
|
||||
'.markdn',
|
||||
'.mdtxt',
|
||||
'.mdtext',
|
||||
'.workbook',
|
||||
];
|
@ -0,0 +1,33 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
export interface WebviewResourceProvider {
|
||||
asWebviewUri(resource: vscode.Uri): vscode.Uri;
|
||||
|
||||
readonly cspSource: string;
|
||||
}
|
||||
|
||||
export function normalizeResource(
|
||||
base: vscode.Uri,
|
||||
resource: vscode.Uri
|
||||
): vscode.Uri {
|
||||
// If we have a windows path and are loading a workspace with an authority,
|
||||
// make sure we use a unc path with an explicit localhost authority.
|
||||
//
|
||||
// Otherwise, the `<base>` rule will insert the authority into the resolved resource
|
||||
// URI incorrectly.
|
||||
if (base.authority && !resource.authority) {
|
||||
const driveMatch = resource.path.match(/^\/(\w):\//);
|
||||
if (driveMatch) {
|
||||
return vscode.Uri.file(`\\\\localhost\\${driveMatch[1]}$\\${resource.fsPath.replace(/^\w:\\/, '')}`).with({
|
||||
fragment: resource.fragment,
|
||||
query: resource.query
|
||||
});
|
||||
}
|
||||
}
|
||||
return resource;
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import { Disposable } from '../util/dispose';
|
||||
import { isMarkdownFile } from './file';
|
||||
|
||||
export class TopmostLineMonitor extends Disposable {
|
||||
|
||||
private readonly pendingUpdates = new Map<string, number>();
|
||||
private readonly throttle = 50;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this._register(vscode.window.onDidChangeTextEditorVisibleRanges(event => {
|
||||
if (isMarkdownFile(event.textEditor.document)) {
|
||||
const line = getVisibleLine(event.textEditor);
|
||||
if (typeof line === 'number') {
|
||||
this.updateLine(event.textEditor.document.uri, line);
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private readonly _onChanged = this._register(new vscode.EventEmitter<{ readonly resource: vscode.Uri, readonly line: number }>());
|
||||
public readonly onDidChanged = this._onChanged.event;
|
||||
|
||||
private updateLine(
|
||||
resource: vscode.Uri,
|
||||
line: number
|
||||
) {
|
||||
const key = resource.toString();
|
||||
if (!this.pendingUpdates.has(key)) {
|
||||
// schedule update
|
||||
setTimeout(() => {
|
||||
if (this.pendingUpdates.has(key)) {
|
||||
this._onChanged.fire({
|
||||
resource,
|
||||
line: this.pendingUpdates.get(key) as number
|
||||
});
|
||||
this.pendingUpdates.delete(key);
|
||||
}
|
||||
}, this.throttle);
|
||||
}
|
||||
|
||||
this.pendingUpdates.set(key, line);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the top-most visible range of `editor`.
|
||||
*
|
||||
* Returns a fractional line number based the visible character within the line.
|
||||
* Floor to get real line number
|
||||
*/
|
||||
export function getVisibleLine(
|
||||
editor: vscode.TextEditor
|
||||
): number | undefined {
|
||||
if (!editor.visibleRanges.length) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const firstVisiblePosition = editor.visibleRanges[0].start;
|
||||
const lineNumber = firstVisiblePosition.line;
|
||||
const line = editor.document.lineAt(lineNumber);
|
||||
const progress = firstVisiblePosition.character / (line.text.length + 2);
|
||||
return lineNumber + progress;
|
||||
}
|
Reference in New Issue
Block a user