typed-dom
Advanced tools
Comparing version 0.0.263 to 0.0.264
50
dom.ts
@@ -33,2 +33,3 @@ import { Symbol, document } from 'spica/global'; | ||
SVG = 'SVG', | ||
MathML = 'MathML', | ||
} | ||
@@ -38,7 +39,7 @@ | ||
export type Attrs = Record<string, string | EventListener | null | undefined>; | ||
export type Children = Iterable<string | Node> | string; | ||
export type Children = Iterable<string | Node> | string | undefined; | ||
export interface Factory<M extends TagNameMap> { | ||
<T extends keyof M & string>(tag: T, children?: Children): M[T]; | ||
<T extends keyof M & string>(tag: T, attrs?: Attrs, children?: Children): M[T]; | ||
<T extends keyof M & string>(tag: T, attrs: Attrs | undefined, children?: Children): M[T]; | ||
} | ||
@@ -84,2 +85,3 @@ | ||
export function element<M extends SVGElementTagNameMap>(context: Document | ShadowRoot, ns: NS.SVG): Factory<M>; | ||
export function element<M extends TagNameMap>(context: Document | ShadowRoot, ns: NS.MathML): Factory<M>; | ||
export function element<M extends TagNameMap>(context: Document | ShadowRoot, ns: NS): Factory<M> { | ||
@@ -106,2 +108,4 @@ const cache = memoize(elem, (_, ns, tag) => `${ns}:${tag}`); | ||
return context.createElementNS('http://www.w3.org/2000/svg', tag); | ||
case NS.MathML: | ||
return context.createElementNS('http://www.w3.org/1998/Math/MathML', tag); | ||
} | ||
@@ -112,8 +116,8 @@ } | ||
export function define<T extends Element | DocumentFragment | ShadowRoot>(node: T, children?: Children): T; | ||
export function define<T extends Element>(node: T, attrs?: Attrs | Children, children?: Children): T { | ||
export function define<T extends Element | DocumentFragment | ShadowRoot>(node: T, attrs?: Attrs | Children, children?: Children): T { | ||
return isChildren(attrs) | ||
? defineChildren(node, attrs) | ||
: defineChildren(defineAttrs(node, attrs), children); | ||
: defineChildren(defineAttrs(node as Element, attrs) as T, children); | ||
} | ||
function defineAttrs<T extends Element>(el: T, attrs?: Attrs): T { | ||
function defineAttrs<T extends Element>(el: T, attrs: Attrs): T { | ||
if (!attrs) return el; | ||
@@ -154,3 +158,3 @@ for (const name in attrs) { | ||
} | ||
function defineChildren<T extends ParentNode & Node>(node: T, children?: Children): T { | ||
function defineChildren<T extends ParentNode & Node>(node: T, children: Children): T { | ||
if (children === void 0) return node; | ||
@@ -173,6 +177,36 @@ if (typeof children === 'string') { | ||
export function isChildren(param: Attrs | Children | ShadowRootInit | undefined): param is Children { | ||
return !!param?.[Symbol.iterator]; | ||
export function isChildren(value: Attrs | Children | ShadowRootInit): value is Children { | ||
return !!value?.[Symbol.iterator]; | ||
} | ||
export function append<T extends ParentNode & Node>(node: T, children: Children): T { | ||
if (children === void 0) return node; | ||
if (typeof children === 'string') { | ||
node.append(children); | ||
} | ||
else { | ||
for (const child of children) { | ||
typeof child === 'object' | ||
? node.appendChild(child) | ||
: node.append(child); | ||
} | ||
} | ||
return node; | ||
} | ||
export function prepend<T extends ParentNode & Node>(node: T, children: Children): T { | ||
if (children === void 0) return node; | ||
if (typeof children === 'string') { | ||
node.prepend(children); | ||
} | ||
else { | ||
for (const child of children) { | ||
typeof child === 'object' | ||
? node.insertBefore(child, null) | ||
: node.prepend(child); | ||
} | ||
} | ||
return node; | ||
} | ||
export function defrag<T extends Node | string>(nodes: ArrayLike<T>): T[]; | ||
@@ -179,0 +213,0 @@ export function defrag(nodes: ArrayLike<Node | string>): (Node | string)[] { |
@@ -5,5 +5,5 @@ import 'spica/global'; | ||
export { El } from './src/proxy'; | ||
export { NS, Attrs, Children, Factory, shadow, frag, html, svg, text, element, define, defrag } from './src/util/dom'; | ||
export { NS, Attrs, Children, Factory, shadow, frag, html, svg, text, element, define, append, prepend, defrag } from './src/util/dom'; | ||
export { listen, delegate, bind, once, wait, currentTarget } from './src/util/listener'; | ||
export { apply } from './src/util/query'; | ||
export { querySelector, querySelectorAll } from './src/util/query'; | ||
export { identity } from './src/util/identity'; | ||
@@ -10,0 +10,0 @@ |
{ | ||
"name": "typed-dom", | ||
"version": "0.0.263", | ||
"version": "0.0.264", | ||
"description": "A value-level and type-level DOM builder.", | ||
@@ -34,2 +34,5 @@ "private": false, | ||
], | ||
"dependencies": { | ||
"typed-query-selector": "^2.6.1" | ||
}, | ||
"devDependencies": { | ||
@@ -63,3 +66,3 @@ "@types/benchmark": "2.1.1", | ||
"power-assert": "^1.6.1", | ||
"spica": "0.0.523", | ||
"spica": "0.0.524", | ||
"tsify": "^5.0.4", | ||
@@ -66,0 +69,0 @@ "typescript": "4.6.3", |
@@ -1,13 +0,13 @@ | ||
import { apply } from './query'; | ||
import { querySelector, querySelectorAll } from './query'; | ||
import { html } from './dom'; | ||
describe('Unit: util/query', () => { | ||
describe('apply', () => { | ||
describe('querySelector', () => { | ||
it('', () => { | ||
assert.deepStrictEqual( | ||
[...apply(html('div', [html('br'), html('br')]), 'br', {})].map(el => el.outerHTML), | ||
['<br>', '<br>']); | ||
querySelector(html('a', { id: '1' }, [html('a', { id: '2' })]), ':scope')?.id, | ||
'1'); | ||
assert.deepStrictEqual( | ||
[...apply(html('div', [html('br'), html('br')]), 'br:not([id])', { id: '' })].map(el => el.outerHTML), | ||
['<br id="">', '<br id="">']); | ||
querySelector(html('a', { id: '1' }, [html('a', { id: '2' })]), ':scope > a')?.id, | ||
'2'); | ||
}); | ||
@@ -17,2 +17,17 @@ | ||
describe('querySelectorAll', () => { | ||
it('', () => { | ||
assert.deepStrictEqual( | ||
querySelectorAll(html('a', { id: '1' }, [html('a', { id: '2' }), html('a', { id: '3' })]), ':scope').map(el => el.id), | ||
['1']); | ||
assert.deepStrictEqual( | ||
querySelectorAll(html('a', { id: '1' }, [html('a', { id: '2' }), html('a', { id: '3' })]), ':scope > a').map(el => el.id), | ||
['2', '3']); | ||
assert.deepStrictEqual( | ||
querySelectorAll(html('a', { id: '1' }, [html('a', { id: '2' }), html('a', { id: '3' })]), 'a').map(el => el.id), | ||
['1', '2', '3']); | ||
}); | ||
}); | ||
}); |
33
query.ts
@@ -1,12 +0,27 @@ | ||
import { Attrs, define } from './dom'; | ||
import type { ParseSelector } from 'typed-query-selector/parser'; | ||
export function apply<T extends keyof HTMLElementTagNameMap>(node: ParentNode, selector: T, attrs: Attrs): NodeListOf<HTMLElementTagNameMap[T]> | ||
export function apply<T extends keyof SVGElementTagNameMap>(node: ParentNode, selector: T, attrs: Attrs): NodeListOf<SVGElementTagNameMap[T]> | ||
export function apply<T extends Element = Element>(node: ParentNode, selector: string, attrs: Attrs): NodeListOf<T> | ||
export function apply<T extends Element = Element>(node: ParentNode, selector: string, attrs: Attrs): NodeListOf<T> { | ||
const ns = node.querySelectorAll<T>(selector); | ||
for (let i = 0, len = ns.length; i < len; ++i) { | ||
define(ns[i], attrs); | ||
export function querySelector<T extends keyof HTMLElementTagNameMap>(node: ParentNode, selector: T): HTMLElementTagNameMap[T] | null; | ||
export function querySelector<T extends keyof SVGElementTagNameMap>(node: ParentNode, selector: T): SVGElementTagNameMap[T] | null; | ||
export function querySelector<T extends string>(node: ParentNode, selector: T): ParseSelector<T>; | ||
export function querySelector<T extends Element = Element>(node: ParentNode, selector: string): T | null; | ||
export function querySelector(node: ParentNode | Element, selector: string): Element | null { | ||
return 'matches' in node && node.matches(selector) | ||
? node | ||
: node.querySelector(selector); | ||
} | ||
export function querySelectorAll<T extends keyof HTMLElementTagNameMap>(node: ParentNode, selector: T): HTMLElementTagNameMap[T][]; | ||
export function querySelectorAll<T extends keyof SVGElementTagNameMap>(node: ParentNode, selector: T): SVGElementTagNameMap[T][]; | ||
export function querySelectorAll<T extends string>(node: ParentNode, selector: T): ParseSelector<T>[]; | ||
export function querySelectorAll<T extends Element = Element>(node: ParentNode, selector: string): T[]; | ||
export function querySelectorAll(node: ParentNode | Element, selector: string): Element[] { | ||
const acc: Element[] = []; | ||
if ('matches' in node && node.matches(selector)) { | ||
acc.push(node); | ||
} | ||
return ns; | ||
const nodes = node.querySelectorAll(selector); | ||
for (let i = 0, len = nodes.length; i < len; ++i) { | ||
acc.push(nodes[i]); | ||
} | ||
return acc; | ||
} |
@@ -83,3 +83,3 @@ # typed-dom | ||
Custom elements will be defined by extending `ShadowHostHTMLElementTagNameMap`, `HTMLElementTagNameMap`, or `SVGElementTagNameMap` interface. | ||
Custom elements can be defined by extending `ShadowHostHTMLElementTagNameMap`, `HTMLElementTagNameMap`, or `SVGElementTagNameMap` interface. | ||
@@ -135,3 +135,3 @@ ```ts | ||
const registry = new CustomElementRegistry(); | ||
// This Host function creates a proxy and attaches its shadow root in the base document (light DOM). | ||
// This Host function creates a proxy and makes its shadow DOM in the base document (light DOM). | ||
export const Host = API<ShadowHostHTMLElementTagNameMap>(h, el => | ||
@@ -145,3 +145,3 @@ shadow(el, { mode: 'open', registry })); | ||
export const HTML = API<ScopedCustomHTMLElementTagNameMap>(html); | ||
// This Shadow function creates a proxy and attaches its shadow root in a shadow DOM. | ||
// This Shadow function creates a scoped custom element proxy and makes its shadow DOM in a shadow DOM. | ||
export const Shadow = API<ShadowHostScopedCustomHTMLElementTagNameMap>(html, shadow); | ||
@@ -163,2 +163,4 @@ ``` | ||
- define | ||
- append | ||
- prepend | ||
- defrag | ||
@@ -170,3 +172,4 @@ - listen | ||
- currentTarget | ||
- apply | ||
- querySelector | ||
- querySelectorAll | ||
@@ -173,0 +176,0 @@ ## Usage |
@@ -89,11 +89,11 @@ import { Symbol } from 'spica/global'; | ||
function isElChildren(param: Attrs | El.Children): param is El.Children { | ||
if (param === void 0) return false; | ||
if (param[Symbol.iterator]) return true; | ||
for (const name in param as Attrs | El.Children.Struct) { | ||
if (!hasOwnProperty(param, name)) continue; | ||
const value = param[name]; | ||
return !!value && typeof value === 'object'; | ||
function isElChildren(value: Attrs | El.Children): value is El.Children { | ||
if (value === void 0) return false; | ||
if (value[Symbol.iterator]) return true; | ||
for (const name in value as Attrs | El.Children.Struct) { | ||
if (!hasOwnProperty(value, name)) continue; | ||
const val = value[name]; | ||
return !!val && typeof val === 'object'; | ||
} | ||
return true; | ||
} |
@@ -33,2 +33,3 @@ import { Symbol, document } from 'spica/global'; | ||
SVG = 'SVG', | ||
MathML = 'MathML', | ||
} | ||
@@ -38,7 +39,7 @@ | ||
export type Attrs = Record<string, string | EventListener | null | undefined>; | ||
export type Children = Iterable<string | Node> | string; | ||
export type Children = Iterable<string | Node> | string | undefined; | ||
export interface Factory<M extends TagNameMap> { | ||
<T extends keyof M & string>(tag: T, children?: Children): M[T]; | ||
<T extends keyof M & string>(tag: T, attrs?: Attrs, children?: Children): M[T]; | ||
<T extends keyof M & string>(tag: T, attrs: Attrs | undefined, children?: Children): M[T]; | ||
} | ||
@@ -84,2 +85,3 @@ | ||
export function element<M extends SVGElementTagNameMap>(context: Document | ShadowRoot, ns: NS.SVG): Factory<M>; | ||
export function element<M extends TagNameMap>(context: Document | ShadowRoot, ns: NS.MathML): Factory<M>; | ||
export function element<M extends TagNameMap>(context: Document | ShadowRoot, ns: NS): Factory<M> { | ||
@@ -106,2 +108,4 @@ const cache = memoize(elem, (_, ns, tag) => `${ns}:${tag}`); | ||
return context.createElementNS('http://www.w3.org/2000/svg', tag); | ||
case NS.MathML: | ||
return context.createElementNS('http://www.w3.org/1998/Math/MathML', tag); | ||
} | ||
@@ -112,8 +116,8 @@ } | ||
export function define<T extends Element | DocumentFragment | ShadowRoot>(node: T, children?: Children): T; | ||
export function define<T extends Element>(node: T, attrs?: Attrs | Children, children?: Children): T { | ||
export function define<T extends Element | DocumentFragment | ShadowRoot>(node: T, attrs?: Attrs | Children, children?: Children): T { | ||
return isChildren(attrs) | ||
? defineChildren(node, attrs) | ||
: defineChildren(defineAttrs(node, attrs), children); | ||
: defineChildren(defineAttrs(node as Element, attrs) as T, children); | ||
} | ||
function defineAttrs<T extends Element>(el: T, attrs?: Attrs): T { | ||
function defineAttrs<T extends Element>(el: T, attrs: Attrs): T { | ||
if (!attrs) return el; | ||
@@ -154,3 +158,3 @@ for (const name in attrs) { | ||
} | ||
function defineChildren<T extends ParentNode & Node>(node: T, children?: Children): T { | ||
function defineChildren<T extends ParentNode & Node>(node: T, children: Children): T { | ||
if (children === void 0) return node; | ||
@@ -173,6 +177,36 @@ if (typeof children === 'string') { | ||
export function isChildren(param: Attrs | Children | ShadowRootInit | undefined): param is Children { | ||
return !!param?.[Symbol.iterator]; | ||
export function isChildren(value: Attrs | Children | ShadowRootInit): value is Children { | ||
return !!value?.[Symbol.iterator]; | ||
} | ||
export function append<T extends ParentNode & Node>(node: T, children: Children): T { | ||
if (children === void 0) return node; | ||
if (typeof children === 'string') { | ||
node.append(children); | ||
} | ||
else { | ||
for (const child of children) { | ||
typeof child === 'object' | ||
? node.appendChild(child) | ||
: node.append(child); | ||
} | ||
} | ||
return node; | ||
} | ||
export function prepend<T extends ParentNode & Node>(node: T, children: Children): T { | ||
if (children === void 0) return node; | ||
if (typeof children === 'string') { | ||
node.prepend(children); | ||
} | ||
else { | ||
for (const child of children) { | ||
typeof child === 'object' | ||
? node.insertBefore(child, null) | ||
: node.prepend(child); | ||
} | ||
} | ||
return node; | ||
} | ||
export function defrag<T extends Node | string>(nodes: ArrayLike<T>): T[]; | ||
@@ -179,0 +213,0 @@ export function defrag(nodes: ArrayLike<Node | string>): (Node | string)[] { |
@@ -1,13 +0,13 @@ | ||
import { apply } from './query'; | ||
import { querySelector, querySelectorAll } from './query'; | ||
import { html } from './dom'; | ||
describe('Unit: util/query', () => { | ||
describe('apply', () => { | ||
describe('querySelector', () => { | ||
it('', () => { | ||
assert.deepStrictEqual( | ||
[...apply(html('div', [html('br'), html('br')]), 'br', {})].map(el => el.outerHTML), | ||
['<br>', '<br>']); | ||
querySelector(html('a', { id: '1' }, [html('a', { id: '2' })]), ':scope')?.id, | ||
'1'); | ||
assert.deepStrictEqual( | ||
[...apply(html('div', [html('br'), html('br')]), 'br:not([id])', { id: '' })].map(el => el.outerHTML), | ||
['<br id="">', '<br id="">']); | ||
querySelector(html('a', { id: '1' }, [html('a', { id: '2' })]), ':scope > a')?.id, | ||
'2'); | ||
}); | ||
@@ -17,2 +17,17 @@ | ||
describe('querySelectorAll', () => { | ||
it('', () => { | ||
assert.deepStrictEqual( | ||
querySelectorAll(html('a', { id: '1' }, [html('a', { id: '2' }), html('a', { id: '3' })]), ':scope').map(el => el.id), | ||
['1']); | ||
assert.deepStrictEqual( | ||
querySelectorAll(html('a', { id: '1' }, [html('a', { id: '2' }), html('a', { id: '3' })]), ':scope > a').map(el => el.id), | ||
['2', '3']); | ||
assert.deepStrictEqual( | ||
querySelectorAll(html('a', { id: '1' }, [html('a', { id: '2' }), html('a', { id: '3' })]), 'a').map(el => el.id), | ||
['1', '2', '3']); | ||
}); | ||
}); | ||
}); |
@@ -1,12 +0,27 @@ | ||
import { Attrs, define } from './dom'; | ||
import type { ParseSelector } from 'typed-query-selector/parser'; | ||
export function apply<T extends keyof HTMLElementTagNameMap>(node: ParentNode, selector: T, attrs: Attrs): NodeListOf<HTMLElementTagNameMap[T]> | ||
export function apply<T extends keyof SVGElementTagNameMap>(node: ParentNode, selector: T, attrs: Attrs): NodeListOf<SVGElementTagNameMap[T]> | ||
export function apply<T extends Element = Element>(node: ParentNode, selector: string, attrs: Attrs): NodeListOf<T> | ||
export function apply<T extends Element = Element>(node: ParentNode, selector: string, attrs: Attrs): NodeListOf<T> { | ||
const ns = node.querySelectorAll<T>(selector); | ||
for (let i = 0, len = ns.length; i < len; ++i) { | ||
define(ns[i], attrs); | ||
export function querySelector<T extends keyof HTMLElementTagNameMap>(node: ParentNode, selector: T): HTMLElementTagNameMap[T] | null; | ||
export function querySelector<T extends keyof SVGElementTagNameMap>(node: ParentNode, selector: T): SVGElementTagNameMap[T] | null; | ||
export function querySelector<T extends string>(node: ParentNode, selector: T): ParseSelector<T>; | ||
export function querySelector<T extends Element = Element>(node: ParentNode, selector: string): T | null; | ||
export function querySelector(node: ParentNode | Element, selector: string): Element | null { | ||
return 'matches' in node && node.matches(selector) | ||
? node | ||
: node.querySelector(selector); | ||
} | ||
export function querySelectorAll<T extends keyof HTMLElementTagNameMap>(node: ParentNode, selector: T): HTMLElementTagNameMap[T][]; | ||
export function querySelectorAll<T extends keyof SVGElementTagNameMap>(node: ParentNode, selector: T): SVGElementTagNameMap[T][]; | ||
export function querySelectorAll<T extends string>(node: ParentNode, selector: T): ParseSelector<T>[]; | ||
export function querySelectorAll<T extends Element = Element>(node: ParentNode, selector: string): T[]; | ||
export function querySelectorAll(node: ParentNode | Element, selector: string): Element[] { | ||
const acc: Element[] = []; | ||
if ('matches' in node && node.matches(selector)) { | ||
acc.push(node); | ||
} | ||
return ns; | ||
const nodes = node.querySelectorAll(selector); | ||
for (let i = 0, len = nodes.length; i < len; ++i) { | ||
acc.push(nodes[i]); | ||
} | ||
return acc; | ||
} |
@@ -1,2 +0,2 @@ | ||
import { API, Shadow, HTML, SVG, NS, shadow, frag, html, svg, text, element, define, defrag, listen, once, wait, bind, delegate, currentTarget, apply, identity } from '../..'; | ||
import { API, Shadow, HTML, SVG, NS, shadow, frag, html, svg, text, element, define, append, prepend, defrag, listen, once, wait, bind, delegate, currentTarget, querySelector, querySelectorAll, identity } from '../..'; | ||
@@ -58,2 +58,10 @@ describe('Interface: Package', function () { | ||
it('append', function () { | ||
assert(typeof append === 'function'); | ||
}); | ||
it('prepend', function () { | ||
assert(typeof prepend === 'function'); | ||
}); | ||
it('defrag', function () { | ||
@@ -87,6 +95,10 @@ assert(typeof defrag === 'function'); | ||
it('apply', function () { | ||
assert(typeof apply === 'function'); | ||
it('querySelector', function () { | ||
assert(typeof querySelector === 'function'); | ||
}); | ||
it('querySelectorAll', function () { | ||
assert(typeof querySelectorAll === 'function'); | ||
}); | ||
it('identity', function () { | ||
@@ -93,0 +105,0 @@ assert(typeof identity === 'function'); |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
672592
15827
381
1
+ Addedtyped-query-selector@^2.6.1
+ Addedtyped-query-selector@2.12.0(transitive)