This commit is contained in:
2025-11-02 19:17:20 +08:00
parent ebf784146e
commit e71b69db5f
2575 changed files with 1242294 additions and 95 deletions

View File

@@ -0,0 +1,55 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { mainWindow } from './window.js';
class WindowManager {
constructor() {
// --- Zoom Factor
this.mapWindowIdToZoomFactor = new Map();
}
static { this.INSTANCE = new WindowManager(); }
getZoomFactor(targetWindow) {
return this.mapWindowIdToZoomFactor.get(this.getWindowId(targetWindow)) ?? 1;
}
getWindowId(targetWindow) {
return targetWindow.vscodeWindowId;
}
}
export function addMatchMediaChangeListener(targetWindow, query, callback) {
if (typeof query === 'string') {
query = targetWindow.matchMedia(query);
}
query.addEventListener('change', callback);
}
/** The zoom scale for an index, e.g. 1, 1.2, 1.4 */
export function getZoomFactor(targetWindow) {
return WindowManager.INSTANCE.getZoomFactor(targetWindow);
}
const userAgent = navigator.userAgent;
export const isFirefox = (userAgent.indexOf('Firefox') >= 0);
export const isWebKit = (userAgent.indexOf('AppleWebKit') >= 0);
export const isChrome = (userAgent.indexOf('Chrome') >= 0);
export const isSafari = (!isChrome && (userAgent.indexOf('Safari') >= 0));
export const isWebkitWebView = (!isChrome && !isSafari && isWebKit);
export const isElectron = (userAgent.indexOf('Electron/') >= 0);
export const isAndroid = (userAgent.indexOf('Android') >= 0);
let standalone = false;
if (typeof mainWindow.matchMedia === 'function') {
const standaloneMatchMedia = mainWindow.matchMedia('(display-mode: standalone) or (display-mode: window-controls-overlay)');
const fullScreenMatchMedia = mainWindow.matchMedia('(display-mode: fullscreen)');
standalone = standaloneMatchMedia.matches;
addMatchMediaChangeListener(mainWindow, standaloneMatchMedia, ({ matches }) => {
// entering fullscreen would change standaloneMatchMedia.matches to false
// if standalone is true (running as PWA) and entering fullscreen, skip this change
if (standalone && fullScreenMatchMedia.matches) {
return;
}
// otherwise update standalone (browser to PWA or PWA to browser)
standalone = matches;
});
}
export function isStandalone() {
return standalone;
}
//# sourceMappingURL=browser.js.map

File diff suppressed because one or more lines are too long

View File

@@ -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 browser from './browser.js';
import { mainWindow } from './window.js';
import * as platform from '../common/platform.js';
/**
* Browser feature we can support in current platform, browser and environment.
*/
export const BrowserFeatures = {
clipboard: {
writeText: (platform.isNative
|| (document.queryCommandSupported && document.queryCommandSupported('copy'))
|| !!(navigator && navigator.clipboard && navigator.clipboard.writeText)),
readText: (platform.isNative
|| !!(navigator && navigator.clipboard && navigator.clipboard.readText))
},
keyboard: (() => {
if (platform.isNative || browser.isStandalone()) {
return 0 /* KeyboardSupport.Always */;
}
if (navigator.keyboard || browser.isSafari) {
return 1 /* KeyboardSupport.FullScreen */;
}
return 2 /* KeyboardSupport.None */;
})(),
// 'ontouchstart' in window always evaluates to true with typescript's modern typings. This causes `window` to be
// `never` later in `window.navigator`. That's why we need the explicit `window as Window` cast
touch: 'ontouchstart' in mainWindow || navigator.maxTouchPoints > 0,
pointerEvents: mainWindow.PointerEvent && ('ontouchstart' in mainWindow || navigator.maxTouchPoints > 0)
};
//# sourceMappingURL=canIUse.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src/vs/base/browser/canIUse.ts","vs/base/browser/canIUse.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAEhG,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,KAAK,QAAQ,MAAM,uBAAuB,CAAC;AAQlD;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC9B,SAAS,EAAE;QACV,SAAS,EAAE,CACV,QAAQ,CAAC,QAAQ;eACd,CAAC,QAAQ,CAAC,qBAAqB,IAAI,QAAQ,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC;eAC1E,CAAC,CAAC,CAAC,SAAS,IAAI,SAAS,CAAC,SAAS,IAAI,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,CACxE;QACD,QAAQ,EAAE,CACT,QAAQ,CAAC,QAAQ;eACd,CAAC,CAAC,CAAC,SAAS,IAAI,SAAS,CAAC,SAAS,IAAI,SAAS,CAAC,SAAS,CAAC,QAAQ,CAAC,CACvE;KACD;IACD,QAAQ,EAAE,CAAC,GAAG,EAAE;QACf,IAAI,QAAQ,CAAC,QAAQ,IAAI,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC;YACjD,sCAA8B;QAC/B,CAAC;QAED,IAAU,SAAU,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;YACnD,0CAAkC;QACnC,CAAC;QAED,oCAA4B;IAC7B,CAAC,CAAC,EAAE;IAEJ,iHAAiH;IACjH,+FAA+F;IAC/F,KAAK,EAAE,cAAc,IAAI,UAAU,IAAI,SAAS,CAAC,cAAc,GAAG,CAAC;IACnE,aAAa,EAAE,UAAU,CAAC,YAAY,IAAI,CAAC,cAAc,IAAI,UAAU,IAAI,SAAS,CAAC,cAAc,GAAG,CAAC,CAAC;CACxG,CAAC","file":"canIUse.js","sourceRoot":"file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as browser from './browser.js';\nimport { mainWindow } from './window.js';\nimport * as platform from '../common/platform.js';\n\nexport const enum KeyboardSupport {\n\tAlways,\n\tFullScreen,\n\tNone\n}\n\n/**\n * Browser feature we can support in current platform, browser and environment.\n */\nexport const BrowserFeatures = {\n\tclipboard: {\n\t\twriteText: (\n\t\t\tplatform.isNative\n\t\t\t|| (document.queryCommandSupported && document.queryCommandSupported('copy'))\n\t\t\t|| !!(navigator && navigator.clipboard && navigator.clipboard.writeText)\n\t\t),\n\t\treadText: (\n\t\t\tplatform.isNative\n\t\t\t|| !!(navigator && navigator.clipboard && navigator.clipboard.readText)\n\t\t)\n\t},\n\tkeyboard: (() => {\n\t\tif (platform.isNative || browser.isStandalone()) {\n\t\t\treturn KeyboardSupport.Always;\n\t\t}\n\n\t\tif ((<any>navigator).keyboard || browser.isSafari) {\n\t\t\treturn KeyboardSupport.FullScreen;\n\t\t}\n\n\t\treturn KeyboardSupport.None;\n\t})(),\n\n\t// 'ontouchstart' in window always evaluates to true with typescript's modern typings. This causes `window` to be\n\t// `never` later in `window.navigator`. That's why we need the explicit `window as Window` cast\n\ttouch: 'ontouchstart' in mainWindow || navigator.maxTouchPoints > 0,\n\tpointerEvents: mainWindow.PointerEvent && ('ontouchstart' in mainWindow || navigator.maxTouchPoints > 0)\n};\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as browser from './browser.js';\nimport { mainWindow } from './window.js';\nimport * as platform from '../common/platform.js';\n\nexport const enum KeyboardSupport {\n\tAlways,\n\tFullScreen,\n\tNone\n}\n\n/**\n * Browser feature we can support in current platform, browser and environment.\n */\nexport const BrowserFeatures = {\n\tclipboard: {\n\t\twriteText: (\n\t\t\tplatform.isNative\n\t\t\t|| (document.queryCommandSupported && document.queryCommandSupported('copy'))\n\t\t\t|| !!(navigator && navigator.clipboard && navigator.clipboard.writeText)\n\t\t),\n\t\treadText: (\n\t\t\tplatform.isNative\n\t\t\t|| !!(navigator && navigator.clipboard && navigator.clipboard.readText)\n\t\t)\n\t},\n\tkeyboard: (() => {\n\t\tif (platform.isNative || browser.isStandalone()) {\n\t\t\treturn KeyboardSupport.Always;\n\t\t}\n\n\t\tif ((<any>navigator).keyboard || browser.isSafari) {\n\t\t\treturn KeyboardSupport.FullScreen;\n\t\t}\n\n\t\treturn KeyboardSupport.None;\n\t})(),\n\n\t// 'ontouchstart' in window always evaluates to true with typescript's modern typings. This causes `window` to be\n\t// `never` later in `window.navigator`. That's why we need the explicit `window as Window` cast\n\ttouch: 'ontouchstart' in mainWindow || navigator.maxTouchPoints > 0,\n\tpointerEvents: mainWindow.PointerEvent && ('ontouchstart' in mainWindow || navigator.maxTouchPoints > 0)\n};\n"]}

View File

@@ -0,0 +1,6 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export {};
//# sourceMappingURL=contextmenu.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src/vs/base/browser/contextmenu.ts","vs/base/browser/contextmenu.ts"],"names":[],"mappings":"AAAA;;;gGAGgG","file":"contextmenu.js","sourceRoot":"file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { StandardMouseEvent } from './mouseEvent.js';\nimport { IActionViewItemOptions } from './ui/actionbar/actionViewItems.js';\nimport { IActionViewItem } from './ui/actionbar/actionbar.js';\nimport { AnchorAlignment, AnchorAxisAlignment, IAnchor } from './ui/contextview/contextview.js';\nimport { IAction, IActionRunner } from '../common/actions.js';\nimport { ResolvedKeybinding } from '../common/keybindings.js';\nimport { OmitOptional } from '../common/types.js';\n\nexport interface IContextMenuEvent {\n}\n\n/**\n * A specific context menu location to position the menu at.\n * Uses some TypeScript type tricks to prevent allowing to\n * pass in a `MouseEvent` and force people to use `StandardMouseEvent`.\n */\ntype ContextMenuLocation = OmitOptional<IAnchor> & { getModifierState?: never };\n\nexport interface IContextMenuDelegate {\n\t/**\n\t * The anchor where to position the context view.\n\t * Use a `HTMLElement` to position the view at the element,\n\t * a `StandardMouseEvent` to position it at the mouse position\n\t * or an `ContextMenuLocation` to position it at a specific location.\n\t */\n\tgetAnchor(): HTMLElement | StandardMouseEvent | ContextMenuLocation;\n\tgetActions(): readonly IAction[];\n\tgetActionViewItem?(action: IAction, options: IActionViewItemOptions): IActionViewItem | undefined;\n\tgetActionsContext?(event?: IContextMenuEvent): unknown;\n\tgetKeyBinding?(action: IAction): ResolvedKeybinding | undefined;\n\tgetMenuClassName?(): string;\n\tonHide?(didCancel: boolean): void;\n\tactionRunner?: IActionRunner;\n\tskipTelemetry?: boolean;\n\tautoSelectFirstItem?: boolean;\n\tanchorAlignment?: AnchorAlignment;\n\tanchorAxisAlignment?: AnchorAxisAlignment;\n\tdomForShadowRoot?: HTMLElement;\n\t/**\n\t * custom context menus with higher layers are rendered higher in z-index order\n\t */\n\tlayer?: number;\n}\n\nexport interface IContextMenuProvider {\n\tshowContextMenu(delegate: IContextMenuDelegate): void;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { StandardMouseEvent } from './mouseEvent.js';\nimport { IActionViewItemOptions } from './ui/actionbar/actionViewItems.js';\nimport { IActionViewItem } from './ui/actionbar/actionbar.js';\nimport { AnchorAlignment, AnchorAxisAlignment, IAnchor } from './ui/contextview/contextview.js';\nimport { IAction, IActionRunner } from '../common/actions.js';\nimport { ResolvedKeybinding } from '../common/keybindings.js';\nimport { OmitOptional } from '../common/types.js';\n\nexport interface IContextMenuEvent {\n}\n\n/**\n * A specific context menu location to position the menu at.\n * Uses some TypeScript type tricks to prevent allowing to\n * pass in a `MouseEvent` and force people to use `StandardMouseEvent`.\n */\ntype ContextMenuLocation = OmitOptional<IAnchor> & { getModifierState?: never };\n\nexport interface IContextMenuDelegate {\n\t/**\n\t * The anchor where to position the context view.\n\t * Use a `HTMLElement` to position the view at the element,\n\t * a `StandardMouseEvent` to position it at the mouse position\n\t * or an `ContextMenuLocation` to position it at a specific location.\n\t */\n\tgetAnchor(): HTMLElement | StandardMouseEvent | ContextMenuLocation;\n\tgetActions(): readonly IAction[];\n\tgetActionViewItem?(action: IAction, options: IActionViewItemOptions): IActionViewItem | undefined;\n\tgetActionsContext?(event?: IContextMenuEvent): unknown;\n\tgetKeyBinding?(action: IAction): ResolvedKeybinding | undefined;\n\tgetMenuClassName?(): string;\n\tonHide?(didCancel: boolean): void;\n\tactionRunner?: IActionRunner;\n\tskipTelemetry?: boolean;\n\tautoSelectFirstItem?: boolean;\n\tanchorAlignment?: AnchorAlignment;\n\tanchorAxisAlignment?: AnchorAxisAlignment;\n\tdomForShadowRoot?: HTMLElement;\n\t/**\n\t * custom context menus with higher layers are rendered higher in z-index order\n\t */\n\tlayer?: number;\n}\n\nexport interface IContextMenuProvider {\n\tshowContextMenu(delegate: IContextMenuDelegate): void;\n}\n"]}

View File

@@ -0,0 +1,67 @@
import { FileAccess } from '../common/network.js';
function asFragment(raw) {
return raw;
}
export function asCssValueWithDefault(cssPropertyValue, dflt) {
if (cssPropertyValue !== undefined) {
const variableMatch = cssPropertyValue.match(/^\s*var\((.+)\)$/);
if (variableMatch) {
const varArguments = variableMatch[1].split(',', 2);
if (varArguments.length === 2) {
dflt = asCssValueWithDefault(varArguments[1].trim(), dflt);
}
return `var(${varArguments[0]}, ${dflt})`;
}
return cssPropertyValue;
}
return dflt;
}
export function identValue(value) {
const out = value.replaceAll(/[^_\-a-z0-9]/gi, '');
if (out !== value) {
console.warn(`CSS ident value ${value} modified to ${out} to be safe for CSS`);
}
return asFragment(out);
}
export function stringValue(value) {
return asFragment(`'${value.replaceAll(/'/g, '\\000027')}'`);
}
/**
* returns url('...')
*/
export function asCSSUrl(uri) {
if (!uri) {
return asFragment(`url('')`);
}
return inline `url('${asFragment(CSS.escape(FileAccess.uriToBrowserUri(uri).toString(true)))}')`;
}
export function className(value, escapingExpected = false) {
const out = CSS.escape(value);
if (!escapingExpected && out !== value) {
console.warn(`CSS class name ${value} modified to ${out} to be safe for CSS`);
}
return asFragment(out);
}
/**
* Template string tag that that constructs a CSS fragment.
*
* All expressions in the template must be css safe values.
*/
export function inline(strings, ...values) {
return asFragment(strings.reduce((result, str, i) => {
const value = values[i] || '';
return result + str + value;
}, ''));
}
export class Builder {
constructor() {
this._parts = [];
}
push(...parts) {
this._parts.push(...parts);
}
join(joiner = '\n') {
return asFragment(this._parts.join(joiner));
}
}
//# sourceMappingURL=cssValue.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,27 @@
import { Mimes } from '../common/mime.js';
// Common data transfers
export const DataTransfers = {
/**
* Application specific resource transfer type
*/
RESOURCES: 'ResourceURLs',
/**
* Browser specific transfer type to download
*/
DOWNLOAD_URL: 'DownloadURL',
/**
* Browser specific transfer type for files
*/
FILES: 'Files',
/**
* Typically transfer type for copy/paste transfers.
*/
TEXT: Mimes.text,
/**
* Internal type used to pass around text/uri-list data.
*
* This is needed to work around https://bugs.chromium.org/p/chromium/issues/detail?id=239745.
*/
INTERNAL_URI_LIST: 'application/vnd.code.uri-list',
};
//# sourceMappingURL=dnd.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src/vs/base/browser/dnd.ts","vs/base/browser/dnd.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE1C,wBAAwB;AACxB,MAAM,CAAC,MAAM,aAAa,GAAG;IAE5B;;OAEG;IACH,SAAS,EAAE,cAAc;IAEzB;;OAEG;IACH,YAAY,EAAE,aAAa;IAE3B;;OAEG;IACH,KAAK,EAAE,OAAO;IAEd;;OAEG;IACH,IAAI,EAAE,KAAK,CAAC,IAAI;IAEhB;;;;OAIG;IACH,iBAAiB,EAAE,+BAA+B;CAClD,CAAC","file":"dnd.js","sourceRoot":"file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src","sourcesContent":["\nimport { Mimes } from '../common/mime.js';\n\n// Common data transfers\nexport const DataTransfers = {\n\n\t/**\n\t * Application specific resource transfer type\n\t */\n\tRESOURCES: 'ResourceURLs',\n\n\t/**\n\t * Browser specific transfer type to download\n\t */\n\tDOWNLOAD_URL: 'DownloadURL',\n\n\t/**\n\t * Browser specific transfer type for files\n\t */\n\tFILES: 'Files',\n\n\t/**\n\t * Typically transfer type for copy/paste transfers.\n\t */\n\tTEXT: Mimes.text,\n\n\t/**\n\t * Internal type used to pass around text/uri-list data.\n\t *\n\t * This is needed to work around https://bugs.chromium.org/p/chromium/issues/detail?id=239745.\n\t */\n\tINTERNAL_URI_LIST: 'application/vnd.code.uri-list',\n};\n\nexport interface IDragAndDropData {\n\tupdate(dataTransfer: DataTransfer): void;\n\tgetData(): unknown;\n}\n","\nimport { Mimes } from '../common/mime.js';\n\n// Common data transfers\nexport const DataTransfers = {\n\n\t/**\n\t * Application specific resource transfer type\n\t */\n\tRESOURCES: 'ResourceURLs',\n\n\t/**\n\t * Browser specific transfer type to download\n\t */\n\tDOWNLOAD_URL: 'DownloadURL',\n\n\t/**\n\t * Browser specific transfer type for files\n\t */\n\tFILES: 'Files',\n\n\t/**\n\t * Typically transfer type for copy/paste transfers.\n\t */\n\tTEXT: Mimes.text,\n\n\t/**\n\t * Internal type used to pass around text/uri-list data.\n\t *\n\t * This is needed to work around https://bugs.chromium.org/p/chromium/issues/detail?id=239745.\n\t */\n\tINTERNAL_URI_LIST: 'application/vnd.code.uri-list',\n};\n\nexport interface IDragAndDropData {\n\tupdate(dataTransfer: DataTransfer): void;\n\tgetData(): unknown;\n}\n"]}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,303 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Schemas } from '../common/network.js';
import { reset } from './dom.js';
// eslint-disable-next-line no-restricted-imports
import dompurify from './dompurify/dompurify.js';
/**
* List of safe, non-input html tags.
*/
export const basicMarkupHtmlTags = Object.freeze([
'a',
'abbr',
'b',
'bdo',
'blockquote',
'br',
'caption',
'cite',
'code',
'col',
'colgroup',
'dd',
'del',
'details',
'dfn',
'div',
'dl',
'dt',
'em',
'figcaption',
'figure',
'h1',
'h2',
'h3',
'h4',
'h5',
'h6',
'hr',
'i',
'img',
'ins',
'kbd',
'label',
'li',
'mark',
'ol',
'p',
'pre',
'q',
'rp',
'rt',
'ruby',
's',
'samp',
'small',
'small',
'source',
'span',
'strike',
'strong',
'sub',
'summary',
'sup',
'table',
'tbody',
'td',
'tfoot',
'th',
'thead',
'time',
'tr',
'tt',
'u',
'ul',
'var',
'video',
'wbr',
]);
export const defaultAllowedAttrs = Object.freeze([
'href',
'target',
'src',
'alt',
'title',
'for',
'name',
'role',
'tabindex',
'x-dispatch',
'required',
'checked',
'placeholder',
'type',
'start',
'width',
'height',
'align',
]);
const fakeRelativeUrlProtocol = 'vscode-relative-path';
function validateLink(value, allowedProtocols) {
if (allowedProtocols.override === '*') {
return true; // allow all protocols
}
try {
const url = new URL(value, fakeRelativeUrlProtocol + '://');
if (allowedProtocols.override.includes(url.protocol.replace(/:$/, ''))) {
return true;
}
if (allowedProtocols.allowRelativePaths
&& url.protocol === fakeRelativeUrlProtocol + ':'
&& !value.trim().toLowerCase().startsWith(fakeRelativeUrlProtocol)) {
return true;
}
return false;
}
catch (e) {
return false;
}
}
/**
* Hooks dompurify using `afterSanitizeAttributes` to check that all `href` and `src`
* attributes are valid.
*/
function hookDomPurifyHrefAndSrcSanitizer(allowedLinkProtocols, allowedMediaProtocols) {
dompurify.addHook('afterSanitizeAttributes', (node) => {
// check all href/src attributes for validity
for (const attr of ['href', 'src']) {
if (node.hasAttribute(attr)) {
const attrValue = node.getAttribute(attr);
if (attr === 'href') {
if (!attrValue.startsWith('#') && !validateLink(attrValue, allowedLinkProtocols)) {
node.removeAttribute(attr);
}
}
else { // 'src'
if (!validateLink(attrValue, allowedMediaProtocols)) {
node.removeAttribute(attr);
}
}
}
}
});
}
const defaultDomPurifyConfig = Object.freeze({
ALLOWED_TAGS: [...basicMarkupHtmlTags],
ALLOWED_ATTR: [...defaultAllowedAttrs],
// We sanitize the src/href attributes later if needed
ALLOW_UNKNOWN_PROTOCOLS: true,
});
/**
* Sanitizes an html string.
*
* @param untrusted The HTML string to sanitize.
* @param config Optional configuration for sanitization. If not provided, defaults to a safe configuration.
*
* @returns A sanitized string of html.
*/
export function sanitizeHtml(untrusted, config) {
return doSanitizeHtml(untrusted, config, 'trusted');
}
function doSanitizeHtml(untrusted, config, outputType) {
try {
const resolvedConfig = { ...defaultDomPurifyConfig };
if (config?.allowedTags) {
if (config.allowedTags.override) {
resolvedConfig.ALLOWED_TAGS = [...config.allowedTags.override];
}
if (config.allowedTags.augment) {
resolvedConfig.ALLOWED_TAGS = [...(resolvedConfig.ALLOWED_TAGS ?? []), ...config.allowedTags.augment];
}
}
let resolvedAttributes = [...defaultAllowedAttrs];
if (config?.allowedAttributes) {
if (config.allowedAttributes.override) {
resolvedAttributes = [...config.allowedAttributes.override];
}
if (config.allowedAttributes.augment) {
resolvedAttributes = [...resolvedAttributes, ...config.allowedAttributes.augment];
}
}
// All attr names are lower-case in the sanitizer hooks
resolvedAttributes = resolvedAttributes.map((attr) => {
if (typeof attr === 'string') {
return attr.toLowerCase();
}
return {
attributeName: attr.attributeName.toLowerCase(),
shouldKeep: attr.shouldKeep,
};
});
const allowedAttrNames = new Set(resolvedAttributes.map(attr => typeof attr === 'string' ? attr : attr.attributeName));
const allowedAttrPredicates = new Map();
for (const attr of resolvedAttributes) {
if (typeof attr === 'string') {
// New string attribute value clears previously set predicates
allowedAttrPredicates.delete(attr);
}
else {
allowedAttrPredicates.set(attr.attributeName, attr);
}
}
resolvedConfig.ALLOWED_ATTR = Array.from(allowedAttrNames);
hookDomPurifyHrefAndSrcSanitizer({
override: config?.allowedLinkProtocols?.override ?? [Schemas.http, Schemas.https],
allowRelativePaths: config?.allowRelativeLinkPaths ?? false
}, {
override: config?.allowedMediaProtocols?.override ?? [Schemas.http, Schemas.https],
allowRelativePaths: config?.allowRelativeMediaPaths ?? false
});
if (config?.replaceWithPlaintext) {
dompurify.addHook('uponSanitizeElement', replaceWithPlainTextHook);
}
if (allowedAttrPredicates.size) {
dompurify.addHook('uponSanitizeAttribute', (node, e) => {
const predicate = allowedAttrPredicates.get(e.attrName);
if (predicate) {
const result = predicate.shouldKeep(node, e);
if (typeof result === 'string') {
e.keepAttr = true;
e.attrValue = result;
}
else {
e.keepAttr = result;
}
}
else {
e.keepAttr = allowedAttrNames.has(e.attrName);
}
});
}
if (outputType === 'dom') {
return dompurify.sanitize(untrusted, {
...resolvedConfig,
RETURN_DOM_FRAGMENT: true
});
}
else {
return dompurify.sanitize(untrusted, {
...resolvedConfig,
RETURN_TRUSTED_TYPE: true
});
}
}
finally {
dompurify.removeAllHooks();
}
}
const selfClosingTags = ['area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr'];
function replaceWithPlainTextHook(element, data, _config) {
if (!data.allowedTags[data.tagName] && data.tagName !== 'body') {
const replacement = convertTagToPlaintext(element);
if (element.nodeType === Node.COMMENT_NODE) {
// Workaround for https://github.com/cure53/DOMPurify/issues/1005
// The comment will be deleted in the next phase. However if we try to remove it now, it will cause
// an exception. Instead we insert the text node before the comment.
element.parentElement?.insertBefore(replacement, element);
}
else {
element.parentElement?.replaceChild(replacement, element);
}
}
}
export function convertTagToPlaintext(element) {
let startTagText;
let endTagText;
if (element.nodeType === Node.COMMENT_NODE) {
startTagText = `<!--${element.textContent}-->`;
}
else {
const tagName = element.tagName.toLowerCase();
const isSelfClosing = selfClosingTags.includes(tagName);
const attrString = element.attributes.length ?
' ' + Array.from(element.attributes)
.map(attr => `${attr.name}="${attr.value}"`)
.join(' ')
: '';
startTagText = `<${tagName}${attrString}>`;
if (!isSelfClosing) {
endTagText = `</${tagName}>`;
}
}
const fragment = document.createDocumentFragment();
const textNode = element.ownerDocument.createTextNode(startTagText);
fragment.appendChild(textNode);
while (element.firstChild) {
fragment.appendChild(element.firstChild);
}
const endTagTextNode = endTagText ? element.ownerDocument.createTextNode(endTagText) : undefined;
if (endTagTextNode) {
fragment.appendChild(endTagTextNode);
}
return fragment;
}
/**
* Sanitizes the given `value` and reset the given `node` with it.
*/
export function safeSetInnerHtml(node, untrusted, config) {
const fragment = doSanitizeHtml(untrusted, config, 'dom');
reset(node, fragment);
}
//# sourceMappingURL=domSanitize.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,142 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { DisposableStore, toDisposable } from '../common/lifecycle.js';
import { autorun } from '../common/observable.js';
import { isFirefox } from './browser.js';
import { getWindows, sharedMutationObserver } from './dom.js';
import { mainWindow } from './window.js';
const globalStylesheets = new Map();
/**
* A version of createStyleSheet which has a unified API to initialize/set the style content.
*/
export function createStyleSheet2() {
return new WrappedStyleElement();
}
class WrappedStyleElement {
constructor() {
this._currentCssStyle = '';
this._styleSheet = undefined;
}
setStyle(cssStyle) {
if (cssStyle === this._currentCssStyle) {
return;
}
this._currentCssStyle = cssStyle;
if (!this._styleSheet) {
this._styleSheet = createStyleSheet(mainWindow.document.head, (s) => s.textContent = cssStyle);
}
else {
this._styleSheet.textContent = cssStyle;
}
}
dispose() {
if (this._styleSheet) {
this._styleSheet.remove();
this._styleSheet = undefined;
}
}
}
export function createStyleSheet(container = mainWindow.document.head, beforeAppend, disposableStore) {
const style = document.createElement('style');
style.type = 'text/css';
style.media = 'screen';
beforeAppend?.(style);
container.appendChild(style);
if (disposableStore) {
disposableStore.add(toDisposable(() => style.remove()));
}
// With <head> as container, the stylesheet becomes global and is tracked
// to support auxiliary windows to clone the stylesheet.
if (container === mainWindow.document.head) {
const globalStylesheetClones = new Set();
globalStylesheets.set(style, globalStylesheetClones);
if (disposableStore) {
disposableStore.add(toDisposable(() => globalStylesheets.delete(style)));
}
for (const { window: targetWindow, disposables } of getWindows()) {
if (targetWindow === mainWindow) {
continue; // main window is already tracked
}
const cloneDisposable = disposables.add(cloneGlobalStyleSheet(style, globalStylesheetClones, targetWindow));
disposableStore?.add(cloneDisposable);
}
}
return style;
}
function cloneGlobalStyleSheet(globalStylesheet, globalStylesheetClones, targetWindow) {
const disposables = new DisposableStore();
const clone = globalStylesheet.cloneNode(true);
targetWindow.document.head.appendChild(clone);
disposables.add(toDisposable(() => clone.remove()));
for (const rule of getDynamicStyleSheetRules(globalStylesheet)) {
clone.sheet?.insertRule(rule.cssText, clone.sheet?.cssRules.length);
}
disposables.add(sharedMutationObserver.observe(globalStylesheet, disposables, { childList: true, subtree: isFirefox, characterData: isFirefox })(() => {
clone.textContent = globalStylesheet.textContent;
}));
globalStylesheetClones.add(clone);
disposables.add(toDisposable(() => globalStylesheetClones.delete(clone)));
return disposables;
}
let _sharedStyleSheet = null;
function getSharedStyleSheet() {
if (!_sharedStyleSheet) {
_sharedStyleSheet = createStyleSheet();
}
return _sharedStyleSheet;
}
function getDynamicStyleSheetRules(style) {
if (style?.sheet?.rules) {
// Chrome, IE
return style.sheet.rules;
}
if (style?.sheet?.cssRules) {
// FF
return style.sheet.cssRules;
}
return [];
}
export function createCSSRule(selector, cssText, style = getSharedStyleSheet()) {
if (!style || !cssText) {
return;
}
style.sheet?.insertRule(`${selector} {${cssText}}`, 0);
// Apply rule also to all cloned global stylesheets
for (const clonedGlobalStylesheet of globalStylesheets.get(style) ?? []) {
createCSSRule(selector, cssText, clonedGlobalStylesheet);
}
}
export function removeCSSRulesContainingSelector(ruleName, style = getSharedStyleSheet()) {
if (!style) {
return;
}
const rules = getDynamicStyleSheetRules(style);
const toDelete = [];
for (let i = 0; i < rules.length; i++) {
const rule = rules[i];
if (isCSSStyleRule(rule) && rule.selectorText.indexOf(ruleName) !== -1) {
toDelete.push(i);
}
}
for (let i = toDelete.length - 1; i >= 0; i--) {
style.sheet?.deleteRule(toDelete[i]);
}
// Remove rules also from all cloned global stylesheets
for (const clonedGlobalStylesheet of globalStylesheets.get(style) ?? []) {
removeCSSRulesContainingSelector(ruleName, clonedGlobalStylesheet);
}
}
function isCSSStyleRule(rule) {
return typeof rule.selectorText === 'string';
}
export function createStyleSheetFromObservable(css) {
const store = new DisposableStore();
const w = store.add(createStyleSheet2());
store.add(autorun(reader => {
w.setStyle(css.read(reader));
}));
return store;
}
//# sourceMappingURL=domStylesheets.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,21 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Emitter } from '../common/event.js';
export class DomEmitter {
get event() {
return this.emitter.event;
}
constructor(element, type, useCapture) {
const fn = (e) => this.emitter.fire(e);
this.emitter = new Emitter({
onWillAddFirstListener: () => element.addEventListener(type, fn, useCapture),
onDidRemoveLastListener: () => element.removeEventListener(type, fn, useCapture)
});
}
dispose() {
this.emitter.dispose();
}
}
//# sourceMappingURL=event.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src/vs/base/browser/event.ts","vs/base/browser/event.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAGhG,OAAO,EAAE,OAAO,EAAsB,MAAM,oBAAoB,CAAC;AAgBjE,MAAM,OAAO,UAAU;IAItB,IAAI,KAAK;QACR,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;IAC3B,CAAC;IAKD,YAAY,OAAqB,EAAE,IAAO,EAAE,UAAoB;QAC/D,MAAM,EAAE,GAAG,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAmB,CAAC,CAAC;QAChE,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAC;YAC1B,sBAAsB,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,gBAAgB,CAAC,IAAI,EAAE,EAAE,EAAE,UAAU,CAAC;YAC5E,uBAAuB,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,mBAAmB,CAAC,IAAI,EAAE,EAAE,EAAE,UAAU,CAAC;SAChF,CAAC,CAAC;IACJ,CAAC;IAED,OAAO;QACN,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;IACxB,CAAC;CACD","file":"event.js","sourceRoot":"file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { GestureEvent } from './touch.js';\nimport { Emitter, Event as BaseEvent } from '../common/event.js';\nimport { IDisposable } from '../common/lifecycle.js';\n\nexport type EventHandler = HTMLElement | HTMLDocument | Window;\n\nexport interface DOMEventMap extends HTMLElementEventMap, DocumentEventMap, WindowEventMap {\n\t'-monaco-gesturetap': GestureEvent;\n\t'-monaco-gesturechange': GestureEvent;\n\t'-monaco-gesturestart': GestureEvent;\n\t'-monaco-gesturesend': GestureEvent;\n\t'-monaco-gesturecontextmenu': GestureEvent;\n\t'compositionstart': CompositionEvent;\n\t'compositionupdate': CompositionEvent;\n\t'compositionend': CompositionEvent;\n}\n\nexport class DomEmitter<K extends keyof DOMEventMap> implements IDisposable {\n\n\tprivate readonly emitter: Emitter<DOMEventMap[K]>;\n\n\tget event(): BaseEvent<DOMEventMap[K]> {\n\t\treturn this.emitter.event;\n\t}\n\n\tconstructor(element: Window & typeof globalThis, type: WindowEventMap, useCapture?: boolean);\n\tconstructor(element: Document, type: DocumentEventMap, useCapture?: boolean);\n\tconstructor(element: EventHandler, type: K, useCapture?: boolean);\n\tconstructor(element: EventHandler, type: K, useCapture?: boolean) {\n\t\tconst fn = (e: Event) => this.emitter.fire(e as DOMEventMap[K]);\n\t\tthis.emitter = new Emitter({\n\t\t\tonWillAddFirstListener: () => element.addEventListener(type, fn, useCapture),\n\t\t\tonDidRemoveLastListener: () => element.removeEventListener(type, fn, useCapture)\n\t\t});\n\t}\n\n\tdispose(): void {\n\t\tthis.emitter.dispose();\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { GestureEvent } from './touch.js';\nimport { Emitter, Event as BaseEvent } from '../common/event.js';\nimport { IDisposable } from '../common/lifecycle.js';\n\nexport type EventHandler = HTMLElement | HTMLDocument | Window;\n\nexport interface DOMEventMap extends HTMLElementEventMap, DocumentEventMap, WindowEventMap {\n\t'-monaco-gesturetap': GestureEvent;\n\t'-monaco-gesturechange': GestureEvent;\n\t'-monaco-gesturestart': GestureEvent;\n\t'-monaco-gesturesend': GestureEvent;\n\t'-monaco-gesturecontextmenu': GestureEvent;\n\t'compositionstart': CompositionEvent;\n\t'compositionupdate': CompositionEvent;\n\t'compositionend': CompositionEvent;\n}\n\nexport class DomEmitter<K extends keyof DOMEventMap> implements IDisposable {\n\n\tprivate readonly emitter: Emitter<DOMEventMap[K]>;\n\n\tget event(): BaseEvent<DOMEventMap[K]> {\n\t\treturn this.emitter.event;\n\t}\n\n\tconstructor(element: Window & typeof globalThis, type: WindowEventMap, useCapture?: boolean);\n\tconstructor(element: Document, type: DocumentEventMap, useCapture?: boolean);\n\tconstructor(element: EventHandler, type: K, useCapture?: boolean);\n\tconstructor(element: EventHandler, type: K, useCapture?: boolean) {\n\t\tconst fn = (e: Event) => this.emitter.fire(e as DOMEventMap[K]);\n\t\tthis.emitter = new Emitter({\n\t\t\tonWillAddFirstListener: () => element.addEventListener(type, fn, useCapture),\n\t\t\tonDidRemoveLastListener: () => element.removeEventListener(type, fn, useCapture)\n\t\t});\n\t}\n\n\tdispose(): void {\n\t\tthis.emitter.dispose();\n\t}\n}\n"]}

View File

@@ -0,0 +1,254 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export class FastDomNode {
constructor(domNode) {
this.domNode = domNode;
this._maxWidth = '';
this._width = '';
this._height = '';
this._top = '';
this._left = '';
this._bottom = '';
this._right = '';
this._paddingLeft = '';
this._fontFamily = '';
this._fontWeight = '';
this._fontSize = '';
this._fontStyle = '';
this._fontFeatureSettings = '';
this._fontVariationSettings = '';
this._textDecoration = '';
this._lineHeight = '';
this._letterSpacing = '';
this._className = '';
this._display = '';
this._position = '';
this._visibility = '';
this._color = '';
this._backgroundColor = '';
this._layerHint = false;
this._contain = 'none';
this._boxShadow = '';
}
focus() {
this.domNode.focus();
}
setMaxWidth(_maxWidth) {
const maxWidth = numberAsPixels(_maxWidth);
if (this._maxWidth === maxWidth) {
return;
}
this._maxWidth = maxWidth;
this.domNode.style.maxWidth = this._maxWidth;
}
setWidth(_width) {
const width = numberAsPixels(_width);
if (this._width === width) {
return;
}
this._width = width;
this.domNode.style.width = this._width;
}
setHeight(_height) {
const height = numberAsPixels(_height);
if (this._height === height) {
return;
}
this._height = height;
this.domNode.style.height = this._height;
}
setTop(_top) {
const top = numberAsPixels(_top);
if (this._top === top) {
return;
}
this._top = top;
this.domNode.style.top = this._top;
}
setLeft(_left) {
const left = numberAsPixels(_left);
if (this._left === left) {
return;
}
this._left = left;
this.domNode.style.left = this._left;
}
setBottom(_bottom) {
const bottom = numberAsPixels(_bottom);
if (this._bottom === bottom) {
return;
}
this._bottom = bottom;
this.domNode.style.bottom = this._bottom;
}
setRight(_right) {
const right = numberAsPixels(_right);
if (this._right === right) {
return;
}
this._right = right;
this.domNode.style.right = this._right;
}
setPaddingLeft(_paddingLeft) {
const paddingLeft = numberAsPixels(_paddingLeft);
if (this._paddingLeft === paddingLeft) {
return;
}
this._paddingLeft = paddingLeft;
this.domNode.style.paddingLeft = this._paddingLeft;
}
setFontFamily(fontFamily) {
if (this._fontFamily === fontFamily) {
return;
}
this._fontFamily = fontFamily;
this.domNode.style.fontFamily = this._fontFamily;
}
setFontWeight(fontWeight) {
if (this._fontWeight === fontWeight) {
return;
}
this._fontWeight = fontWeight;
this.domNode.style.fontWeight = this._fontWeight;
}
setFontSize(_fontSize) {
const fontSize = numberAsPixels(_fontSize);
if (this._fontSize === fontSize) {
return;
}
this._fontSize = fontSize;
this.domNode.style.fontSize = this._fontSize;
}
setFontStyle(fontStyle) {
if (this._fontStyle === fontStyle) {
return;
}
this._fontStyle = fontStyle;
this.domNode.style.fontStyle = this._fontStyle;
}
setFontFeatureSettings(fontFeatureSettings) {
if (this._fontFeatureSettings === fontFeatureSettings) {
return;
}
this._fontFeatureSettings = fontFeatureSettings;
this.domNode.style.fontFeatureSettings = this._fontFeatureSettings;
}
setFontVariationSettings(fontVariationSettings) {
if (this._fontVariationSettings === fontVariationSettings) {
return;
}
this._fontVariationSettings = fontVariationSettings;
this.domNode.style.fontVariationSettings = this._fontVariationSettings;
}
setTextDecoration(textDecoration) {
if (this._textDecoration === textDecoration) {
return;
}
this._textDecoration = textDecoration;
this.domNode.style.textDecoration = this._textDecoration;
}
setLineHeight(_lineHeight) {
const lineHeight = numberAsPixels(_lineHeight);
if (this._lineHeight === lineHeight) {
return;
}
this._lineHeight = lineHeight;
this.domNode.style.lineHeight = this._lineHeight;
}
setLetterSpacing(_letterSpacing) {
const letterSpacing = numberAsPixels(_letterSpacing);
if (this._letterSpacing === letterSpacing) {
return;
}
this._letterSpacing = letterSpacing;
this.domNode.style.letterSpacing = this._letterSpacing;
}
setClassName(className) {
if (this._className === className) {
return;
}
this._className = className;
this.domNode.className = this._className;
}
toggleClassName(className, shouldHaveIt) {
this.domNode.classList.toggle(className, shouldHaveIt);
this._className = this.domNode.className;
}
setDisplay(display) {
if (this._display === display) {
return;
}
this._display = display;
this.domNode.style.display = this._display;
}
setPosition(position) {
if (this._position === position) {
return;
}
this._position = position;
this.domNode.style.position = this._position;
}
setVisibility(visibility) {
if (this._visibility === visibility) {
return;
}
this._visibility = visibility;
this.domNode.style.visibility = this._visibility;
}
setColor(color) {
if (this._color === color) {
return;
}
this._color = color;
this.domNode.style.color = this._color;
}
setBackgroundColor(backgroundColor) {
if (this._backgroundColor === backgroundColor) {
return;
}
this._backgroundColor = backgroundColor;
this.domNode.style.backgroundColor = this._backgroundColor;
}
setLayerHinting(layerHint) {
if (this._layerHint === layerHint) {
return;
}
this._layerHint = layerHint;
this.domNode.style.transform = this._layerHint ? 'translate3d(0px, 0px, 0px)' : '';
}
setBoxShadow(boxShadow) {
if (this._boxShadow === boxShadow) {
return;
}
this._boxShadow = boxShadow;
this.domNode.style.boxShadow = boxShadow;
}
setContain(contain) {
if (this._contain === contain) {
return;
}
this._contain = contain;
this.domNode.style.contain = this._contain;
}
setAttribute(name, value) {
this.domNode.setAttribute(name, value);
}
removeAttribute(name) {
this.domNode.removeAttribute(name);
}
appendChild(child) {
this.domNode.appendChild(child.domNode);
}
removeChild(child) {
this.domNode.removeChild(child.domNode);
}
}
function numberAsPixels(value) {
return (typeof value === 'number' ? `${value}px` : value);
}
export function createFastDomNode(domNode) {
return new FastDomNode(domNode);
}
//# sourceMappingURL=fastDomNode.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,41 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { mainWindow } from './window.js';
import { isElectron, isMacintosh, isWindows } from '../common/platform.js';
/**
* The best font-family to be used in CSS based on the platform:
* - Windows: Segoe preferred, fallback to sans-serif
* - macOS: standard system font, fallback to sans-serif
* - Linux: standard system font preferred, fallback to Ubuntu fonts
*
* Note: this currently does not adjust for different locales.
*/
export const DEFAULT_FONT_FAMILY = isWindows ? '"Segoe WPC", "Segoe UI", sans-serif' : isMacintosh ? '-apple-system, BlinkMacSystemFont, sans-serif' : 'system-ui, "Ubuntu", "Droid Sans", sans-serif';
export const getFonts = async () => {
try {
// @ts-ignore
const fonts = await mainWindow.queryLocalFonts();
const fontsArray = [...fonts];
const families = fontsArray.map(font => font.family);
return families;
}
catch (error) {
console.error(`Failed to query fonts: ${error}`);
return [];
}
};
export const getFontSnippets = async () => {
if (!isElectron) {
return [];
}
const fonts = await getFonts();
const snippets = fonts.map(font => {
return {
body: `${font}`
};
});
return snippets;
};
//# sourceMappingURL=fonts.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src/vs/base/browser/fonts.ts","vs/base/browser/fonts.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAEhG,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAE3E;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,SAAS,CAAC,CAAC,CAAC,qCAAqC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,+CAA+C,CAAC,CAAC,CAAC,+CAA+C,CAAC;AAMvM,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,IAAuB,EAAE;IACrD,IAAI,CAAC;QACJ,aAAa;QACb,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,eAAe,EAAgB,CAAC;QAC/D,MAAM,UAAU,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;QAC9B,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrD,OAAO,QAAQ,CAAC;IACjB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CAAC,0BAA0B,KAAK,EAAE,CAAC,CAAC;QACjD,OAAO,EAAE,CAAC;IACX,CAAC;AACF,CAAC,CAAC;AAGF,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,IAAmC,EAAE;IACxE,IAAI,CAAC,UAAU,EAAE,CAAC;QACjB,OAAO,EAAE,CAAC;IACX,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,QAAQ,EAAE,CAAC;IAC/B,MAAM,QAAQ,GAAyB,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;QACvD,OAAO;YACN,IAAI,EAAE,GAAG,IAAI,EAAE;SACf,CAAC;IACH,CAAC,CAAC,CAAC;IACH,OAAO,QAAQ,CAAC;AACjB,CAAC,CAAC","file":"fonts.js","sourceRoot":"file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { mainWindow } from './window.js';\nimport { IJSONSchemaSnippet } from '../common/jsonSchema.js';\nimport { isElectron, isMacintosh, isWindows } from '../common/platform.js';\n\n/**\n * The best font-family to be used in CSS based on the platform:\n * - Windows: Segoe preferred, fallback to sans-serif\n * - macOS: standard system font, fallback to sans-serif\n * - Linux: standard system font preferred, fallback to Ubuntu fonts\n *\n * Note: this currently does not adjust for different locales.\n */\nexport const DEFAULT_FONT_FAMILY = isWindows ? '\"Segoe WPC\", \"Segoe UI\", sans-serif' : isMacintosh ? '-apple-system, BlinkMacSystemFont, sans-serif' : 'system-ui, \"Ubuntu\", \"Droid Sans\", sans-serif';\n\ninterface FontData {\n\treadonly family: string;\n}\n\nexport const getFonts = async (): Promise<string[]> => {\n\ttry {\n\t\t// @ts-ignore\n\t\tconst fonts = await mainWindow.queryLocalFonts() as FontData[];\n\t\tconst fontsArray = [...fonts];\n\t\tconst families = fontsArray.map(font => font.family);\n\t\treturn families;\n\t} catch (error) {\n\t\tconsole.error(`Failed to query fonts: ${error}`);\n\t\treturn [];\n\t}\n};\n\n\nexport const getFontSnippets = async (): Promise<IJSONSchemaSnippet[]> => {\n\tif (!isElectron) {\n\t\treturn [];\n\t}\n\tconst fonts = await getFonts();\n\tconst snippets: IJSONSchemaSnippet[] = fonts.map(font => {\n\t\treturn {\n\t\t\tbody: `${font}`\n\t\t};\n\t});\n\treturn snippets;\n};\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { mainWindow } from './window.js';\nimport { IJSONSchemaSnippet } from '../common/jsonSchema.js';\nimport { isElectron, isMacintosh, isWindows } from '../common/platform.js';\n\n/**\n * The best font-family to be used in CSS based on the platform:\n * - Windows: Segoe preferred, fallback to sans-serif\n * - macOS: standard system font, fallback to sans-serif\n * - Linux: standard system font preferred, fallback to Ubuntu fonts\n *\n * Note: this currently does not adjust for different locales.\n */\nexport const DEFAULT_FONT_FAMILY = isWindows ? '\"Segoe WPC\", \"Segoe UI\", sans-serif' : isMacintosh ? '-apple-system, BlinkMacSystemFont, sans-serif' : 'system-ui, \"Ubuntu\", \"Droid Sans\", sans-serif';\n\ninterface FontData {\n\treadonly family: string;\n}\n\nexport const getFonts = async (): Promise<string[]> => {\n\ttry {\n\t\t// @ts-ignore\n\t\tconst fonts = await mainWindow.queryLocalFonts() as FontData[];\n\t\tconst fontsArray = [...fonts];\n\t\tconst families = fontsArray.map(font => font.family);\n\t\treturn families;\n\t} catch (error) {\n\t\tconsole.error(`Failed to query fonts: ${error}`);\n\t\treturn [];\n\t}\n};\n\n\nexport const getFontSnippets = async (): Promise<IJSONSchemaSnippet[]> => {\n\tif (!isElectron) {\n\t\treturn [];\n\t}\n\tconst fonts = await getFonts();\n\tconst snippets: IJSONSchemaSnippet[] = fonts.map(font => {\n\t\treturn {\n\t\t\tbody: `${font}`\n\t\t};\n\t});\n\treturn snippets;\n};\n"]}

View File

@@ -0,0 +1,161 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as DOM from './dom.js';
export function renderText(text, _options, target) {
const element = target ?? document.createElement('div');
element.textContent = text;
return element;
}
export function renderFormattedText(formattedText, options, target) {
const element = target ?? document.createElement('div');
element.textContent = '';
_renderFormattedText(element, parseFormattedText(formattedText, !!options?.renderCodeSegments), options?.actionHandler, options?.renderCodeSegments);
return element;
}
class StringStream {
constructor(source) {
this.source = source;
this.index = 0;
}
eos() {
return this.index >= this.source.length;
}
next() {
const next = this.peek();
this.advance();
return next;
}
peek() {
return this.source[this.index];
}
advance() {
this.index++;
}
}
function _renderFormattedText(element, treeNode, actionHandler, renderCodeSegments) {
let child;
if (treeNode.type === 2 /* FormatType.Text */) {
child = document.createTextNode(treeNode.content || '');
}
else if (treeNode.type === 3 /* FormatType.Bold */) {
child = document.createElement('b');
}
else if (treeNode.type === 4 /* FormatType.Italics */) {
child = document.createElement('i');
}
else if (treeNode.type === 7 /* FormatType.Code */ && renderCodeSegments) {
child = document.createElement('code');
}
else if (treeNode.type === 5 /* FormatType.Action */ && actionHandler) {
const a = document.createElement('a');
actionHandler.disposables.add(DOM.addStandardDisposableListener(a, 'click', (event) => {
actionHandler.callback(String(treeNode.index), event);
}));
child = a;
}
else if (treeNode.type === 8 /* FormatType.NewLine */) {
child = document.createElement('br');
}
else if (treeNode.type === 1 /* FormatType.Root */) {
child = element;
}
if (child && element !== child) {
element.appendChild(child);
}
if (child && Array.isArray(treeNode.children)) {
treeNode.children.forEach((nodeChild) => {
_renderFormattedText(child, nodeChild, actionHandler, renderCodeSegments);
});
}
}
function parseFormattedText(content, parseCodeSegments) {
const root = {
type: 1 /* FormatType.Root */,
children: []
};
let actionViewItemIndex = 0;
let current = root;
const stack = [];
const stream = new StringStream(content);
while (!stream.eos()) {
let next = stream.next();
const isEscapedFormatType = (next === '\\' && formatTagType(stream.peek(), parseCodeSegments) !== 0 /* FormatType.Invalid */);
if (isEscapedFormatType) {
next = stream.next(); // unread the backslash if it escapes a format tag type
}
if (!isEscapedFormatType && isFormatTag(next, parseCodeSegments) && next === stream.peek()) {
stream.advance();
if (current.type === 2 /* FormatType.Text */) {
current = stack.pop();
}
const type = formatTagType(next, parseCodeSegments);
if (current.type === type || (current.type === 5 /* FormatType.Action */ && type === 6 /* FormatType.ActionClose */)) {
current = stack.pop();
}
else {
const newCurrent = {
type: type,
children: []
};
if (type === 5 /* FormatType.Action */) {
newCurrent.index = actionViewItemIndex;
actionViewItemIndex++;
}
current.children.push(newCurrent);
stack.push(current);
current = newCurrent;
}
}
else if (next === '\n') {
if (current.type === 2 /* FormatType.Text */) {
current = stack.pop();
}
current.children.push({
type: 8 /* FormatType.NewLine */
});
}
else {
if (current.type !== 2 /* FormatType.Text */) {
const textCurrent = {
type: 2 /* FormatType.Text */,
content: next
};
current.children.push(textCurrent);
stack.push(current);
current = textCurrent;
}
else {
current.content += next;
}
}
}
if (current.type === 2 /* FormatType.Text */) {
current = stack.pop();
}
if (stack.length) {
// incorrectly formatted string literal
}
return root;
}
function isFormatTag(char, supportCodeSegments) {
return formatTagType(char, supportCodeSegments) !== 0 /* FormatType.Invalid */;
}
function formatTagType(char, supportCodeSegments) {
switch (char) {
case '*':
return 3 /* FormatType.Bold */;
case '_':
return 4 /* FormatType.Italics */;
case '[':
return 5 /* FormatType.Action */;
case ']':
return 6 /* FormatType.ActionClose */;
case '`':
return supportCodeSegments ? 7 /* FormatType.Code */ : 0 /* FormatType.Invalid */;
default:
return 0 /* FormatType.Invalid */;
}
}
//# sourceMappingURL=formattedTextRenderer.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,81 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as dom from './dom.js';
import { DisposableStore, toDisposable } from '../common/lifecycle.js';
export class GlobalPointerMoveMonitor {
constructor() {
this._hooks = new DisposableStore();
this._pointerMoveCallback = null;
this._onStopCallback = null;
}
dispose() {
this.stopMonitoring(false);
this._hooks.dispose();
}
stopMonitoring(invokeStopCallback, browserEvent) {
if (!this.isMonitoring()) {
// Not monitoring
return;
}
// Unhook
this._hooks.clear();
this._pointerMoveCallback = null;
const onStopCallback = this._onStopCallback;
this._onStopCallback = null;
if (invokeStopCallback && onStopCallback) {
onStopCallback(browserEvent);
}
}
isMonitoring() {
return !!this._pointerMoveCallback;
}
startMonitoring(initialElement, pointerId, initialButtons, pointerMoveCallback, onStopCallback) {
if (this.isMonitoring()) {
this.stopMonitoring(false);
}
this._pointerMoveCallback = pointerMoveCallback;
this._onStopCallback = onStopCallback;
let eventSource = initialElement;
try {
initialElement.setPointerCapture(pointerId);
this._hooks.add(toDisposable(() => {
try {
initialElement.releasePointerCapture(pointerId);
}
catch (err) {
// See https://github.com/microsoft/vscode/issues/161731
//
// `releasePointerCapture` sometimes fails when being invoked with the exception:
// DOMException: Failed to execute 'releasePointerCapture' on 'Element':
// No active pointer with the given id is found.
//
// There's no need to do anything in case of failure
}
}));
}
catch (err) {
// See https://github.com/microsoft/vscode/issues/144584
// See https://github.com/microsoft/vscode/issues/146947
// `setPointerCapture` sometimes fails when being invoked
// from a `mousedown` listener on macOS and Windows
// and it always fails on Linux with the exception:
// DOMException: Failed to execute 'setPointerCapture' on 'Element':
// No active pointer with the given id is found.
// In case of failure, we bind the listeners on the window
eventSource = dom.getWindow(initialElement);
}
this._hooks.add(dom.addDisposableListener(eventSource, dom.EventType.POINTER_MOVE, (e) => {
if (e.buttons !== initialButtons) {
// Buttons state has changed in the meantime
this.stopMonitoring(true);
return;
}
e.preventDefault();
this._pointerMoveCallback(e);
}));
this._hooks.add(dom.addDisposableListener(eventSource, dom.EventType.POINTER_UP, (e) => this.stopMonitoring(true)));
}
}
//# sourceMappingURL=globalPointerMoveMonitor.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,6 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export {};
//# sourceMappingURL=history.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src/vs/base/browser/history.ts","vs/base/browser/history.ts"],"names":[],"mappings":"AAAA;;;gGAGgG","file":"history.js","sourceRoot":"file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Event } from '../common/event.js';\n\nexport interface IHistoryNavigationWidget {\n\n\treadonly element: HTMLElement;\n\n\tshowPreviousValue(): void;\n\n\tshowNextValue(): void;\n\n\tonDidFocus: Event<void>;\n\n\tonDidBlur: Event<void>;\n\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Event } from '../common/event.js';\n\nexport interface IHistoryNavigationWidget {\n\n\treadonly element: HTMLElement;\n\n\tshowPreviousValue(): void;\n\n\tshowNextValue(): void;\n\n\tonDidFocus: Event<void>;\n\n\tonDidBlur: Event<void>;\n\n}\n"]}

View File

@@ -0,0 +1,86 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const sameOriginWindowChainCache = new WeakMap();
function getParentWindowIfSameOrigin(w) {
if (!w.parent || w.parent === w) {
return null;
}
// Cannot really tell if we have access to the parent window unless we try to access something in it
try {
const location = w.location;
const parentLocation = w.parent.location;
if (location.origin !== 'null' && parentLocation.origin !== 'null' && location.origin !== parentLocation.origin) {
return null;
}
}
catch (e) {
return null;
}
return w.parent;
}
export class IframeUtils {
/**
* Returns a chain of embedded windows with the same origin (which can be accessed programmatically).
* Having a chain of length 1 might mean that the current execution environment is running outside of an iframe or inside an iframe embedded in a window with a different origin.
*/
static getSameOriginWindowChain(targetWindow) {
let windowChainCache = sameOriginWindowChainCache.get(targetWindow);
if (!windowChainCache) {
windowChainCache = [];
sameOriginWindowChainCache.set(targetWindow, windowChainCache);
let w = targetWindow;
let parent;
do {
parent = getParentWindowIfSameOrigin(w);
if (parent) {
windowChainCache.push({
window: new WeakRef(w),
iframeElement: w.frameElement || null
});
}
else {
windowChainCache.push({
window: new WeakRef(w),
iframeElement: null
});
}
w = parent;
} while (w);
}
return windowChainCache.slice(0);
}
/**
* Returns the position of `childWindow` relative to `ancestorWindow`
*/
static getPositionOfChildWindowRelativeToAncestorWindow(childWindow, ancestorWindow) {
if (!ancestorWindow || childWindow === ancestorWindow) {
return {
top: 0,
left: 0
};
}
let top = 0, left = 0;
const windowChain = this.getSameOriginWindowChain(childWindow);
for (const windowChainEl of windowChain) {
const windowInChain = windowChainEl.window.deref();
top += windowInChain?.scrollY ?? 0;
left += windowInChain?.scrollX ?? 0;
if (windowInChain === ancestorWindow) {
break;
}
if (!windowChainEl.iframeElement) {
break;
}
const boundingRect = windowChainEl.iframeElement.getBoundingClientRect();
top += boundingRect.top;
left += boundingRect.left;
}
return {
top: top,
left: left
};
}
}
//# sourceMappingURL=iframe.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,123 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as browser from './browser.js';
import { EVENT_KEY_CODE_MAP, KeyCodeUtils } from '../common/keyCodes.js';
import { KeyCodeChord } from '../common/keybindings.js';
import * as platform from '../common/platform.js';
function extractKeyCode(e) {
if (e.charCode) {
// "keypress" events mostly
const char = String.fromCharCode(e.charCode).toUpperCase();
return KeyCodeUtils.fromString(char);
}
const keyCode = e.keyCode;
// browser quirks
if (keyCode === 3) {
return 7 /* KeyCode.PauseBreak */;
}
else if (browser.isFirefox) {
switch (keyCode) {
case 59: return 85 /* KeyCode.Semicolon */;
case 60:
if (platform.isLinux) {
return 97 /* KeyCode.IntlBackslash */;
}
break;
case 61: return 86 /* KeyCode.Equal */;
// based on: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode#numpad_keys
case 107: return 109 /* KeyCode.NumpadAdd */;
case 109: return 111 /* KeyCode.NumpadSubtract */;
case 173: return 88 /* KeyCode.Minus */;
case 224:
if (platform.isMacintosh) {
return 57 /* KeyCode.Meta */;
}
break;
}
}
else if (browser.isWebKit) {
if (platform.isMacintosh && keyCode === 93) {
// the two meta keys in the Mac have different key codes (91 and 93)
return 57 /* KeyCode.Meta */;
}
else if (!platform.isMacintosh && keyCode === 92) {
return 57 /* KeyCode.Meta */;
}
}
// cross browser keycodes:
return EVENT_KEY_CODE_MAP[keyCode] || 0 /* KeyCode.Unknown */;
}
const ctrlKeyMod = (platform.isMacintosh ? 256 /* KeyMod.WinCtrl */ : 2048 /* KeyMod.CtrlCmd */);
const altKeyMod = 512 /* KeyMod.Alt */;
const shiftKeyMod = 1024 /* KeyMod.Shift */;
const metaKeyMod = (platform.isMacintosh ? 2048 /* KeyMod.CtrlCmd */ : 256 /* KeyMod.WinCtrl */);
export class StandardKeyboardEvent {
constructor(source) {
this._standardKeyboardEventBrand = true;
const e = source;
this.browserEvent = e;
this.target = e.target;
this.ctrlKey = e.ctrlKey;
this.shiftKey = e.shiftKey;
this.altKey = e.altKey;
this.metaKey = e.metaKey;
this.altGraphKey = e.getModifierState?.('AltGraph');
this.keyCode = extractKeyCode(e);
this.code = e.code;
// console.info(e.type + ": keyCode: " + e.keyCode + ", which: " + e.which + ", charCode: " + e.charCode + ", detail: " + e.detail + " ====> " + this.keyCode + ' -- ' + KeyCode[this.keyCode]);
this.ctrlKey = this.ctrlKey || this.keyCode === 5 /* KeyCode.Ctrl */;
this.altKey = this.altKey || this.keyCode === 6 /* KeyCode.Alt */;
this.shiftKey = this.shiftKey || this.keyCode === 4 /* KeyCode.Shift */;
this.metaKey = this.metaKey || this.keyCode === 57 /* KeyCode.Meta */;
this._asKeybinding = this._computeKeybinding();
this._asKeyCodeChord = this._computeKeyCodeChord();
// console.log(`code: ${e.code}, keyCode: ${e.keyCode}, key: ${e.key}`);
}
preventDefault() {
if (this.browserEvent && this.browserEvent.preventDefault) {
this.browserEvent.preventDefault();
}
}
stopPropagation() {
if (this.browserEvent && this.browserEvent.stopPropagation) {
this.browserEvent.stopPropagation();
}
}
toKeyCodeChord() {
return this._asKeyCodeChord;
}
equals(other) {
return this._asKeybinding === other;
}
_computeKeybinding() {
let key = 0 /* KeyCode.Unknown */;
if (this.keyCode !== 5 /* KeyCode.Ctrl */ && this.keyCode !== 4 /* KeyCode.Shift */ && this.keyCode !== 6 /* KeyCode.Alt */ && this.keyCode !== 57 /* KeyCode.Meta */) {
key = this.keyCode;
}
let result = 0;
if (this.ctrlKey) {
result |= ctrlKeyMod;
}
if (this.altKey) {
result |= altKeyMod;
}
if (this.shiftKey) {
result |= shiftKeyMod;
}
if (this.metaKey) {
result |= metaKeyMod;
}
result |= key;
return result;
}
_computeKeyCodeChord() {
let key = 0 /* KeyCode.Unknown */;
if (this.keyCode !== 5 /* KeyCode.Ctrl */ && this.keyCode !== 4 /* KeyCode.Shift */ && this.keyCode !== 6 /* KeyCode.Alt */ && this.keyCode !== 57 /* KeyCode.Meta */) {
key = this.keyCode;
}
return new KeyCodeChord(this.ctrlKey, this.shiftKey, this.altKey, this.metaKey, key);
}
}
//# sourceMappingURL=keyboardEvent.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,837 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { onUnexpectedError } from '../common/errors.js';
import { escapeDoubleQuotes, parseHrefAndDimensions, removeMarkdownEscapes } from '../common/htmlContent.js';
import { markdownEscapeEscapedIcons } from '../common/iconLabels.js';
import { defaultGenerator } from '../common/idGenerator.js';
import { Lazy } from '../common/lazy.js';
import { DisposableStore } from '../common/lifecycle.js';
import * as marked from '../common/marked/marked.js';
import { parse } from '../common/marshalling.js';
import { FileAccess, Schemas } from '../common/network.js';
import { cloneAndChange } from '../common/objects.js';
import { dirname, resolvePath } from '../common/resources.js';
import { escape } from '../common/strings.js';
import { URI } from '../common/uri.js';
import * as DOM from './dom.js';
import * as domSanitize from './domSanitize.js';
import { convertTagToPlaintext } from './domSanitize.js';
import { StandardKeyboardEvent } from './keyboardEvent.js';
import { StandardMouseEvent } from './mouseEvent.js';
import { renderLabelWithIcons } from './ui/iconLabel/iconLabels.js';
const defaultMarkedRenderers = Object.freeze({
image: ({ href, title, text }) => {
let dimensions = [];
let attributes = [];
if (href) {
({ href, dimensions } = parseHrefAndDimensions(href));
attributes.push(`src="${escapeDoubleQuotes(href)}"`);
}
if (text) {
attributes.push(`alt="${escapeDoubleQuotes(text)}"`);
}
if (title) {
attributes.push(`title="${escapeDoubleQuotes(title)}"`);
}
if (dimensions.length) {
attributes = attributes.concat(dimensions);
}
return '<img ' + attributes.join(' ') + '>';
},
paragraph({ tokens }) {
return `<p>${this.parser.parseInline(tokens)}</p>`;
},
link({ href, title, tokens }) {
let text = this.parser.parseInline(tokens);
if (typeof href !== 'string') {
return '';
}
// Remove markdown escapes. Workaround for https://github.com/chjj/marked/issues/829
if (href === text) { // raw link case
text = removeMarkdownEscapes(text);
}
title = typeof title === 'string' ? escapeDoubleQuotes(removeMarkdownEscapes(title)) : '';
href = removeMarkdownEscapes(href);
// HTML Encode href
href = href.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
return `<a href="${href}" title="${title || href}" draggable="false">${text}</a>`;
},
});
/**
* Low-level way create a html element from a markdown string.
*
* **Note** that for most cases you should be using {@link import('../../editor/browser/widget/markdownRenderer/browser/markdownRenderer.js').MarkdownRenderer MarkdownRenderer}
* which comes with support for pretty code block rendering and which uses the default way of handling links.
*/
export function renderMarkdown(markdown, options = {}, target) {
const disposables = new DisposableStore();
let isDisposed = false;
const markedInstance = new marked.Marked(...(options.markedExtensions ?? []));
const { renderer, codeBlocks, syncCodeBlocks } = createMarkdownRenderer(markedInstance, options, markdown);
const value = preprocessMarkdownString(markdown);
let renderedMarkdown;
if (options.fillInIncompleteTokens) {
// The defaults are applied by parse but not lexer()/parser(), and they need to be present
const opts = {
...markedInstance.defaults,
...options.markedOptions,
renderer
};
const tokens = markedInstance.lexer(value, opts);
const newTokens = fillInIncompleteTokens(tokens);
renderedMarkdown = markedInstance.parser(newTokens, opts);
}
else {
renderedMarkdown = markedInstance.parse(value, { ...options?.markedOptions, renderer, async: false });
}
// Rewrite theme icons
if (markdown.supportThemeIcons) {
const elements = renderLabelWithIcons(renderedMarkdown);
renderedMarkdown = elements.map(e => typeof e === 'string' ? e : e.outerHTML).join('');
}
const renderedContent = document.createElement('div');
const sanitizerConfig = getDomSanitizerConfig(markdown, options.sanitizerConfig ?? {});
domSanitize.safeSetInnerHtml(renderedContent, renderedMarkdown, sanitizerConfig);
// Rewrite links and images before potentially inserting them into the real dom
rewriteRenderedLinks(markdown, options, renderedContent);
let outElement;
if (target) {
outElement = target;
DOM.reset(target, ...renderedContent.children);
}
else {
outElement = renderedContent;
}
if (codeBlocks.length > 0) {
Promise.all(codeBlocks).then((tuples) => {
if (isDisposed) {
return;
}
const renderedElements = new Map(tuples);
const placeholderElements = outElement.querySelectorAll(`div[data-code]`);
for (const placeholderElement of placeholderElements) {
const renderedElement = renderedElements.get(placeholderElement.dataset['code'] ?? '');
if (renderedElement) {
DOM.reset(placeholderElement, renderedElement);
}
}
options.asyncRenderCallback?.();
});
}
else if (syncCodeBlocks.length > 0) {
const renderedElements = new Map(syncCodeBlocks);
const placeholderElements = outElement.querySelectorAll(`div[data-code]`);
for (const placeholderElement of placeholderElements) {
const renderedElement = renderedElements.get(placeholderElement.dataset['code'] ?? '');
if (renderedElement) {
DOM.reset(placeholderElement, renderedElement);
}
}
}
// Signal size changes for image tags
if (options.asyncRenderCallback) {
for (const img of outElement.getElementsByTagName('img')) {
const listener = disposables.add(DOM.addDisposableListener(img, 'load', () => {
listener.dispose();
options.asyncRenderCallback();
}));
}
}
// Add event listeners for links
if (options.actionHandler) {
const clickCb = (e) => {
const mouseEvent = new StandardMouseEvent(DOM.getWindow(outElement), e);
if (!mouseEvent.leftButton && !mouseEvent.middleButton) {
return;
}
activateLink(markdown, options, mouseEvent);
};
disposables.add(DOM.addDisposableListener(outElement, 'click', clickCb));
disposables.add(DOM.addDisposableListener(outElement, 'auxclick', clickCb));
disposables.add(DOM.addDisposableListener(outElement, 'keydown', (e) => {
const keyboardEvent = new StandardKeyboardEvent(e);
if (!keyboardEvent.equals(10 /* KeyCode.Space */) && !keyboardEvent.equals(3 /* KeyCode.Enter */)) {
return;
}
activateLink(markdown, options, keyboardEvent);
}));
}
// Remove/disable inputs
for (const input of [...outElement.getElementsByTagName('input')]) {
if (input.attributes.getNamedItem('type')?.value === 'checkbox') {
input.setAttribute('disabled', '');
}
else {
if (options.sanitizerConfig?.replaceWithPlaintext) {
const replacement = convertTagToPlaintext(input);
input.parentElement?.replaceChild(replacement, input);
}
else {
input.remove();
}
}
}
return {
element: outElement,
dispose: () => {
isDisposed = true;
disposables.dispose();
}
};
}
function rewriteRenderedLinks(markdown, options, root) {
for (const el of root.querySelectorAll('img, audio, video, source')) {
const src = el.getAttribute('src'); // Get the raw 'src' attribute value as text, not the resolved 'src'
if (src) {
let href = src;
try {
if (markdown.baseUri) { // absolute or relative local path, or file: uri
href = resolveWithBaseUri(URI.from(markdown.baseUri), href);
}
}
catch (err) { }
el.setAttribute('src', massageHref(markdown, href, true));
if (options.sanitizerConfig?.remoteImageIsAllowed) {
const uri = URI.parse(href);
if (uri.scheme !== Schemas.file && uri.scheme !== Schemas.data && !options.sanitizerConfig.remoteImageIsAllowed(uri)) {
el.replaceWith(DOM.$('', undefined, el.outerHTML));
}
}
}
}
for (const el of root.querySelectorAll('a')) {
const href = el.getAttribute('href'); // Get the raw 'href' attribute value as text, not the resolved 'href'
el.setAttribute('href', ''); // Clear out href. We use the `data-href` for handling clicks instead
if (!href
|| /^data:|javascript:/i.test(href)
|| (/^command:/i.test(href) && !markdown.isTrusted)
|| /^command:(\/\/\/)?_workbench\.downloadResource/i.test(href)) {
// drop the link
el.replaceWith(...el.childNodes);
}
else {
let resolvedHref = massageHref(markdown, href, false);
if (markdown.baseUri) {
resolvedHref = resolveWithBaseUri(URI.from(markdown.baseUri), href);
}
el.dataset.href = resolvedHref;
}
}
}
function createMarkdownRenderer(marked, options, markdown) {
const renderer = new marked.Renderer(options.markedOptions);
renderer.image = defaultMarkedRenderers.image;
renderer.link = defaultMarkedRenderers.link;
renderer.paragraph = defaultMarkedRenderers.paragraph;
// Will collect [id, renderedElement] tuples
const codeBlocks = [];
const syncCodeBlocks = [];
if (options.codeBlockRendererSync) {
renderer.code = ({ text, lang, raw }) => {
const id = defaultGenerator.nextId();
const value = options.codeBlockRendererSync(postProcessCodeBlockLanguageId(lang), text, raw);
syncCodeBlocks.push([id, value]);
return `<div class="code" data-code="${id}">${escape(text)}</div>`;
};
}
else if (options.codeBlockRenderer) {
renderer.code = ({ text, lang }) => {
const id = defaultGenerator.nextId();
const value = options.codeBlockRenderer(postProcessCodeBlockLanguageId(lang), text);
codeBlocks.push(value.then(element => [id, element]));
return `<div class="code" data-code="${id}">${escape(text)}</div>`;
};
}
if (!markdown.supportHtml) {
// Note: we always pass the output through dompurify after this so that we don't rely on
// marked for real sanitization.
renderer.html = ({ text }) => {
if (options.sanitizerConfig?.replaceWithPlaintext) {
return escape(text);
}
const match = markdown.isTrusted ? text.match(/^(<span[^>]+>)|(<\/\s*span>)$/) : undefined;
return match ? text : '';
};
}
return { renderer, codeBlocks, syncCodeBlocks };
}
function preprocessMarkdownString(markdown) {
let value = markdown.value;
// values that are too long will freeze the UI
if (value.length > 100_000) {
value = `${value.substr(0, 100_000)}`;
}
// escape theme icons
if (markdown.supportThemeIcons) {
value = markdownEscapeEscapedIcons(value);
}
return value;
}
function activateLink(mdStr, options, event) {
const target = event.target.closest('a[data-href]');
if (!DOM.isHTMLElement(target)) {
return;
}
try {
let href = target.dataset['href'];
if (href) {
if (mdStr.baseUri) {
href = resolveWithBaseUri(URI.from(mdStr.baseUri), href);
}
options.actionHandler?.(href, mdStr);
}
}
catch (err) {
onUnexpectedError(err);
}
finally {
event.preventDefault();
}
}
function uriMassage(markdown, part) {
let data;
try {
data = parse(decodeURIComponent(part));
}
catch (e) {
// ignore
}
if (!data) {
return part;
}
data = cloneAndChange(data, value => {
if (markdown.uris && markdown.uris[value]) {
return URI.revive(markdown.uris[value]);
}
else {
return undefined;
}
});
return encodeURIComponent(JSON.stringify(data));
}
function massageHref(markdown, href, isDomUri) {
const data = markdown.uris && markdown.uris[href];
let uri = URI.revive(data);
if (isDomUri) {
if (href.startsWith(Schemas.data + ':')) {
return href;
}
if (!uri) {
uri = URI.parse(href);
}
// this URI will end up as "src"-attribute of a dom node
// and because of that special rewriting needs to be done
// so that the URI uses a protocol that's understood by
// browsers (like http or https)
return FileAccess.uriToBrowserUri(uri).toString(true);
}
if (!uri) {
return href;
}
if (URI.parse(href).toString() === uri.toString()) {
return href; // no transformation performed
}
if (uri.query) {
uri = uri.with({ query: uriMassage(markdown, uri.query) });
}
return uri.toString();
}
function postProcessCodeBlockLanguageId(lang) {
if (!lang) {
return '';
}
const parts = lang.split(/[\s+|:|,|\{|\?]/, 1);
if (parts.length) {
return parts[0];
}
return lang;
}
function resolveWithBaseUri(baseUri, href) {
const hasScheme = /^\w[\w\d+.-]*:/.test(href);
if (hasScheme) {
return href;
}
if (baseUri.path.endsWith('/')) {
return resolvePath(baseUri, href).toString();
}
else {
return resolvePath(dirname(baseUri), href).toString();
}
}
function sanitizeRenderedMarkdown(renderedMarkdown, originalMdStrConfig, options = {}) {
const sanitizerConfig = getDomSanitizerConfig(originalMdStrConfig, options);
return domSanitize.sanitizeHtml(renderedMarkdown, sanitizerConfig);
}
export const allowedMarkdownHtmlTags = Object.freeze([
...domSanitize.basicMarkupHtmlTags,
'input', // Allow inputs for rendering checkboxes. Other types of inputs are removed and the inputs are always disabled
]);
export const allowedMarkdownHtmlAttributes = Object.freeze([
'align',
'autoplay',
'alt',
'colspan',
'controls',
'draggable',
'height',
'href',
'loop',
'muted',
'playsinline',
'poster',
'rowspan',
'src',
'target',
'title',
'type',
'width',
'start',
// Input (For disabled inputs)
'checked',
'disabled',
'value',
// Custom markdown attributes
'data-code',
'data-href',
// Only allow very specific styles
{
attributeName: 'style',
shouldKeep: (element, data) => {
if (element.tagName === 'SPAN') {
if (data.attrName === 'style') {
return /^(color\:(#[0-9a-fA-F]+|var\(--vscode(-[a-zA-Z0-9]+)+\));)?(background-color\:(#[0-9a-fA-F]+|var\(--vscode(-[a-zA-Z0-9]+)+\));)?(border-radius:[0-9]+px;)?$/.test(data.attrValue);
}
}
return false;
}
},
// Only allow codicons for classes
{
attributeName: 'class',
shouldKeep: (element, data) => {
if (element.tagName === 'SPAN') {
if (data.attrName === 'class') {
return /^codicon codicon-[a-z\-]+( codicon-modifier-[a-z\-]+)?$/.test(data.attrValue);
}
}
return false;
},
},
]);
function getDomSanitizerConfig(mdStrConfig, options) {
const isTrusted = mdStrConfig.isTrusted ?? false;
const allowedLinkSchemes = [
Schemas.http,
Schemas.https,
Schemas.mailto,
Schemas.file,
Schemas.vscodeFileResource,
Schemas.vscodeRemote,
Schemas.vscodeRemoteResource,
Schemas.vscodeNotebookCell
];
if (isTrusted) {
allowedLinkSchemes.push(Schemas.command);
}
if (options.allowedLinkSchemes?.augment) {
allowedLinkSchemes.push(...options.allowedLinkSchemes.augment);
}
return {
// allowedTags should included everything that markdown renders to.
// Since we have our own sanitize function for marked, it's possible we missed some tag so let dompurify make sure.
// HTML tags that can result from markdown are from reading https://spec.commonmark.org/0.29/
// HTML table tags that can result from markdown are from https://github.github.com/gfm/#tables-extension-
allowedTags: {
override: options.allowedTags?.override ?? allowedMarkdownHtmlTags
},
allowedAttributes: {
override: options.allowedAttributes?.override ?? allowedMarkdownHtmlAttributes,
},
allowedLinkProtocols: {
override: allowedLinkSchemes,
},
allowRelativeLinkPaths: !!mdStrConfig.baseUri,
allowedMediaProtocols: {
override: [
Schemas.http,
Schemas.https,
Schemas.data,
Schemas.file,
Schemas.vscodeFileResource,
Schemas.vscodeRemote,
Schemas.vscodeRemoteResource,
]
},
replaceWithPlaintext: options.replaceWithPlaintext,
};
}
/**
* Renders `str` as plaintext, stripping out Markdown syntax if it's a {@link IMarkdownString}.
*
* For example `# Header` would be output as `Header`.
*/
export function renderAsPlaintext(str, options) {
if (typeof str === 'string') {
return str;
}
// values that are too long will freeze the UI
let value = str.value ?? '';
if (value.length > 100_000) {
value = `${value.substr(0, 100_000)}`;
}
const html = marked.parse(value, { async: false, renderer: options?.includeCodeBlocksFences ? plainTextWithCodeBlocksRenderer.value : plainTextRenderer.value });
return sanitizeRenderedMarkdown(html, { isTrusted: false }, {})
.toString()
.replace(/&(#\d+|[a-zA-Z]+);/g, m => unescapeInfo.get(m) ?? m)
.trim();
}
const unescapeInfo = new Map([
['&quot;', '"'],
['&nbsp;', ' '],
['&amp;', '&'],
['&#39;', '\''],
['&lt;', '<'],
['&gt;', '>'],
]);
function createPlainTextRenderer() {
const renderer = new marked.Renderer();
renderer.code = ({ text }) => {
return escape(text);
};
renderer.blockquote = ({ text }) => {
return text + '\n';
};
renderer.html = (_) => {
return '';
};
renderer.heading = function ({ tokens }) {
return this.parser.parseInline(tokens) + '\n';
};
renderer.hr = () => {
return '';
};
renderer.list = function ({ items }) {
return items.map(x => this.listitem(x)).join('\n') + '\n';
};
renderer.listitem = ({ text }) => {
return text + '\n';
};
renderer.paragraph = function ({ tokens }) {
return this.parser.parseInline(tokens) + '\n';
};
renderer.table = function ({ header, rows }) {
return header.map(cell => this.tablecell(cell)).join(' ') + '\n' + rows.map(cells => cells.map(cell => this.tablecell(cell)).join(' ')).join('\n') + '\n';
};
renderer.tablerow = ({ text }) => {
return text;
};
renderer.tablecell = function ({ tokens }) {
return this.parser.parseInline(tokens);
};
renderer.strong = ({ text }) => {
return text;
};
renderer.em = ({ text }) => {
return text;
};
renderer.codespan = ({ text }) => {
return escape(text);
};
renderer.br = (_) => {
return '\n';
};
renderer.del = ({ text }) => {
return text;
};
renderer.image = (_) => {
return '';
};
renderer.text = ({ text }) => {
return text;
};
renderer.link = ({ text }) => {
return text;
};
return renderer;
}
const plainTextRenderer = new Lazy(createPlainTextRenderer);
const plainTextWithCodeBlocksRenderer = new Lazy(() => {
const renderer = createPlainTextRenderer();
renderer.code = ({ text }) => {
return `\n\`\`\`\n${escape(text)}\n\`\`\`\n`;
};
return renderer;
});
function mergeRawTokenText(tokens) {
let mergedTokenText = '';
tokens.forEach(token => {
mergedTokenText += token.raw;
});
return mergedTokenText;
}
function completeSingleLinePattern(token) {
if (!token.tokens) {
return undefined;
}
for (let i = token.tokens.length - 1; i >= 0; i--) {
const subtoken = token.tokens[i];
if (subtoken.type === 'text') {
const lines = subtoken.raw.split('\n');
const lastLine = lines[lines.length - 1];
if (lastLine.includes('`')) {
return completeCodespan(token);
}
else if (lastLine.includes('**')) {
return completeDoublestar(token);
}
else if (lastLine.match(/\*\w/)) {
return completeStar(token);
}
else if (lastLine.match(/(^|\s)__\w/)) {
return completeDoubleUnderscore(token);
}
else if (lastLine.match(/(^|\s)_\w/)) {
return completeUnderscore(token);
}
else if (
// Text with start of link target
hasLinkTextAndStartOfLinkTarget(lastLine) ||
// This token doesn't have the link text, eg if it contains other markdown constructs that are in other subtokens.
// But some preceding token does have an unbalanced [ at least
hasStartOfLinkTargetAndNoLinkText(lastLine) && token.tokens.slice(0, i).some(t => t.type === 'text' && t.raw.match(/\[[^\]]*$/))) {
const nextTwoSubTokens = token.tokens.slice(i + 1);
// A markdown link can look like
// [link text](https://microsoft.com "more text")
// Where "more text" is a title for the link or an argument to a vscode command link
if (
// If the link was parsed as a link, then look for a link token and a text token with a quote
nextTwoSubTokens[0]?.type === 'link' && nextTwoSubTokens[1]?.type === 'text' && nextTwoSubTokens[1].raw.match(/^ *"[^"]*$/) ||
// And if the link was not parsed as a link (eg command link), just look for a single quote in this token
lastLine.match(/^[^"]* +"[^"]*$/)) {
return completeLinkTargetArg(token);
}
return completeLinkTarget(token);
}
// Contains the start of link text, and no following tokens contain the link target
else if (lastLine.match(/(^|\s)\[\w*[^\]]*$/)) {
return completeLinkText(token);
}
}
}
return undefined;
}
function hasLinkTextAndStartOfLinkTarget(str) {
return !!str.match(/(^|\s)\[.*\]\(\w*/);
}
function hasStartOfLinkTargetAndNoLinkText(str) {
return !!str.match(/^[^\[]*\]\([^\)]*$/);
}
function completeListItemPattern(list) {
// Patch up this one list item
const lastListItem = list.items[list.items.length - 1];
const lastListSubToken = lastListItem.tokens ? lastListItem.tokens[lastListItem.tokens.length - 1] : undefined;
/*
Example list token structures:
list
list_item
text
text
codespan
link
list_item
text
code // Complete indented codeblock
list_item
text
space
text
text // Incomplete indented codeblock
list_item
text
list // Nested list
list_item
text
text
Contrast with paragraph:
paragraph
text
codespan
*/
const listEndsInHeading = (list) => {
// A list item can be rendered as a heading for some reason when it has a subitem where we haven't rendered the text yet like this:
// 1. list item
// -
const lastItem = list.items.at(-1);
const lastToken = lastItem?.tokens.at(-1);
return lastToken?.type === 'heading' || lastToken?.type === 'list' && listEndsInHeading(lastToken);
};
let newToken;
if (lastListSubToken?.type === 'text' && !('inRawBlock' in lastListItem)) { // Why does Tag have a type of 'text'
newToken = completeSingleLinePattern(lastListSubToken);
}
else if (listEndsInHeading(list)) {
const newList = marked.lexer(list.raw.trim() + ' &nbsp;')[0];
if (newList.type !== 'list') {
// Something went wrong
return;
}
return newList;
}
if (!newToken || newToken.type !== 'paragraph') { // 'text' item inside the list item turns into paragraph
// Nothing to fix, or not a pattern we were expecting
return;
}
const previousListItemsText = mergeRawTokenText(list.items.slice(0, -1));
// Grabbing the `- ` or `1. ` or `* ` off the list item because I can't find a better way to do this
const lastListItemLead = lastListItem.raw.match(/^(\s*(-|\d+\.|\*) +)/)?.[0];
if (!lastListItemLead) {
// Is badly formatted
return;
}
const newListItemText = lastListItemLead +
mergeRawTokenText(lastListItem.tokens.slice(0, -1)) +
newToken.raw;
const newList = marked.lexer(previousListItemsText + newListItemText)[0];
if (newList.type !== 'list') {
// Something went wrong
return;
}
return newList;
}
function completeHeading(token, fullRawText) {
if (token.raw.match(/-\s*$/)) {
return marked.lexer(fullRawText + ' &nbsp;');
}
}
const maxIncompleteTokensFixRounds = 3;
export function fillInIncompleteTokens(tokens) {
for (let i = 0; i < maxIncompleteTokensFixRounds; i++) {
const newTokens = fillInIncompleteTokensOnce(tokens);
if (newTokens) {
tokens = newTokens;
}
else {
break;
}
}
return tokens;
}
function fillInIncompleteTokensOnce(tokens) {
let i;
let newTokens;
for (i = 0; i < tokens.length; i++) {
const token = tokens[i];
if (token.type === 'paragraph' && token.raw.match(/(\n|^)\|/)) {
newTokens = completeTable(tokens.slice(i));
break;
}
}
const lastToken = tokens.at(-1);
if (!newTokens && lastToken?.type === 'list') {
const newListToken = completeListItemPattern(lastToken);
if (newListToken) {
newTokens = [newListToken];
i = tokens.length - 1;
}
}
if (!newTokens && lastToken?.type === 'paragraph') {
// Only operates on a single token, because any newline that follows this should break these patterns
const newToken = completeSingleLinePattern(lastToken);
if (newToken) {
newTokens = [newToken];
i = tokens.length - 1;
}
}
if (newTokens) {
const newTokensList = [
...tokens.slice(0, i),
...newTokens
];
newTokensList.links = tokens.links;
return newTokensList;
}
if (lastToken?.type === 'heading') {
const completeTokens = completeHeading(lastToken, mergeRawTokenText(tokens));
if (completeTokens) {
return completeTokens;
}
}
return null;
}
function completeCodespan(token) {
return completeWithString(token, '`');
}
function completeStar(tokens) {
return completeWithString(tokens, '*');
}
function completeUnderscore(tokens) {
return completeWithString(tokens, '_');
}
function completeLinkTarget(tokens) {
return completeWithString(tokens, ')', false);
}
function completeLinkTargetArg(tokens) {
return completeWithString(tokens, '")', false);
}
function completeLinkText(tokens) {
return completeWithString(tokens, '](https://microsoft.com)', false);
}
function completeDoublestar(tokens) {
return completeWithString(tokens, '**');
}
function completeDoubleUnderscore(tokens) {
return completeWithString(tokens, '__');
}
function completeWithString(tokens, closingString, shouldTrim = true) {
const mergedRawText = mergeRawTokenText(Array.isArray(tokens) ? tokens : [tokens]);
// If it was completed correctly, this should be a single token.
// Expecting either a Paragraph or a List
const trimmedRawText = shouldTrim ? mergedRawText.trimEnd() : mergedRawText;
return marked.lexer(trimmedRawText + closingString)[0];
}
function completeTable(tokens) {
const mergedRawText = mergeRawTokenText(tokens);
const lines = mergedRawText.split('\n');
let numCols; // The number of line1 col headers
let hasSeparatorRow = false;
for (let i = 0; i < lines.length; i++) {
const line = lines[i].trim();
if (typeof numCols === 'undefined' && line.match(/^\s*\|/)) {
const line1Matches = line.match(/(\|[^\|]+)(?=\||$)/g);
if (line1Matches) {
numCols = line1Matches.length;
}
}
else if (typeof numCols === 'number') {
if (line.match(/^\s*\|/)) {
if (i !== lines.length - 1) {
// We got the line1 header row, and the line2 separator row, but there are more lines, and it wasn't parsed as a table!
// That's strange and means that the table is probably malformed in the source, so I won't try to patch it up.
return undefined;
}
// Got a line2 separator row- partial or complete, doesn't matter, we'll replace it with a correct one
hasSeparatorRow = true;
}
else {
// The line after the header row isn't a valid separator row, so the table is malformed, don't fix it up
return undefined;
}
}
}
if (typeof numCols === 'number' && numCols > 0) {
const prefixText = hasSeparatorRow ? lines.slice(0, -1).join('\n') : mergedRawText;
const line1EndsInPipe = !!prefixText.match(/\|\s*$/);
const newRawText = prefixText + (line1EndsInPipe ? '' : '|') + `\n|${' --- |'.repeat(numCols)}`;
return marked.lexer(newRawText);
}
return undefined;
}
//# sourceMappingURL=markdownRenderer.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,148 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as browser from './browser.js';
import { IframeUtils } from './iframe.js';
import * as platform from '../common/platform.js';
export class StandardMouseEvent {
constructor(targetWindow, e) {
this.timestamp = Date.now();
this.browserEvent = e;
this.leftButton = e.button === 0;
this.middleButton = e.button === 1;
this.rightButton = e.button === 2;
this.buttons = e.buttons;
this.defaultPrevented = e.defaultPrevented;
this.target = e.target;
this.detail = e.detail || 1;
if (e.type === 'dblclick') {
this.detail = 2;
}
this.ctrlKey = e.ctrlKey;
this.shiftKey = e.shiftKey;
this.altKey = e.altKey;
this.metaKey = e.metaKey;
if (typeof e.pageX === 'number') {
this.posx = e.pageX;
this.posy = e.pageY;
}
else {
// Probably hit by MSGestureEvent
this.posx = e.clientX + this.target.ownerDocument.body.scrollLeft + this.target.ownerDocument.documentElement.scrollLeft;
this.posy = e.clientY + this.target.ownerDocument.body.scrollTop + this.target.ownerDocument.documentElement.scrollTop;
}
// Find the position of the iframe this code is executing in relative to the iframe where the event was captured.
const iframeOffsets = IframeUtils.getPositionOfChildWindowRelativeToAncestorWindow(targetWindow, e.view);
this.posx -= iframeOffsets.left;
this.posy -= iframeOffsets.top;
}
preventDefault() {
this.browserEvent.preventDefault();
}
stopPropagation() {
this.browserEvent.stopPropagation();
}
}
export class StandardWheelEvent {
constructor(e, deltaX = 0, deltaY = 0) {
this.browserEvent = e || null;
this.target = e ? (e.target || e.targetNode || e.srcElement) : null;
this.deltaY = deltaY;
this.deltaX = deltaX;
let shouldFactorDPR = false;
if (browser.isChrome) {
// Chrome version >= 123 contains the fix to factor devicePixelRatio into the wheel event.
// See https://chromium.googlesource.com/chromium/src.git/+/be51b448441ff0c9d1f17e0f25c4bf1ab3f11f61
const chromeVersionMatch = navigator.userAgent.match(/Chrome\/(\d+)/);
const chromeMajorVersion = chromeVersionMatch ? parseInt(chromeVersionMatch[1]) : 123;
shouldFactorDPR = chromeMajorVersion <= 122;
}
if (e) {
// Old (deprecated) wheel events
const e1 = e;
const e2 = e;
const devicePixelRatio = e.view?.devicePixelRatio || 1;
// vertical delta scroll
if (typeof e1.wheelDeltaY !== 'undefined') {
if (shouldFactorDPR) {
// Refs https://github.com/microsoft/vscode/issues/146403#issuecomment-1854538928
this.deltaY = e1.wheelDeltaY / (120 * devicePixelRatio);
}
else {
this.deltaY = e1.wheelDeltaY / 120;
}
}
else if (typeof e2.VERTICAL_AXIS !== 'undefined' && e2.axis === e2.VERTICAL_AXIS) {
this.deltaY = -e2.detail / 3;
}
else if (e.type === 'wheel') {
// Modern wheel event
// https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent
const ev = e;
if (ev.deltaMode === ev.DOM_DELTA_LINE) {
// the deltas are expressed in lines
if (browser.isFirefox && !platform.isMacintosh) {
this.deltaY = -e.deltaY / 3;
}
else {
this.deltaY = -e.deltaY;
}
}
else {
this.deltaY = -e.deltaY / 40;
}
}
// horizontal delta scroll
if (typeof e1.wheelDeltaX !== 'undefined') {
if (browser.isSafari && platform.isWindows) {
this.deltaX = -(e1.wheelDeltaX / 120);
}
else if (shouldFactorDPR) {
// Refs https://github.com/microsoft/vscode/issues/146403#issuecomment-1854538928
this.deltaX = e1.wheelDeltaX / (120 * devicePixelRatio);
}
else {
this.deltaX = e1.wheelDeltaX / 120;
}
}
else if (typeof e2.HORIZONTAL_AXIS !== 'undefined' && e2.axis === e2.HORIZONTAL_AXIS) {
this.deltaX = -e.detail / 3;
}
else if (e.type === 'wheel') {
// Modern wheel event
// https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent
const ev = e;
if (ev.deltaMode === ev.DOM_DELTA_LINE) {
// the deltas are expressed in lines
if (browser.isFirefox && !platform.isMacintosh) {
this.deltaX = -e.deltaX / 3;
}
else {
this.deltaX = -e.deltaX;
}
}
else {
this.deltaX = -e.deltaX / 40;
}
}
// Assume a vertical scroll if nothing else worked
if (this.deltaY === 0 && this.deltaX === 0 && e.wheelDelta) {
if (shouldFactorDPR) {
// Refs https://github.com/microsoft/vscode/issues/146403#issuecomment-1854538928
this.deltaY = e.wheelDelta / (120 * devicePixelRatio);
}
else {
this.deltaY = e.wheelDelta / 120;
}
}
}
}
preventDefault() {
this.browserEvent?.preventDefault();
}
stopPropagation() {
this.browserEvent?.stopPropagation();
}
}
//# sourceMappingURL=mouseEvent.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,221 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export var inputLatency;
(function (inputLatency) {
const totalKeydownTime = { total: 0, min: Number.MAX_VALUE, max: 0 };
const totalInputTime = { ...totalKeydownTime };
const totalRenderTime = { ...totalKeydownTime };
const totalInputLatencyTime = { ...totalKeydownTime };
let measurementsCount = 0;
const state = {
keydown: 0 /* EventPhase.Before */,
input: 0 /* EventPhase.Before */,
render: 0 /* EventPhase.Before */,
};
/**
* Record the start of the keydown event.
*/
function onKeyDown() {
/** Direct Check C. See explanation in {@link recordIfFinished} */
recordIfFinished();
performance.mark('inputlatency/start');
performance.mark('keydown/start');
state.keydown = 1 /* EventPhase.InProgress */;
queueMicrotask(markKeyDownEnd);
}
inputLatency.onKeyDown = onKeyDown;
/**
* Mark the end of the keydown event.
*/
function markKeyDownEnd() {
if (state.keydown === 1 /* EventPhase.InProgress */) {
performance.mark('keydown/end');
state.keydown = 2 /* EventPhase.Finished */;
}
}
/**
* Record the start of the beforeinput event.
*/
function onBeforeInput() {
performance.mark('input/start');
state.input = 1 /* EventPhase.InProgress */;
/** Schedule Task A. See explanation in {@link recordIfFinished} */
scheduleRecordIfFinishedTask();
}
inputLatency.onBeforeInput = onBeforeInput;
/**
* Record the start of the input event.
*/
function onInput() {
if (state.input === 0 /* EventPhase.Before */) {
// it looks like we didn't receive a `beforeinput`
onBeforeInput();
}
queueMicrotask(markInputEnd);
}
inputLatency.onInput = onInput;
function markInputEnd() {
if (state.input === 1 /* EventPhase.InProgress */) {
performance.mark('input/end');
state.input = 2 /* EventPhase.Finished */;
}
}
/**
* Record the start of the keyup event.
*/
function onKeyUp() {
/** Direct Check D. See explanation in {@link recordIfFinished} */
recordIfFinished();
}
inputLatency.onKeyUp = onKeyUp;
/**
* Record the start of the selectionchange event.
*/
function onSelectionChange() {
/** Direct Check E. See explanation in {@link recordIfFinished} */
recordIfFinished();
}
inputLatency.onSelectionChange = onSelectionChange;
/**
* Record the start of the animation frame performing the rendering.
*/
function onRenderStart() {
// Render may be triggered during input, but we only measure the following animation frame
if (state.keydown === 2 /* EventPhase.Finished */ && state.input === 2 /* EventPhase.Finished */ && state.render === 0 /* EventPhase.Before */) {
// Only measure the first render after keyboard input
performance.mark('render/start');
state.render = 1 /* EventPhase.InProgress */;
queueMicrotask(markRenderEnd);
/** Schedule Task B. See explanation in {@link recordIfFinished} */
scheduleRecordIfFinishedTask();
}
}
inputLatency.onRenderStart = onRenderStart;
/**
* Mark the end of the animation frame performing the rendering.
*/
function markRenderEnd() {
if (state.render === 1 /* EventPhase.InProgress */) {
performance.mark('render/end');
state.render = 2 /* EventPhase.Finished */;
}
}
function scheduleRecordIfFinishedTask() {
// Here we can safely assume that the `setTimeout` will not be
// artificially delayed by 4ms because we schedule it from
// event handlers
setTimeout(recordIfFinished);
}
/**
* Record the input latency sample if input handling and rendering are finished.
*
* The challenge here is that we want to record the latency in such a way that it includes
* also the layout and painting work the browser does during the animation frame task.
*
* Simply scheduling a new task (via `setTimeout`) from the animation frame task would
* schedule the new task at the end of the task queue (after other code that uses `setTimeout`),
* so we need to use multiple strategies to make sure our task runs before others:
*
* We schedule tasks (A and B):
* - we schedule a task A (via a `setTimeout` call) when the input starts in `markInputStart`.
* If the animation frame task is scheduled quickly by the browser, then task A has a very good
* chance of being the very first task after the animation frame and thus will record the input latency.
* - however, if the animation frame task is scheduled a bit later, then task A might execute
* before the animation frame task. We therefore schedule another task B from `markRenderStart`.
*
* We do direct checks in browser event handlers (C, D, E):
* - if the browser has multiple keydown events queued up, they will be scheduled before the `setTimeout` tasks,
* so we do a direct check in the keydown event handler (C).
* - depending on timing, sometimes the animation frame is scheduled even before the `keyup` event, so we
* do a direct check there too (E).
* - the browser oftentimes emits a `selectionchange` event after an `input`, so we do a direct check there (D).
*/
function recordIfFinished() {
if (state.keydown === 2 /* EventPhase.Finished */ && state.input === 2 /* EventPhase.Finished */ && state.render === 2 /* EventPhase.Finished */) {
performance.mark('inputlatency/end');
performance.measure('keydown', 'keydown/start', 'keydown/end');
performance.measure('input', 'input/start', 'input/end');
performance.measure('render', 'render/start', 'render/end');
performance.measure('inputlatency', 'inputlatency/start', 'inputlatency/end');
addMeasure('keydown', totalKeydownTime);
addMeasure('input', totalInputTime);
addMeasure('render', totalRenderTime);
addMeasure('inputlatency', totalInputLatencyTime);
// console.info(
// `input latency=${performance.getEntriesByName('inputlatency')[0].duration.toFixed(1)} [` +
// `keydown=${performance.getEntriesByName('keydown')[0].duration.toFixed(1)}, ` +
// `input=${performance.getEntriesByName('input')[0].duration.toFixed(1)}, ` +
// `render=${performance.getEntriesByName('render')[0].duration.toFixed(1)}` +
// `]`
// );
measurementsCount++;
reset();
}
}
function addMeasure(entryName, cumulativeMeasurement) {
const duration = performance.getEntriesByName(entryName)[0].duration;
cumulativeMeasurement.total += duration;
cumulativeMeasurement.min = Math.min(cumulativeMeasurement.min, duration);
cumulativeMeasurement.max = Math.max(cumulativeMeasurement.max, duration);
}
/**
* Clear the current sample.
*/
function reset() {
performance.clearMarks('keydown/start');
performance.clearMarks('keydown/end');
performance.clearMarks('input/start');
performance.clearMarks('input/end');
performance.clearMarks('render/start');
performance.clearMarks('render/end');
performance.clearMarks('inputlatency/start');
performance.clearMarks('inputlatency/end');
performance.clearMeasures('keydown');
performance.clearMeasures('input');
performance.clearMeasures('render');
performance.clearMeasures('inputlatency');
state.keydown = 0 /* EventPhase.Before */;
state.input = 0 /* EventPhase.Before */;
state.render = 0 /* EventPhase.Before */;
}
/**
* Gets all input latency samples and clears the internal buffers to start recording a new set
* of samples.
*/
function getAndClearMeasurements() {
if (measurementsCount === 0) {
return undefined;
}
// Assemble the result
const result = {
keydown: cumulativeToFinalMeasurement(totalKeydownTime),
input: cumulativeToFinalMeasurement(totalInputTime),
render: cumulativeToFinalMeasurement(totalRenderTime),
total: cumulativeToFinalMeasurement(totalInputLatencyTime),
sampleCount: measurementsCount
};
// Clear the cumulative measurements
clearCumulativeMeasurement(totalKeydownTime);
clearCumulativeMeasurement(totalInputTime);
clearCumulativeMeasurement(totalRenderTime);
clearCumulativeMeasurement(totalInputLatencyTime);
measurementsCount = 0;
return result;
}
inputLatency.getAndClearMeasurements = getAndClearMeasurements;
function cumulativeToFinalMeasurement(cumulative) {
return {
average: cumulative.total / measurementsCount,
max: cumulative.max,
min: cumulative.min,
};
}
function clearCumulativeMeasurement(cumulative) {
cumulative.total = 0;
cumulative.min = Number.MAX_VALUE;
cumulative.max = 0;
}
})(inputLatency || (inputLatency = {}));
//# sourceMappingURL=performance.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,86 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { getWindowId, onDidUnregisterWindow } from './dom.js';
import { Emitter, Event } from '../common/event.js';
import { Disposable, markAsSingleton } from '../common/lifecycle.js';
/**
* See https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio#monitoring_screen_resolution_or_zoom_level_changes
*/
class DevicePixelRatioMonitor extends Disposable {
constructor(targetWindow) {
super();
this._onDidChange = this._register(new Emitter());
this.onDidChange = this._onDidChange.event;
this._listener = () => this._handleChange(targetWindow, true);
this._mediaQueryList = null;
this._handleChange(targetWindow, false);
}
_handleChange(targetWindow, fireEvent) {
this._mediaQueryList?.removeEventListener('change', this._listener);
this._mediaQueryList = targetWindow.matchMedia(`(resolution: ${targetWindow.devicePixelRatio}dppx)`);
this._mediaQueryList.addEventListener('change', this._listener);
if (fireEvent) {
this._onDidChange.fire();
}
}
}
class PixelRatioMonitorImpl extends Disposable {
get value() {
return this._value;
}
constructor(targetWindow) {
super();
this._onDidChange = this._register(new Emitter());
this.onDidChange = this._onDidChange.event;
this._value = this._getPixelRatio(targetWindow);
const dprMonitor = this._register(new DevicePixelRatioMonitor(targetWindow));
this._register(dprMonitor.onDidChange(() => {
this._value = this._getPixelRatio(targetWindow);
this._onDidChange.fire(this._value);
}));
}
_getPixelRatio(targetWindow) {
const ctx = document.createElement('canvas').getContext('2d');
const dpr = targetWindow.devicePixelRatio || 1;
const bsr = ctx.webkitBackingStorePixelRatio ||
ctx.mozBackingStorePixelRatio ||
ctx.msBackingStorePixelRatio ||
ctx.oBackingStorePixelRatio ||
ctx.backingStorePixelRatio || 1;
return dpr / bsr;
}
}
class PixelRatioMonitorFacade {
constructor() {
this.mapWindowIdToPixelRatioMonitor = new Map();
}
_getOrCreatePixelRatioMonitor(targetWindow) {
const targetWindowId = getWindowId(targetWindow);
let pixelRatioMonitor = this.mapWindowIdToPixelRatioMonitor.get(targetWindowId);
if (!pixelRatioMonitor) {
pixelRatioMonitor = markAsSingleton(new PixelRatioMonitorImpl(targetWindow));
this.mapWindowIdToPixelRatioMonitor.set(targetWindowId, pixelRatioMonitor);
markAsSingleton(Event.once(onDidUnregisterWindow)(({ vscodeWindowId }) => {
if (vscodeWindowId === targetWindowId) {
pixelRatioMonitor?.dispose();
this.mapWindowIdToPixelRatioMonitor.delete(targetWindowId);
}
}));
}
return pixelRatioMonitor;
}
getInstance(targetWindow) {
return this._getOrCreatePixelRatioMonitor(targetWindow);
}
}
/**
* Returns the pixel ratio.
*
* This is useful for rendering <canvas> elements at native screen resolution or for being used as
* a cache key when storing font measurements. Fonts might render differently depending on resolution
* and any measurements need to be discarded for example when a window is moved from a monitor to another.
*/
export const PixelRatio = new PixelRatioMonitorFacade();
//# sourceMappingURL=pixelRatio.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,268 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import * as DomUtils from './dom.js';
import { mainWindow } from './window.js';
import { memoize } from '../common/decorators.js';
import { Event as EventUtils } from '../common/event.js';
import { Disposable, markAsSingleton, toDisposable } from '../common/lifecycle.js';
import { LinkedList } from '../common/linkedList.js';
export var EventType;
(function (EventType) {
EventType.Tap = '-monaco-gesturetap';
EventType.Change = '-monaco-gesturechange';
EventType.Start = '-monaco-gesturestart';
EventType.End = '-monaco-gesturesend';
EventType.Contextmenu = '-monaco-gesturecontextmenu';
})(EventType || (EventType = {}));
export class Gesture extends Disposable {
static { this.SCROLL_FRICTION = -0.005; }
static { this.HOLD_DELAY = 700; }
static { this.CLEAR_TAP_COUNT_TIME = 400; } // ms
constructor() {
super();
this.dispatched = false;
this.targets = new LinkedList();
this.ignoreTargets = new LinkedList();
this.activeTouches = {};
this.handle = null;
this._lastSetTapCountTime = 0;
this._register(EventUtils.runAndSubscribe(DomUtils.onDidRegisterWindow, ({ window, disposables }) => {
disposables.add(DomUtils.addDisposableListener(window.document, 'touchstart', (e) => this.onTouchStart(e), { passive: false }));
disposables.add(DomUtils.addDisposableListener(window.document, 'touchend', (e) => this.onTouchEnd(window, e)));
disposables.add(DomUtils.addDisposableListener(window.document, 'touchmove', (e) => this.onTouchMove(e), { passive: false }));
}, { window: mainWindow, disposables: this._store }));
}
static addTarget(element) {
if (!Gesture.isTouchDevice()) {
return Disposable.None;
}
if (!Gesture.INSTANCE) {
Gesture.INSTANCE = markAsSingleton(new Gesture());
}
const remove = Gesture.INSTANCE.targets.push(element);
return toDisposable(remove);
}
static ignoreTarget(element) {
if (!Gesture.isTouchDevice()) {
return Disposable.None;
}
if (!Gesture.INSTANCE) {
Gesture.INSTANCE = markAsSingleton(new Gesture());
}
const remove = Gesture.INSTANCE.ignoreTargets.push(element);
return toDisposable(remove);
}
static isTouchDevice() {
// `'ontouchstart' in window` always evaluates to true with typescript's modern typings. This causes `window` to be
// `never` later in `window.navigator`. That's why we need the explicit `window as Window` cast
return 'ontouchstart' in mainWindow || navigator.maxTouchPoints > 0;
}
dispose() {
if (this.handle) {
this.handle.dispose();
this.handle = null;
}
super.dispose();
}
onTouchStart(e) {
const timestamp = Date.now(); // use Date.now() because on FF e.timeStamp is not epoch based.
if (this.handle) {
this.handle.dispose();
this.handle = null;
}
for (let i = 0, len = e.targetTouches.length; i < len; i++) {
const touch = e.targetTouches.item(i);
this.activeTouches[touch.identifier] = {
id: touch.identifier,
initialTarget: touch.target,
initialTimeStamp: timestamp,
initialPageX: touch.pageX,
initialPageY: touch.pageY,
rollingTimestamps: [timestamp],
rollingPageX: [touch.pageX],
rollingPageY: [touch.pageY]
};
const evt = this.newGestureEvent(EventType.Start, touch.target);
evt.pageX = touch.pageX;
evt.pageY = touch.pageY;
this.dispatchEvent(evt);
}
if (this.dispatched) {
e.preventDefault();
e.stopPropagation();
this.dispatched = false;
}
}
onTouchEnd(targetWindow, e) {
const timestamp = Date.now(); // use Date.now() because on FF e.timeStamp is not epoch based.
const activeTouchCount = Object.keys(this.activeTouches).length;
for (let i = 0, len = e.changedTouches.length; i < len; i++) {
const touch = e.changedTouches.item(i);
if (!this.activeTouches.hasOwnProperty(String(touch.identifier))) {
console.warn('move of an UNKNOWN touch', touch);
continue;
}
const data = this.activeTouches[touch.identifier], holdTime = Date.now() - data.initialTimeStamp;
if (holdTime < Gesture.HOLD_DELAY
&& Math.abs(data.initialPageX - data.rollingPageX.at(-1)) < 30
&& Math.abs(data.initialPageY - data.rollingPageY.at(-1)) < 30) {
const evt = this.newGestureEvent(EventType.Tap, data.initialTarget);
evt.pageX = data.rollingPageX.at(-1);
evt.pageY = data.rollingPageY.at(-1);
this.dispatchEvent(evt);
}
else if (holdTime >= Gesture.HOLD_DELAY
&& Math.abs(data.initialPageX - data.rollingPageX.at(-1)) < 30
&& Math.abs(data.initialPageY - data.rollingPageY.at(-1)) < 30) {
const evt = this.newGestureEvent(EventType.Contextmenu, data.initialTarget);
evt.pageX = data.rollingPageX.at(-1);
evt.pageY = data.rollingPageY.at(-1);
this.dispatchEvent(evt);
}
else if (activeTouchCount === 1) {
const finalX = data.rollingPageX.at(-1);
const finalY = data.rollingPageY.at(-1);
const deltaT = data.rollingTimestamps.at(-1) - data.rollingTimestamps[0];
const deltaX = finalX - data.rollingPageX[0];
const deltaY = finalY - data.rollingPageY[0];
// We need to get all the dispatch targets on the start of the inertia event
const dispatchTo = [...this.targets].filter(t => data.initialTarget instanceof Node && t.contains(data.initialTarget));
this.inertia(targetWindow, dispatchTo, timestamp, // time now
Math.abs(deltaX) / deltaT, // speed
deltaX > 0 ? 1 : -1, // x direction
finalX, // x now
Math.abs(deltaY) / deltaT, // y speed
deltaY > 0 ? 1 : -1, // y direction
finalY // y now
);
}
this.dispatchEvent(this.newGestureEvent(EventType.End, data.initialTarget));
// forget about this touch
delete this.activeTouches[touch.identifier];
}
if (this.dispatched) {
e.preventDefault();
e.stopPropagation();
this.dispatched = false;
}
}
newGestureEvent(type, initialTarget) {
const event = document.createEvent('CustomEvent');
event.initEvent(type, false, true);
event.initialTarget = initialTarget;
event.tapCount = 0;
return event;
}
dispatchEvent(event) {
if (event.type === EventType.Tap) {
const currentTime = (new Date()).getTime();
let setTapCount = 0;
if (currentTime - this._lastSetTapCountTime > Gesture.CLEAR_TAP_COUNT_TIME) {
setTapCount = 1;
}
else {
setTapCount = 2;
}
this._lastSetTapCountTime = currentTime;
event.tapCount = setTapCount;
}
else if (event.type === EventType.Change || event.type === EventType.Contextmenu) {
// tap is canceled by scrolling or context menu
this._lastSetTapCountTime = 0;
}
if (event.initialTarget instanceof Node) {
for (const ignoreTarget of this.ignoreTargets) {
if (ignoreTarget.contains(event.initialTarget)) {
return;
}
}
const targets = [];
for (const target of this.targets) {
if (target.contains(event.initialTarget)) {
let depth = 0;
let now = event.initialTarget;
while (now && now !== target) {
depth++;
now = now.parentElement;
}
targets.push([depth, target]);
}
}
targets.sort((a, b) => a[0] - b[0]);
for (const [_, target] of targets) {
target.dispatchEvent(event);
this.dispatched = true;
}
}
}
inertia(targetWindow, dispatchTo, t1, vX, dirX, x, vY, dirY, y) {
this.handle = DomUtils.scheduleAtNextAnimationFrame(targetWindow, () => {
const now = Date.now();
// velocity: old speed + accel_over_time
const deltaT = now - t1;
let delta_pos_x = 0, delta_pos_y = 0;
let stopped = true;
vX += Gesture.SCROLL_FRICTION * deltaT;
vY += Gesture.SCROLL_FRICTION * deltaT;
if (vX > 0) {
stopped = false;
delta_pos_x = dirX * vX * deltaT;
}
if (vY > 0) {
stopped = false;
delta_pos_y = dirY * vY * deltaT;
}
// dispatch translation event
const evt = this.newGestureEvent(EventType.Change);
evt.translationX = delta_pos_x;
evt.translationY = delta_pos_y;
dispatchTo.forEach(d => d.dispatchEvent(evt));
if (!stopped) {
this.inertia(targetWindow, dispatchTo, now, vX, dirX, x + delta_pos_x, vY, dirY, y + delta_pos_y);
}
});
}
onTouchMove(e) {
const timestamp = Date.now(); // use Date.now() because on FF e.timeStamp is not epoch based.
for (let i = 0, len = e.changedTouches.length; i < len; i++) {
const touch = e.changedTouches.item(i);
if (!this.activeTouches.hasOwnProperty(String(touch.identifier))) {
console.warn('end of an UNKNOWN touch', touch);
continue;
}
const data = this.activeTouches[touch.identifier];
const evt = this.newGestureEvent(EventType.Change, data.initialTarget);
evt.translationX = touch.pageX - data.rollingPageX.at(-1);
evt.translationY = touch.pageY - data.rollingPageY.at(-1);
evt.pageX = touch.pageX;
evt.pageY = touch.pageY;
this.dispatchEvent(evt);
// only keep a few data points, to average the final speed
if (data.rollingPageX.length > 3) {
data.rollingPageX.shift();
data.rollingPageY.shift();
data.rollingTimestamps.shift();
}
data.rollingPageX.push(touch.pageX);
data.rollingPageY.push(touch.pageY);
data.rollingTimestamps.push(timestamp);
}
if (this.dispatched) {
e.preventDefault();
e.stopPropagation();
this.dispatched = false;
}
}
}
__decorate([
memoize
], Gesture, "isTouchDevice", null);
//# sourceMappingURL=touch.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,25 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { onUnexpectedError } from '../common/errors.js';
export function createTrustedTypesPolicy(policyName, policyOptions) {
const monacoEnvironment = globalThis.MonacoEnvironment;
if (monacoEnvironment?.createTrustedTypesPolicy) {
try {
return monacoEnvironment.createTrustedTypesPolicy(policyName, policyOptions);
}
catch (err) {
onUnexpectedError(err);
return undefined;
}
}
try {
return globalThis.trustedTypes?.createPolicy(policyName, policyOptions);
}
catch (err) {
onUnexpectedError(err);
return undefined;
}
}
//# sourceMappingURL=trustedTypes.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src/vs/base/browser/trustedTypes.ts","vs/base/browser/trustedTypes.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAEhG,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,UAAU,wBAAwB,CACvC,UAAkB,EAClB,aAAuB;IASvB,MAAM,iBAAiB,GAAoC,UAAkB,CAAC,iBAAiB,CAAC;IAEhG,IAAI,iBAAiB,EAAE,wBAAwB,EAAE,CAAC;QACjD,IAAI,CAAC;YACJ,OAAO,iBAAiB,CAAC,wBAAwB,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;QAC9E,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,iBAAiB,CAAC,GAAG,CAAC,CAAC;YACvB,OAAO,SAAS,CAAC;QAClB,CAAC;IACF,CAAC;IACD,IAAI,CAAC;QACJ,OAAQ,UAAkB,CAAC,YAAY,EAAE,YAAY,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;IAClF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,iBAAiB,CAAC,GAAG,CAAC,CAAC;QACvB,OAAO,SAAS,CAAC;IAClB,CAAC;AACF,CAAC","file":"trustedTypes.js","sourceRoot":"file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { onUnexpectedError } from '../common/errors.js';\n\nexport function createTrustedTypesPolicy<Options extends TrustedTypePolicyOptions>(\n\tpolicyName: string,\n\tpolicyOptions?: Options,\n): undefined | Pick<TrustedTypePolicy<Options>, 'name' | Extract<keyof Options, keyof TrustedTypePolicyOptions>> {\n\n\tinterface IMonacoEnvironment {\n\t\tcreateTrustedTypesPolicy<Options extends TrustedTypePolicyOptions>(\n\t\t\tpolicyName: string,\n\t\t\tpolicyOptions?: Options,\n\t\t): undefined | Pick<TrustedTypePolicy<Options>, 'name' | Extract<keyof Options, keyof TrustedTypePolicyOptions>>;\n\t}\n\tconst monacoEnvironment: IMonacoEnvironment | undefined = (globalThis as any).MonacoEnvironment;\n\n\tif (monacoEnvironment?.createTrustedTypesPolicy) {\n\t\ttry {\n\t\t\treturn monacoEnvironment.createTrustedTypesPolicy(policyName, policyOptions);\n\t\t} catch (err) {\n\t\t\tonUnexpectedError(err);\n\t\t\treturn undefined;\n\t\t}\n\t}\n\ttry {\n\t\treturn (globalThis as any).trustedTypes?.createPolicy(policyName, policyOptions);\n\t} catch (err) {\n\t\tonUnexpectedError(err);\n\t\treturn undefined;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { onUnexpectedError } from '../common/errors.js';\n\nexport function createTrustedTypesPolicy<Options extends TrustedTypePolicyOptions>(\n\tpolicyName: string,\n\tpolicyOptions?: Options,\n): undefined | Pick<TrustedTypePolicy<Options>, 'name' | Extract<keyof Options, keyof TrustedTypePolicyOptions>> {\n\n\tinterface IMonacoEnvironment {\n\t\tcreateTrustedTypesPolicy<Options extends TrustedTypePolicyOptions>(\n\t\t\tpolicyName: string,\n\t\t\tpolicyOptions?: Options,\n\t\t): undefined | Pick<TrustedTypePolicy<Options>, 'name' | Extract<keyof Options, keyof TrustedTypePolicyOptions>>;\n\t}\n\tconst monacoEnvironment: IMonacoEnvironment | undefined = (globalThis as any).MonacoEnvironment;\n\n\tif (monacoEnvironment?.createTrustedTypesPolicy) {\n\t\ttry {\n\t\t\treturn monacoEnvironment.createTrustedTypesPolicy(policyName, policyOptions);\n\t\t} catch (err) {\n\t\t\tonUnexpectedError(err);\n\t\t\treturn undefined;\n\t\t}\n\t}\n\ttry {\n\t\treturn (globalThis as any).trustedTypes?.createPolicy(policyName, policyOptions);\n\t} catch (err) {\n\t\tonUnexpectedError(err);\n\t\treturn undefined;\n\t}\n}\n"]}

View File

@@ -0,0 +1,374 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { isFirefox } from '../../browser.js';
import { DataTransfers } from '../../dnd.js';
import { addDisposableListener, EventHelper, EventType } from '../../dom.js';
import { EventType as TouchEventType, Gesture } from '../../touch.js';
import { getDefaultHoverDelegate } from '../hover/hoverDelegateFactory.js';
import { SelectBox } from '../selectBox/selectBox.js';
import { Action, ActionRunner, Separator } from '../../../common/actions.js';
import { Disposable } from '../../../common/lifecycle.js';
import * as platform from '../../../common/platform.js';
import * as types from '../../../common/types.js';
import './actionbar.css';
import * as nls from '../../../../nls.js';
import { getBaseLayerHoverDelegate } from '../hover/hoverDelegate2.js';
export class BaseActionViewItem extends Disposable {
get action() {
return this._action;
}
constructor(context, action, options = {}) {
super();
this.options = options;
this._context = context || this;
this._action = action;
if (action instanceof Action) {
this._register(action.onDidChange(event => {
if (!this.element) {
// we have not been rendered yet, so there
// is no point in updating the UI
return;
}
this.handleActionChangeEvent(event);
}));
}
}
handleActionChangeEvent(event) {
if (event.enabled !== undefined) {
this.updateEnabled();
}
if (event.checked !== undefined) {
this.updateChecked();
}
if (event.class !== undefined) {
this.updateClass();
}
if (event.label !== undefined) {
this.updateLabel();
this.updateTooltip();
}
if (event.tooltip !== undefined) {
this.updateTooltip();
}
}
get actionRunner() {
if (!this._actionRunner) {
this._actionRunner = this._register(new ActionRunner());
}
return this._actionRunner;
}
set actionRunner(actionRunner) {
this._actionRunner = actionRunner;
}
isEnabled() {
return this._action.enabled;
}
setActionContext(newContext) {
this._context = newContext;
}
render(container) {
const element = this.element = container;
this._register(Gesture.addTarget(container));
const enableDragging = this.options && this.options.draggable;
if (enableDragging) {
container.draggable = true;
if (isFirefox) {
// Firefox: requires to set a text data transfer to get going
this._register(addDisposableListener(container, EventType.DRAG_START, e => e.dataTransfer?.setData(DataTransfers.TEXT, this._action.label)));
}
}
this._register(addDisposableListener(element, TouchEventType.Tap, e => this.onClick(e, true))); // Preserve focus on tap #125470
this._register(addDisposableListener(element, EventType.MOUSE_DOWN, e => {
if (!enableDragging) {
EventHelper.stop(e, true); // do not run when dragging is on because that would disable it
}
if (this._action.enabled && e.button === 0) {
element.classList.add('active');
}
}));
if (platform.isMacintosh) {
// macOS: allow to trigger the button when holding Ctrl+key and pressing the
// main mouse button. This is for scenarios where e.g. some interaction forces
// the Ctrl+key to be pressed and hold but the user still wants to interact
// with the actions (for example quick access in quick navigation mode).
this._register(addDisposableListener(element, EventType.CONTEXT_MENU, e => {
if (e.button === 0 && e.ctrlKey === true) {
this.onClick(e);
}
}));
}
this._register(addDisposableListener(element, EventType.CLICK, e => {
EventHelper.stop(e, true);
// menus do not use the click event
if (!(this.options && this.options.isMenu)) {
this.onClick(e);
}
}));
this._register(addDisposableListener(element, EventType.DBLCLICK, e => {
EventHelper.stop(e, true);
}));
[EventType.MOUSE_UP, EventType.MOUSE_OUT].forEach(event => {
this._register(addDisposableListener(element, event, e => {
EventHelper.stop(e);
element.classList.remove('active');
}));
});
}
onClick(event, preserveFocus = false) {
EventHelper.stop(event, true);
const context = types.isUndefinedOrNull(this._context) ? this.options?.useEventAsContext ? event : { preserveFocus } : this._context;
this.actionRunner.run(this._action, context);
}
// Only set the tabIndex on the element once it is about to get focused
// That way this element wont be a tab stop when it is not needed #106441
focus() {
if (this.element) {
this.element.tabIndex = 0;
this.element.focus();
this.element.classList.add('focused');
}
}
blur() {
if (this.element) {
this.element.blur();
this.element.tabIndex = -1;
this.element.classList.remove('focused');
}
}
setFocusable(focusable) {
if (this.element) {
this.element.tabIndex = focusable ? 0 : -1;
}
}
get trapsArrowNavigation() {
return false;
}
updateEnabled() {
// implement in subclass
}
updateLabel() {
// implement in subclass
}
getClass() {
return this.action.class;
}
getTooltip() {
return this.action.tooltip;
}
getHoverContents() {
return this.getTooltip();
}
updateTooltip() {
if (!this.element) {
return;
}
const title = this.getHoverContents() ?? '';
this.updateAriaLabel();
if (!this.customHover && title !== '') {
const hoverDelegate = this.options.hoverDelegate ?? getDefaultHoverDelegate('element');
this.customHover = this._store.add(getBaseLayerHoverDelegate().setupManagedHover(hoverDelegate, this.element, title));
}
else if (this.customHover) {
this.customHover.update(title);
}
}
updateAriaLabel() {
if (this.element) {
const title = this.getTooltip() ?? '';
this.element.setAttribute('aria-label', title);
}
}
updateClass() {
// implement in subclass
}
updateChecked() {
// implement in subclass
}
dispose() {
if (this.element) {
this.element.remove();
this.element = undefined;
}
this._context = undefined;
super.dispose();
}
}
export class ActionViewItem extends BaseActionViewItem {
constructor(context, action, options) {
options = {
...options,
icon: options.icon !== undefined ? options.icon : false,
label: options.label !== undefined ? options.label : true,
};
super(context, action, options);
this.options = options;
this.cssClass = '';
}
render(container) {
super.render(container);
types.assertType(this.element);
const label = document.createElement('a');
label.classList.add('action-label');
label.setAttribute('role', this.getDefaultAriaRole());
this.label = label;
this.element.appendChild(label);
if (this.options.label && this.options.keybinding && !this.options.keybindingNotRenderedWithLabel) {
const kbLabel = document.createElement('span');
kbLabel.classList.add('keybinding');
kbLabel.textContent = this.options.keybinding;
this.element.appendChild(kbLabel);
}
this.updateClass();
this.updateLabel();
this.updateTooltip();
this.updateEnabled();
this.updateChecked();
}
getDefaultAriaRole() {
if (this._action.id === Separator.ID) {
return 'presentation'; // A separator is a presentation item
}
else {
if (this.options.isMenu) {
return 'menuitem';
}
else if (this.options.isTabList) {
return 'tab';
}
else {
return 'button';
}
}
}
// Only set the tabIndex on the element once it is about to get focused
// That way this element wont be a tab stop when it is not needed #106441
focus() {
if (this.label) {
this.label.tabIndex = 0;
this.label.focus();
}
}
blur() {
if (this.label) {
this.label.tabIndex = -1;
}
}
setFocusable(focusable) {
if (this.label) {
this.label.tabIndex = focusable ? 0 : -1;
}
}
updateLabel() {
if (this.options.label && this.label) {
this.label.textContent = this.action.label;
}
}
getTooltip() {
let title = null;
if (this.action.tooltip) {
title = this.action.tooltip;
}
else if (this.action.label) {
title = this.action.label;
if (this.options.keybinding) {
title = nls.localize(0, "{0} ({1})", title, this.options.keybinding);
}
}
return title ?? undefined;
}
updateClass() {
if (this.cssClass && this.label) {
this.label.classList.remove(...this.cssClass.split(' '));
}
if (this.options.icon) {
this.cssClass = this.getClass();
if (this.label) {
this.label.classList.add('codicon');
if (this.cssClass) {
this.label.classList.add(...this.cssClass.split(' '));
}
}
this.updateEnabled();
}
else {
this.label?.classList.remove('codicon');
}
}
updateEnabled() {
if (this.action.enabled) {
if (this.label) {
this.label.removeAttribute('aria-disabled');
this.label.classList.remove('disabled');
}
this.element?.classList.remove('disabled');
}
else {
if (this.label) {
this.label.setAttribute('aria-disabled', 'true');
this.label.classList.add('disabled');
}
this.element?.classList.add('disabled');
}
}
updateAriaLabel() {
if (this.label) {
const title = this.getTooltip() ?? '';
this.label.setAttribute('aria-label', title);
}
}
updateChecked() {
if (this.label) {
if (this.action.checked !== undefined) {
this.label.classList.toggle('checked', this.action.checked);
if (this.options.isTabList) {
this.label.setAttribute('aria-selected', this.action.checked ? 'true' : 'false');
}
else {
this.label.setAttribute('aria-checked', this.action.checked ? 'true' : 'false');
this.label.setAttribute('role', 'checkbox');
}
}
else {
this.label.classList.remove('checked');
this.label.removeAttribute(this.options.isTabList ? 'aria-selected' : 'aria-checked');
this.label.setAttribute('role', this.getDefaultAriaRole());
}
}
}
}
export class SelectActionViewItem extends BaseActionViewItem {
constructor(ctx, action, options, selected, contextViewProvider, styles, selectBoxOptions) {
super(ctx, action);
this.selectBox = new SelectBox(options, selected, contextViewProvider, styles, selectBoxOptions);
this.selectBox.setFocusable(false);
this._register(this.selectBox);
this.registerListeners();
}
select(index) {
this.selectBox.select(index);
}
registerListeners() {
this._register(this.selectBox.onDidSelect(e => this.runAction(e.selected, e.index)));
}
runAction(option, index) {
this.actionRunner.run(this._action, this.getActionContext(option, index));
}
getActionContext(option, index) {
return option;
}
setFocusable(focusable) {
this.selectBox.setFocusable(focusable);
}
focus() {
this.selectBox?.focus();
}
blur() {
this.selectBox?.blur();
}
render(container) {
this.selectBox.render(container);
}
}
//# sourceMappingURL=actionViewItems.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,124 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-action-bar {
white-space: nowrap;
height: 100%;
}
.monaco-action-bar .actions-container {
display: flex;
margin: 0 auto;
padding: 0;
height: 100%;
width: 100%;
align-items: center;
}
.monaco-action-bar.vertical .actions-container {
display: inline-block;
}
.monaco-action-bar .action-item {
display: block;
align-items: center;
justify-content: center;
cursor: pointer;
position: relative; /* DO NOT REMOVE - this is the key to preventing the ghosting icon bug in Chrome 42 */
}
.monaco-action-bar .action-item.disabled {
cursor: default;
}
.monaco-action-bar .action-item .icon,
.monaco-action-bar .action-item .codicon {
display: block;
}
.monaco-action-bar .action-item .codicon {
display: flex;
align-items: center;
width: 16px;
height: 16px;
}
.monaco-action-bar .action-label {
display: flex;
font-size: 11px;
padding: 3px;
border-radius: 5px;
}
.monaco-action-bar .action-item.disabled .action-label:not(.icon) ,
.monaco-action-bar .action-item.disabled .action-label:not(.icon)::before,
.monaco-action-bar .action-item.disabled .action-label:not(.icon):hover {
color: var(--vscode-disabledForeground);
}
/* Unable to change color of SVGs, hence opacity is used */
.monaco-action-bar .action-item.disabled .action-label.icon ,
.monaco-action-bar .action-item.disabled .action-label.icon::before,
.monaco-action-bar .action-item.disabled .action-label.icon:hover {
opacity: 0.6;
}
/* Vertical actions */
.monaco-action-bar.vertical {
text-align: left;
}
.monaco-action-bar.vertical .action-item {
display: block;
}
.monaco-action-bar.vertical .action-label.separator {
display: block;
border-bottom: 1px solid var(--vscode-disabledForeground);
padding-top: 1px;
margin-left: .8em;
margin-right: .8em;
}
.monaco-action-bar .action-item .action-label.separator {
width: 1px;
height: 16px;
margin: 5px 4px !important;
cursor: default;
min-width: 1px;
padding: 0;
background-color: var(--vscode-disabledForeground);
}
.secondary-actions .monaco-action-bar .action-label {
margin-left: 6px;
}
/* Action Items */
.monaco-action-bar .action-item.select-container {
overflow: hidden; /* somehow the dropdown overflows its container, we prevent it here to not push */
flex: 1;
max-width: 170px;
min-width: 60px;
display: flex;
align-items: center;
justify-content: center;
margin-right: 10px;
}
.monaco-action-bar .action-item.action-dropdown-item {
display: flex;
}
.monaco-action-bar .action-item.action-dropdown-item > .action-dropdown-item-separator {
display: flex;
align-items: center;
cursor: default;
}
.monaco-action-bar .action-item.action-dropdown-item > .action-dropdown-item-separator > div {
width: 1px;
}

View File

@@ -0,0 +1,443 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as DOM from '../../dom.js';
import { StandardKeyboardEvent } from '../../keyboardEvent.js';
import { ActionViewItem, BaseActionViewItem } from './actionViewItems.js';
import { createInstantHoverDelegate } from '../hover/hoverDelegateFactory.js';
import { ActionRunner, Separator } from '../../../common/actions.js';
import { Emitter } from '../../../common/event.js';
import { Disposable, DisposableMap, DisposableStore, dispose } from '../../../common/lifecycle.js';
import * as types from '../../../common/types.js';
import './actionbar.css';
export class ActionBar extends Disposable {
get onDidBlur() { return this._onDidBlur.event; }
get onDidCancel() { return this._onDidCancel.event; }
get onDidRun() { return this._onDidRun.event; }
get onWillRun() { return this._onWillRun.event; }
constructor(container, options = {}) {
super();
this._actionRunnerDisposables = this._register(new DisposableStore());
this.viewItemDisposables = this._register(new DisposableMap());
// Trigger Key Tracking
this.triggerKeyDown = false;
this.focusable = true;
this._onDidBlur = this._register(new Emitter());
this._onDidCancel = this._register(new Emitter({ onWillAddFirstListener: () => this.cancelHasListener = true }));
this.cancelHasListener = false;
this._onDidRun = this._register(new Emitter());
this._onWillRun = this._register(new Emitter());
this.options = options;
this._context = options.context ?? null;
this._orientation = this.options.orientation ?? 0 /* ActionsOrientation.HORIZONTAL */;
this._triggerKeys = {
keyDown: this.options.triggerKeys?.keyDown ?? false,
keys: this.options.triggerKeys?.keys ?? [3 /* KeyCode.Enter */, 10 /* KeyCode.Space */]
};
this._hoverDelegate = options.hoverDelegate ?? this._register(createInstantHoverDelegate());
if (this.options.actionRunner) {
this._actionRunner = this.options.actionRunner;
}
else {
this._actionRunner = new ActionRunner();
this._actionRunnerDisposables.add(this._actionRunner);
}
this._actionRunnerDisposables.add(this._actionRunner.onDidRun(e => this._onDidRun.fire(e)));
this._actionRunnerDisposables.add(this._actionRunner.onWillRun(e => this._onWillRun.fire(e)));
this.viewItems = [];
this.focusedItem = undefined;
this.domNode = document.createElement('div');
this.domNode.className = 'monaco-action-bar';
let previousKeys;
let nextKeys;
switch (this._orientation) {
case 0 /* ActionsOrientation.HORIZONTAL */:
previousKeys = [15 /* KeyCode.LeftArrow */];
nextKeys = [17 /* KeyCode.RightArrow */];
break;
case 1 /* ActionsOrientation.VERTICAL */:
previousKeys = [16 /* KeyCode.UpArrow */];
nextKeys = [18 /* KeyCode.DownArrow */];
this.domNode.className += ' vertical';
break;
}
this._register(DOM.addDisposableListener(this.domNode, DOM.EventType.KEY_DOWN, e => {
const event = new StandardKeyboardEvent(e);
let eventHandled = true;
const focusedItem = typeof this.focusedItem === 'number' ? this.viewItems[this.focusedItem] : undefined;
if (previousKeys && (event.equals(previousKeys[0]) || event.equals(previousKeys[1]))) {
eventHandled = this.focusPrevious();
}
else if (nextKeys && (event.equals(nextKeys[0]) || event.equals(nextKeys[1]))) {
eventHandled = this.focusNext();
}
else if (event.equals(9 /* KeyCode.Escape */) && this.cancelHasListener) {
this._onDidCancel.fire();
}
else if (event.equals(14 /* KeyCode.Home */)) {
eventHandled = this.focusFirst();
}
else if (event.equals(13 /* KeyCode.End */)) {
eventHandled = this.focusLast();
}
else if (event.equals(2 /* KeyCode.Tab */) && focusedItem instanceof BaseActionViewItem && focusedItem.trapsArrowNavigation) {
// Tab, so forcibly focus next #219199
eventHandled = this.focusNext(undefined, true);
}
else if (this.isTriggerKeyEvent(event)) {
// Staying out of the else branch even if not triggered
if (this._triggerKeys.keyDown) {
this.doTrigger(event);
}
else {
this.triggerKeyDown = true;
}
}
else {
eventHandled = false;
}
if (eventHandled) {
event.preventDefault();
event.stopPropagation();
}
}));
this._register(DOM.addDisposableListener(this.domNode, DOM.EventType.KEY_UP, e => {
const event = new StandardKeyboardEvent(e);
// Run action on Enter/Space
if (this.isTriggerKeyEvent(event)) {
if (!this._triggerKeys.keyDown && this.triggerKeyDown) {
this.triggerKeyDown = false;
this.doTrigger(event);
}
event.preventDefault();
event.stopPropagation();
}
// Recompute focused item
else if (event.equals(2 /* KeyCode.Tab */) || event.equals(1024 /* KeyMod.Shift */ | 2 /* KeyCode.Tab */) || event.equals(16 /* KeyCode.UpArrow */) || event.equals(18 /* KeyCode.DownArrow */) || event.equals(15 /* KeyCode.LeftArrow */) || event.equals(17 /* KeyCode.RightArrow */)) {
this.updateFocusedItem();
}
}));
this.focusTracker = this._register(DOM.trackFocus(this.domNode));
this._register(this.focusTracker.onDidBlur(() => {
if (DOM.getActiveElement() === this.domNode || !DOM.isAncestor(DOM.getActiveElement(), this.domNode)) {
this._onDidBlur.fire();
this.previouslyFocusedItem = this.focusedItem;
this.focusedItem = undefined;
this.triggerKeyDown = false;
}
}));
this._register(this.focusTracker.onDidFocus(() => this.updateFocusedItem()));
this.actionsList = document.createElement('ul');
this.actionsList.className = 'actions-container';
if (this.options.highlightToggledItems) {
this.actionsList.classList.add('highlight-toggled');
}
this.actionsList.setAttribute('role', this.options.ariaRole || 'toolbar');
if (this.options.ariaLabel) {
this.actionsList.setAttribute('aria-label', this.options.ariaLabel);
}
this.domNode.appendChild(this.actionsList);
container.appendChild(this.domNode);
}
refreshRole() {
if (this.length() >= 1) {
this.actionsList.setAttribute('role', this.options.ariaRole || 'toolbar');
}
else {
this.actionsList.setAttribute('role', 'presentation');
}
}
// Some action bars should not be focusable at times
// When an action bar is not focusable make sure to make all the elements inside it not focusable
// When an action bar is focusable again, make sure the first item can be focused
setFocusable(focusable) {
this.focusable = focusable;
if (this.focusable) {
const firstEnabled = this.viewItems.find(vi => vi instanceof BaseActionViewItem && vi.isEnabled());
if (firstEnabled instanceof BaseActionViewItem) {
firstEnabled.setFocusable(true);
}
}
else {
this.viewItems.forEach(vi => {
if (vi instanceof BaseActionViewItem) {
vi.setFocusable(false);
}
});
}
}
isTriggerKeyEvent(event) {
let ret = false;
this._triggerKeys.keys.forEach(keyCode => {
ret = ret || event.equals(keyCode);
});
return ret;
}
updateFocusedItem() {
for (let i = 0; i < this.actionsList.children.length; i++) {
const elem = this.actionsList.children[i];
if (DOM.isAncestor(DOM.getActiveElement(), elem)) {
this.focusedItem = i;
this.viewItems[this.focusedItem]?.showHover?.();
break;
}
}
}
get context() {
return this._context;
}
set context(context) {
this._context = context;
this.viewItems.forEach(i => i.setActionContext(context));
}
get actionRunner() {
return this._actionRunner;
}
set actionRunner(actionRunner) {
this._actionRunner = actionRunner;
// when setting a new `IActionRunner` make sure to dispose old listeners and
// start to forward events from the new listener
this._actionRunnerDisposables.clear();
this._actionRunnerDisposables.add(this._actionRunner.onDidRun(e => this._onDidRun.fire(e)));
this._actionRunnerDisposables.add(this._actionRunner.onWillRun(e => this._onWillRun.fire(e)));
this.viewItems.forEach(item => item.actionRunner = actionRunner);
}
getContainer() {
return this.domNode;
}
getAction(indexOrElement) {
// by index
if (typeof indexOrElement === 'number') {
return this.viewItems[indexOrElement]?.action;
}
// by element
if (DOM.isHTMLElement(indexOrElement)) {
while (indexOrElement.parentElement !== this.actionsList) {
if (!indexOrElement.parentElement) {
return undefined;
}
indexOrElement = indexOrElement.parentElement;
}
for (let i = 0; i < this.actionsList.childNodes.length; i++) {
if (this.actionsList.childNodes[i] === indexOrElement) {
return this.viewItems[i].action;
}
}
}
return undefined;
}
push(arg, options = {}) {
const actions = Array.isArray(arg) ? arg : [arg];
let index = types.isNumber(options.index) ? options.index : null;
actions.forEach((action) => {
const actionViewItemElement = document.createElement('li');
actionViewItemElement.className = 'action-item';
actionViewItemElement.setAttribute('role', 'presentation');
let item;
const viewItemOptions = { hoverDelegate: this._hoverDelegate, ...options, isTabList: this.options.ariaRole === 'tablist' };
if (this.options.actionViewItemProvider) {
item = this.options.actionViewItemProvider(action, viewItemOptions);
}
if (!item) {
item = new ActionViewItem(this.context, action, viewItemOptions);
}
// Prevent native context menu on actions
if (!this.options.allowContextMenu) {
this.viewItemDisposables.set(item, DOM.addDisposableListener(actionViewItemElement, DOM.EventType.CONTEXT_MENU, (e) => {
DOM.EventHelper.stop(e, true);
}));
}
item.actionRunner = this._actionRunner;
item.setActionContext(this.context);
item.render(actionViewItemElement);
if (index === null || index < 0 || index >= this.actionsList.children.length) {
this.actionsList.appendChild(actionViewItemElement);
this.viewItems.push(item);
}
else {
this.actionsList.insertBefore(actionViewItemElement, this.actionsList.children[index]);
this.viewItems.splice(index, 0, item);
index++;
}
});
// We need to allow for the first enabled item to be focused on using tab navigation #106441
if (this.focusable) {
let didFocus = false;
for (const item of this.viewItems) {
if (!(item instanceof BaseActionViewItem)) {
continue;
}
let focus;
if (didFocus) {
focus = false; // already focused an item
}
else if (item.action.id === Separator.ID) {
focus = false; // never focus a separator
}
else if (!item.isEnabled() && this.options.focusOnlyEnabledItems) {
focus = false; // never focus a disabled item
}
else {
focus = true;
}
if (focus) {
item.setFocusable(true);
didFocus = true;
}
else {
item.setFocusable(false);
}
}
}
if (typeof this.focusedItem === 'number') {
// After a clear actions might be re-added to simply toggle some actions. We should preserve focus #97128
this.focus(this.focusedItem);
}
this.refreshRole();
}
clear() {
if (this.isEmpty()) {
return;
}
this.viewItems = dispose(this.viewItems);
this.viewItemDisposables.clearAndDisposeAll();
DOM.clearNode(this.actionsList);
this.refreshRole();
}
length() {
return this.viewItems.length;
}
isEmpty() {
return this.viewItems.length === 0;
}
focus(arg) {
let selectFirst = false;
let index = undefined;
if (arg === undefined) {
selectFirst = true;
}
else if (typeof arg === 'number') {
index = arg;
}
else if (typeof arg === 'boolean') {
selectFirst = arg;
}
if (selectFirst && typeof this.focusedItem === 'undefined') {
const firstEnabled = this.viewItems.findIndex(item => item.isEnabled());
// Focus the first enabled item
this.focusedItem = firstEnabled === -1 ? undefined : firstEnabled;
this.updateFocus(undefined, undefined, true);
}
else {
if (index !== undefined) {
this.focusedItem = index;
}
this.updateFocus(undefined, undefined, true);
}
}
focusFirst() {
this.focusedItem = this.length() - 1;
return this.focusNext(true);
}
focusLast() {
this.focusedItem = 0;
return this.focusPrevious(true);
}
focusNext(forceLoop, forceFocus) {
if (typeof this.focusedItem === 'undefined') {
this.focusedItem = this.viewItems.length - 1;
}
else if (this.viewItems.length <= 1) {
return false;
}
const startIndex = this.focusedItem;
let item;
do {
if (!forceLoop && this.options.preventLoopNavigation && this.focusedItem + 1 >= this.viewItems.length) {
this.focusedItem = startIndex;
return false;
}
this.focusedItem = (this.focusedItem + 1) % this.viewItems.length;
item = this.viewItems[this.focusedItem];
} while (this.focusedItem !== startIndex && ((this.options.focusOnlyEnabledItems && !item.isEnabled()) || item.action.id === Separator.ID));
this.updateFocus(undefined, undefined, forceFocus);
return true;
}
focusPrevious(forceLoop) {
if (typeof this.focusedItem === 'undefined') {
this.focusedItem = 0;
}
else if (this.viewItems.length <= 1) {
return false;
}
const startIndex = this.focusedItem;
let item;
do {
this.focusedItem = this.focusedItem - 1;
if (this.focusedItem < 0) {
if (!forceLoop && this.options.preventLoopNavigation) {
this.focusedItem = startIndex;
return false;
}
this.focusedItem = this.viewItems.length - 1;
}
item = this.viewItems[this.focusedItem];
} while (this.focusedItem !== startIndex && ((this.options.focusOnlyEnabledItems && !item.isEnabled()) || item.action.id === Separator.ID));
this.updateFocus(true);
return true;
}
updateFocus(fromRight, preventScroll, forceFocus = false) {
if (typeof this.focusedItem === 'undefined') {
this.actionsList.focus({ preventScroll });
}
if (this.previouslyFocusedItem !== undefined && this.previouslyFocusedItem !== this.focusedItem) {
this.viewItems[this.previouslyFocusedItem]?.blur();
}
const actionViewItem = this.focusedItem !== undefined ? this.viewItems[this.focusedItem] : undefined;
if (actionViewItem) {
let focusItem = true;
if (!types.isFunction(actionViewItem.focus)) {
focusItem = false;
}
if (this.options.focusOnlyEnabledItems && types.isFunction(actionViewItem.isEnabled) && !actionViewItem.isEnabled()) {
focusItem = false;
}
if (actionViewItem.action.id === Separator.ID) {
focusItem = false;
}
if (!focusItem) {
this.actionsList.focus({ preventScroll });
this.previouslyFocusedItem = undefined;
}
else if (forceFocus || this.previouslyFocusedItem !== this.focusedItem) {
actionViewItem.focus(fromRight);
this.previouslyFocusedItem = this.focusedItem;
}
if (focusItem) {
actionViewItem.showHover?.();
}
}
}
doTrigger(event) {
if (typeof this.focusedItem === 'undefined') {
return; //nothing to focus
}
// trigger action
const actionViewItem = this.viewItems[this.focusedItem];
if (actionViewItem instanceof BaseActionViewItem) {
const context = (actionViewItem._context === null || actionViewItem._context === undefined) ? event : actionViewItem._context;
this.run(actionViewItem._action, context);
}
}
async run(action, context) {
await this._actionRunner.run(action, context);
}
dispose() {
this._context = undefined;
this.viewItems = dispose(this.viewItems);
this.getContainer().remove();
super.dispose();
}
}
//# sourceMappingURL=actionbar.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,9 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-aria-container {
position: absolute; /* try to hide from window but not from screen readers */
left:-999em;
}

View File

@@ -0,0 +1,82 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as dom from '../../dom.js';
import './aria.css';
// Use a max length since we are inserting the whole msg in the DOM and that can cause browsers to freeze for long messages #94233
const MAX_MESSAGE_LENGTH = 20000;
let ariaContainer;
let alertContainer;
let alertContainer2;
let statusContainer;
let statusContainer2;
export function setARIAContainer(parent) {
ariaContainer = document.createElement('div');
ariaContainer.className = 'monaco-aria-container';
const createAlertContainer = () => {
const element = document.createElement('div');
element.className = 'monaco-alert';
element.setAttribute('role', 'alert');
element.setAttribute('aria-atomic', 'true');
ariaContainer.appendChild(element);
return element;
};
alertContainer = createAlertContainer();
alertContainer2 = createAlertContainer();
const createStatusContainer = () => {
const element = document.createElement('div');
element.className = 'monaco-status';
element.setAttribute('aria-live', 'polite');
element.setAttribute('aria-atomic', 'true');
ariaContainer.appendChild(element);
return element;
};
statusContainer = createStatusContainer();
statusContainer2 = createStatusContainer();
parent.appendChild(ariaContainer);
}
/**
* Given the provided message, will make sure that it is read as alert to screen readers.
*/
export function alert(msg) {
if (!ariaContainer) {
return;
}
// Use alternate containers such that duplicated messages get read out by screen readers #99466
if (alertContainer.textContent !== msg) {
dom.clearNode(alertContainer2);
insertMessage(alertContainer, msg);
}
else {
dom.clearNode(alertContainer);
insertMessage(alertContainer2, msg);
}
}
/**
* Given the provided message, will make sure that it is read as status to screen readers.
*/
export function status(msg) {
if (!ariaContainer) {
return;
}
if (statusContainer.textContent !== msg) {
dom.clearNode(statusContainer2);
insertMessage(statusContainer, msg);
}
else {
dom.clearNode(statusContainer);
insertMessage(statusContainer2, msg);
}
}
function insertMessage(target, msg) {
dom.clearNode(target);
if (msg.length > MAX_MESSAGE_LENGTH) {
msg = msg.substr(0, MAX_MESSAGE_LENGTH);
}
target.textContent = msg;
// See https://www.paciellogroup.com/blog/2012/06/html5-accessibility-chops-aria-rolealert-browser-support/
target.style.visibility = 'hidden';
target.style.visibility = 'visible';
}
//# sourceMappingURL=aria.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,36 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-breadcrumbs {
user-select: none;
-webkit-user-select: none;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: flex-start;
outline-style: none;
}
.monaco-breadcrumbs .monaco-breadcrumb-item {
display: flex;
align-items: center;
flex: 0 1 auto;
white-space: nowrap;
cursor: pointer;
align-self: center;
height: 100%;
outline: none;
}
.monaco-breadcrumbs.disabled .monaco-breadcrumb-item {
cursor: default;
}
.monaco-breadcrumbs .monaco-breadcrumb-item .codicon-breadcrumb-separator {
color: inherit;
}
.monaco-breadcrumbs .monaco-breadcrumb-item:first-of-type::before {
content: ' ';
}

View File

@@ -0,0 +1,2 @@
import './breadcrumbsWidget.css';
//# sourceMappingURL=breadcrumbsWidget.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src/vs/base/browser/ui/breadcrumbs/breadcrumbsWidget.ts","vs/base/browser/ui/breadcrumbs/breadcrumbsWidget.ts"],"names":[],"mappings":"AACA,OAAO,yBAAyB,CAAC","file":"breadcrumbsWidget.js","sourceRoot":"file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src","sourcesContent":["\nimport './breadcrumbsWidget.css';\n\nexport interface IBreadcrumbsWidgetStyles {\n\treadonly breadcrumbsBackground: string | undefined;\n\treadonly breadcrumbsForeground: string | undefined;\n\treadonly breadcrumbsHoverForeground: string | undefined;\n\treadonly breadcrumbsFocusForeground: string | undefined;\n\treadonly breadcrumbsFocusAndSelectionForeground: string | undefined;\n}\n","\nimport './breadcrumbsWidget.css';\n\nexport interface IBreadcrumbsWidgetStyles {\n\treadonly breadcrumbsBackground: string | undefined;\n\treadonly breadcrumbsForeground: string | undefined;\n\treadonly breadcrumbsHoverForeground: string | undefined;\n\treadonly breadcrumbsFocusForeground: string | undefined;\n\treadonly breadcrumbsFocusAndSelectionForeground: string | undefined;\n}\n"]}

View File

@@ -0,0 +1,174 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-text-button {
box-sizing: border-box;
display: flex;
width: 100%;
padding: 4px;
border-radius: 2px;
text-align: center;
cursor: pointer;
justify-content: center;
align-items: center;
border: 1px solid var(--vscode-button-border, transparent);
line-height: 18px;
}
.monaco-text-button:focus {
outline-offset: 2px !important;
}
.monaco-text-button:hover {
text-decoration: none !important;
}
.monaco-button.disabled:focus,
.monaco-button.disabled {
opacity: 0.4 !important;
cursor: default;
}
.monaco-text-button .codicon {
margin: 0 0.2em;
color: inherit !important;
}
.monaco-text-button.monaco-text-button-with-short-label {
flex-direction: row;
flex-wrap: wrap;
padding: 0 4px;
overflow: hidden;
height: 28px;
}
.monaco-text-button.monaco-text-button-with-short-label > .monaco-button-label {
flex-basis: 100%;
}
.monaco-text-button.monaco-text-button-with-short-label > .monaco-button-label-short {
flex-grow: 1;
width: 0;
overflow: hidden;
}
.monaco-text-button.monaco-text-button-with-short-label > .monaco-button-label,
.monaco-text-button.monaco-text-button-with-short-label > .monaco-button-label-short {
display: flex;
justify-content: center;
align-items: center;
font-weight: normal;
font-style: inherit;
padding: 4px 0;
}
.monaco-button-dropdown {
display: flex;
cursor: pointer;
}
.monaco-button-dropdown.disabled {
cursor: default;
}
.monaco-button-dropdown > .monaco-button:focus {
outline-offset: -1px !important;
}
.monaco-button-dropdown.disabled > .monaco-button.disabled,
.monaco-button-dropdown.disabled > .monaco-button.disabled:focus,
.monaco-button-dropdown.disabled > .monaco-button-dropdown-separator {
opacity: 0.4 !important;
}
.monaco-button-dropdown > .monaco-button.monaco-text-button {
border-right-width: 0 !important;
}
.monaco-button-dropdown .monaco-button-dropdown-separator {
padding: 4px 0;
cursor: default;
}
.monaco-button-dropdown .monaco-button-dropdown-separator > div {
height: 100%;
width: 1px;
}
.monaco-button-dropdown > .monaco-button.monaco-dropdown-button {
border: 1px solid var(--vscode-button-border, transparent);
border-left-width: 0 !important;
border-radius: 0 2px 2px 0;
display: flex;
align-items: center;
}
.monaco-button-dropdown > .monaco-button.monaco-text-button {
border-radius: 2px 0 0 2px;
}
.monaco-description-button {
display: flex;
flex-direction: column;
align-items: center;
margin: 4px 5px; /* allows button focus outline to be visible */
}
.monaco-description-button .monaco-button-description {
font-style: italic;
font-size: 11px;
padding: 4px 20px;
}
.monaco-description-button .monaco-button-label,
.monaco-description-button .monaco-button-description {
display: flex;
justify-content: center;
align-items: center;
}
.monaco-description-button .monaco-button-label > .codicon,
.monaco-description-button .monaco-button-description > .codicon {
margin: 0 0.2em;
color: inherit !important;
}
/* default color styles - based on CSS variables */
.monaco-button.default-colors,
.monaco-button-dropdown.default-colors > .monaco-button{
color: var(--vscode-button-foreground);
background-color: var(--vscode-button-background);
}
.monaco-button.default-colors:hover,
.monaco-button-dropdown.default-colors > .monaco-button:hover {
background-color: var(--vscode-button-hoverBackground);
}
.monaco-button.default-colors.secondary,
.monaco-button-dropdown.default-colors > .monaco-button.secondary {
color: var(--vscode-button-secondaryForeground);
background-color: var(--vscode-button-secondaryBackground);
}
.monaco-button.default-colors.secondary:hover,
.monaco-button-dropdown.default-colors > .monaco-button.secondary:hover {
background-color: var(--vscode-button-secondaryHoverBackground);
}
.monaco-button-dropdown.default-colors .monaco-button-dropdown-separator {
background-color: var(--vscode-button-background);
border-top: 1px solid var(--vscode-button-border);
border-bottom: 1px solid var(--vscode-button-border);
}
.monaco-button-dropdown.default-colors .monaco-button.secondary + .monaco-button-dropdown-separator {
background-color: var(--vscode-button-secondaryBackground);
}
.monaco-button-dropdown.default-colors .monaco-button-dropdown-separator > div {
background-color: var(--vscode-button-separator);
}

View File

@@ -0,0 +1,230 @@
import { addDisposableListener, EventHelper, EventType, reset, trackFocus } from '../../dom.js';
import { StandardKeyboardEvent } from '../../keyboardEvent.js';
import { renderMarkdown, renderAsPlaintext } from '../../markdownRenderer.js';
import { Gesture, EventType as TouchEventType } from '../../touch.js';
import { getDefaultHoverDelegate } from '../hover/hoverDelegateFactory.js';
import { renderLabelWithIcons } from '../iconLabel/iconLabels.js';
import { Color } from '../../../common/color.js';
import { Emitter } from '../../../common/event.js';
import { isMarkdownString, markdownStringEqual } from '../../../common/htmlContent.js';
import { Disposable } from '../../../common/lifecycle.js';
import { ThemeIcon } from '../../../common/themables.js';
import './button.css';
import { getBaseLayerHoverDelegate } from '../hover/hoverDelegate2.js';
import { safeSetInnerHtml } from '../../domSanitize.js';
export const unthemedButtonStyles = {
buttonBackground: '#0E639C',
buttonHoverBackground: '#006BB3',
buttonSeparator: Color.white.toString(),
buttonForeground: Color.white.toString(),
buttonBorder: undefined,
buttonSecondaryBackground: undefined,
buttonSecondaryForeground: undefined,
buttonSecondaryHoverBackground: undefined
};
// Only allow a very limited set of inline html tags
const buttonSanitizerConfig = Object.freeze({
allowedTags: {
override: ['b', 'i', 'u', 'code', 'span'],
},
allowedAttributes: {
override: ['class'],
},
});
export class Button extends Disposable {
get onDidClick() { return this._onDidClick.event; }
constructor(container, options) {
super();
this._label = '';
this._onDidClick = this._register(new Emitter());
this._onDidEscape = this._register(new Emitter());
this.options = options;
this._element = document.createElement('a');
this._element.classList.add('monaco-button');
this._element.tabIndex = 0;
this._element.setAttribute('role', 'button');
this._element.classList.toggle('secondary', !!options.secondary);
const background = options.secondary ? options.buttonSecondaryBackground : options.buttonBackground;
const foreground = options.secondary ? options.buttonSecondaryForeground : options.buttonForeground;
this._element.style.color = foreground || '';
this._element.style.backgroundColor = background || '';
if (options.supportShortLabel) {
this._labelShortElement = document.createElement('div');
this._labelShortElement.classList.add('monaco-button-label-short');
this._element.appendChild(this._labelShortElement);
this._labelElement = document.createElement('div');
this._labelElement.classList.add('monaco-button-label');
this._element.appendChild(this._labelElement);
this._element.classList.add('monaco-text-button-with-short-label');
}
if (typeof options.title === 'string') {
this.setTitle(options.title);
}
if (typeof options.ariaLabel === 'string') {
this._element.setAttribute('aria-label', options.ariaLabel);
}
container.appendChild(this._element);
this.enabled = !options.disabled;
this._register(Gesture.addTarget(this._element));
[EventType.CLICK, TouchEventType.Tap].forEach(eventType => {
this._register(addDisposableListener(this._element, eventType, e => {
if (!this.enabled) {
EventHelper.stop(e);
return;
}
this._onDidClick.fire(e);
}));
});
this._register(addDisposableListener(this._element, EventType.KEY_DOWN, e => {
const event = new StandardKeyboardEvent(e);
let eventHandled = false;
if (this.enabled && (event.equals(3 /* KeyCode.Enter */) || event.equals(10 /* KeyCode.Space */))) {
this._onDidClick.fire(e);
eventHandled = true;
}
else if (event.equals(9 /* KeyCode.Escape */)) {
this._onDidEscape.fire(e);
this._element.blur();
eventHandled = true;
}
if (eventHandled) {
EventHelper.stop(event, true);
}
}));
this._register(addDisposableListener(this._element, EventType.MOUSE_OVER, e => {
if (!this._element.classList.contains('disabled')) {
this.updateBackground(true);
}
}));
this._register(addDisposableListener(this._element, EventType.MOUSE_OUT, e => {
this.updateBackground(false); // restore standard styles
}));
// Also set hover background when button is focused for feedback
this.focusTracker = this._register(trackFocus(this._element));
this._register(this.focusTracker.onDidFocus(() => { if (this.enabled) {
this.updateBackground(true);
} }));
this._register(this.focusTracker.onDidBlur(() => { if (this.enabled) {
this.updateBackground(false);
} }));
}
dispose() {
super.dispose();
this._element.remove();
}
getContentElements(content) {
const elements = [];
for (let segment of renderLabelWithIcons(content)) {
if (typeof (segment) === 'string') {
segment = segment.trim();
// Ignore empty segment
if (segment === '') {
continue;
}
// Convert string segments to <span> nodes
const node = document.createElement('span');
node.textContent = segment;
elements.push(node);
}
else {
elements.push(segment);
}
}
return elements;
}
updateBackground(hover) {
let background;
if (this.options.secondary) {
background = hover ? this.options.buttonSecondaryHoverBackground : this.options.buttonSecondaryBackground;
}
else {
background = hover ? this.options.buttonHoverBackground : this.options.buttonBackground;
}
if (background) {
this._element.style.backgroundColor = background;
}
}
get element() {
return this._element;
}
set label(value) {
if (this._label === value) {
return;
}
if (isMarkdownString(this._label) && isMarkdownString(value) && markdownStringEqual(this._label, value)) {
return;
}
this._element.classList.add('monaco-text-button');
const labelElement = this.options.supportShortLabel ? this._labelElement : this._element;
if (isMarkdownString(value)) {
const rendered = renderMarkdown(value, undefined, document.createElement('span'));
rendered.dispose();
// Don't include outer `<p>`
const root = rendered.element.querySelector('p')?.innerHTML;
if (root) {
safeSetInnerHtml(labelElement, root, buttonSanitizerConfig);
}
else {
reset(labelElement);
}
}
else {
if (this.options.supportIcons) {
reset(labelElement, ...this.getContentElements(value));
}
else {
labelElement.textContent = value;
}
}
let title = '';
if (typeof this.options.title === 'string') {
title = this.options.title;
}
else if (this.options.title) {
title = renderAsPlaintext(value);
}
this.setTitle(title);
this._setAriaLabel();
this._label = value;
}
get label() {
return this._label;
}
_setAriaLabel() {
if (typeof this.options.ariaLabel === 'string') {
this._element.setAttribute('aria-label', this.options.ariaLabel);
}
else if (typeof this.options.title === 'string') {
this._element.setAttribute('aria-label', this.options.title);
}
}
set icon(icon) {
this._setAriaLabel();
const oldIcons = Array.from(this._element.classList).filter(item => item.startsWith('codicon-'));
this._element.classList.remove(...oldIcons);
this._element.classList.add(...ThemeIcon.asClassNameArray(icon));
}
set enabled(value) {
if (value) {
this._element.classList.remove('disabled');
this._element.setAttribute('aria-disabled', String(false));
this._element.tabIndex = 0;
}
else {
this._element.classList.add('disabled');
this._element.setAttribute('aria-disabled', String(true));
}
}
get enabled() {
return !this._element.classList.contains('disabled');
}
setTitle(title) {
if (!this._hover && title !== '') {
this._hover = this._register(getBaseLayerHoverDelegate().setupManagedHover(this.options.hoverDelegate ?? getDefaultHoverDelegate('element'), this._element, title));
}
else if (this._hover) {
this._hover.update(title);
}
}
}
//# sourceMappingURL=button.js.map

File diff suppressed because one or more lines are too long

View File

@@ -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.
*--------------------------------------------------------------------------------------------*/
.codicon-wrench-subaction {
opacity: 0.5;
}
@keyframes codicon-spin {
100% {
transform:rotate(360deg);
}
}
.codicon-sync.codicon-modifier-spin,
.codicon-loading.codicon-modifier-spin,
.codicon-gear.codicon-modifier-spin,
.codicon-notebook-state-executing.codicon-modifier-spin {
/* Use steps to throttle FPS to reduce CPU usage */
animation: codicon-spin 1.5s steps(30) infinite;
}
.codicon-modifier-disabled {
opacity: 0.4;
}
/* custom speed & easing for loading icon */
.codicon-loading,
.codicon-tree-item-loading::before {
animation-duration: 1s !important;
animation-timing-function: cubic-bezier(0.53, 0.21, 0.29, 0.67) !important;
}

View File

@@ -0,0 +1,25 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
@font-face {
font-family: "codicon";
font-display: block;
src: url(./codicon.ttf) format("truetype");
}
.codicon[class*='codicon-'] {
font: normal normal normal 16px/1 codicon;
display: inline-block;
text-decoration: none;
text-rendering: auto;
text-align: center;
text-transform: none;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
user-select: none;
-webkit-user-select: none;
}
/* icon rules are dynamically created by the platform theme service (see iconsStyleSheet.ts) */

View File

@@ -0,0 +1,7 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import './codicon/codicon.css';
import './codicon/codicon-modifiers.css';
//# sourceMappingURL=codiconStyles.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src/vs/base/browser/ui/codicons/codiconStyles.ts","vs/base/browser/ui/codicons/codiconStyles.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAEhG,OAAO,uBAAuB,CAAC;AAC/B,OAAO,iCAAiC,CAAC","file":"codiconStyles.js","sourceRoot":"file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport './codicon/codicon.css';\nimport './codicon/codicon-modifiers.css';\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport './codicon/codicon.css';\nimport './codicon/codicon-modifiers.css';\n"]}

View File

@@ -0,0 +1,16 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.context-view {
position: absolute;
}
.context-view.fixed {
all: initial;
font-family: inherit;
font-size: 13px;
position: fixed;
color: inherit;
}

View File

@@ -0,0 +1,296 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { BrowserFeatures } from '../../canIUse.js';
import * as DOM from '../../dom.js';
import { Disposable, DisposableStore, toDisposable } from '../../../common/lifecycle.js';
import * as platform from '../../../common/platform.js';
import { Range } from '../../../common/range.js';
import './contextview.css';
export function isAnchor(obj) {
const anchor = obj;
return !!anchor && typeof anchor.x === 'number' && typeof anchor.y === 'number';
}
export var LayoutAnchorMode;
(function (LayoutAnchorMode) {
LayoutAnchorMode[LayoutAnchorMode["AVOID"] = 0] = "AVOID";
LayoutAnchorMode[LayoutAnchorMode["ALIGN"] = 1] = "ALIGN";
})(LayoutAnchorMode || (LayoutAnchorMode = {}));
/**
* Lays out a one dimensional view next to an anchor in a viewport.
*
* @returns The view offset within the viewport.
*/
export function layout(viewportSize, viewSize, anchor) {
const layoutAfterAnchorBoundary = anchor.mode === LayoutAnchorMode.ALIGN ? anchor.offset : anchor.offset + anchor.size;
const layoutBeforeAnchorBoundary = anchor.mode === LayoutAnchorMode.ALIGN ? anchor.offset + anchor.size : anchor.offset;
if (anchor.position === 0 /* LayoutAnchorPosition.Before */) {
if (viewSize <= viewportSize - layoutAfterAnchorBoundary) {
return layoutAfterAnchorBoundary; // happy case, lay it out after the anchor
}
if (viewSize <= layoutBeforeAnchorBoundary) {
return layoutBeforeAnchorBoundary - viewSize; // ok case, lay it out before the anchor
}
return Math.max(viewportSize - viewSize, 0); // sad case, lay it over the anchor
}
else {
if (viewSize <= layoutBeforeAnchorBoundary) {
return layoutBeforeAnchorBoundary - viewSize; // happy case, lay it out before the anchor
}
if (viewSize <= viewportSize - layoutAfterAnchorBoundary) {
return layoutAfterAnchorBoundary; // ok case, lay it out after the anchor
}
return 0; // sad case, lay it over the anchor
}
}
export class ContextView extends Disposable {
static { this.BUBBLE_UP_EVENTS = ['click', 'keydown', 'focus', 'blur']; }
static { this.BUBBLE_DOWN_EVENTS = ['click']; }
constructor(container, domPosition) {
super();
this.container = null;
this.useFixedPosition = false;
this.useShadowDOM = false;
this.delegate = null;
this.toDisposeOnClean = Disposable.None;
this.toDisposeOnSetContainer = Disposable.None;
this.shadowRoot = null;
this.shadowRootHostElement = null;
this.view = DOM.$('.context-view');
DOM.hide(this.view);
this.setContainer(container, domPosition);
this._register(toDisposable(() => this.setContainer(null, 1 /* ContextViewDOMPosition.ABSOLUTE */)));
}
setContainer(container, domPosition) {
this.useFixedPosition = domPosition !== 1 /* ContextViewDOMPosition.ABSOLUTE */;
const usedShadowDOM = this.useShadowDOM;
this.useShadowDOM = domPosition === 3 /* ContextViewDOMPosition.FIXED_SHADOW */;
if (container === this.container && usedShadowDOM === this.useShadowDOM) {
return; // container is the same and no shadow DOM usage has changed
}
if (this.container) {
this.toDisposeOnSetContainer.dispose();
this.view.remove();
if (this.shadowRoot) {
this.shadowRoot = null;
this.shadowRootHostElement?.remove();
this.shadowRootHostElement = null;
}
this.container = null;
}
if (container) {
this.container = container;
if (this.useShadowDOM) {
this.shadowRootHostElement = DOM.$('.shadow-root-host');
this.container.appendChild(this.shadowRootHostElement);
this.shadowRoot = this.shadowRootHostElement.attachShadow({ mode: 'open' });
const style = document.createElement('style');
style.textContent = SHADOW_ROOT_CSS;
this.shadowRoot.appendChild(style);
this.shadowRoot.appendChild(this.view);
this.shadowRoot.appendChild(DOM.$('slot'));
}
else {
this.container.appendChild(this.view);
}
const toDisposeOnSetContainer = new DisposableStore();
ContextView.BUBBLE_UP_EVENTS.forEach(event => {
toDisposeOnSetContainer.add(DOM.addStandardDisposableListener(this.container, event, e => {
this.onDOMEvent(e, false);
}));
});
ContextView.BUBBLE_DOWN_EVENTS.forEach(event => {
toDisposeOnSetContainer.add(DOM.addStandardDisposableListener(this.container, event, e => {
this.onDOMEvent(e, true);
}, true));
});
this.toDisposeOnSetContainer = toDisposeOnSetContainer;
}
}
show(delegate) {
if (this.isVisible()) {
this.hide();
}
// Show static box
DOM.clearNode(this.view);
this.view.className = 'context-view monaco-component';
this.view.style.top = '0px';
this.view.style.left = '0px';
this.view.style.zIndex = `${2575 + (delegate.layer ?? 0)}`;
this.view.style.position = this.useFixedPosition ? 'fixed' : 'absolute';
DOM.show(this.view);
// Render content
this.toDisposeOnClean = delegate.render(this.view) || Disposable.None;
// Set active delegate
this.delegate = delegate;
// Layout
this.doLayout();
// Focus
this.delegate.focus?.();
}
getViewElement() {
return this.view;
}
layout() {
if (!this.isVisible()) {
return;
}
if (this.delegate.canRelayout === false && !(platform.isIOS && BrowserFeatures.pointerEvents)) {
this.hide();
return;
}
this.delegate?.layout?.();
this.doLayout();
}
doLayout() {
// Check that we still have a delegate - this.delegate.layout may have hidden
if (!this.isVisible()) {
return;
}
// Get anchor
const anchor = this.delegate.getAnchor();
// Compute around
let around;
// Get the element's position and size (to anchor the view)
if (DOM.isHTMLElement(anchor)) {
const elementPosition = DOM.getDomNodePagePosition(anchor);
// In areas where zoom is applied to the element or its ancestors, we need to adjust the size of the element
// e.g. The title bar has counter zoom behavior meaning it applies the inverse of zoom level.
// Window Zoom Level: 1.5, Title Bar Zoom: 1/1.5, Size Multiplier: 1.5
const zoom = DOM.getDomNodeZoomLevel(anchor);
around = {
top: elementPosition.top * zoom,
left: elementPosition.left * zoom,
width: elementPosition.width * zoom,
height: elementPosition.height * zoom
};
}
else if (isAnchor(anchor)) {
around = {
top: anchor.y,
left: anchor.x,
width: anchor.width || 1,
height: anchor.height || 2
};
}
else {
around = {
top: anchor.posy,
left: anchor.posx,
// We are about to position the context view where the mouse
// cursor is. To prevent the view being exactly under the mouse
// when showing and thus potentially triggering an action within,
// we treat the mouse location like a small sized block element.
width: 2,
height: 2
};
}
const viewSizeWidth = DOM.getTotalWidth(this.view);
const viewSizeHeight = DOM.getTotalHeight(this.view);
const anchorPosition = this.delegate.anchorPosition ?? 0 /* AnchorPosition.BELOW */;
const anchorAlignment = this.delegate.anchorAlignment ?? 0 /* AnchorAlignment.LEFT */;
const anchorAxisAlignment = this.delegate.anchorAxisAlignment ?? 0 /* AnchorAxisAlignment.VERTICAL */;
let top;
let left;
const activeWindow = DOM.getActiveWindow();
if (anchorAxisAlignment === 0 /* AnchorAxisAlignment.VERTICAL */) {
const verticalAnchor = { offset: around.top - activeWindow.pageYOffset, size: around.height, position: anchorPosition === 0 /* AnchorPosition.BELOW */ ? 0 /* LayoutAnchorPosition.Before */ : 1 /* LayoutAnchorPosition.After */ };
const horizontalAnchor = { offset: around.left, size: around.width, position: anchorAlignment === 0 /* AnchorAlignment.LEFT */ ? 0 /* LayoutAnchorPosition.Before */ : 1 /* LayoutAnchorPosition.After */, mode: LayoutAnchorMode.ALIGN };
top = layout(activeWindow.innerHeight, viewSizeHeight, verticalAnchor) + activeWindow.pageYOffset;
// if view intersects vertically with anchor, we must avoid the anchor
if (Range.intersects({ start: top, end: top + viewSizeHeight }, { start: verticalAnchor.offset, end: verticalAnchor.offset + verticalAnchor.size })) {
horizontalAnchor.mode = LayoutAnchorMode.AVOID;
}
left = layout(activeWindow.innerWidth, viewSizeWidth, horizontalAnchor);
}
else {
const horizontalAnchor = { offset: around.left, size: around.width, position: anchorAlignment === 0 /* AnchorAlignment.LEFT */ ? 0 /* LayoutAnchorPosition.Before */ : 1 /* LayoutAnchorPosition.After */ };
const verticalAnchor = { offset: around.top, size: around.height, position: anchorPosition === 0 /* AnchorPosition.BELOW */ ? 0 /* LayoutAnchorPosition.Before */ : 1 /* LayoutAnchorPosition.After */, mode: LayoutAnchorMode.ALIGN };
left = layout(activeWindow.innerWidth, viewSizeWidth, horizontalAnchor);
// if view intersects horizontally with anchor, we must avoid the anchor
if (Range.intersects({ start: left, end: left + viewSizeWidth }, { start: horizontalAnchor.offset, end: horizontalAnchor.offset + horizontalAnchor.size })) {
verticalAnchor.mode = LayoutAnchorMode.AVOID;
}
top = layout(activeWindow.innerHeight, viewSizeHeight, verticalAnchor) + activeWindow.pageYOffset;
}
this.view.classList.remove('top', 'bottom', 'left', 'right');
this.view.classList.add(anchorPosition === 0 /* AnchorPosition.BELOW */ ? 'bottom' : 'top');
this.view.classList.add(anchorAlignment === 0 /* AnchorAlignment.LEFT */ ? 'left' : 'right');
this.view.classList.toggle('fixed', this.useFixedPosition);
const containerPosition = DOM.getDomNodePagePosition(this.container);
// Account for container scroll when positioning the context view
const containerScrollTop = this.container.scrollTop || 0;
const containerScrollLeft = this.container.scrollLeft || 0;
this.view.style.top = `${top - (this.useFixedPosition ? DOM.getDomNodePagePosition(this.view).top : containerPosition.top) + containerScrollTop}px`;
this.view.style.left = `${left - (this.useFixedPosition ? DOM.getDomNodePagePosition(this.view).left : containerPosition.left) + containerScrollLeft}px`;
this.view.style.width = 'initial';
}
hide(data) {
const delegate = this.delegate;
this.delegate = null;
if (delegate?.onHide) {
delegate.onHide(data);
}
this.toDisposeOnClean.dispose();
DOM.hide(this.view);
}
isVisible() {
return !!this.delegate;
}
onDOMEvent(e, onCapture) {
if (this.delegate) {
if (this.delegate.onDOMEvent) {
this.delegate.onDOMEvent(e, DOM.getWindow(e).document.activeElement);
}
else if (onCapture && !DOM.isAncestor(e.target, this.container)) {
this.hide();
}
}
}
dispose() {
this.hide();
super.dispose();
}
}
const SHADOW_ROOT_CSS = /* css */ `
:host {
all: initial; /* 1st rule so subsequent properties are reset. */
}
.codicon[class*='codicon-'] {
font: normal normal normal 16px/1 codicon;
display: inline-block;
text-decoration: none;
text-rendering: auto;
text-align: center;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
:host {
font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "HelveticaNeue-Light", system-ui, "Ubuntu", "Droid Sans", sans-serif;
}
:host-context(.mac) { font-family: -apple-system, BlinkMacSystemFont, sans-serif; }
:host-context(.mac:lang(zh-Hans)) { font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", sans-serif; }
:host-context(.mac:lang(zh-Hant)) { font-family: -apple-system, BlinkMacSystemFont, "PingFang TC", sans-serif; }
:host-context(.mac:lang(ja)) { font-family: -apple-system, BlinkMacSystemFont, "Hiragino Kaku Gothic Pro", sans-serif; }
:host-context(.mac:lang(ko)) { font-family: -apple-system, BlinkMacSystemFont, "Apple SD Gothic Neo", "Nanum Gothic", "AppleGothic", sans-serif; }
:host-context(.windows) { font-family: "Segoe WPC", "Segoe UI", sans-serif; }
:host-context(.windows:lang(zh-Hans)) { font-family: "Segoe WPC", "Segoe UI", "Microsoft YaHei", sans-serif; }
:host-context(.windows:lang(zh-Hant)) { font-family: "Segoe WPC", "Segoe UI", "Microsoft Jhenghei", sans-serif; }
:host-context(.windows:lang(ja)) { font-family: "Segoe WPC", "Segoe UI", "Yu Gothic UI", "Meiryo UI", sans-serif; }
:host-context(.windows:lang(ko)) { font-family: "Segoe WPC", "Segoe UI", "Malgun Gothic", "Dotom", sans-serif; }
:host-context(.linux) { font-family: system-ui, "Ubuntu", "Droid Sans", sans-serif; }
:host-context(.linux:lang(zh-Hans)) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans SC", "Source Han Sans CN", "Source Han Sans", sans-serif; }
:host-context(.linux:lang(zh-Hant)) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans TC", "Source Han Sans TW", "Source Han Sans", sans-serif; }
:host-context(.linux:lang(ja)) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans J", "Source Han Sans JP", "Source Han Sans", sans-serif; }
:host-context(.linux:lang(ko)) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans K", "Source Han Sans JR", "Source Han Sans", "UnDotum", "FBaekmuk Gulim", sans-serif; }
`;
//# sourceMappingURL=contextview.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,24 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-count-badge {
padding: 3px 6px;
border-radius: 11px;
font-size: 11px;
min-width: 18px;
min-height: 18px;
line-height: 11px;
font-weight: normal;
text-align: center;
display: inline-block;
box-sizing: border-box;
}
.monaco-count-badge.long {
padding: 2px 3px;
border-radius: 2px;
min-height: auto;
line-height: normal;
}

View File

@@ -0,0 +1,50 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { $, append } from '../../dom.js';
import { format } from '../../../common/strings.js';
import './countBadge.css';
import { Disposable, MutableDisposable, toDisposable } from '../../../common/lifecycle.js';
import { getBaseLayerHoverDelegate } from '../hover/hoverDelegate2.js';
export class CountBadge extends Disposable {
constructor(container, options, styles) {
super();
this.options = options;
this.styles = styles;
this.count = 0;
this.hover = this._register(new MutableDisposable());
this.element = append(container, $('.monaco-count-badge'));
this._register(toDisposable(() => container.removeChild(this.element)));
this.countFormat = this.options.countFormat || '{0}';
this.titleFormat = this.options.titleFormat || '';
this.setCount(this.options.count || 0);
this.updateHover();
}
setCount(count) {
this.count = count;
this.render();
}
setTitleFormat(titleFormat) {
this.titleFormat = titleFormat;
this.updateHover();
this.render();
}
updateHover() {
if (this.titleFormat !== '' && !this.hover.value) {
this.hover.value = getBaseLayerHoverDelegate().setupDelayedHoverAtMouse(this.element, () => ({ content: format(this.titleFormat, this.count), appearance: { compact: true } }));
}
else if (this.titleFormat === '' && this.hover.value) {
this.hover.value = undefined;
}
}
render() {
this.element.textContent = format(this.countFormat, this.count);
this.element.style.backgroundColor = this.styles.badgeBackground ?? '';
this.element.style.color = this.styles.badgeForeground ?? '';
if (this.styles.badgeBorder) {
this.element.style.border = `1px solid ${this.styles.badgeBorder}`;
}
}
}
//# sourceMappingURL=countBadge.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,246 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/** Dialog: Modal Block */
.monaco-dialog-modal-block {
position: fixed;
height: 100%;
width: 100%;
left: 0;
top: 0;
z-index: 2575; /* Above Context Views, Below Workbench Hover */
display: flex;
justify-content: center;
align-items: center;
}
.monaco-dialog-modal-block.dimmed {
background: rgba(0, 0, 0, 0.3);
}
/** Dialog: Container */
.monaco-dialog-box {
display: flex;
flex-direction: column-reverse;
width: min-content;
min-width: 500px;
max-width: 90vw;
min-height: 75px;
padding: 10px;
transform: translate3d(0px, 0px, 0px);
border-radius: 3px;
}
.monaco-dialog-box.align-vertical {
min-width: 350px; /* more narrow when aligned vertically */
}
/** Dialog: Title Actions Row */
.monaco-dialog-box .dialog-toolbar-row {
height: 22px;
padding-bottom: 4px;
}
.monaco-dialog-box .dialog-toolbar-row .actions-container {
justify-content: flex-end;
}
/** Dialog: Message/Footer Row */
.monaco-dialog-box .dialog-message-row,
.monaco-dialog-box .dialog-footer-row {
display: flex;
flex-grow: 1;
align-items: center;
padding: 0 10px;
}
.monaco-dialog-box.align-vertical .dialog-message-row {
flex-direction: column;
}
.monaco-dialog-box .dialog-message-row > .dialog-icon.codicon {
flex: 0 0 48px;
height: 48px;
font-size: 48px;
}
.monaco-dialog-box.align-vertical .dialog-message-row > .dialog-icon.codicon {
flex: 0 0 64px;
height: 64px;
font-size: 64px;
}
.monaco-dialog-box:not(.align-vertical) .dialog-message-row > .dialog-icon.codicon {
align-self: baseline;
}
/** Dialog: Message/Footer Container */
.monaco-dialog-box .dialog-message-row .dialog-message-container,
.monaco-dialog-box .dialog-footer-row {
display: flex;
flex-direction: column;
overflow: hidden;
text-overflow: ellipsis;
user-select: text;
-webkit-user-select: text;
word-wrap: break-word; /* never overflow long words, but break to next line */
white-space: normal;
}
.monaco-dialog-box .dialog-footer-row {
margin-top: 20px;
}
.monaco-dialog-box:not(.align-vertical) .dialog-message-row .dialog-message-container,
.monaco-dialog-box:not(.align-vertical) .dialog-footer-row {
padding-left: 24px;
}
.monaco-dialog-box.align-vertical .dialog-message-row .dialog-message-container,
.monaco-dialog-box.align-vertical .dialog-footer-row {
align-items: center;
text-align: center;
}
.monaco-dialog-box .dialog-message-row .dialog-message-container ul,
.monaco-dialog-box .dialog-footer-row ul {
padding-inline-start: 20px; /* reduce excessive indent of list items in the dialog */
}
/** Dialog: Message */
.monaco-dialog-box .dialog-message-row .dialog-message-container .dialog-message {
line-height: 22px;
font-size: 18px;
flex: 1; /* let the message always grow */
white-space: normal;
word-wrap: break-word; /* never overflow long words, but break to next line */
min-height: 48px; /* matches icon height */
margin-bottom: 8px;
display: flex;
align-items: center;
}
/** Dialog: Details */
.monaco-dialog-box .dialog-message-row .dialog-message-container .dialog-message-detail {
line-height: 22px;
flex: 1; /* let the message always grow */
}
.monaco-dialog-box .dialog-message-row .dialog-message-container .dialog-message a:focus {
outline-width: 1px;
outline-style: solid;
}
/** Dialog: Checkbox */
.monaco-dialog-box .dialog-message-row .dialog-message-container .dialog-checkbox-row {
padding: 15px 0px 0px;
display: flex;
}
.monaco-dialog-box .dialog-message-row .dialog-message-container .dialog-checkbox-row .dialog-checkbox-message {
cursor: pointer;
user-select: none;
-webkit-user-select: none;
flex: 1;
}
/** Dialog: Input */
.monaco-dialog-box .dialog-message-row .dialog-message-container .dialog-message-input {
padding: 15px 0px 0px;
display: flex;
}
.monaco-dialog-box .dialog-message-row .dialog-message-container .dialog-message-input .monaco-inputbox {
flex: 1;
}
/** Dialog: File Path */
.monaco-dialog-box code {
font-family: var(--monaco-monospace-font);
}
/** Dialog: Buttons Row */
.monaco-dialog-box > .dialog-buttons-row {
display: flex;
align-items: center;
padding-right: 1px;
overflow: hidden; /* buttons row should never overflow */
}
.monaco-dialog-box > .dialog-buttons-row {
display: flex;
white-space: nowrap;
padding: 20px 10px 10px;
}
/** Dialog: Buttons */
.monaco-dialog-box > .dialog-buttons-row > .dialog-buttons {
display: flex;
width: 100%;
}
.monaco-dialog-box:not(.align-vertical) > .dialog-buttons-row > .dialog-buttons {
overflow: hidden;
justify-content: flex-end;
margin-left: 67px; /* for long buttons, force align with text */
}
.monaco-dialog-box.align-vertical > .dialog-buttons-row > .dialog-buttons {
margin-left: 5px;
margin-right: 5px;
flex-direction: column;
}
.monaco-dialog-box > .dialog-buttons-row > .dialog-buttons > .monaco-button {
padding: 4px 10px;
overflow: hidden;
text-overflow: ellipsis;
margin: 4px 5px; /* allows button focus outline to be visible */
outline-offset: 2px !important;
}
.monaco-dialog-box.align-vertical > .dialog-buttons-row > .dialog-buttons > .monaco-button {
margin: 4px 0; /* allows button focus outline to be visible */
}
.monaco-dialog-box:not(.align-vertical) > .dialog-buttons-row > .dialog-buttons > .monaco-button {
width: fit-content;
}
/** Dialog: Dropdown */
.monaco-dialog-box:not(.align-vertical) > .dialog-buttons-row > .dialog-buttons > .monaco-button-dropdown {
margin: 4px 5px;
}
.monaco-dialog-box.align-vertical > .dialog-buttons-row > .dialog-buttons > .monaco-button-dropdown {
width: 100%;
}
.monaco-dialog-box > .dialog-buttons-row > .dialog-buttons > .monaco-button-dropdown:focus-within {
/**
* This is a trick to make the focus outline appear on the entire
* container of the dropdown button to ensure the dialog box looks
* consistent to dialogs without dropdown buttons.
*/
outline-offset: 2px !important;
outline-width: 1px;
outline-style: solid;
outline-color: var(--vscode-focusBorder);
border-radius: 2px;
}
.monaco-dialog-box > .dialog-buttons-row > .dialog-buttons > .monaco-button-dropdown > .monaco-text-button {
padding-left: 10px;
padding-right: 10px;
}
.monaco-dialog-box.align-vertical > .dialog-buttons-row > .dialog-buttons > .monaco-button-dropdown > .monaco-text-button {
width: 100%;
}
.monaco-dialog-box > .dialog-buttons-row > .dialog-buttons > .monaco-button-dropdown > .monaco-dropdown-button {
padding-left: 5px;
padding-right: 5px;
}

View File

@@ -0,0 +1,6 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import './dialog.css';
//# sourceMappingURL=dialog.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src/vs/base/browser/ui/dialog/dialog.ts","vs/base/browser/ui/dialog/dialog.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAEhG,OAAO,cAAc,CAAC","file":"dialog.js","sourceRoot":"file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport './dialog.css';\n\nexport interface IDialogStyles {\n\treadonly dialogForeground: string | undefined;\n\treadonly dialogBackground: string | undefined;\n\treadonly dialogShadow: string | undefined;\n\treadonly dialogBorder: string | undefined;\n\treadonly errorIconForeground: string | undefined;\n\treadonly warningIconForeground: string | undefined;\n\treadonly infoIconForeground: string | undefined;\n\treadonly textLinkForeground: string | undefined;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport './dialog.css';\n\nexport interface IDialogStyles {\n\treadonly dialogForeground: string | undefined;\n\treadonly dialogBackground: string | undefined;\n\treadonly dialogShadow: string | undefined;\n\treadonly dialogBorder: string | undefined;\n\treadonly errorIconForeground: string | undefined;\n\treadonly warningIconForeground: string | undefined;\n\treadonly infoIconForeground: string | undefined;\n\treadonly textLinkForeground: string | undefined;\n}\n"]}

View File

@@ -0,0 +1,28 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-drag-image {
display: inline-block;
padding: 1px 7px;
border-radius: 10px;
font-size: 12px;
position: absolute;
z-index: 1000;
/* Default styles */
background-color: var(--vscode-list-activeSelectionBackground);
color: var(--vscode-list-activeSelectionForeground);
outline: 1px solid var(--vscode-list-focusOutline);
outline-offset: -1px;
/*
* Browsers apply an effect to the drag image when the div becomes too
* large which makes them unreadable. Use max width so it does not happen
*/
max-width: 120px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}

View File

@@ -0,0 +1,26 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { $ } from '../../dom.js';
import './dnd.css';
export function applyDragImage(event, container, label, extraClasses = []) {
if (!event.dataTransfer) {
return;
}
const dragImage = $('.monaco-drag-image');
dragImage.textContent = label;
dragImage.classList.add(...extraClasses);
const getDragImageContainer = (e) => {
while (e && !e.classList.contains('monaco-workbench')) {
e = e.parentElement;
}
return e || container.ownerDocument.body;
};
const dragContainer = getDragImageContainer(container);
dragContainer.appendChild(dragImage);
event.dataTransfer.setDragImage(dragImage, -10, -10);
// Removes the element when the DND operation is done
setTimeout(() => dragImage.remove(), 0);
}
//# sourceMappingURL=dnd.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src/vs/base/browser/ui/dnd/dnd.ts","vs/base/browser/ui/dnd/dnd.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAEhG,OAAO,EAAE,CAAC,EAAE,MAAM,cAAc,CAAC;AACjC,OAAO,WAAW,CAAC;AAEnB,MAAM,UAAU,cAAc,CAAC,KAAgB,EAAE,SAAsB,EAAE,KAAa,EAAE,eAAyB,EAAE;IAClH,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;QACzB,OAAO;IACR,CAAC;IAED,MAAM,SAAS,GAAG,CAAC,CAAC,oBAAoB,CAAC,CAAC;IAC1C,SAAS,CAAC,WAAW,GAAG,KAAK,CAAC;IAC9B,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC;IAEzC,MAAM,qBAAqB,GAAG,CAAC,CAAqB,EAAE,EAAE;QACvD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;YACvD,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC;QACrB,CAAC;QACD,OAAO,CAAC,IAAI,SAAS,CAAC,aAAa,CAAC,IAAI,CAAC;IAC1C,CAAC,CAAC;IAEF,MAAM,aAAa,GAAG,qBAAqB,CAAC,SAAS,CAAC,CAAC;IACvD,aAAa,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IACrC,KAAK,CAAC,YAAY,CAAC,YAAY,CAAC,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;IAErD,qDAAqD;IACrD,UAAU,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;AACzC,CAAC","file":"dnd.js","sourceRoot":"file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { $ } from '../../dom.js';\nimport './dnd.css';\n\nexport function applyDragImage(event: DragEvent, container: HTMLElement, label: string, extraClasses: string[] = []): void {\n\tif (!event.dataTransfer) {\n\t\treturn;\n\t}\n\n\tconst dragImage = $('.monaco-drag-image');\n\tdragImage.textContent = label;\n\tdragImage.classList.add(...extraClasses);\n\n\tconst getDragImageContainer = (e: HTMLElement | null) => {\n\t\twhile (e && !e.classList.contains('monaco-workbench')) {\n\t\t\te = e.parentElement;\n\t\t}\n\t\treturn e || container.ownerDocument.body;\n\t};\n\n\tconst dragContainer = getDragImageContainer(container);\n\tdragContainer.appendChild(dragImage);\n\tevent.dataTransfer.setDragImage(dragImage, -10, -10);\n\n\t// Removes the element when the DND operation is done\n\tsetTimeout(() => dragImage.remove(), 0);\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { $ } from '../../dom.js';\nimport './dnd.css';\n\nexport function applyDragImage(event: DragEvent, container: HTMLElement, label: string, extraClasses: string[] = []): void {\n\tif (!event.dataTransfer) {\n\t\treturn;\n\t}\n\n\tconst dragImage = $('.monaco-drag-image');\n\tdragImage.textContent = label;\n\tdragImage.classList.add(...extraClasses);\n\n\tconst getDragImageContainer = (e: HTMLElement | null) => {\n\t\twhile (e && !e.classList.contains('monaco-workbench')) {\n\t\t\te = e.parentElement;\n\t\t}\n\t\treturn e || container.ownerDocument.body;\n\t};\n\n\tconst dragContainer = getDragImageContainer(container);\n\tdragContainer.appendChild(dragImage);\n\tevent.dataTransfer.setDragImage(dragImage, -10, -10);\n\n\t// Removes the element when the DND operation is done\n\tsetTimeout(() => dragImage.remove(), 0);\n}\n"]}

View File

@@ -0,0 +1,46 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-dropdown {
height: 100%;
padding: 0;
}
.monaco-dropdown > .dropdown-label {
cursor: pointer;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.monaco-dropdown > .dropdown-label > .action-label.disabled {
cursor: default;
}
.monaco-dropdown-with-primary {
display: flex !important;
flex-direction: row;
border-radius: 5px;
}
.monaco-dropdown-with-primary > .action-container > .action-label {
margin-right: 0;
}
.monaco-dropdown-with-primary > .dropdown-action-container > .monaco-dropdown > .dropdown-label .codicon[class*='codicon-'] {
font-size: 12px;
padding-left: 0px;
padding-right: 0px;
line-height: 16px;
margin-left: -3px;
}
.monaco-dropdown-with-primary > .dropdown-action-container > .monaco-dropdown > .dropdown-label > .action-label {
display: block;
background-size: 16px;
background-position: center center;
background-repeat: no-repeat;
}

View File

@@ -0,0 +1,139 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { $, addDisposableListener, append, EventHelper, EventType, isMouseEvent } from '../../dom.js';
import { StandardKeyboardEvent } from '../../keyboardEvent.js';
import { EventType as GestureEventType, Gesture } from '../../touch.js';
import { ActionRunner } from '../../../common/actions.js';
import { Emitter } from '../../../common/event.js';
import './dropdown.css';
export class BaseDropdown extends ActionRunner {
constructor(container, options) {
super();
this._onDidChangeVisibility = this._register(new Emitter());
this.onDidChangeVisibility = this._onDidChangeVisibility.event;
this._element = append(container, $('.monaco-dropdown'));
this._label = append(this._element, $('.dropdown-label'));
let labelRenderer = options.labelRenderer;
if (!labelRenderer) {
labelRenderer = (container) => {
container.textContent = options.label || '';
return null;
};
}
for (const event of [EventType.CLICK, EventType.MOUSE_DOWN, GestureEventType.Tap]) {
this._register(addDisposableListener(this.element, event, e => EventHelper.stop(e, true))); // prevent default click behaviour to trigger
}
for (const event of [EventType.MOUSE_DOWN, GestureEventType.Tap]) {
this._register(addDisposableListener(this._label, event, e => {
if (isMouseEvent(e) && e.button !== 0) {
// prevent right click trigger to allow separate context menu (https://github.com/microsoft/vscode/issues/151064)
return;
}
if (this.visible) {
this.hide();
}
else {
this.show();
}
}));
}
this._register(addDisposableListener(this._label, EventType.KEY_DOWN, e => {
const event = new StandardKeyboardEvent(e);
if (event.equals(3 /* KeyCode.Enter */) || event.equals(10 /* KeyCode.Space */)) {
EventHelper.stop(e, true); // https://github.com/microsoft/vscode/issues/57997
if (this.visible) {
this.hide();
}
else {
this.show();
}
}
}));
const cleanupFn = labelRenderer(this._label);
if (cleanupFn) {
this._register(cleanupFn);
}
this._register(Gesture.addTarget(this._label));
}
get element() {
return this._element;
}
show() {
if (!this.visible) {
this.visible = true;
this._onDidChangeVisibility.fire(true);
}
}
hide() {
if (this.visible) {
this.visible = false;
this._onDidChangeVisibility.fire(false);
}
}
dispose() {
super.dispose();
this.hide();
if (this.boxContainer) {
this.boxContainer.remove();
this.boxContainer = undefined;
}
if (this.contents) {
this.contents.remove();
this.contents = undefined;
}
if (this._label) {
this._label.remove();
this._label = undefined;
}
}
}
export class DropdownMenu extends BaseDropdown {
constructor(container, _options) {
super(container, _options);
this._options = _options;
this._actions = [];
this.actions = _options.actions || [];
}
set menuOptions(options) {
this._menuOptions = options;
}
get menuOptions() {
return this._menuOptions;
}
get actions() {
if (this._options.actionProvider) {
return this._options.actionProvider.getActions();
}
return this._actions;
}
set actions(actions) {
this._actions = actions;
}
show() {
super.show();
this.element.classList.add('active');
this._options.contextMenuProvider.showContextMenu({
getAnchor: () => this.element,
getActions: () => this.actions,
getActionsContext: () => this.menuOptions ? this.menuOptions.context : null,
getActionViewItem: (action, options) => this.menuOptions && this.menuOptions.actionViewItemProvider ? this.menuOptions.actionViewItemProvider(action, options) : undefined,
getKeyBinding: action => this.menuOptions && this.menuOptions.getKeyBinding ? this.menuOptions.getKeyBinding(action) : undefined,
getMenuClassName: () => this._options.menuClassName || '',
onHide: () => this.onHide(),
actionRunner: this.menuOptions ? this.menuOptions.actionRunner : undefined,
anchorAlignment: this.menuOptions ? this.menuOptions.anchorAlignment : 0 /* AnchorAlignment.LEFT */,
domForShadowRoot: this._options.menuAsChild ? this.element : undefined,
skipTelemetry: this._options.skipTelemetry
});
}
hide() {
super.hide();
}
onHide() {
this.hide();
this.element.classList.remove('active');
}
}
//# sourceMappingURL=dropdown.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,107 @@
import { Emitter } from '../../../common/event.js';
import { $, append } from '../../dom.js';
import { BaseActionViewItem } from '../actionbar/actionViewItems.js';
import { getBaseLayerHoverDelegate } from '../hover/hoverDelegate2.js';
import { getDefaultHoverDelegate } from '../hover/hoverDelegateFactory.js';
import './dropdown.css';
import { DropdownMenu } from './dropdown.js';
export class DropdownMenuActionViewItem extends BaseActionViewItem {
get onDidChangeVisibility() { return this._onDidChangeVisibility.event; }
constructor(action, menuActionsOrProvider, contextMenuProvider, options = Object.create(null)) {
super(null, action, options);
this.actionItem = null;
this._onDidChangeVisibility = this._register(new Emitter());
this.menuActionsOrProvider = menuActionsOrProvider;
this.contextMenuProvider = contextMenuProvider;
this.options = options;
if (this.options.actionRunner) {
this.actionRunner = this.options.actionRunner;
}
}
render(container) {
this.actionItem = container;
const labelRenderer = (el) => {
this.element = append(el, $('a.action-label'));
return this.renderLabel(this.element);
};
const isActionsArray = Array.isArray(this.menuActionsOrProvider);
const options = {
contextMenuProvider: this.contextMenuProvider,
labelRenderer: labelRenderer,
menuAsChild: this.options.menuAsChild,
actions: isActionsArray ? this.menuActionsOrProvider : undefined,
actionProvider: isActionsArray ? undefined : this.menuActionsOrProvider,
skipTelemetry: this.options.skipTelemetry
};
this.dropdownMenu = this._register(new DropdownMenu(container, options));
this._register(this.dropdownMenu.onDidChangeVisibility(visible => {
this.element?.setAttribute('aria-expanded', `${visible}`);
this._onDidChangeVisibility.fire(visible);
}));
this.dropdownMenu.menuOptions = {
actionViewItemProvider: this.options.actionViewItemProvider,
actionRunner: this.actionRunner,
getKeyBinding: this.options.keybindingProvider,
context: this._context
};
if (this.options.anchorAlignmentProvider) {
const that = this;
this.dropdownMenu.menuOptions = {
...this.dropdownMenu.menuOptions,
get anchorAlignment() {
return that.options.anchorAlignmentProvider();
}
};
}
this.updateTooltip();
this.updateEnabled();
}
renderLabel(element) {
let classNames = [];
if (typeof this.options.classNames === 'string') {
classNames = this.options.classNames.split(/\s+/g).filter(s => !!s);
}
else if (this.options.classNames) {
classNames = this.options.classNames;
}
// todo@aeschli: remove codicon, should come through `this.options.classNames`
if (!classNames.find(c => c === 'icon')) {
classNames.push('codicon');
}
element.classList.add(...classNames);
if (this._action.label) {
this._register(getBaseLayerHoverDelegate().setupManagedHover(this.options.hoverDelegate ?? getDefaultHoverDelegate('mouse'), element, this._action.label));
}
return null;
}
getTooltip() {
let title = null;
if (this.action.tooltip) {
title = this.action.tooltip;
}
else if (this.action.label) {
title = this.action.label;
}
return title ?? undefined;
}
setActionContext(newContext) {
super.setActionContext(newContext);
if (this.dropdownMenu) {
if (this.dropdownMenu.menuOptions) {
this.dropdownMenu.menuOptions.context = newContext;
}
else {
this.dropdownMenu.menuOptions = { context: newContext };
}
}
}
show() {
this.dropdownMenu?.show();
}
updateEnabled() {
const disabled = !this.action.enabled;
this.actionItem?.classList.toggle('disabled', disabled);
this.element?.classList.toggle('disabled', disabled);
}
}
//# sourceMappingURL=dropdownActionViewItem.js.map

File diff suppressed because one or more lines are too long

View File

@@ -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.
*--------------------------------------------------------------------------------------------*/
/* ---------- Find input ---------- */
.monaco-findInput {
position: relative;
}
.monaco-findInput .monaco-inputbox {
font-size: 13px;
width: 100%;
}
.monaco-findInput > .controls {
position: absolute;
top: 3px;
right: 2px;
}
.vs .monaco-findInput.disabled {
background-color: #E1E1E1;
}
/* Theming */
.vs-dark .monaco-findInput.disabled {
background-color: #333;
}
/* Highlighting */
.monaco-findInput.highlight-0 .controls,
.hc-light .monaco-findInput.highlight-0 .controls {
animation: monaco-findInput-highlight-0 100ms linear 0s;
}
.monaco-findInput.highlight-1 .controls,
.hc-light .monaco-findInput.highlight-1 .controls {
animation: monaco-findInput-highlight-1 100ms linear 0s;
}
.hc-black .monaco-findInput.highlight-0 .controls,
.vs-dark .monaco-findInput.highlight-0 .controls {
animation: monaco-findInput-highlight-dark-0 100ms linear 0s;
}
.hc-black .monaco-findInput.highlight-1 .controls,
.vs-dark .monaco-findInput.highlight-1 .controls {
animation: monaco-findInput-highlight-dark-1 100ms linear 0s;
}
@keyframes monaco-findInput-highlight-0 {
0% { background: rgba(253, 255, 0, 0.8); }
100% { background: transparent; }
}
@keyframes monaco-findInput-highlight-1 {
0% { background: rgba(253, 255, 0, 0.8); }
/* Made intentionally different such that the CSS minifier does not collapse the two animations into a single one*/
99% { background: transparent; }
}
@keyframes monaco-findInput-highlight-dark-0 {
0% { background: rgba(255, 255, 255, 0.44); }
100% { background: transparent; }
}
@keyframes monaco-findInput-highlight-dark-1 {
0% { background: rgba(255, 255, 255, 0.44); }
/* Made intentionally different such that the CSS minifier does not collapse the two animations into a single one*/
99% { background: transparent; }
}

View File

@@ -0,0 +1,293 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as dom from '../../dom.js';
import { CaseSensitiveToggle, RegexToggle, WholeWordsToggle } from './findInputToggles.js';
import { HistoryInputBox } from '../inputbox/inputBox.js';
import { Widget } from '../widget.js';
import { Emitter } from '../../../common/event.js';
import './findInput.css';
import * as nls from '../../../../nls.js';
import { DisposableStore, MutableDisposable } from '../../../common/lifecycle.js';
import { createInstantHoverDelegate } from '../hover/hoverDelegateFactory.js';
const NLS_DEFAULT_LABEL = nls.localize(1, "input");
export class FindInput extends Widget {
get onDidOptionChange() { return this._onDidOptionChange.event; }
get onKeyDown() { return this._onKeyDown.event; }
get onMouseDown() { return this._onMouseDown.event; }
get onCaseSensitiveKeyDown() { return this._onCaseSensitiveKeyDown.event; }
get onRegexKeyDown() { return this._onRegexKeyDown.event; }
constructor(parent, contextViewProvider, options) {
super();
this.fixFocusOnOptionClickEnabled = true;
this.imeSessionInProgress = false;
this.additionalTogglesDisposables = this._register(new MutableDisposable());
this.additionalToggles = [];
this._onDidOptionChange = this._register(new Emitter());
this._onKeyDown = this._register(new Emitter());
this._onMouseDown = this._register(new Emitter());
this._onInput = this._register(new Emitter());
this._onKeyUp = this._register(new Emitter());
this._onCaseSensitiveKeyDown = this._register(new Emitter());
this._onRegexKeyDown = this._register(new Emitter());
this._lastHighlightFindOptions = 0;
this.placeholder = options.placeholder || '';
this.validation = options.validation;
this.label = options.label || NLS_DEFAULT_LABEL;
this.showCommonFindToggles = !!options.showCommonFindToggles;
const appendCaseSensitiveLabel = options.appendCaseSensitiveLabel || '';
const appendWholeWordsLabel = options.appendWholeWordsLabel || '';
const appendRegexLabel = options.appendRegexLabel || '';
const flexibleHeight = !!options.flexibleHeight;
const flexibleWidth = !!options.flexibleWidth;
const flexibleMaxHeight = options.flexibleMaxHeight;
this.domNode = document.createElement('div');
this.domNode.classList.add('monaco-findInput');
this.inputBox = this._register(new HistoryInputBox(this.domNode, contextViewProvider, {
placeholder: this.placeholder || '',
ariaLabel: this.label || '',
validationOptions: {
validation: this.validation
},
showHistoryHint: options.showHistoryHint,
flexibleHeight,
flexibleWidth,
flexibleMaxHeight,
inputBoxStyles: options.inputBoxStyles,
history: options.history
}));
const hoverDelegate = this._register(createInstantHoverDelegate());
if (this.showCommonFindToggles) {
this.regex = this._register(new RegexToggle({
appendTitle: appendRegexLabel,
isChecked: false,
hoverDelegate,
...options.toggleStyles
}));
this._register(this.regex.onChange(viaKeyboard => {
this._onDidOptionChange.fire(viaKeyboard);
if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) {
this.inputBox.focus();
}
this.validate();
}));
this._register(this.regex.onKeyDown(e => {
this._onRegexKeyDown.fire(e);
}));
this.wholeWords = this._register(new WholeWordsToggle({
appendTitle: appendWholeWordsLabel,
isChecked: false,
hoverDelegate,
...options.toggleStyles
}));
this._register(this.wholeWords.onChange(viaKeyboard => {
this._onDidOptionChange.fire(viaKeyboard);
if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) {
this.inputBox.focus();
}
this.validate();
}));
this.caseSensitive = this._register(new CaseSensitiveToggle({
appendTitle: appendCaseSensitiveLabel,
isChecked: false,
hoverDelegate,
...options.toggleStyles
}));
this._register(this.caseSensitive.onChange(viaKeyboard => {
this._onDidOptionChange.fire(viaKeyboard);
if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) {
this.inputBox.focus();
}
this.validate();
}));
this._register(this.caseSensitive.onKeyDown(e => {
this._onCaseSensitiveKeyDown.fire(e);
}));
// Arrow-Key support to navigate between options
const indexes = [this.caseSensitive.domNode, this.wholeWords.domNode, this.regex.domNode];
this.onkeydown(this.domNode, (event) => {
if (event.equals(15 /* KeyCode.LeftArrow */) || event.equals(17 /* KeyCode.RightArrow */) || event.equals(9 /* KeyCode.Escape */)) {
const index = indexes.indexOf(this.domNode.ownerDocument.activeElement);
if (index >= 0) {
let newIndex = -1;
if (event.equals(17 /* KeyCode.RightArrow */)) {
newIndex = (index + 1) % indexes.length;
}
else if (event.equals(15 /* KeyCode.LeftArrow */)) {
if (index === 0) {
newIndex = indexes.length - 1;
}
else {
newIndex = index - 1;
}
}
if (event.equals(9 /* KeyCode.Escape */)) {
indexes[index].blur();
this.inputBox.focus();
}
else if (newIndex >= 0) {
indexes[newIndex].focus();
}
dom.EventHelper.stop(event, true);
}
}
});
}
this.controls = document.createElement('div');
this.controls.className = 'controls';
this.controls.style.display = this.showCommonFindToggles ? '' : 'none';
if (this.caseSensitive) {
this.controls.append(this.caseSensitive.domNode);
}
if (this.wholeWords) {
this.controls.appendChild(this.wholeWords.domNode);
}
if (this.regex) {
this.controls.appendChild(this.regex.domNode);
}
this.setAdditionalToggles(options?.additionalToggles);
if (this.controls) {
this.domNode.appendChild(this.controls);
}
parent?.appendChild(this.domNode);
this._register(dom.addDisposableListener(this.inputBox.inputElement, 'compositionstart', (e) => {
this.imeSessionInProgress = true;
}));
this._register(dom.addDisposableListener(this.inputBox.inputElement, 'compositionend', (e) => {
this.imeSessionInProgress = false;
this._onInput.fire();
}));
this.onkeydown(this.inputBox.inputElement, (e) => this._onKeyDown.fire(e));
this.onkeyup(this.inputBox.inputElement, (e) => this._onKeyUp.fire(e));
this.oninput(this.inputBox.inputElement, (e) => this._onInput.fire());
this.onmousedown(this.inputBox.inputElement, (e) => this._onMouseDown.fire(e));
}
get onDidChange() {
return this.inputBox.onDidChange;
}
layout(style) {
this.inputBox.layout();
this.updateInputBoxPadding(style.collapsedFindWidget);
}
enable() {
this.domNode.classList.remove('disabled');
this.inputBox.enable();
this.regex?.enable();
this.wholeWords?.enable();
this.caseSensitive?.enable();
for (const toggle of this.additionalToggles) {
toggle.enable();
}
}
disable() {
this.domNode.classList.add('disabled');
this.inputBox.disable();
this.regex?.disable();
this.wholeWords?.disable();
this.caseSensitive?.disable();
for (const toggle of this.additionalToggles) {
toggle.disable();
}
}
setFocusInputOnOptionClick(value) {
this.fixFocusOnOptionClickEnabled = value;
}
setEnabled(enabled) {
if (enabled) {
this.enable();
}
else {
this.disable();
}
}
setAdditionalToggles(toggles) {
for (const currentToggle of this.additionalToggles) {
currentToggle.domNode.remove();
}
this.additionalToggles = [];
this.additionalTogglesDisposables.value = new DisposableStore();
for (const toggle of toggles ?? []) {
this.additionalTogglesDisposables.value.add(toggle);
this.controls.appendChild(toggle.domNode);
this.additionalTogglesDisposables.value.add(toggle.onChange(viaKeyboard => {
this._onDidOptionChange.fire(viaKeyboard);
if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) {
this.inputBox.focus();
}
}));
this.additionalToggles.push(toggle);
}
if (this.additionalToggles.length > 0) {
this.controls.style.display = '';
}
this.updateInputBoxPadding();
}
updateInputBoxPadding(controlsHidden = false) {
if (controlsHidden) {
this.inputBox.paddingRight = 0;
}
else {
this.inputBox.paddingRight =
((this.caseSensitive?.width() ?? 0) + (this.wholeWords?.width() ?? 0) + (this.regex?.width() ?? 0))
+ this.additionalToggles.reduce((r, t) => r + t.width(), 0);
}
}
getValue() {
return this.inputBox.value;
}
setValue(value) {
if (this.inputBox.value !== value) {
this.inputBox.value = value;
}
}
select() {
this.inputBox.select();
}
focus() {
this.inputBox.focus();
}
getCaseSensitive() {
return this.caseSensitive?.checked ?? false;
}
setCaseSensitive(value) {
if (this.caseSensitive) {
this.caseSensitive.checked = value;
}
}
getWholeWords() {
return this.wholeWords?.checked ?? false;
}
setWholeWords(value) {
if (this.wholeWords) {
this.wholeWords.checked = value;
}
}
getRegex() {
return this.regex?.checked ?? false;
}
setRegex(value) {
if (this.regex) {
this.regex.checked = value;
this.validate();
}
}
focusOnCaseSensitive() {
this.caseSensitive?.focus();
}
highlightFindOptions() {
this.domNode.classList.remove('highlight-' + (this._lastHighlightFindOptions));
this._lastHighlightFindOptions = 1 - this._lastHighlightFindOptions;
this.domNode.classList.add('highlight-' + (this._lastHighlightFindOptions));
}
validate() {
this.inputBox.validate();
}
showMessage(message) {
this.inputBox.showMessage(message);
}
clearMessage() {
this.inputBox.hideMessage();
}
}
//# sourceMappingURL=findInput.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,51 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { getDefaultHoverDelegate } from '../hover/hoverDelegateFactory.js';
import { Toggle } from '../toggle/toggle.js';
import { Codicon } from '../../../common/codicons.js';
import * as nls from '../../../../nls.js';
const NLS_CASE_SENSITIVE_TOGGLE_LABEL = nls.localize(2, "Match Case");
const NLS_WHOLE_WORD_TOGGLE_LABEL = nls.localize(3, "Match Whole Word");
const NLS_REGEX_TOGGLE_LABEL = nls.localize(4, "Use Regular Expression");
export class CaseSensitiveToggle extends Toggle {
constructor(opts) {
super({
icon: Codicon.caseSensitive,
title: NLS_CASE_SENSITIVE_TOGGLE_LABEL + opts.appendTitle,
isChecked: opts.isChecked,
hoverDelegate: opts.hoverDelegate ?? getDefaultHoverDelegate('element'),
inputActiveOptionBorder: opts.inputActiveOptionBorder,
inputActiveOptionForeground: opts.inputActiveOptionForeground,
inputActiveOptionBackground: opts.inputActiveOptionBackground
});
}
}
export class WholeWordsToggle extends Toggle {
constructor(opts) {
super({
icon: Codicon.wholeWord,
title: NLS_WHOLE_WORD_TOGGLE_LABEL + opts.appendTitle,
isChecked: opts.isChecked,
hoverDelegate: opts.hoverDelegate ?? getDefaultHoverDelegate('element'),
inputActiveOptionBorder: opts.inputActiveOptionBorder,
inputActiveOptionForeground: opts.inputActiveOptionForeground,
inputActiveOptionBackground: opts.inputActiveOptionBackground
});
}
}
export class RegexToggle extends Toggle {
constructor(opts) {
super({
icon: Codicon.regex,
title: NLS_REGEX_TOGGLE_LABEL + opts.appendTitle,
isChecked: opts.isChecked,
hoverDelegate: opts.hoverDelegate ?? getDefaultHoverDelegate('element'),
inputActiveOptionBorder: opts.inputActiveOptionBorder,
inputActiveOptionForeground: opts.inputActiveOptionForeground,
inputActiveOptionBackground: opts.inputActiveOptionBackground
});
}
}
//# sourceMappingURL=findInputToggles.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["vs/base/browser/ui/findinput/findInputToggles.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAEhG,OAAO,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAE3E,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACtD,OAAO,KAAK,GAAG,MAAM,oBAAoB,CAAC;AAW1C,MAAM,+BAA+B,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAiB,EAAE,YAAY,CAAC,CAAC;AACtF,MAAM,2BAA2B,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAkB,EAAE,kBAAkB,CAAC,CAAC;AACzF,MAAM,sBAAsB,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAkB,EAAE,wBAAwB,CAAC,CAAC;AAE1F,MAAM,OAAO,mBAAoB,SAAQ,MAAM;IAC9C,YAAY,IAA0B;QACrC,KAAK,CAAC;YACL,IAAI,EAAE,OAAO,CAAC,aAAa;YAC3B,KAAK,EAAE,+BAA+B,GAAG,IAAI,CAAC,WAAW;YACzD,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,aAAa,EAAE,IAAI,CAAC,aAAa,IAAI,uBAAuB,CAAC,SAAS,CAAC;YACvE,uBAAuB,EAAE,IAAI,CAAC,uBAAuB;YACrD,2BAA2B,EAAE,IAAI,CAAC,2BAA2B;YAC7D,2BAA2B,EAAE,IAAI,CAAC,2BAA2B;SAC7D,CAAC,CAAC;IACJ,CAAC;CACD;AAED,MAAM,OAAO,gBAAiB,SAAQ,MAAM;IAC3C,YAAY,IAA0B;QACrC,KAAK,CAAC;YACL,IAAI,EAAE,OAAO,CAAC,SAAS;YACvB,KAAK,EAAE,2BAA2B,GAAG,IAAI,CAAC,WAAW;YACrD,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,aAAa,EAAE,IAAI,CAAC,aAAa,IAAI,uBAAuB,CAAC,SAAS,CAAC;YACvE,uBAAuB,EAAE,IAAI,CAAC,uBAAuB;YACrD,2BAA2B,EAAE,IAAI,CAAC,2BAA2B;YAC7D,2BAA2B,EAAE,IAAI,CAAC,2BAA2B;SAC7D,CAAC,CAAC;IACJ,CAAC;CACD;AAED,MAAM,OAAO,WAAY,SAAQ,MAAM;IACtC,YAAY,IAA0B;QACrC,KAAK,CAAC;YACL,IAAI,EAAE,OAAO,CAAC,KAAK;YACnB,KAAK,EAAE,sBAAsB,GAAG,IAAI,CAAC,WAAW;YAChD,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,aAAa,EAAE,IAAI,CAAC,aAAa,IAAI,uBAAuB,CAAC,SAAS,CAAC;YACvE,uBAAuB,EAAE,IAAI,CAAC,uBAAuB;YACrD,2BAA2B,EAAE,IAAI,CAAC,2BAA2B;YAC7D,2BAA2B,EAAE,IAAI,CAAC,2BAA2B;SAC7D,CAAC,CAAC;IACJ,CAAC;CACD","file":"findInputToggles.js","sourceRoot":"file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { getDefaultHoverDelegate } from '../hover/hoverDelegateFactory.js';\nimport { IHoverDelegate } from '../hover/hoverDelegate.js';\nimport { Toggle } from '../toggle/toggle.js';\nimport { Codicon } from '../../../common/codicons.js';\nimport * as nls from '../../../../nls.js';\n\nexport interface IFindInputToggleOpts {\n\treadonly appendTitle: string;\n\treadonly isChecked: boolean;\n\treadonly inputActiveOptionBorder: string | undefined;\n\treadonly inputActiveOptionForeground: string | undefined;\n\treadonly inputActiveOptionBackground: string | undefined;\n\treadonly hoverDelegate?: IHoverDelegate;\n}\n\nconst NLS_CASE_SENSITIVE_TOGGLE_LABEL = nls.localize('caseDescription', \"Match Case\");\nconst NLS_WHOLE_WORD_TOGGLE_LABEL = nls.localize('wordsDescription', \"Match Whole Word\");\nconst NLS_REGEX_TOGGLE_LABEL = nls.localize('regexDescription', \"Use Regular Expression\");\n\nexport class CaseSensitiveToggle extends Toggle {\n\tconstructor(opts: IFindInputToggleOpts) {\n\t\tsuper({\n\t\t\ticon: Codicon.caseSensitive,\n\t\t\ttitle: NLS_CASE_SENSITIVE_TOGGLE_LABEL + opts.appendTitle,\n\t\t\tisChecked: opts.isChecked,\n\t\t\thoverDelegate: opts.hoverDelegate ?? getDefaultHoverDelegate('element'),\n\t\t\tinputActiveOptionBorder: opts.inputActiveOptionBorder,\n\t\t\tinputActiveOptionForeground: opts.inputActiveOptionForeground,\n\t\t\tinputActiveOptionBackground: opts.inputActiveOptionBackground\n\t\t});\n\t}\n}\n\nexport class WholeWordsToggle extends Toggle {\n\tconstructor(opts: IFindInputToggleOpts) {\n\t\tsuper({\n\t\t\ticon: Codicon.wholeWord,\n\t\t\ttitle: NLS_WHOLE_WORD_TOGGLE_LABEL + opts.appendTitle,\n\t\t\tisChecked: opts.isChecked,\n\t\t\thoverDelegate: opts.hoverDelegate ?? getDefaultHoverDelegate('element'),\n\t\t\tinputActiveOptionBorder: opts.inputActiveOptionBorder,\n\t\t\tinputActiveOptionForeground: opts.inputActiveOptionForeground,\n\t\t\tinputActiveOptionBackground: opts.inputActiveOptionBackground\n\t\t});\n\t}\n}\n\nexport class RegexToggle extends Toggle {\n\tconstructor(opts: IFindInputToggleOpts) {\n\t\tsuper({\n\t\t\ticon: Codicon.regex,\n\t\t\ttitle: NLS_REGEX_TOGGLE_LABEL + opts.appendTitle,\n\t\t\tisChecked: opts.isChecked,\n\t\t\thoverDelegate: opts.hoverDelegate ?? getDefaultHoverDelegate('element'),\n\t\t\tinputActiveOptionBorder: opts.inputActiveOptionBorder,\n\t\t\tinputActiveOptionForeground: opts.inputActiveOptionForeground,\n\t\t\tinputActiveOptionBackground: opts.inputActiveOptionBackground\n\t\t});\n\t}\n}\n"]}

View File

@@ -0,0 +1,174 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as dom from '../../dom.js';
import { Toggle } from '../toggle/toggle.js';
import { HistoryInputBox } from '../inputbox/inputBox.js';
import { Widget } from '../widget.js';
import { Codicon } from '../../../common/codicons.js';
import { Emitter } from '../../../common/event.js';
import './findInput.css';
import * as nls from '../../../../nls.js';
import { getDefaultHoverDelegate } from '../hover/hoverDelegateFactory.js';
const NLS_DEFAULT_LABEL = nls.localize(5, "input");
const NLS_PRESERVE_CASE_LABEL = nls.localize(6, "Preserve Case");
class PreserveCaseToggle extends Toggle {
constructor(opts) {
super({
// TODO: does this need its own icon?
icon: Codicon.preserveCase,
title: NLS_PRESERVE_CASE_LABEL + opts.appendTitle,
isChecked: opts.isChecked,
hoverDelegate: opts.hoverDelegate ?? getDefaultHoverDelegate('element'),
inputActiveOptionBorder: opts.inputActiveOptionBorder,
inputActiveOptionForeground: opts.inputActiveOptionForeground,
inputActiveOptionBackground: opts.inputActiveOptionBackground,
});
}
}
export class ReplaceInput extends Widget {
get onDidOptionChange() { return this._onDidOptionChange.event; }
get onKeyDown() { return this._onKeyDown.event; }
get onPreserveCaseKeyDown() { return this._onPreserveCaseKeyDown.event; }
constructor(parent, contextViewProvider, _showOptionButtons, options) {
super();
this._showOptionButtons = _showOptionButtons;
this.fixFocusOnOptionClickEnabled = true;
this.cachedOptionsWidth = 0;
this._onDidOptionChange = this._register(new Emitter());
this._onKeyDown = this._register(new Emitter());
this._onMouseDown = this._register(new Emitter());
this._onInput = this._register(new Emitter());
this._onKeyUp = this._register(new Emitter());
this._onPreserveCaseKeyDown = this._register(new Emitter());
this.contextViewProvider = contextViewProvider;
this.placeholder = options.placeholder || '';
this.validation = options.validation;
this.label = options.label || NLS_DEFAULT_LABEL;
const appendPreserveCaseLabel = options.appendPreserveCaseLabel || '';
const history = options.history || new Set([]);
const flexibleHeight = !!options.flexibleHeight;
const flexibleWidth = !!options.flexibleWidth;
const flexibleMaxHeight = options.flexibleMaxHeight;
this.domNode = document.createElement('div');
this.domNode.classList.add('monaco-findInput');
this.inputBox = this._register(new HistoryInputBox(this.domNode, this.contextViewProvider, {
ariaLabel: this.label || '',
placeholder: this.placeholder || '',
validationOptions: {
validation: this.validation
},
history,
showHistoryHint: options.showHistoryHint,
flexibleHeight,
flexibleWidth,
flexibleMaxHeight,
inputBoxStyles: options.inputBoxStyles
}));
this.preserveCase = this._register(new PreserveCaseToggle({
appendTitle: appendPreserveCaseLabel,
isChecked: false,
...options.toggleStyles
}));
this._register(this.preserveCase.onChange(viaKeyboard => {
this._onDidOptionChange.fire(viaKeyboard);
if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) {
this.inputBox.focus();
}
this.validate();
}));
this._register(this.preserveCase.onKeyDown(e => {
this._onPreserveCaseKeyDown.fire(e);
}));
if (this._showOptionButtons) {
this.cachedOptionsWidth = this.preserveCase.width();
}
else {
this.cachedOptionsWidth = 0;
}
// Arrow-Key support to navigate between options
const indexes = [this.preserveCase.domNode];
this.onkeydown(this.domNode, (event) => {
if (event.equals(15 /* KeyCode.LeftArrow */) || event.equals(17 /* KeyCode.RightArrow */) || event.equals(9 /* KeyCode.Escape */)) {
const index = indexes.indexOf(this.domNode.ownerDocument.activeElement);
if (index >= 0) {
let newIndex = -1;
if (event.equals(17 /* KeyCode.RightArrow */)) {
newIndex = (index + 1) % indexes.length;
}
else if (event.equals(15 /* KeyCode.LeftArrow */)) {
if (index === 0) {
newIndex = indexes.length - 1;
}
else {
newIndex = index - 1;
}
}
if (event.equals(9 /* KeyCode.Escape */)) {
indexes[index].blur();
this.inputBox.focus();
}
else if (newIndex >= 0) {
indexes[newIndex].focus();
}
dom.EventHelper.stop(event, true);
}
}
});
const controls = document.createElement('div');
controls.className = 'controls';
controls.style.display = this._showOptionButtons ? 'block' : 'none';
controls.appendChild(this.preserveCase.domNode);
this.domNode.appendChild(controls);
parent?.appendChild(this.domNode);
this.onkeydown(this.inputBox.inputElement, (e) => this._onKeyDown.fire(e));
this.onkeyup(this.inputBox.inputElement, (e) => this._onKeyUp.fire(e));
this.oninput(this.inputBox.inputElement, (e) => this._onInput.fire());
this.onmousedown(this.inputBox.inputElement, (e) => this._onMouseDown.fire(e));
}
enable() {
this.domNode.classList.remove('disabled');
this.inputBox.enable();
this.preserveCase.enable();
}
disable() {
this.domNode.classList.add('disabled');
this.inputBox.disable();
this.preserveCase.disable();
}
setEnabled(enabled) {
if (enabled) {
this.enable();
}
else {
this.disable();
}
}
select() {
this.inputBox.select();
}
focus() {
this.inputBox.focus();
}
getPreserveCase() {
return this.preserveCase.checked;
}
setPreserveCase(value) {
this.preserveCase.checked = value;
}
focusOnPreserve() {
this.preserveCase.focus();
}
validate() {
this.inputBox?.validate();
}
set width(newWidth) {
this.inputBox.paddingRight = this.cachedOptionsWidth;
this.domNode.style.width = newWidth + 'px';
}
dispose() {
super.dispose();
}
}
//# sourceMappingURL=replaceInput.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,128 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as dom from '../../dom.js';
import { getBaseLayerHoverDelegate } from '../hover/hoverDelegate2.js';
import { getDefaultHoverDelegate } from '../hover/hoverDelegateFactory.js';
import { renderLabelWithIcons } from '../iconLabel/iconLabels.js';
import { Disposable } from '../../../common/lifecycle.js';
import * as objects from '../../../common/objects.js';
/**
* A widget which can render a label with substring highlights, often
* originating from a filter function like the fuzzy matcher.
*/
export class HighlightedLabel extends Disposable {
/**
* Create a new {@link HighlightedLabel}.
*
* @param container The parent container to append to.
*/
constructor(container, options) {
super();
this.options = options;
this.text = '';
this.title = '';
this.highlights = [];
this.didEverRender = false;
this.supportIcons = options?.supportIcons ?? false;
this.domNode = dom.append(container, dom.$('span.monaco-highlighted-label'));
}
/**
* The label's DOM node.
*/
get element() {
return this.domNode;
}
/**
* Set the label and highlights.
*
* @param text The label to display.
* @param highlights The ranges to highlight.
* @param title An optional title for the hover tooltip.
* @param escapeNewLines Whether to escape new lines.
* @returns
*/
set(text, highlights = [], title = '', escapeNewLines) {
if (!text) {
text = '';
}
if (escapeNewLines) {
// adjusts highlights inplace
text = HighlightedLabel.escapeNewLines(text, highlights);
}
if (this.didEverRender && this.text === text && this.title === title && objects.equals(this.highlights, highlights)) {
return;
}
this.text = text;
this.title = title;
this.highlights = highlights;
this.render();
}
render() {
const children = [];
let pos = 0;
for (const highlight of this.highlights) {
if (highlight.end === highlight.start) {
continue;
}
if (pos < highlight.start) {
const substring = this.text.substring(pos, highlight.start);
if (this.supportIcons) {
children.push(...renderLabelWithIcons(substring));
}
else {
children.push(substring);
}
pos = highlight.start;
}
const substring = this.text.substring(pos, highlight.end);
const element = dom.$('span.highlight', undefined, ...this.supportIcons ? renderLabelWithIcons(substring) : [substring]);
if (highlight.extraClasses) {
element.classList.add(...highlight.extraClasses);
}
children.push(element);
pos = highlight.end;
}
if (pos < this.text.length) {
const substring = this.text.substring(pos);
if (this.supportIcons) {
children.push(...renderLabelWithIcons(substring));
}
else {
children.push(substring);
}
}
dom.reset(this.domNode, ...children);
if (!this.customHover && this.title !== '') {
const hoverDelegate = this.options?.hoverDelegate ?? getDefaultHoverDelegate('mouse');
this.customHover = this._register(getBaseLayerHoverDelegate().setupManagedHover(hoverDelegate, this.domNode, this.title));
}
else if (this.customHover) {
this.customHover.update(this.title);
}
this.didEverRender = true;
}
static escapeNewLines(text, highlights) {
let total = 0;
let extra = 0;
return text.replace(/\r\n|\r|\n/g, (match, offset) => {
extra = match === '\r\n' ? -1 : 0;
offset += total;
for (const highlight of highlights) {
if (highlight.end <= offset) {
continue;
}
if (highlight.start >= offset) {
highlight.start += extra;
}
if (highlight.end >= offset) {
highlight.end += extra;
}
}
total += extra;
return '\u23CE';
});
}
}
//# sourceMappingURL=highlightedLabel.js.map

File diff suppressed because one or more lines are too long

View File

@@ -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.
*--------------------------------------------------------------------------------------------*/
export function isManagedHoverTooltipMarkdownString(obj) {
const candidate = obj;
return typeof candidate === 'object' && 'markdown' in candidate && 'markdownNotSupportedFallback' in candidate;
}
// #endregion Managed hover
//# sourceMappingURL=hover.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,6 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export {};
//# sourceMappingURL=hoverDelegate.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,37 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Disposable } from '../../../common/lifecycle.js';
let baseHoverDelegate = {
showInstantHover: () => undefined,
showDelayedHover: () => undefined,
setupDelayedHover: () => Disposable.None,
setupDelayedHoverAtMouse: () => Disposable.None,
hideHover: () => undefined,
showAndFocusLastHover: () => undefined,
setupManagedHover: () => ({
dispose: () => undefined,
show: () => undefined,
hide: () => undefined,
update: () => undefined,
}),
showManagedHover: () => undefined
};
/**
* Sets the hover delegate for use **only in the `base/` layer**.
*/
export function setBaseLayerHoverDelegate(hoverDelegate) {
baseHoverDelegate = hoverDelegate;
}
/**
* Gets the hover delegate for use **only in the `base/` layer**.
*
* Since the hover service depends on various platform services, this delegate essentially bypasses
* the standard dependency injection mechanism by injecting a global hover service at start up. The
* only reason this should be used is if `IHoverService` is not available.
*/
export function getBaseLayerHoverDelegate() {
return baseHoverDelegate;
}
//# sourceMappingURL=hoverDelegate2.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src/vs/base/browser/ui/hover/hoverDelegate2.ts","vs/base/browser/ui/hover/hoverDelegate2.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAEhG,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAG1D,IAAI,iBAAiB,GAAoB;IACxC,gBAAgB,EAAE,GAAG,EAAE,CAAC,SAAS;IACjC,gBAAgB,EAAE,GAAG,EAAE,CAAC,SAAS;IACjC,iBAAiB,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI;IACxC,wBAAwB,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI;IAC/C,SAAS,EAAE,GAAG,EAAE,CAAC,SAAS;IAC1B,qBAAqB,EAAE,GAAG,EAAE,CAAC,SAAS;IACtC,iBAAiB,EAAE,GAAG,EAAE,CAAC,CAAC;QACzB,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;QACxB,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS;QACrB,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS;QACrB,MAAM,EAAE,GAAG,EAAE,CAAC,SAAS;KACvB,CAAC;IACF,gBAAgB,EAAE,GAAG,EAAE,CAAC,SAAS;CACjC,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,yBAAyB,CAAC,aAA8B;IACvE,iBAAiB,GAAG,aAAa,CAAC;AACnC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,yBAAyB;IACxC,OAAO,iBAAiB,CAAC;AAC1B,CAAC","file":"hoverDelegate2.js","sourceRoot":"file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Disposable } from '../../../common/lifecycle.js';\nimport { IHoverDelegate2 } from './hover.js';\n\nlet baseHoverDelegate: IHoverDelegate2 = {\n\tshowInstantHover: () => undefined,\n\tshowDelayedHover: () => undefined,\n\tsetupDelayedHover: () => Disposable.None,\n\tsetupDelayedHoverAtMouse: () => Disposable.None,\n\thideHover: () => undefined,\n\tshowAndFocusLastHover: () => undefined,\n\tsetupManagedHover: () => ({\n\t\tdispose: () => undefined,\n\t\tshow: () => undefined,\n\t\thide: () => undefined,\n\t\tupdate: () => undefined,\n\t}),\n\tshowManagedHover: () => undefined\n};\n\n/**\n * Sets the hover delegate for use **only in the `base/` layer**.\n */\nexport function setBaseLayerHoverDelegate(hoverDelegate: IHoverDelegate2): void {\n\tbaseHoverDelegate = hoverDelegate;\n}\n\n/**\n * Gets the hover delegate for use **only in the `base/` layer**.\n *\n * Since the hover service depends on various platform services, this delegate essentially bypasses\n * the standard dependency injection mechanism by injecting a global hover service at start up. The\n * only reason this should be used is if `IHoverService` is not available.\n */\nexport function getBaseLayerHoverDelegate(): IHoverDelegate2 {\n\treturn baseHoverDelegate;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Disposable } from '../../../common/lifecycle.js';\nimport { IHoverDelegate2 } from './hover.js';\n\nlet baseHoverDelegate: IHoverDelegate2 = {\n\tshowInstantHover: () => undefined,\n\tshowDelayedHover: () => undefined,\n\tsetupDelayedHover: () => Disposable.None,\n\tsetupDelayedHoverAtMouse: () => Disposable.None,\n\thideHover: () => undefined,\n\tshowAndFocusLastHover: () => undefined,\n\tsetupManagedHover: () => ({\n\t\tdispose: () => undefined,\n\t\tshow: () => undefined,\n\t\thide: () => undefined,\n\t\tupdate: () => undefined,\n\t}),\n\tshowManagedHover: () => undefined\n};\n\n/**\n * Sets the hover delegate for use **only in the `base/` layer**.\n */\nexport function setBaseLayerHoverDelegate(hoverDelegate: IHoverDelegate2): void {\n\tbaseHoverDelegate = hoverDelegate;\n}\n\n/**\n * Gets the hover delegate for use **only in the `base/` layer**.\n *\n * Since the hover service depends on various platform services, this delegate essentially bypasses\n * the standard dependency injection mechanism by injecting a global hover service at start up. The\n * only reason this should be used is if `IHoverService` is not available.\n */\nexport function getBaseLayerHoverDelegate(): IHoverDelegate2 {\n\treturn baseHoverDelegate;\n}\n"]}

View File

@@ -0,0 +1,32 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Lazy } from '../../../common/lazy.js';
const nullHoverDelegateFactory = () => ({
get delay() { return -1; },
dispose: () => { },
showHover: () => { return undefined; },
});
let hoverDelegateFactory = nullHoverDelegateFactory;
const defaultHoverDelegateMouse = new Lazy(() => hoverDelegateFactory('mouse', false));
const defaultHoverDelegateElement = new Lazy(() => hoverDelegateFactory('element', false));
// TODO: Remove when getDefaultHoverDelegate is no longer used
export function setHoverDelegateFactory(hoverDelegateProvider) {
hoverDelegateFactory = hoverDelegateProvider;
}
// TODO: Refine type for use in new IHoverService interface
export function getDefaultHoverDelegate(placement) {
if (placement === 'element') {
return defaultHoverDelegateElement.value;
}
return defaultHoverDelegateMouse.value;
}
// TODO: Create equivalent in IHoverService
export function createInstantHoverDelegate() {
// Creates a hover delegate with instant hover enabled.
// This hover belongs to the consumer and requires the them to dispose it.
// Instant hover only makes sense for 'element' placement.
return hoverDelegateFactory('element', true);
}
//# sourceMappingURL=hoverDelegateFactory.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,225 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-hover {
cursor: default;
position: absolute;
overflow: hidden;
user-select: text;
-webkit-user-select: text;
box-sizing: border-box;
line-height: 1.5em;
white-space: var(--vscode-hover-whiteSpace, normal);
}
.monaco-hover.fade-in {
animation: fadein 100ms linear;
}
.monaco-hover.hidden {
display: none;
}
.monaco-hover a:hover:not(.disabled) {
cursor: pointer;
}
.monaco-hover .hover-contents:not(.html-hover-contents) {
padding: 4px 8px;
}
.monaco-hover .markdown-hover > .hover-contents:not(.code-hover-contents) {
max-width: var(--vscode-hover-maxWidth, 500px);
word-wrap: break-word;
}
.monaco-hover .markdown-hover > .hover-contents:not(.code-hover-contents) hr {
min-width: 100%;
}
.monaco-hover p,
.monaco-hover .code,
.monaco-hover ul,
.monaco-hover h1,
.monaco-hover h2,
.monaco-hover h3,
.monaco-hover h4,
.monaco-hover h5,
.monaco-hover h6 {
margin: 8px 0;
}
.monaco-hover h1,
.monaco-hover h2,
.monaco-hover h3,
.monaco-hover h4,
.monaco-hover h5,
.monaco-hover h6 {
line-height: 1.1;
}
.monaco-hover code {
font-family: var(--monaco-monospace-font);
}
.monaco-hover hr {
box-sizing: border-box;
border-left: 0px;
border-right: 0px;
margin-top: 4px;
margin-bottom: -4px;
margin-left: -8px;
margin-right: -8px;
height: 1px;
}
.monaco-hover p:first-child,
.monaco-hover .code:first-child,
.monaco-hover ul:first-child {
margin-top: 0;
}
.monaco-hover p:last-child,
.monaco-hover .code:last-child,
.monaco-hover ul:last-child {
margin-bottom: 0;
}
/* MarkupContent Layout */
.monaco-hover ul {
padding-left: 20px;
}
.monaco-hover ol {
padding-left: 20px;
}
.monaco-hover li > p {
margin-bottom: 0;
}
.monaco-hover li > ul {
margin-top: 0;
}
.monaco-hover code {
border-radius: 3px;
padding: 0 0.4em;
}
.monaco-hover .monaco-tokenized-source {
white-space: var(--vscode-hover-sourceWhiteSpace, pre-wrap);
}
.monaco-hover .hover-row.status-bar {
font-size: 12px;
line-height: 22px;
}
.monaco-hover .hover-row.status-bar .info {
font-style: italic;
padding: 0px 8px;
}
.monaco-hover .hover-row.status-bar .actions {
display: flex;
padding: 0px 8px;
width: 100%;
}
.monaco-hover .hover-row.status-bar .actions .action-container {
margin-right: 16px;
cursor: pointer;
overflow: hidden;
text-wrap: nowrap;
text-overflow: ellipsis;
}
.monaco-hover .hover-row.status-bar .actions .action-container .action .icon {
padding-right: 4px;
vertical-align: middle;
}
.monaco-hover .hover-row.status-bar .actions .action-container a {
color: var(--vscode-textLink-foreground);
text-decoration: var(--text-link-decoration);
}
.monaco-hover .hover-row.status-bar .actions .action-container a .icon.codicon {
color: var(--vscode-textLink-foreground);
}
.monaco-hover .markdown-hover .hover-contents .codicon {
color: inherit;
font-size: inherit;
vertical-align: middle;
}
.monaco-hover .hover-contents a.code-link:hover,
.monaco-hover .hover-contents a.code-link {
color: inherit;
}
.monaco-hover .hover-contents a.code-link:before {
content: '(';
}
.monaco-hover .hover-contents a.code-link:after {
content: ')';
}
.monaco-hover .hover-contents a.code-link > span {
text-decoration: underline;
/** Hack to force underline to show **/
border-bottom: 1px solid transparent;
text-underline-position: under;
color: var(--vscode-textLink-foreground);
}
.monaco-hover .hover-contents a.code-link > span:hover {
color: var(--vscode-textLink-activeForeground);
}
/**
* Spans in markdown hovers need a margin-bottom to avoid looking cramped:
* https://github.com/microsoft/vscode/issues/101496
* This was later refined to only apply when the last child of a rendered markdown block (before the
* border or a `hr`) uses background color:
* https://github.com/microsoft/vscode/issues/228136
*/
.monaco-hover .markdown-hover .hover-contents:not(.code-hover-contents):not(.html-hover-contents) p:last-child [style*="background-color"] {
margin-bottom: 4px;
display: inline-block;
}
/**
* Add a slight margin to try vertically align codicons with any text
* https://github.com/microsoft/vscode/issues/221359
*/
.monaco-hover .markdown-hover .hover-contents:not(.code-hover-contents):not(.html-hover-contents) span.codicon {
margin-bottom: 2px;
}
.monaco-hover-content .action-container a {
-webkit-user-select: none;
user-select: none;
}
.monaco-hover-content .action-container.disabled {
pointer-events: none;
opacity: 0.4;
cursor: default;
}
/* Prevent text selection in all button-like elements within hovers */
.monaco-hover .action-container,
.monaco-hover .action,
.monaco-hover button,
.monaco-hover .monaco-button,
.monaco-hover .monaco-text-button,
.monaco-hover [role="button"] {
-webkit-user-select: none;
user-select: none;
}

View File

@@ -0,0 +1,91 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as dom from '../../dom.js';
import { StandardKeyboardEvent } from '../../keyboardEvent.js';
import { DomScrollableElement } from '../scrollbar/scrollableElement.js';
import { Disposable } from '../../../common/lifecycle.js';
import './hoverWidget.css';
import { localize } from '../../../../nls.js';
const $ = dom.$;
export class HoverWidget extends Disposable {
constructor(fadeIn) {
super();
this.containerDomNode = document.createElement('div');
this.containerDomNode.className = 'monaco-hover';
this.containerDomNode.classList.toggle('fade-in', !!fadeIn);
this.containerDomNode.tabIndex = 0;
this.containerDomNode.setAttribute('role', 'tooltip');
this.contentsDomNode = document.createElement('div');
this.contentsDomNode.className = 'monaco-hover-content';
this.scrollbar = this._register(new DomScrollableElement(this.contentsDomNode, {
consumeMouseWheelIfScrollbarIsNeeded: true
}));
this.containerDomNode.appendChild(this.scrollbar.getDomNode());
}
onContentsChanged() {
this.scrollbar.scanDomNode();
}
}
export class HoverAction extends Disposable {
static render(parent, actionOptions, keybindingLabel) {
return new HoverAction(parent, actionOptions, keybindingLabel);
}
constructor(parent, actionOptions, keybindingLabel) {
super();
this.actionLabel = actionOptions.label;
this.actionKeybindingLabel = keybindingLabel;
this.actionContainer = dom.append(parent, $('div.action-container'));
this.actionContainer.setAttribute('tabindex', '0');
this.action = dom.append(this.actionContainer, $('a.action'));
this.action.setAttribute('role', 'button');
if (actionOptions.iconClass) {
const iconElement = dom.append(this.action, $(`span.icon`));
iconElement.classList.add(...actionOptions.iconClass.split(' '));
}
this.actionRenderedLabel = keybindingLabel ? `${actionOptions.label} (${keybindingLabel})` : actionOptions.label;
const label = dom.append(this.action, $('span'));
label.textContent = this.actionRenderedLabel;
this._store.add(new ClickAction(this.actionContainer, actionOptions.run));
this._store.add(new KeyDownAction(this.actionContainer, actionOptions.run, [3 /* KeyCode.Enter */, 10 /* KeyCode.Space */]));
this.setEnabled(true);
}
setEnabled(enabled) {
if (enabled) {
this.actionContainer.classList.remove('disabled');
this.actionContainer.removeAttribute('aria-disabled');
}
else {
this.actionContainer.classList.add('disabled');
this.actionContainer.setAttribute('aria-disabled', 'true');
}
}
}
export function getHoverAccessibleViewHint(shouldHaveHint, keybinding) {
return shouldHaveHint && keybinding ? localize(7, "Inspect this in the accessible view with {0}.", keybinding) : shouldHaveHint ? localize(8, "Inspect this in the accessible view via the command Open Accessible View which is currently not triggerable via keybinding.") : '';
}
export class ClickAction extends Disposable {
constructor(container, run) {
super();
this._register(dom.addDisposableListener(container, dom.EventType.CLICK, e => {
e.stopPropagation();
e.preventDefault();
run(container);
}));
}
}
export class KeyDownAction extends Disposable {
constructor(container, run, keyCodes) {
super();
this._register(dom.addDisposableListener(container, dom.EventType.KEY_DOWN, e => {
const event = new StandardKeyboardEvent(e);
if (keyCodes.some(keyCode => event.equals(keyCode))) {
e.stopPropagation();
e.preventDefault();
run(container);
}
}));
}
}
//# sourceMappingURL=hoverWidget.js.map

Some files were not shown because too many files have changed in this diff Show More