Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/microsoft/vscode.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/vs/base/browser/dom.ts')
-rw-r--r--src/vs/base/browser/dom.ts145
1 files changed, 86 insertions, 59 deletions
diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts
index 4d08566a4f6..4019ea90b61 100644
--- a/src/vs/base/browser/dom.ts
+++ b/src/vs/base/browser/dom.ts
@@ -1734,50 +1734,87 @@ export function computeClippingRect(elementOrRect: HTMLElement | DOMRectReadOnly
return { top, right, bottom, left };
}
-interface DomNodeAttributes {
- role?: string;
- ariaHidden?: boolean;
- style?: StyleAttributes;
-}
+type HTMLElementAttributeKeys<T> = Partial<{ [K in keyof T]: T[K] extends Function ? never : T[K] extends object ? HTMLElementAttributeKeys<T[K]> : T[K] }>;
+type ElementAttributes<T> = HTMLElementAttributeKeys<T> & Record<string, any>;
+type RemoveHTMLElement<T> = T extends HTMLElement ? never : T;
+type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
+type ArrayToObj<T extends readonly any[]> = UnionToIntersection<RemoveHTMLElement<T[number]>>;
+type HHTMLElementTagNameMap = HTMLElementTagNameMap & { '': HTMLDivElement };
-interface StyleAttributes {
- height?: number | string;
- width?: number | string;
-}
+type TagToElement<T> = T extends `${infer TStart}#${string}`
+ ? TStart extends keyof HHTMLElementTagNameMap
+ ? HHTMLElementTagNameMap[TStart]
+ : HTMLElement
+ : T extends `${infer TStart}.${string}`
+ ? TStart extends keyof HHTMLElementTagNameMap
+ ? HHTMLElementTagNameMap[TStart]
+ : HTMLElement
+ : T extends keyof HTMLElementTagNameMap
+ ? HTMLElementTagNameMap[T]
+ : HTMLElement;
-//<div role="presentation" aria-hidden="true" class="scroll-decoration"></div>
+type TagToElementAndId<TTag> = TTag extends `${infer TTag}@${infer TId}`
+ ? { element: TagToElement<TTag>; id: TId }
+ : { element: TagToElement<TTag>; id: 'root' };
+
+type TagToRecord<TTag> = TagToElementAndId<TTag> extends { element: infer TElement; id: infer TId }
+ ? Record<(TId extends string ? TId : never) | 'root', TElement>
+ : never;
+
+type Child = HTMLElement | string | Record<string, HTMLElement>;
+type Children = []
+ | [Child]
+ | [Child, Child]
+ | [Child, Child, Child]
+ | [Child, Child, Child, Child]
+ | [Child, Child, Child, Child, Child]
+ | [Child, Child, Child, Child, Child, Child]
+ | [Child, Child, Child, Child, Child, Child, Child]
+ | [Child, Child, Child, Child, Child, Child, Child, Child]
+ | [Child, Child, Child, Child, Child, Child, Child, Child, Child]
+ | [Child, Child, Child, Child, Child, Child, Child, Child, Child, Child]
+ | [Child, Child, Child, Child, Child, Child, Child, Child, Child, Child, Child]
+ | [Child, Child, Child, Child, Child, Child, Child, Child, Child, Child, Child, Child]
+ | [Child, Child, Child, Child, Child, Child, Child, Child, Child, Child, Child, Child, Child]
+ | [Child, Child, Child, Child, Child, Child, Child, Child, Child, Child, Child, Child, Child, Child]
+ | [Child, Child, Child, Child, Child, Child, Child, Child, Child, Child, Child, Child, Child, Child, Child]
+ | [Child, Child, Child, Child, Child, Child, Child, Child, Child, Child, Child, Child, Child, Child, Child, Child];
+
+const H_REGEX = /(?<tag>[\w\-]+)?(?:#(?<id>[\w\-]+))?(?<class>(?:\.(?:[\w\-]+))*)(?:@(?<name>(?:[\w\_])+))?/;
/**
* A helper function to create nested dom nodes.
*
*
* ```ts
- * private readonly htmlElements = h('div.code-view', [
- * h('div.title', { $: 'title' }),
+ * const elements = h('div.code-view', [
+ * h('div.title@title'),
* h('div.container', [
- * h('div.gutter', { $: 'gutterDiv' }),
- * h('div', { $: 'editor' }),
+ * h('div.gutter@gutterDiv'),
+ * h('div@editor'),
* ]),
* ]);
- * private readonly editor = createEditor(this.htmlElements.editor);
+ * const editor = createEditor(elements.editor);
* ```
*/
-export function h<TTag extends string, TId extends string>(
- tag: TTag,
- attributes: { $: TId } & DomNodeAttributes
-): Record<TId | 'root', TagToElement<TTag>>;
-export function h<TTag extends string>(tag: TTag, attributes: DomNodeAttributes): Record<'root', TagToElement<TTag>>;
-export function h<TTag extends string, T extends (HTMLElement | string | Record<string, HTMLElement>)[]>(
- tag: TTag,
- children: T
-): (ArrayToObj<T> & Record<'root', TagToElement<TTag>>) extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never;
-export function h<TTag extends string, TId extends string, T extends (HTMLElement | string | Record<string, HTMLElement>)[]>(
- tag: TTag,
- attributes: { $: TId } & DomNodeAttributes,
- children: T
-): (ArrayToObj<T> & Record<TId, TagToElement<TTag>>) extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never;
-export function h(tag: string, ...args: [] | [attributes: { $: string } & DomNodeAttributes | Record<string, any>, children?: any[]] | [children: any[]]): Record<string, HTMLElement> {
- let attributes: { $?: string } & DomNodeAttributes;
+export function h<TTag extends string>
+ (tag: TTag):
+ TagToRecord<TTag> extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never;
+
+export function h<TTag extends string, T extends Children>
+ (tag: TTag, children: T):
+ (ArrayToObj<T> & TagToRecord<TTag>) extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never;
+
+export function h<TTag extends string>
+ (tag: TTag, attributes: Partial<ElementAttributes<TagToElement<TTag>>>):
+ TagToRecord<TTag> extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never;
+
+export function h<TTag extends string, T extends Children>
+ (tag: TTag, attributes: Partial<ElementAttributes<TagToElement<TTag>>>, children: T):
+ (ArrayToObj<T> & TagToRecord<TTag>) extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never;
+
+export function h(tag: string, ...args: [] | [attributes: { $: string } & Partial<ElementAttributes<HTMLElement>> | Record<string, any>, children?: any[]] | [children: any[]]): Record<string, HTMLElement> {
+ let attributes: { $?: string } & Partial<ElementAttributes<HTMLElement>>;
let children: (Record<string, HTMLElement> | HTMLElement)[] | undefined;
if (Array.isArray(args[0])) {
@@ -1788,14 +1825,29 @@ export function h(tag: string, ...args: [] | [attributes: { $: string } & DomNod
children = args[1];
}
- const [tagName, className] = tag.split('.');
+ const match = H_REGEX.exec(tag);
+
+ if (!match || !match.groups) {
+ throw new Error('Bad use of h');
+ }
+
+ const tagName = match.groups['tag'] || 'div';
const el = document.createElement(tagName);
- if (className) {
- el.className = className;
+
+ if (match.groups['id']) {
+ el.id = match.groups['id'];
+ }
+
+ if (match.groups['class']) {
+ el.className = match.groups['class'].replace(/\./g, ' ').trim();
}
const result: Record<string, HTMLElement> = {};
+ if (match.groups['name']) {
+ result[match.groups['name']] = el;
+ }
+
if (children) {
for (const c of children) {
if (c instanceof HTMLElement) {
@@ -1810,10 +1862,6 @@ export function h(tag: string, ...args: [] | [attributes: { $: string } & DomNod
}
for (const [key, value] of Object.entries(attributes)) {
- if (key === '$') {
- result[value] = el;
- continue;
- }
if (key === 'style') {
for (const [cssKey, cssValue] of Object.entries(value)) {
el.style.setProperty(
@@ -1834,24 +1882,3 @@ export function h(tag: string, ...args: [] | [attributes: { $: string } & DomNod
function camelCaseToHyphenCase(str: string) {
return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
}
-
-type RemoveHTMLElement<T> = T extends HTMLElement ? never : T;
-
-type ArrayToObj<T extends any[]> = UnionToIntersection<RemoveHTMLElement<T[number]>>;
-
-
-type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
-
-type HTMLElementsByTagName = {
- div: HTMLDivElement;
- span: HTMLSpanElement;
- a: HTMLAnchorElement;
-};
-
-type TagToElement<T> = T extends `${infer TStart}.${string}`
- ? TStart extends keyof HTMLElementsByTagName
- ? HTMLElementsByTagName[TStart]
- : HTMLElement
- : T extends keyof HTMLElementsByTagName
- ? HTMLElementsByTagName[T]
- : HTMLElement;