New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

ultrahtml

Package Overview
Dependencies
Maintainers
1
Versions
34
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ultrahtml - npm Package Compare versions

Comparing version 0.2.1 to 0.3.0

dist/index.js.map

26

CHANGELOG.md
# ultrahtml
## 0.3.0
### Minor Changes
- 2de70f3: Add `ultrahtml/selector` module which exports `querySelector`, `querySelectorAll`, and `matches` functions.
To use `querySelectorAll`, pass the root `Node` as the first argument and any valid CSS selector as the second argument. Note that if a CSS selector you need is not yet implemented, you are invited to [open an issue](https://github.com/natemoo-re/ultrahtml/issues).
```js
import { parse } from "ultrahtml";
import { querySelectorAll, matches } from "ultrahtml/selector";
const doc = parse(`
<html>
<head>
<title>Demo</title>
/head>
<body>
<h1>Hello world!</h1>
</body>
</html>
`);
const h1 = querySelector(doc, "h1");
const match = matches(h1, "h1");
```
## 0.2.1

@@ -4,0 +30,0 @@

388

dist/index.js

@@ -1,387 +0,1 @@

"use strict";
export const DOCUMENT_NODE = 0;
export const ELEMENT_NODE = 1;
export const TEXT_NODE = 2;
export const COMMENT_NODE = 3;
export const DOCTYPE_NODE = 4;
const VOID_TAGS = { img: 1, br: 1, hr: 1, meta: 1, link: 1, base: 1, input: 1 };
const SPLIT_ATTRS_RE = /([\@\.a-z0-9_\:\-]*)\s*?=?\s*?(['"]?)(.*?)\2\s+/gim;
const DOM_PARSER_RE = /(?:<(\/?)([a-zA-Z][a-zA-Z0-9\:-]*)(?:\s([^>]*?))?((?:\s*\/)?)>|(<\!\-\-)([\s\S]*?)(\-\->)|(<\!)([\s\S]*?)(>))/gm;
function splitAttrs(str) {
let obj = {};
let token;
if (str) {
SPLIT_ATTRS_RE.lastIndex = 0;
str = " " + (str || "") + " ";
while (token = SPLIT_ATTRS_RE.exec(str)) {
if (token[0] === " ")
continue;
obj[token[1]] = token[3];
}
}
return obj;
}
export function parse(input) {
let str = typeof input === "string" ? input : input.value;
let doc, parent, token, text, i, bStart, bText, bEnd, tag;
const tags = [];
DOM_PARSER_RE.lastIndex = 0;
parent = doc = {
type: DOCUMENT_NODE,
children: []
};
let lastIndex = 0;
function commitTextNode() {
text = str.substring(lastIndex, DOM_PARSER_RE.lastIndex - token[0].length);
if (text) {
parent.children.push({
type: TEXT_NODE,
value: text,
parent
});
}
}
while (token = DOM_PARSER_RE.exec(str)) {
bStart = token[5] || token[8];
bText = token[6] || token[9];
bEnd = token[7] || token[10];
if (bStart === "<!--") {
i = DOM_PARSER_RE.lastIndex - token[0].length;
tag = {
type: COMMENT_NODE,
value: bText,
parent,
loc: [
{
start: i,
end: i + bStart.length
},
{
start: DOM_PARSER_RE.lastIndex - bEnd.length,
end: DOM_PARSER_RE.lastIndex
}
]
};
tags.push(tag);
tag.parent.children.push(tag);
} else if (bStart === "<!") {
i = DOM_PARSER_RE.lastIndex - token[0].length;
tag = {
type: DOCTYPE_NODE,
value: bText,
parent,
loc: [
{
start: i,
end: i + bStart.length
},
{
start: DOM_PARSER_RE.lastIndex - bEnd.length,
end: DOM_PARSER_RE.lastIndex
}
]
};
tags.push(tag);
tag.parent.children.push(tag);
} else if (token[1] !== "/") {
commitTextNode();
tag = {
type: ELEMENT_NODE,
name: token[2] + "",
attributes: splitAttrs(token[3]),
parent,
children: [],
loc: [
{
start: DOM_PARSER_RE.lastIndex - token[0].length,
end: DOM_PARSER_RE.lastIndex
}
]
};
tags.push(tag);
tag.parent.children.push(tag);
if (token[4] && token[4].indexOf("/") > -1 || VOID_TAGS.hasOwnProperty(tag.name)) {
tag.loc[1] = tag.loc[0];
tag.isSelfClosingTag = true;
} else {
parent = tag;
}
} else {
commitTextNode();
if (token[2] + "" === parent.name) {
tag = parent;
parent = tag.parent;
tag.loc.push({
start: DOM_PARSER_RE.lastIndex - token[0].length,
end: DOM_PARSER_RE.lastIndex
});
text = str.substring(tag.loc[0].end, tag.loc[1].start);
if (tag.children.length === 0) {
tag.children.push({
type: TEXT_NODE,
value: text,
parent
});
}
} else if (token[2] + "" === tags[tags.length - 1].name && tags[tags.length - 1].isSelfClosingTag === true) {
tag = tags[tags.length - 1];
tag.loc.push({
start: DOM_PARSER_RE.lastIndex - token[0].length,
end: DOM_PARSER_RE.lastIndex
});
}
}
lastIndex = DOM_PARSER_RE.lastIndex;
}
text = str.slice(lastIndex);
parent.children.push({
type: TEXT_NODE,
value: text,
parent
});
return doc;
}
class Walker {
constructor(callback) {
this.callback = callback;
}
async visit(node, parent, index) {
await this.callback(node, parent, index);
if (Array.isArray(node.children)) {
let promises = [];
for (let i = 0; i < node.children.length; i++) {
const child = node.children[i];
promises.push(this.visit(child, node, i));
}
await Promise.all(promises);
}
}
}
class WalkerSync {
constructor(callback) {
this.callback = callback;
}
visit(node, parent, index) {
this.callback(node, parent, index);
if (Array.isArray(node.children)) {
for (let i = 0; i < node.children.length; i++) {
const child = node.children[i];
this.visit(child, node, i);
}
}
}
}
const HTMLString = Symbol("HTMLString");
const AttrString = Symbol("AttrString");
function mark(str, tags = [HTMLString]) {
const v = { value: str };
for (const tag of tags) {
Object.defineProperty(v, tag, {
value: true,
enumerable: false,
writable: false
});
}
return v;
}
export function __unsafeHTML(str) {
return mark(str);
}
const ESCAPE_CHARS = {
"&": "&amp;",
"<": "&lt;",
">": "&gt;"
};
function escapeHTML(str) {
return str.replace(/[&<>]/g, (c) => ESCAPE_CHARS[c] || c);
}
export function attrs(attributes) {
let attrStr = "";
for (const [key, value] of Object.entries(attributes)) {
attrStr += ` ${key}="${value}"`;
}
return mark(attrStr, [HTMLString, AttrString]);
}
export function html(tmpl, ...vals) {
let buf = "";
for (let i = 0; i < tmpl.length; i++) {
buf += tmpl[i];
const expr = vals[i];
if (buf.endsWith("...") && expr && typeof expr === "object") {
buf = buf.slice(0, -3).trimEnd();
buf += attrs(expr).value;
} else if (expr && expr[AttrString]) {
buf = buf.trimEnd();
buf += expr.value;
} else if (expr && expr[HTMLString]) {
buf += expr.value;
} else if (typeof expr === "string") {
buf += escapeHTML(expr);
} else if (expr || expr === 0) {
buf += String(expr);
}
}
return mark(buf);
}
export function walk(node, callback) {
const walker = new Walker(callback);
return walker.visit(node);
}
export function walkSync(node, callback) {
const walker = new WalkerSync(callback);
return walker.visit(node);
}
function resolveSantizeOptions({
components = {},
sanitize = true
}) {
var _a;
if (sanitize === true) {
return {
allowElements: Object.keys(components),
dropElements: ["script"],
allowComponents: false,
allowCustomElements: false,
allowComments: false
};
} else if (sanitize === false) {
return {
dropElements: [],
allowComponents: true,
allowCustomElements: true,
allowComments: true
};
} else {
const dropElements = /* @__PURE__ */ new Set([]);
if (!((_a = sanitize.allowElements) == null ? void 0 : _a.includes("script"))) {
dropElements.add("script");
}
for (const dropElement of sanitize.dropElements ?? []) {
dropElements.add(dropElement);
}
return {
allowComponents: false,
allowCustomElements: false,
allowComments: false,
...sanitize,
allowElements: [
...Object.keys(components),
...sanitize.allowElements ?? []
],
dropElements: Array.from(dropElements)
};
}
}
function getNodeType(node) {
if (node.name.includes("-"))
return "custom-element";
if (/[\_\$A-Z]/.test(node.name[0]) || node.name.includes("."))
return "component";
return "element";
}
function getAction(name, type, sanitize) {
var _a, _b, _c;
if (((_a = sanitize.allowElements) == null ? void 0 : _a.length) > 0) {
if (sanitize.allowElements.includes(name))
return "allow";
}
if (((_b = sanitize.blockElements) == null ? void 0 : _b.length) > 0) {
if (sanitize.blockElements.includes(name))
return "block";
}
if (((_c = sanitize.dropElements) == null ? void 0 : _c.length) > 0) {
if (sanitize.dropElements.find((n) => n === name))
return "drop";
}
if (type === "component" && !sanitize.allowComponents)
return "drop";
if (type === "custom-element" && !sanitize.allowCustomElements)
return "drop";
return "allow";
}
function sanitizeAttributes(node, sanitize) {
var _a, _b, _c, _d, _e, _f;
const attrs2 = node.attributes;
for (const key of Object.keys(node.attributes)) {
if (((_a = sanitize.allowAttributes) == null ? void 0 : _a[key]) && ((_b = sanitize.allowAttributes) == null ? void 0 : _b[key].includes(node.name)) || ((_c = sanitize.allowAttributes) == null ? void 0 : _c[key].includes("*"))) {
continue;
}
if (((_d = sanitize.dropAttributes) == null ? void 0 : _d[key]) && ((_e = sanitize.dropAttributes) == null ? void 0 : _e[key].includes(node.name)) || ((_f = sanitize.dropAttributes) == null ? void 0 : _f[key].includes("*"))) {
delete attrs2[key];
}
}
return attrs2;
}
async function renderElement(node, opts) {
const type = getNodeType(node);
const { name } = node;
const action = getAction(
name,
type,
opts.sanitize
);
if (action === "drop")
return "";
if (action === "block")
return await Promise.all(
node.children.map((child) => render(child, opts))
).then((res) => res.join(""));
const component = opts.components[node.name];
if (typeof component === "string")
return renderElement({ ...node, name: component }, opts);
const attributes = sanitizeAttributes(
node,
opts.sanitize
);
if (typeof component === "function") {
const value = await component(
attributes,
mark(
await Promise.all(
node.children.map((child) => render(child, opts))
).then((res) => res.join(""))
)
);
if (value && value[HTMLString])
return value.value;
return escapeHTML(String(value));
}
if (VOID_TAGS.hasOwnProperty(name)) {
return `<${node.name}${attrs(attributes).value}>`;
}
return `<${node.name}${attrs(attributes).value}>${await Promise.all(
node.children.map((child) => render(child, opts))
).then((res) => res.join(""))}</${node.name}>`;
}
export async function render(node, opts = {}) {
const sanitize = resolveSantizeOptions(opts);
switch (node.type) {
case DOCUMENT_NODE: {
return Promise.all(
node.children.map((child) => render(child, opts))
).then((res) => res.join(""));
}
case ELEMENT_NODE:
return renderElement(node, {
components: opts.components ?? {},
sanitize
});
case TEXT_NODE: {
return `${node.value}`;
}
case COMMENT_NODE: {
if (sanitize.allowComments) {
return `<!--${node.value}-->`;
} else {
return "";
}
}
case DOCTYPE_NODE: {
return `<!${node.value}>`;
}
}
return "";
}
export async function transform(input, opts = {}) {
return render(parse(input), opts);
}
var I=0,P=1,M=2,$=3,j=4,O={img:1,br:1,hr:1,meta:1,link:1,base:1,input:1},w=/([\@\.a-z0-9_\:\-]*)\s*?=?\s*?(['"]?)(.*?)\2\s+/gim,c=/(?:<(\/?)([a-zA-Z][a-zA-Z0-9\:-]*)(?:\s([^>]*?))?((?:\s*\/)?)>|(<\!\-\-)([\s\S]*?)(\-\->)|(<\!)([\s\S]*?)(>))/gm;function S(t){let e={},r;if(t)for(w.lastIndex=0,t=" "+(t||"")+" ";r=w.exec(t);)r[0]!==" "&&(e[r[1]]=r[3]);return e}function A(t){let e=typeof t=="string"?t:t.value,r,l,n,o,a,i,p,u,s,d=[];c.lastIndex=0,l=r={type:0,children:[]};let h=0;function b(){o=e.substring(h,c.lastIndex-n[0].length),o&&l.children.push({type:2,value:o,parent:l})}for(;n=c.exec(e);)i=n[5]||n[8],p=n[6]||n[9],u=n[7]||n[10],i==="<!--"?(a=c.lastIndex-n[0].length,s={type:3,value:p,parent:l,loc:[{start:a,end:a+i.length},{start:c.lastIndex-u.length,end:c.lastIndex}]},d.push(s),s.parent.children.push(s)):i==="<!"?(a=c.lastIndex-n[0].length,s={type:4,value:p,parent:l,loc:[{start:a,end:a+i.length},{start:c.lastIndex-u.length,end:c.lastIndex}]},d.push(s),s.parent.children.push(s)):n[1]!=="/"?(b(),s={type:1,name:n[2]+"",attributes:S(n[3]),parent:l,children:[],loc:[{start:c.lastIndex-n[0].length,end:c.lastIndex}]},d.push(s),s.parent.children.push(s),n[4]&&n[4].indexOf("/")>-1||O.hasOwnProperty(s.name)?(s.loc[1]=s.loc[0],s.isSelfClosingTag=!0):l=s):(b(),n[2]+""===l.name?(s=l,l=s.parent,s.loc.push({start:c.lastIndex-n[0].length,end:c.lastIndex}),o=e.substring(s.loc[0].end,s.loc[1].start),s.children.length===0&&s.children.push({type:2,value:o,parent:l})):n[2]+""===d[d.length-1].name&&d[d.length-1].isSelfClosingTag===!0&&(s=d[d.length-1],s.loc.push({start:c.lastIndex-n[0].length,end:c.lastIndex}))),h=c.lastIndex;return o=e.slice(h),l.children.push({type:2,value:o,parent:l}),r}var E=class{constructor(e){this.callback=e}async visit(e,r,l){if(await this.callback(e,r,l),Array.isArray(e.children)){let n=[];for(let o=0;o<e.children.length;o++){let a=e.children[o];n.push(this.visit(a,e,o))}await Promise.all(n)}}},y=class{constructor(e){this.callback=e}visit(e,r,l){if(this.callback(e,r,l),Array.isArray(e.children))for(let n=0;n<e.children.length;n++){let o=e.children[n];this.visit(o,e,n)}}},f=Symbol("HTMLString"),T=Symbol("AttrString");function g(t,e=[f]){let r={value:t};for(let l of e)Object.defineProperty(r,l,{value:!0,enumerable:!1,writable:!1});return r}function L(t){return g(t)}var C={"&":"&amp;","<":"&lt;",">":"&gt;"};function x(t){return t.replace(/[&<>]/g,e=>C[e]||e)}function N(t){let e="";for(let[r,l]of Object.entries(t))e+=` ${r}="${l}"`;return g(e,[f,T])}function V(t,...e){let r="";for(let l=0;l<t.length;l++){r+=t[l];let n=e[l];r.endsWith("...")&&n&&typeof n=="object"?(r=r.slice(0,-3).trimEnd(),r+=N(n).value):n&&n[T]?(r=r.trimEnd(),r+=n.value):n&&n[f]?r+=n.value:typeof n=="string"?r+=x(n):(n||n===0)&&(r+=String(n))}return g(r)}function q(t,e){return new E(e).visit(t)}function H(t,e){return new y(e).visit(t)}function R({components:t={},sanitize:e=!0}){var r;if(e===!0)return{allowElements:Object.keys(t),dropElements:["script"],allowComponents:!1,allowCustomElements:!1,allowComments:!1};if(e===!1)return{dropElements:[],allowComponents:!0,allowCustomElements:!0,allowComments:!0};{let l=new Set([]);(r=e.allowElements)!=null&&r.includes("script")||l.add("script");for(let n of e.dropElements??[])l.add(n);return{allowComponents:!1,allowCustomElements:!1,allowComments:!1,...e,allowElements:[...Object.keys(t),...e.allowElements??[]],dropElements:Array.from(l)}}}function _(t){return t.name.includes("-")?"custom-element":/[\_\$A-Z]/.test(t.name[0])||t.name.includes(".")?"component":"element"}function D(t,e,r){var l,n,o;return((l=r.allowElements)==null?void 0:l.length)>0&&r.allowElements.includes(t)?"allow":((n=r.blockElements)==null?void 0:n.length)>0&&r.blockElements.includes(t)?"block":((o=r.dropElements)==null?void 0:o.length)>0&&r.dropElements.find(a=>a===t)||e==="component"&&!r.allowComponents||e==="custom-element"&&!r.allowCustomElements?"drop":"allow"}function k(t,e){var l,n,o,a,i,p;let r=t.attributes;for(let u of Object.keys(t.attributes))((l=e.allowAttributes)==null?void 0:l[u])&&((n=e.allowAttributes)==null?void 0:n[u].includes(t.name))||((o=e.allowAttributes)==null?void 0:o[u].includes("*"))||(((a=e.dropAttributes)==null?void 0:a[u])&&((i=e.dropAttributes)==null?void 0:i[u].includes(t.name))||((p=e.dropAttributes)==null?void 0:p[u].includes("*")))&&delete r[u];return r}async function v(t,e){let r=_(t),{name:l}=t,n=D(l,r,e.sanitize);if(n==="drop")return"";if(n==="block")return await Promise.all(t.children.map(i=>m(i,e))).then(i=>i.join(""));let o=e.components[t.name];if(typeof o=="string")return v({...t,name:o},e);let a=k(t,e.sanitize);if(typeof o=="function"){let i=await o(a,g(await Promise.all(t.children.map(p=>m(p,e))).then(p=>p.join(""))));return i&&i[f]?i.value:x(String(i))}return O.hasOwnProperty(l)?`<${t.name}${N(a).value}>`:`<${t.name}${N(a).value}>${await Promise.all(t.children.map(i=>m(i,e))).then(i=>i.join(""))}</${t.name}>`}async function m(t,e={}){let r=R(e);switch(t.type){case 0:return Promise.all(t.children.map(l=>m(l,e))).then(l=>l.join(""));case 1:return v(t,{components:e.components??{},sanitize:r});case 2:return`${t.value}`;case 3:return r.allowComments?`<!--${t.value}-->`:"";case 4:return`<!${t.value}>`}return""}async function X(t,e={}){return m(A(t),e)}export{$ as COMMENT_NODE,j as DOCTYPE_NODE,I as DOCUMENT_NODE,P as ELEMENT_NODE,M as TEXT_NODE,L as __unsafeHTML,N as attrs,V as html,A as parse,m as render,X as transform,q as walk,H as walkSync};
{
"name": "ultrahtml",
"type": "module",
"version": "0.2.1",
"version": "0.3.0",
"types": "./dist/index.d.ts",

@@ -15,2 +15,3 @@ "repository": {

"files": [
"selector.d.ts",
"dist",

@@ -21,2 +22,3 @@ "CHANGELOG.md"

".": "./dist/index.js",
"./selector": "./dist/selector.js",
"./dist/*": "./dist/*",

@@ -40,2 +42,5 @@ "./package.json": "./package.json"

"packageManager": "pnpm@7.6.0",
"dependencies": {
"parsel-js": "^1.0.2"
},
"devDependencies": {

@@ -50,3 +55,5 @@ "@changesets/cli": "^2.18.1",

"scripts": {
"build": "esbuild src/index.ts --target=node14 --outfile=dist/index.js && tsc -p .",
"build:index": "esbuild src/index.ts --bundle --format=esm --minify --sourcemap=external --target=node14 --outfile=dist/index.js",
"build:selector": "esbuild src/selector.ts --format=esm --minify --sourcemap=external --target=node14 --outfile=dist/selector.js",
"build": "pnpm run build:index && pnpm run build:selector && tsc -p .",
"lint": "prettier \"**/*.{js,ts,md}\"",

@@ -53,0 +60,0 @@ "test": "vitest"

@@ -12,2 +12,3 @@ # `ultrahtml`

- Handy `html` template utility
- `querySelector` and `querySelectorAll` support using `ultrahtml/selector`

@@ -14,0 +15,0 @@ #### `walk`

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc