diff --git a/jsx-runtime/index.d.ts b/jsx-runtime/index.d.ts
index 055d91b..b69253a 100644
--- a/jsx-runtime/index.d.ts
+++ b/jsx-runtime/index.d.ts
@@ -1 +1 @@
-export type * from "../dist/jsx-runtime.d.ts"
+export type * from '../dist/jsx-runtime.d.ts'
diff --git a/package.json b/package.json
index cd46414..61d6f9c 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "zeed-dom",
"type": "module",
- "version": "0.10.7",
+ "version": "0.10.8",
"description": "🌱 Lightweight offline DOM",
"author": {
"name": "Dirk Holtwick",
@@ -68,16 +68,15 @@
"css-what": "^6.1.0"
},
"devDependencies": {
- "@antfu/eslint-config": "^0.40.2",
- "@antfu/ni": "^0.21.5",
- "@types/node": "^20.4.9",
- "@vitest/coverage-c8": "^0.33.0",
- "@vitest/coverage-v8": "^0.34.1",
+ "@antfu/eslint-config": "^0.43.1",
+ "@antfu/ni": "^0.21.8",
+ "@types/node": "^20.7.1",
+ "@vitest/coverage-v8": "^0.34.5",
"c8": "^8.0.1",
- "eslint": "^8.47.0",
+ "eslint": "^8.50.0",
"tsup": "^7.2.0",
- "typescript": "^5.1.6",
+ "typescript": "^5.2.2",
"vite": "^4.4.9",
- "vitest": "^0.34.1"
+ "vitest": "^0.34.5"
}
}
diff --git a/src/env.d.ts b/src/env.d.ts
index 720aaab..db7de5e 100644
--- a/src/env.d.ts
+++ b/src/env.d.ts
@@ -3,4 +3,4 @@ declare namespace JSX {
interface IntrinsicElements {
[elemName: string]: any
}
-}
\ No newline at end of file
+}
diff --git a/src/index.ts b/src/index.ts
index 77e61d9..3465551 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -9,3 +9,4 @@ export { escapeHTML, unescapeHTML } from './encoding'
export { tidyDOM } from './tidy'
export { CDATA, html } from './html'
export { xml } from './xml'
+export { handleHTML } from './manipulate'
diff --git a/src/manipulate.spec.ts b/src/manipulate.spec.ts
new file mode 100644
index 0000000..1961a06
--- /dev/null
+++ b/src/manipulate.spec.ts
@@ -0,0 +1,34 @@
+// Copyright (c) 2020 Dirk Holtwick. All rights reserved. https://holtwick.de/copyright
+
+import { handleHTML } from "./manipulate"
+
+describe("manipulate", () => {
+
+ it("should manipulate html", () => {
+ const html = `
+
+
+
+
+
+ `
+
+ let rhtml = handleHTML(html, document => {
+ let img = document.querySelector('.img-wrapper img')
+ console.log('img', img)
+ if (img) {
+ img.setAttribute('title', 'hello')
+ }
+ })
+
+ expect(rhtml).toMatchInlineSnapshot( `
+ "
+
+
+
+
+
+ "
+ `)
+ })
+})
diff --git a/src/manipulate.ts b/src/manipulate.ts
new file mode 100644
index 0000000..ac55ad2
--- /dev/null
+++ b/src/manipulate.ts
@@ -0,0 +1,8 @@
+import type { VDocumentFragment, VHTMLDocument } from './vdom'
+import { parseHTML } from './vdomparser'
+
+export function handleHTML(html: string, handler: (document: VHTMLDocument | VDocumentFragment) => void) {
+ const document = parseHTML(html)
+ handler(document)
+ return document.render()
+}
diff --git a/src/vcss.ts b/src/vcss.ts
index d450c88..a10eac3 100644
--- a/src/vcss.ts
+++ b/src/vcss.ts
@@ -33,6 +33,7 @@ export function matchSelector(
}
const handleRules = (element: VElement, rules: any[]) => {
+ // let pos = 0
let success = false
for (const part of rules) {
const { type, name, action, value, _ignoreCase = true, data } = part
@@ -102,12 +103,18 @@ export function matchSelector(
// } else if (type === 'descendant') {
// element = element.
}
+ // else if (type === 'descendant') {
+ // for (const child of element.childNodes)
+ // handleRules(child, rules.slice(pos))
+ // }
else {
console.warn('Unknown CSS selector type', type, selector, rules)
}
// log(success, selector, part, element)
if (!success)
break
+
+ // pos += 1
}
return success
}
diff --git a/src/vdom.spec.tsx b/src/vdom.spec.tsx
index 2573dfd..0356f42 100644
--- a/src/vdom.spec.tsx
+++ b/src/vdom.spec.tsx
@@ -206,13 +206,13 @@ describe("VDOM", () => {
it("should handle dataSet stuff", () => {
let el = Test
- expect(el.attributes).toEqual({ "data-lang": "en" })
+ expect(el.attributesObject).toEqual({ "data-lang": "en" })
expect(el.render()).toEqual('Test
')
expect(el.querySelector("[data-lang]").textContent).toEqual("Test")
let frag = parseHTML(el.render())
- expect(frag.firstChild.attributes).toEqual({ "data-lang": "en" })
+ expect(frag.firstChild.attributesObject).toEqual({ "data-lang": "en" })
expect(frag.render()).toEqual('Test
')
})
diff --git a/src/vdom.ts b/src/vdom.ts
index 1e1c65c..5725d6c 100644
--- a/src/vdom.ts
+++ b/src/vdom.ts
@@ -146,11 +146,13 @@ export class VNode {
}
}
+ /** Remove node */
remove() {
this?.parentNode?.removeChild(this)
return this
}
+ /** Replace content of node with text or nodes */
replaceChildren(...nodes: any[]) {
this._childNodes = nodes.map(n =>
typeof n === 'string' ? new VTextNode(n) : n.remove(),
@@ -158,6 +160,7 @@ export class VNode {
this._fixChildNodesParent()
}
+ /** Replace node itself with nodes */
replaceWith(...nodes: any[]) {
const p = this._parentNode
if (p) {
@@ -176,7 +179,6 @@ export class VNode {
_indexInParent() {
if (this._parentNode)
return this._parentNode.childNodes.indexOf(this)
-
return -1
}
@@ -204,7 +206,6 @@ export class VNode {
const i = this._indexInParent()
if (i != null)
return this.parentNode.childNodes[i + 1] || null
-
return null
}
@@ -212,7 +213,6 @@ export class VNode {
const i = this._indexInParent()
if (i > 0)
return this.parentNode.childNodes[i - 1] || null
-
return null
}
@@ -220,10 +220,8 @@ export class VNode {
const elements: VElement[] = []
if (this instanceof VElement)
elements.push(this)
-
for (const child of this._childNodes)
elements.push(...child.flatten())
-
return elements
}
@@ -232,7 +230,6 @@ export class VNode {
nodes.push(this)
for (const child of this._childNodes)
nodes.push(...child.flattenNodes())
-
return nodes
}
@@ -356,6 +353,11 @@ export class VNodeQuery extends VNode {
}
}
+interface Attr {
+ name: string
+ value: string
+}
+
export class VElement extends VNodeQuery {
_originalTagName: string
_nodeName: any
@@ -386,8 +388,13 @@ export class VElement extends VNodeQuery {
return node
}
- get attributes() {
- return this._attributes
+ get attributes(): Attr[] {
+ return Object.entries(this._attributes).map(([name, value]): Attr => ({ name, value }))
+ // return this._attributes
+ }
+
+ get attributesObject() {
+ return { ...this._attributes }
}
_findAttributeName(name: string) {
@@ -451,6 +458,11 @@ export class VElement extends VNodeQuery {
return this._nodeName
}
+ /** Private function to easily change the tagName */
+ setTagName(name: string) {
+ this._nodeName = name.toUpperCase()
+ }
+
get id(): string | null {
return this._attributes.id || null
}
@@ -549,7 +561,7 @@ export class VElement extends VNodeQuery {
render(h = htmlVDOM) {
return h(
this._originalTagName || this.tagName,
- this.attributes,
+ this._attributes,
this._childNodes.map(c => c.render(h)).join(''), // children:string is not escaped again
)
}
diff --git a/tsconfig.json b/tsconfig.json
index f935731..5048ff9 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,30 +1,30 @@
{
"compilerOptions": {
- "baseUrl": ".",
"target": "ES2019",
- "declaration": true,
- "esModuleInterop": true,
- "isolatedModules": true,
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
],
+ "jsx": "react",
+ "jsxFactory": "h",
+ "jsxFragmentFactory": "Fragment",
"module": "ESNext",
"moduleResolution": "Node",
- "resolveJsonModule": true,
- "sourceMap": true,
- "strict": true,
- "strictNullChecks": true,
+ "baseUrl": ".",
"types": [
"node",
"vitest/globals"
],
+ "resolveJsonModule": true,
"allowJs": true,
- "jsx": "react",
- "jsxFactory": "h",
- "jsxFragmentFactory": "Fragment"
+ "declaration": true,
+ "sourceMap": true,
+ "isolatedModules": true,
+ "esModuleInterop": true,
+ "strict": true,
+ "strictNullChecks": true
},
"include": [
"src/**/*",