@gjsify/domparser 0.59.1 → 0.61.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -0
- package/lib/esm/dom/element.js +1 -1
- package/lib/esm/xml/parse-xml.js +1 -1
- package/lib/types/dom/element.d.ts +19 -0
- package/lib/types/namespaces.spec.d.ts +2 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -35,6 +35,17 @@ console.log(map.documentElement?.getAttribute('width'));
|
|
|
35
35
|
console.log(map.querySelectorAll('layer > data').length);
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
+
### XML namespaces
|
|
39
|
+
|
|
40
|
+
The XML scanner resolves `xmlns` and `xmlns:p` while it parses, so a document is read by namespace and local name, not by whichever prefix a server picked:
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
const doc = new DOMParser().parseFromString(multistatus, 'application/xml');
|
|
44
|
+
for (const href of doc.getElementsByTagNameNS('DAV:', 'href')) console.log(href.textContent);
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`namespaceURI` and `prefix` are on every element; `localName` of `<D:href>` is `href`. `getElementsByTagNameNS(ns, local)` takes `'*'` for either argument and `null` for "no namespace". An undeclared prefix resolves to `null`, and so does every HTML element — the HTML tree builder has no foreign content. The frozen `tagName` / `nodeName` spellings are unchanged.
|
|
48
|
+
|
|
38
49
|
### What the HTML mode gives you
|
|
39
50
|
|
|
40
51
|
- implicit `html`/`head`/`body`, the void-element set, the implied-end-tag table, table sections, `<template>` content as a fragment, EOF auto-close;
|
package/lib/esm/dom/element.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"../_virtual/_rolldown/runtime.js";import{DOMNode as e}from"./node.js";import{HTML_ADAPTER as t,XML_ADAPTER as n}from"../dom-adapter.js";import{quoteSelectorString as r}from"../selectors/parse.js";import{closestSelector as i,matchesSelector as a,selectAll as o,selectOne as s}from"../selectors/query.js";import"../selectors/index.js";import{serializeInner as c,serializeOuter as l}from"./serialize.js";var DOMElement=class extends e{tagName;localName;content;_html;_attrs=new Map;constructor(e,t=!1){let n=e.toLowerCase();super(1,t?n.toUpperCase():e.toUpperCase()),this.localName=n,this.tagName=t?n.toUpperCase():n,this._html=t}get id(){return this._attrs.get(`id`)??``}get className(){return this._attrs.get(`class`)??``}get parentElement(){let e=this.parentNode;return e!==null&&e.nodeType===1?e:null}get firstElementChild(){return this.children[0]??null}get lastElementChild(){let e=this.children;return e[e.length-1]??null}get nextElementSibling(){return this._sibling(1)}get previousElementSibling(){return this._sibling(-1)}_sibling(e){let t=this.parentNode;if(t===null)return null;let n=t.childNodes;for(let t=n.indexOf(this)+e;t>=0&&t<n.length;t+=e)if(n[t].nodeType===1)return n[t];return null}get children(){return this.childNodes.filter(e=>e.nodeType===1)}getAttribute(e){return this._attrs.has(e)?this._attrs.get(e)??null:null}setAttribute(e,t){this._attrs.set(e,t)}hasAttribute(e){return this._attrs.has(e)}get attributes(){return Array.from(this._attrs.entries()).map(([e,t])=>({name:e,value:t}))}get innerHTML(){return c(this,this._html)}get outerHTML(){return l(this,this._html)}_adapter(){return this._html?t:n}querySelector(e){return s(e,this,this._adapter())}querySelectorAll(e){return o(e,this,this._adapter())}matches(e){return a(e,this,this._adapter())}closest(e){return i(e,this,this._adapter())}getElementsByClassName(e){let t=e.trim().split(/\s+/).filter(e=>e!==``);return t.length===0?[]:this.querySelectorAll(t.map(e=>`[class~=`+r(e)+`]`).join(``))}};export{DOMElement};
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";import{DOMNode as e}from"./node.js";import{HTML_ADAPTER as t,XML_ADAPTER as n}from"../dom-adapter.js";import{quoteSelectorString as r}from"../selectors/parse.js";import{closestSelector as i,matchesSelector as a,selectAll as o,selectOne as s}from"../selectors/query.js";import"../selectors/index.js";import{serializeInner as c,serializeOuter as l}from"./serialize.js";var DOMElement=class extends e{tagName;localName;namespaceURI=null;prefix=null;content;_html;_attrs=new Map;constructor(e,t=!1){let n=e.toLowerCase();super(1,t?n.toUpperCase():e.toUpperCase()),this.localName=n,this.tagName=t?n.toUpperCase():n,this._html=t}get id(){return this._attrs.get(`id`)??``}get className(){return this._attrs.get(`class`)??``}get parentElement(){let e=this.parentNode;return e!==null&&e.nodeType===1?e:null}get firstElementChild(){return this.children[0]??null}get lastElementChild(){let e=this.children;return e[e.length-1]??null}get nextElementSibling(){return this._sibling(1)}get previousElementSibling(){return this._sibling(-1)}_sibling(e){let t=this.parentNode;if(t===null)return null;let n=t.childNodes;for(let t=n.indexOf(this)+e;t>=0&&t<n.length;t+=e)if(n[t].nodeType===1)return n[t];return null}get children(){return this.childNodes.filter(e=>e.nodeType===1)}getAttribute(e){return this._attrs.has(e)?this._attrs.get(e)??null:null}setAttribute(e,t){this._attrs.set(e,t)}hasAttribute(e){return this._attrs.has(e)}get attributes(){return Array.from(this._attrs.entries()).map(([e,t])=>({name:e,value:t}))}get innerHTML(){return c(this,this._html)}get outerHTML(){return l(this,this._html)}_adapter(){return this._html?t:n}querySelector(e){return s(e,this,this._adapter())}querySelectorAll(e){return o(e,this,this._adapter())}matches(e){return a(e,this,this._adapter())}closest(e){return i(e,this,this._adapter())}getElementsByTagNameNS(e,t){let n=t.toLowerCase(),r=[],visit=t=>{for(let i of t.childNodes){if(i.nodeType!==1)continue;let t=i;(e===`*`||t.namespaceURI===e)&&(n===`*`||t.localName===n)&&r.push(t),visit(t)}};return visit(this),r}getElementsByClassName(e){let t=e.trim().split(/\s+/).filter(e=>e!==``);return t.length===0?[]:this.querySelectorAll(t.map(e=>`[class~=`+r(e)+`]`).join(``))}};export{DOMElement};
|
package/lib/esm/xml/parse-xml.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"../_virtual/_rolldown/runtime.js";import{DOMNode as e}from"../dom/node.js";import{DOMComment as t}from"../dom/comment.js";import{DOMElement as n}from"../dom/element.js";import{DOMDocument as r}from"../dom/document.js";import{DOMDocumentType as i}from"../dom/doctype.js";import{decodeXml as a}from"../entities/decode.js";const o=/\s+([\w:.-]+)\s*=\s*(?:"([^"]*)"|'([^']*)'|(\S+))/g;function asciiLower(e){return e.replace(/[A-Z]+/g,e=>e.toLowerCase())}function parseAttributes(e,t){let n;for(o.lastIndex=0;(n=o.exec(e))!==null;)t.setAttribute(n[1],a(n[2]??n[3]??n[4]??``))}function parseXml(o){let s=new r,c=[s],l=
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";import{DOMNode as e}from"../dom/node.js";import{DOMComment as t}from"../dom/comment.js";import{DOMElement as n}from"../dom/element.js";import{DOMDocument as r}from"../dom/document.js";import{DOMDocumentType as i}from"../dom/doctype.js";import{decodeXml as a}from"../entities/decode.js";const o=/\s+([\w:.-]+)\s*=\s*(?:"([^"]*)"|'([^']*)'|(\S+))/g;function asciiLower(e){return e.replace(/[A-Z]+/g,e=>e.toLowerCase())}function openScope(e,t){let n=null;for(let{name:r,value:i}of t.attributes){let t=r===`xmlns`?``:r.startsWith(`xmlns:`)?r.slice(6):null;t!==null&&(n??=new Map(e),n.set(t,i))}return n??e}function applyName(e,t,n){let r=t.indexOf(`:`),i=r>0?t.slice(0,r):null;i!==null&&(e.prefix=i,e.localName=t.slice(r+1).toLowerCase()),e.namespaceURI=n.get(i??``)||null}function parseAttributes(e,t){let n;for(o.lastIndex=0;(n=o.exec(e))!==null;)t.setAttribute(n[1],a(n[2]??n[3]??n[4]??``))}function parseXml(o){let s=new r,c=[s],l=[new Map([[`xml`,`http://www.w3.org/XML/1998/namespace`]])],u=0,d=o.length;for(;u<d;){let r=o.indexOf(`<`,u);if(r===-1){let t=o.slice(u);if(t.trim()){let n=new e(3,`#text`,a(t)),r=c[c.length-1];n.parentNode=r,r.childNodes.push(n)}break}if(r>u){let t=o.slice(u,r);if(t.trim()){let n=new e(3,`#text`,a(t)),r=c[c.length-1];n.parentNode=r,r.childNodes.push(n)}}if(o.startsWith(`<![CDATA[`,r)){let t=o.indexOf(`]]>`,r);if(t===-1)break;let n=new e(4,`#cdata-section`,o.slice(r+9,t)),i=c[c.length-1];n.parentNode=i,i.childNodes.push(n),u=t+3;continue}if(o.startsWith(`<!--`,r)){let e=o.indexOf(`-->`,r),n=new t(o.slice(r+4,e===-1?d:e)),i=c[c.length-1];n.parentNode=i,i.childNodes.push(n),u=e===-1?d:e+3;continue}if(asciiLower(o.slice(r,r+9))===`<!doctype`){let e=findTagEnd(o,r+9),t=new i(o.slice(r+9,e===-1?d:e).trim().split(/[\s[]/)[0]??``,``,``);t.parentNode=s,s.childNodes.push(t),u=e===-1?d:e+1;continue}if(o.startsWith(`<?`,r)||o.startsWith(`<!`,r)){let e=o.indexOf(`>`,r);u=e===-1?d:e+1;continue}let f=findTagEnd(o,r+1);if(f===-1)break;let p=o.slice(r+1,f);if(p.startsWith(`/`)){c.length>1&&(c.pop(),l.pop()),u=f+1;continue}let m=p.endsWith(`/`),h=m?p.slice(0,-1):p,g=h.search(/\s/),_=(g===-1?h:h.slice(0,g)).trim();if(!_){u=f+1;continue}let v=new n(_);g!==-1&&parseAttributes(h.slice(g),v);let y=openScope(l[l.length-1],v);applyName(v,_,y);let b=c[c.length-1];v.parentNode=b,b.childNodes.push(v),b===s&&!s.documentElement&&(s.documentElement=v),m||(c.push(v),l.push(y)),u=f+1}return s}function findTagEnd(e,t){let n=!1,r=!1;for(let i=t;i<e.length;i++){let t=e[i];if(t===`"`&&!n){r=!r;continue}if(t===`'`&&!r){n=!n;continue}if(t===`>`&&!n&&!r)return i}return-1}export{parseXml};
|
|
@@ -9,7 +9,20 @@ export declare class DOMElement extends DOMNode {
|
|
|
9
9
|
* `src/xml-shape.spec.ts` fails if it moves.
|
|
10
10
|
*/
|
|
11
11
|
tagName: string;
|
|
12
|
+
/**
|
|
13
|
+
* The name without its prefix, folded to lower case like `tagName` (a
|
|
14
|
+
* prefixed XML element reports `multistatus` for `<D:multistatus>`).
|
|
15
|
+
*/
|
|
12
16
|
localName: string;
|
|
17
|
+
/**
|
|
18
|
+
* XML only: what the element's prefix — or the default `xmlns` — resolved to
|
|
19
|
+
* where it was parsed; `null` for an element in no namespace, an undeclared
|
|
20
|
+
* prefix, and EVERY HTML element (the tree builder has no foreign content,
|
|
21
|
+
* ADR 0026, so it cannot tell an SVG child from an HTML one).
|
|
22
|
+
*/
|
|
23
|
+
namespaceURI: string | null;
|
|
24
|
+
/** XML only: the prefix as written (`D` for `<D:multistatus>`), else `null`. */
|
|
25
|
+
prefix: string | null;
|
|
13
26
|
/** `<template>` holds its children here, never in `childNodes`. */
|
|
14
27
|
content?: DOMDocumentFragment;
|
|
15
28
|
/**
|
|
@@ -43,6 +56,12 @@ export declare class DOMElement extends DOMNode {
|
|
|
43
56
|
querySelectorAll(selector: string): DOMElement[];
|
|
44
57
|
matches(selector: string): boolean;
|
|
45
58
|
closest(selector: string): DOMElement | null;
|
|
59
|
+
/**
|
|
60
|
+
* Descendants (not the element itself) in document order. `'*'` matches any
|
|
61
|
+
* namespace or any name; `null` matches an element in no namespace. Local
|
|
62
|
+
* names are compared the way `localName` is stored, i.e. ASCII-folded.
|
|
63
|
+
*/
|
|
64
|
+
getElementsByTagNameNS(namespaceURI: string | null, localName: string): DOMElement[];
|
|
46
65
|
/** A space-separated list, and EVERY name in it has to be present. */
|
|
47
66
|
getElementsByClassName(names: string): DOMElement[];
|
|
48
67
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gjsify/domparser",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.61.0",
|
|
4
4
|
"description": "DOMParser for GJS — HTML5 parser, XML scanner, CSS Selectors 4 engine and the full entity table, dependency-free",
|
|
5
5
|
"module": "lib/esm/index.js",
|
|
6
6
|
"types": "lib/types/index.d.ts",
|
|
@@ -64,8 +64,8 @@
|
|
|
64
64
|
"web-api"
|
|
65
65
|
],
|
|
66
66
|
"devDependencies": {
|
|
67
|
-
"@gjsify/cli": "^0.
|
|
68
|
-
"@gjsify/unit": "^0.
|
|
67
|
+
"@gjsify/cli": "^0.61.0",
|
|
68
|
+
"@gjsify/unit": "^0.61.0",
|
|
69
69
|
"@types/node": "^25.9.2",
|
|
70
70
|
"typescript": "^6.0.3"
|
|
71
71
|
},
|