feat: 添加vscode编辑器

This commit is contained in:
dhx
2022-09-29 16:48:09 +08:00
parent a93bdac4ff
commit 150898ec1e
1126 changed files with 933348 additions and 0 deletions
@@ -0,0 +1,5 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export {};
@@ -0,0 +1,218 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import './iconlabel.css';
import * as dom from '../../dom.js';
import { HighlightedLabel } from '../highlightedlabel/highlightedLabel.js';
import { setupCustomHover, setupNativeHover } from './iconLabelHover.js';
import { Disposable } from '../../../common/lifecycle.js';
import { equals } from '../../../common/objects.js';
import { Range } from '../../../common/range.js';
class FastLabelNode {
constructor(_element) {
this._element = _element;
}
get element() {
return this._element;
}
set textContent(content) {
if (this.disposed || content === this._textContent) {
return;
}
this._textContent = content;
this._element.textContent = content;
}
set className(className) {
if (this.disposed || className === this._className) {
return;
}
this._className = className;
this._element.className = className;
}
set empty(empty) {
if (this.disposed || empty === this._empty) {
return;
}
this._empty = empty;
this._element.style.marginLeft = empty ? '0' : '';
}
dispose() {
this.disposed = true;
}
}
export class IconLabel extends Disposable {
constructor(container, options) {
super();
this.customHovers = new Map();
this.domNode = this._register(new FastLabelNode(dom.append(container, dom.$('.monaco-icon-label'))));
this.labelContainer = dom.append(this.domNode.element, dom.$('.monaco-icon-label-container'));
const nameContainer = dom.append(this.labelContainer, dom.$('span.monaco-icon-name-container'));
this.descriptionContainer = this._register(new FastLabelNode(dom.append(this.labelContainer, dom.$('span.monaco-icon-description-container'))));
if ((options === null || options === void 0 ? void 0 : options.supportHighlights) || (options === null || options === void 0 ? void 0 : options.supportIcons)) {
this.nameNode = new LabelWithHighlights(nameContainer, !!options.supportIcons);
}
else {
this.nameNode = new Label(nameContainer);
}
if (options === null || options === void 0 ? void 0 : options.supportDescriptionHighlights) {
this.descriptionNodeFactory = () => new HighlightedLabel(dom.append(this.descriptionContainer.element, dom.$('span.label-description')), { supportIcons: !!options.supportIcons });
}
else {
this.descriptionNodeFactory = () => this._register(new FastLabelNode(dom.append(this.descriptionContainer.element, dom.$('span.label-description'))));
}
this.hoverDelegate = options === null || options === void 0 ? void 0 : options.hoverDelegate;
}
get element() {
return this.domNode.element;
}
setLabel(label, description, options) {
const classes = ['monaco-icon-label'];
if (options) {
if (options.extraClasses) {
classes.push(...options.extraClasses);
}
if (options.italic) {
classes.push('italic');
}
if (options.strikethrough) {
classes.push('strikethrough');
}
}
this.domNode.className = classes.join(' ');
this.setupHover((options === null || options === void 0 ? void 0 : options.descriptionTitle) ? this.labelContainer : this.element, options === null || options === void 0 ? void 0 : options.title);
this.nameNode.setLabel(label, options);
if (description || this.descriptionNode) {
if (!this.descriptionNode) {
this.descriptionNode = this.descriptionNodeFactory(); // description node is created lazily on demand
}
if (this.descriptionNode instanceof HighlightedLabel) {
this.descriptionNode.set(description || '', options ? options.descriptionMatches : undefined);
this.setupHover(this.descriptionNode.element, options === null || options === void 0 ? void 0 : options.descriptionTitle);
}
else {
this.descriptionNode.textContent = description || '';
this.setupHover(this.descriptionNode.element, (options === null || options === void 0 ? void 0 : options.descriptionTitle) || '');
this.descriptionNode.empty = !description;
}
}
}
setupHover(htmlElement, tooltip) {
const previousCustomHover = this.customHovers.get(htmlElement);
if (previousCustomHover) {
previousCustomHover.dispose();
this.customHovers.delete(htmlElement);
}
if (!tooltip) {
htmlElement.removeAttribute('title');
return;
}
if (!this.hoverDelegate) {
setupNativeHover(htmlElement, tooltip);
}
else {
const hoverDisposable = setupCustomHover(this.hoverDelegate, htmlElement, tooltip);
if (hoverDisposable) {
this.customHovers.set(htmlElement, hoverDisposable);
}
}
}
dispose() {
super.dispose();
for (const disposable of this.customHovers.values()) {
disposable.dispose();
}
this.customHovers.clear();
}
}
class Label {
constructor(container) {
this.container = container;
this.label = undefined;
this.singleLabel = undefined;
}
setLabel(label, options) {
if (this.label === label && equals(this.options, options)) {
return;
}
this.label = label;
this.options = options;
if (typeof label === 'string') {
if (!this.singleLabel) {
this.container.innerText = '';
this.container.classList.remove('multiple');
this.singleLabel = dom.append(this.container, dom.$('a.label-name', { id: options === null || options === void 0 ? void 0 : options.domId }));
}
this.singleLabel.textContent = label;
}
else {
this.container.innerText = '';
this.container.classList.add('multiple');
this.singleLabel = undefined;
for (let i = 0; i < label.length; i++) {
const l = label[i];
const id = (options === null || options === void 0 ? void 0 : options.domId) && `${options === null || options === void 0 ? void 0 : options.domId}_${i}`;
dom.append(this.container, dom.$('a.label-name', { id, 'data-icon-label-count': label.length, 'data-icon-label-index': i, 'role': 'treeitem' }, l));
if (i < label.length - 1) {
dom.append(this.container, dom.$('span.label-separator', undefined, (options === null || options === void 0 ? void 0 : options.separator) || '/'));
}
}
}
}
}
function splitMatches(labels, separator, matches) {
if (!matches) {
return undefined;
}
let labelStart = 0;
return labels.map(label => {
const labelRange = { start: labelStart, end: labelStart + label.length };
const result = matches
.map(match => Range.intersect(labelRange, match))
.filter(range => !Range.isEmpty(range))
.map(({ start, end }) => ({ start: start - labelStart, end: end - labelStart }));
labelStart = labelRange.end + separator.length;
return result;
});
}
class LabelWithHighlights {
constructor(container, supportIcons) {
this.container = container;
this.supportIcons = supportIcons;
this.label = undefined;
this.singleLabel = undefined;
}
setLabel(label, options) {
if (this.label === label && equals(this.options, options)) {
return;
}
this.label = label;
this.options = options;
if (typeof label === 'string') {
if (!this.singleLabel) {
this.container.innerText = '';
this.container.classList.remove('multiple');
this.singleLabel = new HighlightedLabel(dom.append(this.container, dom.$('a.label-name', { id: options === null || options === void 0 ? void 0 : options.domId })), { supportIcons: this.supportIcons });
}
this.singleLabel.set(label, options === null || options === void 0 ? void 0 : options.matches, undefined, options === null || options === void 0 ? void 0 : options.labelEscapeNewLines);
}
else {
this.container.innerText = '';
this.container.classList.add('multiple');
this.singleLabel = undefined;
const separator = (options === null || options === void 0 ? void 0 : options.separator) || '/';
const matches = splitMatches(label, separator, options === null || options === void 0 ? void 0 : options.matches);
for (let i = 0; i < label.length; i++) {
const l = label[i];
const m = matches ? matches[i] : undefined;
const id = (options === null || options === void 0 ? void 0 : options.domId) && `${options === null || options === void 0 ? void 0 : options.domId}_${i}`;
const name = dom.$('a.label-name', { id, 'data-icon-label-count': label.length, 'data-icon-label-index': i, 'role': 'treeitem' });
const highlightedLabel = new HighlightedLabel(dom.append(this.container, name), { supportIcons: this.supportIcons });
highlightedLabel.set(l, m, undefined, options === null || options === void 0 ? void 0 : options.labelEscapeNewLines);
if (i < label.length - 1) {
dom.append(name, dom.$('span.label-separator', undefined, separator));
}
}
}
}
}
@@ -0,0 +1,176 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import * as dom from '../../dom.js';
import { TimeoutTimer } from '../../../common/async.js';
import { CancellationTokenSource } from '../../../common/cancellation.js';
import { isMarkdownString } from '../../../common/htmlContent.js';
import { stripIcons } from '../../../common/iconLabels.js';
import { DisposableStore } from '../../../common/lifecycle.js';
import { isFunction, isString } from '../../../common/types.js';
import { localize } from '../../../../nls.js';
export function setupNativeHover(htmlElement, tooltip) {
if (isString(tooltip)) {
// Icons don't render in the native hover so we strip them out
htmlElement.title = stripIcons(tooltip);
}
else if (tooltip === null || tooltip === void 0 ? void 0 : tooltip.markdownNotSupportedFallback) {
htmlElement.title = tooltip.markdownNotSupportedFallback;
}
else {
htmlElement.removeAttribute('title');
}
}
class UpdatableHoverWidget {
constructor(hoverDelegate, target, fadeInAnimation) {
this.hoverDelegate = hoverDelegate;
this.target = target;
this.fadeInAnimation = fadeInAnimation;
}
update(content, focus, options) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
if (this._cancellationTokenSource) {
// there's an computation ongoing, cancel it
this._cancellationTokenSource.dispose(true);
this._cancellationTokenSource = undefined;
}
if (this.isDisposed) {
return;
}
let resolvedContent;
if (content === undefined || isString(content) || content instanceof HTMLElement) {
resolvedContent = content;
}
else if (!isFunction(content.markdown)) {
resolvedContent = (_a = content.markdown) !== null && _a !== void 0 ? _a : content.markdownNotSupportedFallback;
}
else {
// compute the content, potentially long-running
// show 'Loading' if no hover is up yet
if (!this._hoverWidget) {
this.show(localize('iconLabel.loading', "Loading..."), focus);
}
// compute the content
this._cancellationTokenSource = new CancellationTokenSource();
const token = this._cancellationTokenSource.token;
resolvedContent = yield content.markdown(token);
if (resolvedContent === undefined) {
resolvedContent = content.markdownNotSupportedFallback;
}
if (this.isDisposed || token.isCancellationRequested) {
// either the widget has been closed in the meantime
// or there has been a new call to `update`
return;
}
}
this.show(resolvedContent, focus, options);
});
}
show(content, focus, options) {
const oldHoverWidget = this._hoverWidget;
if (this.hasContent(content)) {
const hoverOptions = Object.assign({ content, target: this.target, showPointer: this.hoverDelegate.placement === 'element', hoverPosition: 2 /* HoverPosition.BELOW */, skipFadeInAnimation: !this.fadeInAnimation || !!oldHoverWidget }, options);
this._hoverWidget = this.hoverDelegate.showHover(hoverOptions, focus);
}
oldHoverWidget === null || oldHoverWidget === void 0 ? void 0 : oldHoverWidget.dispose();
}
hasContent(content) {
if (!content) {
return false;
}
if (isMarkdownString(content)) {
return !!content.value;
}
return true;
}
get isDisposed() {
var _a;
return (_a = this._hoverWidget) === null || _a === void 0 ? void 0 : _a.isDisposed;
}
dispose() {
var _a, _b;
(_a = this._hoverWidget) === null || _a === void 0 ? void 0 : _a.dispose();
(_b = this._cancellationTokenSource) === null || _b === void 0 ? void 0 : _b.dispose(true);
this._cancellationTokenSource = undefined;
}
}
export function setupCustomHover(hoverDelegate, htmlElement, content, options) {
let hoverPreparation;
let hoverWidget;
const hideHover = (disposeWidget, disposePreparation) => {
var _a;
if (disposeWidget) {
hoverWidget === null || hoverWidget === void 0 ? void 0 : hoverWidget.dispose();
hoverWidget = undefined;
}
if (disposePreparation) {
hoverPreparation === null || hoverPreparation === void 0 ? void 0 : hoverPreparation.dispose();
hoverPreparation = undefined;
}
(_a = hoverDelegate.onDidHideHover) === null || _a === void 0 ? void 0 : _a.call(hoverDelegate);
};
const triggerShowHover = (delay, focus, target) => {
return new TimeoutTimer(() => __awaiter(this, void 0, void 0, function* () {
if (!hoverWidget || hoverWidget.isDisposed) {
hoverWidget = new UpdatableHoverWidget(hoverDelegate, target || htmlElement, delay > 0);
yield hoverWidget.update(content, focus, options);
}
}), delay);
};
const onMouseOver = () => {
if (hoverPreparation) {
return;
}
const toDispose = new DisposableStore();
const onMouseLeave = (e) => hideHover(false, e.fromElement === htmlElement);
toDispose.add(dom.addDisposableListener(htmlElement, dom.EventType.MOUSE_LEAVE, onMouseLeave, true));
const onMouseDown = () => hideHover(true, true);
toDispose.add(dom.addDisposableListener(htmlElement, dom.EventType.MOUSE_DOWN, onMouseDown, true));
const target = {
targetElements: [htmlElement],
dispose: () => { }
};
if (hoverDelegate.placement === undefined || hoverDelegate.placement === 'mouse') {
// track the mouse position
const onMouseMove = (e) => {
target.x = e.x + 10;
if ((e.target instanceof HTMLElement) && e.target.classList.contains('action-label')) {
hideHover(true, true);
}
};
toDispose.add(dom.addDisposableListener(htmlElement, dom.EventType.MOUSE_MOVE, onMouseMove, true));
}
toDispose.add(triggerShowHover(hoverDelegate.delay, false, target));
hoverPreparation = toDispose;
};
const mouseOverDomEmitter = dom.addDisposableListener(htmlElement, dom.EventType.MOUSE_OVER, onMouseOver, true);
const hover = {
show: focus => {
hideHover(false, true); // terminate a ongoing mouse over preparation
triggerShowHover(0, focus); // show hover immediately
},
hide: () => {
hideHover(true, true);
},
update: (newContent, hoverOptions) => __awaiter(this, void 0, void 0, function* () {
content = newContent;
yield (hoverWidget === null || hoverWidget === void 0 ? void 0 : hoverWidget.update(content, undefined, hoverOptions));
}),
dispose: () => {
mouseOverDomEmitter.dispose();
hideHover(true, true);
}
};
return hover;
}
@@ -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.
*--------------------------------------------------------------------------------------------*/
import * as dom from '../../dom.js';
import { CSSIcon } from '../../../common/codicons.js';
const labelWithIconsRegex = new RegExp(`(\\\\)?\\$\\((${CSSIcon.iconNameExpression}(?:${CSSIcon.iconModifierExpression})?)\\)`, 'g');
export function renderLabelWithIcons(text) {
const elements = new Array();
let match;
let textStart = 0, textStop = 0;
while ((match = labelWithIconsRegex.exec(text)) !== null) {
textStop = match.index || 0;
elements.push(text.substring(textStart, textStop));
textStart = (match.index || 0) + match[0].length;
const [, escaped, codicon] = match;
elements.push(escaped ? `$(${codicon})` : renderIcon({ id: codicon }));
}
if (textStart < text.length) {
elements.push(text.substring(textStart));
}
return elements;
}
export function renderIcon(icon) {
const node = dom.$(`span`);
node.classList.add(...CSSIcon.asClassNameArray(icon));
return node;
}
@@ -0,0 +1,104 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/* ---------- Icon label ---------- */
.monaco-icon-label {
display: flex; /* required for icons support :before rule */
overflow: hidden;
text-overflow: ellipsis;
}
.monaco-icon-label::before {
/* svg icons rendered as background image */
background-size: 16px;
background-position: left center;
background-repeat: no-repeat;
padding-right: 6px;
width: 16px;
height: 22px;
line-height: inherit !important;
display: inline-block;
/* fonts icons */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
vertical-align: top;
flex-shrink: 0; /* fix for https://github.com/microsoft/vscode/issues/13787 */
}
.monaco-icon-label > .monaco-icon-label-container {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
flex: 1;
}
.monaco-icon-label > .monaco-icon-label-container > .monaco-icon-name-container > .label-name {
color: inherit;
white-space: pre; /* enable to show labels that include multiple whitespaces */
}
.monaco-icon-label > .monaco-icon-label-container > .monaco-icon-name-container > .label-name > .label-separator {
margin: 0 2px;
opacity: 0.5;
}
.monaco-icon-label > .monaco-icon-label-container > .monaco-icon-description-container > .label-description {
opacity: .7;
margin-left: 0.5em;
font-size: 0.9em;
white-space: pre; /* enable to show labels that include multiple whitespaces */
}
.monaco-icon-label.nowrap > .monaco-icon-label-container > .monaco-icon-description-container > .label-description{
white-space: nowrap
}
.vs .monaco-icon-label > .monaco-icon-label-container > .monaco-icon-description-container > .label-description {
opacity: .95;
}
.monaco-icon-label.italic > .monaco-icon-label-container > .monaco-icon-name-container > .label-name,
.monaco-icon-label.italic > .monaco-icon-label-container > .monaco-icon-description-container > .label-description {
font-style: italic;
}
.monaco-icon-label.deprecated {
text-decoration: line-through;
opacity: 0.66;
}
/* make sure apply italic font style to decorations as well */
.monaco-icon-label.italic::after {
font-style: italic;
}
.monaco-icon-label.strikethrough > .monaco-icon-label-container > .monaco-icon-name-container > .label-name,
.monaco-icon-label.strikethrough > .monaco-icon-label-container > .monaco-icon-description-container > .label-description {
text-decoration: line-through;
}
.monaco-icon-label::after {
opacity: 0.75;
font-size: 90%;
font-weight: 600;
margin: auto 16px 0 5px; /* https://github.com/microsoft/vscode/issues/113223 */
text-align: center;
}
/* make sure selection color wins when a label is being selected */
.monaco-list:focus .selected .monaco-icon-label, /* list */
.monaco-list:focus .selected .monaco-icon-label::after
{
color: inherit !important;
}
.monaco-list-row.focused.selected .label-description,
.monaco-list-row.selected .label-description {
opacity: .8;
}