Last active
April 21, 2024 22:58
-
-
Save nyteshade/31b3a6b3a84fb4f8304b0c685bac9616 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function() { | |
const HTML = new Proxy( | |
class HTML { | |
static create( | |
name, | |
content, | |
style = {}, | |
attributes = {}, | |
webComponentName = undefined, | |
useDocument = undefined, | |
children = [] | |
) { | |
const params = [ | |
'name', 'style', 'attributes', 'webComponentName', 'content', | |
'useDocument', 'children', | |
]; | |
let _opts = ( | |
// Check to see if we have individual parameters or a config object | |
// they would be in content and content must be a non null object type | |
// it must also contain any of the parameters by name. | |
(typeof content === 'object' && content) && | |
params.some(param => Reflect.has(content ?? {}, param)) | |
// we have a config object; what was passed to the content parameter is it | |
? content | |
// we have individual parameters, make a config object from them | |
: { | |
style, attributes, content: (Array.isArray(content) ? undefined : content), webComponentName, useDocument, children: Array.isArray(content) ? content : children | |
} | |
); | |
// Validate each parameter is in a usable state for going forward with | |
// defaults for unsuplied values | |
Object.assign(_opts, { | |
style: _opts.style ?? {}, | |
attributes: _opts.attributes ?? {}, | |
content: _opts.content, | |
webComponentName: _opts.webComponentName, | |
useDocument: _opts.useDocument ?? top.document, | |
children: _opts.children ?? [] | |
}) | |
const doc = _opts.useDocument; | |
const options = _opts.webComponentName ? { is: _opts.webComponentName } : undefined; | |
const element = doc.createElement(name, options); | |
for (let [key, value] of Object.entries(_opts.attributes ?? {})) { | |
const attr = doc.createAttribute(key); | |
attr.value = value; | |
element.setAttributeNode(attr); | |
} | |
for (let [key, value] of Object.entries(_opts.style ?? {})) { | |
element.style[key] = value; | |
} | |
// avoid this for non-text values | |
if (_opts.content) { | |
element.append(doc.createTextNode(_opts.content)); | |
} | |
for (const child of _opts.children) { | |
element.append(child); | |
} | |
return element; | |
} | |
}, | |
{ | |
get(target, property, receiver) { | |
if (typeof property === 'string' && property !== 'create') { | |
return HTML.create.bind(HTML, property); | |
} | |
return Reflect.get(target, property, receiver); | |
} | |
} | |
); | |
globalThis['HTML'] = HTML; | |
})() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This allows a short hand creation of HTML createElement objects with little markup such as
Note that
HTML.<tag-name>(...)
is possible through the use ofProxy
andFunction.bind()
. It actually does the following:Defaults are applied as expected