diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..eae23ff --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,43 @@ +{ + // Enable the ESlint flat config support + "eslint.experimental.useFlatConfig": true, + + // Disable the default formatter, use eslint instead + "prettier.enable": false, + "editor.formatOnSave": false, + + // Auto fix + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit", + "source.organizeImports": "never" + }, + + // Silent the stylistic rules in you IDE, but still auto fix them + "eslint.rules.customizations": [ + { "rule": "style/*", "severity": "off" }, + { "rule": "format/*", "severity": "off" }, + { "rule": "*-indent", "severity": "off" }, + { "rule": "*-spacing", "severity": "off" }, + { "rule": "*-spaces", "severity": "off" }, + { "rule": "*-order", "severity": "off" }, + { "rule": "*-dangle", "severity": "off" }, + { "rule": "*-newline", "severity": "off" }, + { "rule": "*quotes", "severity": "off" }, + { "rule": "*semi", "severity": "off" } + ], + + // Enable eslint for all supported languages + "eslint.validate": [ + "javascript", + "javascriptreact", + "typescript", + "typescriptreact", + "vue", + "html", + "markdown", + "json", + "jsonc", + "yaml", + "toml" + ] +} diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..c7530fc --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,5 @@ +import antfu from '@antfu/eslint-config' + +export default antfu({ + ignores: ['dist', '**/dist/**', 'node_modules', '**/node_modules/**', 'build', '**/build/**', 'tmp', '**/tmp/**', 'demos', '**/demos/**', 'coverage', '**/coverage/**', '_archive', '**/_archive/**', '*.spec.*', '**/*.spec.*/**', 'vitest.config.ts', '**/vitest.config.ts/**', '*.md', '**/*.md/**', '*.yml', '**/*.yml/**'], +}) diff --git a/examples/auto-jsx/index.js b/examples/auto-jsx/index.js index 5fb5501..0a02729 100644 --- a/examples/auto-jsx/index.js +++ b/examples/auto-jsx/index.js @@ -1,8 +1,10 @@ /* eslint-disable no-console */ 'use strict' exports.__esModule = true -const dom = (
    +const dom = ( +
    1. hostic
    2. hostic-dom
    3. -
    ) +
+) console.log(dom) diff --git a/package.json b/package.json index e721fcc..805ee2a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "zeed-dom", "type": "module", - "version": "0.10.11", + "version": "0.11.0", "description": "🌱 Lightweight offline DOM", "author": { "name": "Dirk Holtwick", @@ -68,15 +68,15 @@ "css-what": "^6.1.0" }, "devDependencies": { - "@antfu/eslint-config": "^0.43.1", - "@antfu/ni": "^0.21.8", - "@types/node": "^20.8.4", - "@vitest/coverage-v8": "^0.34.6", + "@antfu/eslint-config": "^2.4.5", + "@antfu/ni": "^0.21.12", + "@types/node": "^20.10.4", + "@vitest/coverage-v8": "^1.0.4", "c8": "^8.0.1", - "eslint": "^8.51.0", - "tsup": "^7.2.0", - "typescript": "^5.2.2", - "vite": "^4.4.11", - "vitest": "^0.34.6" + "eslint": "^8.55.0", + "tsup": "^8.0.1", + "typescript": "^5.3.3", + "vite": "^5.0.9", + "vitest": "^1.0.4" } } diff --git a/src/encoding-he.ts b/src/encoding-he.ts index bc3dcc7..45be6aa 100644 --- a/src/encoding-he.ts +++ b/src/encoding-he.ts @@ -1,4 +1,4 @@ -// eslint-disable-next-line @typescript-eslint/ban-ts-comment +/* eslint-disable ts/ban-ts-comment */ // @ts-nocheck import { hasOwn } from './utils' @@ -3822,17 +3822,133 @@ const decodeMapNumeric = { 159: '\u0178', } const invalidReferenceCodePoints = [ - 1, 2, 3, 4, 5, 6, 7, 8, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, 64976, 64977, 64978, 64979, 64980, - 64981, 64982, 64983, 64984, 64985, 64986, 64987, 64988, 64989, 64990, 64991, - 64992, 64993, 64994, 64995, 64996, 64997, 64998, 64999, 65000, 65001, 65002, - 65003, 65004, 65005, 65006, 65007, 65534, 65535, 131070, 131071, 196606, - 196607, 262142, 262143, 327678, 327679, 393214, 393215, 458750, 458751, - 524286, 524287, 589822, 589823, 655358, 655359, 720894, 720895, 786430, - 786431, 851966, 851967, 917502, 917503, 983038, 983039, 1048574, 1048575, - 1114110, 1114111, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 11, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 64976, + 64977, + 64978, + 64979, + 64980, + 64981, + 64982, + 64983, + 64984, + 64985, + 64986, + 64987, + 64988, + 64989, + 64990, + 64991, + 64992, + 64993, + 64994, + 64995, + 64996, + 64997, + 64998, + 64999, + 65000, + 65001, + 65002, + 65003, + 65004, + 65005, + 65006, + 65007, + 65534, + 65535, + 131070, + 131071, + 196606, + 196607, + 262142, + 262143, + 327678, + 327679, + 393214, + 393215, + 458750, + 458751, + 524286, + 524287, + 589822, + 589823, + 655358, + 655359, + 720894, + 720895, + 786430, + 786431, + 851966, + 851967, + 917502, + 917503, + 983038, + 983039, + 1048574, + 1048575, + 1114110, + 1114111, ] /* -------------------------------------------------------------------------- */ diff --git a/src/encoding.spec.ts b/src/encoding.spec.ts index ea113a8..55f6124 100644 --- a/src/encoding.spec.ts +++ b/src/encoding.spec.ts @@ -1,8 +1,8 @@ -import { escapeHTML } from "." +import { escapeHTML } from '.' -describe("encoding", () => { - it("should encoding", () => { - expect(escapeHTML(" &")).toEqual("<and> &") +describe('encoding', () => { + it('should encoding', () => { + expect(escapeHTML(' &')).toEqual('<and> &') }) }) diff --git a/src/encoding.ts b/src/encoding.ts index 046feac..b2f62d7 100644 --- a/src/encoding.ts +++ b/src/encoding.ts @@ -7,6 +7,8 @@ export function escapeHTML(text: string) { .replace(/>/g, '>') .replace(/'/g, ''') .replace(/"/g, '"') + .replace(/\xA0/g, ' ') + .replace(/\xAD/g, '­') } // encode(text, { diff --git a/src/h.spec.ts b/src/h.spec.ts index c3e0bc0..063b387 100644 --- a/src/h.spec.ts +++ b/src/h.spec.ts @@ -1,20 +1,20 @@ // (C)opyright 2021-07-20 Dirk Holtwick, holtwick.it. All rights reserved. -import { hArgumentParser } from "./h" +import { hArgumentParser } from './h' -describe("h", () => { - it("should flatten", () => { - let values = hArgumentParser("div", ["a", ["b", ["c", "d"], "e"]]) +describe('h', () => { + it('should flatten', () => { + const values = hArgumentParser('div', ['a', ['b', ['c', 'd'], 'e']]) expect(values).toEqual({ attrs: {}, - children: ["a", "b", "c", "d", "e"], - tag: "div", + children: ['a', 'b', 'c', 'd', 'e'], + tag: 'div', }) }) - it("should handle attrs", () => { - let values = hArgumentParser( - "div", + it('should handle attrs', () => { + const values = hArgumentParser( + 'div', { attrs: { a: 1, @@ -23,8 +23,8 @@ describe("h", () => { c: 3, d: 4, }, - "a", - "b" + 'a', + 'b', ) expect(values).toEqual({ attrs: { @@ -33,8 +33,8 @@ describe("h", () => { c: 3, d: 4, }, - children: ["a", "b"], - tag: "div", + children: ['a', 'b'], + tag: 'div', }) }) }) diff --git a/src/html.spec.tsx b/src/html.spec.tsx index e5c2ed9..a45b6c1 100644 --- a/src/html.spec.tsx +++ b/src/html.spec.tsx @@ -1,46 +1,46 @@ // Copyright (c) 2020 Dirk Holtwick. All rights reserved. https://holtwick.de/copyright /** @jsx h */ -import { html as h, CDATA } from "./html" +import { CDATA, html as h } from './html' -describe("HTML", () => { - it("should generate a string", () => { - let s = h("a", { href: "example.com" }, "Welcome & Hello & Ciao") +describe('hTML', () => { + it('should generate a string', () => { + const s = h('a', { href: 'example.com' }, 'Welcome & Hello & Ciao') expect(s).toEqual( - 'Welcome & Hello &amp; Ciao' + 'Welcome & Hello &amp; Ciao', ) // the second & is correct, because plain string should be unescaped }) - it("should nest", () => { - let s = h("a", { href: "example.com" }, h("hr"), h("b", {}, "Welcome")) + it('should nest', () => { + const s = h('a', { href: 'example.com' }, h('hr'), h('b', {}, 'Welcome')) expect(s).toEqual('
Welcome
') }) - it("should use JSX", () => { - let spread = { - title: "Hello", - id: "greeting", + it('should use JSX', () => { + const spread = { + title: 'Hello', + id: 'greeting', } - let s = ( + const s = ( ) expect(s).toEqual( - '
Welcome
' + '
Welcome
', ) }) - it("should keep cdata", () => { - let s = {"Do not escape! & "} + it('should keep cdata', () => { + const s = {'Do not escape! & '} expect(s).toMatchInlineSnapshot(`"Do not escape! & ]]>"`) - let s2 =
{CDATA("Do not escape! & ")}
+ const s2 =
{CDATA('Do not escape! & ')}
expect(s2).toMatchInlineSnapshot( - `"
Do not escape! & ]]>
"` + `"
Do not escape! & ]]>
"`, ) }) }) diff --git a/src/html.ts b/src/html.ts index 7ee23eb..98ae32e 100644 --- a/src/html.ts +++ b/src/html.ts @@ -45,8 +45,8 @@ export function markup( const hasChildren = !( (typeof children === 'string' && children === '') || (Array.isArray(children) - && (children.length === 0 - || (children.length === 1 && children[0] === ''))) + && (children.length === 0 + || (children.length === 1 && children[0] === ''))) || children == null ) diff --git a/src/htmlparser.spec.ts b/src/htmlparser.spec.ts index bfae6ca..e3c7603 100644 --- a/src/htmlparser.spec.ts +++ b/src/htmlparser.spec.ts @@ -1,7 +1,8 @@ -import { createHTMLDocument, parseHTML, VHTMLDocument, VTextNode } from "." +import type { VHTMLDocument } from '.' +import { VTextNode, createHTMLDocument, parseHTML } from '.' -describe("htmlparser", () => { - it("should parse without errors", async () => { +describe('htmlparser', () => { + it('should parse without errors', async () => { const sample = ` @@ -13,35 +14,35 @@ describe("htmlparser", () => { ` - let dom = parseHTML(sample) as VHTMLDocument + const dom = parseHTML(sample) as VHTMLDocument expect(dom != null).toBe(true) expect(dom.render()).toEqual(sample) expect(dom.head != null).toBe(true) }) - it("should escape correctly", () => { - let dom = createHTMLDocument() - dom.body?.appendChild(" { + const dom = createHTMLDocument() + dom.body?.appendChild('</</"` + `"</</"`, ) expect(dom.render()).toMatchInlineSnapshot( - `"</</"` + `"</</"`, ) }) - it("should handle entities correctly", () => { + it('should handle entities correctly', () => { // https://github.com/holtwick/zeed-dom/issues/3 - let dom = parseHTML("

Let's go

") as VHTMLDocument + const dom = parseHTML('

Let's go

') as VHTMLDocument expect(dom.textContent).toMatchInlineSnapshot(`"Let's go"`) expect(dom.render()).toMatchInlineSnapshot(`"

Let's go

"`) }) - it("should ignore escape for script etc.", () => { + it('should ignore escape for script etc.', () => { const html = `` - let dom = parseHTML(html) as VHTMLDocument + const dom = parseHTML(html) as VHTMLDocument expect(dom.textContent).toMatchInlineSnapshot(` " var x = 1 & 4 @@ -108,7 +109,7 @@ $('body') `) }) - it("should not recurse on bad fragment", () => { + it('should not recurse on bad fragment', () => { const tests = [ '<', '<<', diff --git a/src/manipulate.spec.ts b/src/manipulate.spec.ts index 1961a06..b8fb340 100644 --- a/src/manipulate.spec.ts +++ b/src/manipulate.spec.ts @@ -1,31 +1,37 @@ // Copyright (c) 2020 Dirk Holtwick. All rights reserved. https://holtwick.de/copyright -import { handleHTML } from "./manipulate" +import { handleHTML } from './manipulate' -describe("manipulate", () => { - - it("should manipulate html", () => { +describe('manipulate', () => { + it('should manipulate html', () => { const html = ` + + Some - More! +

+ This is   spaaace! ` - let rhtml = handleHTML(html, document => { - let img = document.querySelector('.img-wrapper img') - console.log('img', img) - if (img) { + const rhtml = handleHTML(html, (document) => { + const img = document.querySelector('.img-wrapper img') + // console.log('img', img) + if (img) img.setAttribute('title', 'hello') - } }) - expect(rhtml).toMatchInlineSnapshot( ` + expect(rhtml).toMatchInlineSnapshot(` " - + + + Some - More! + -

\\"\\"

+

+ This is   spaaace! " diff --git a/src/tidy.spec.tsx b/src/tidy.spec.tsx index 05da200..18dc630 100644 --- a/src/tidy.spec.tsx +++ b/src/tidy.spec.tsx @@ -1,27 +1,42 @@ // (C)opyright 2021-07-20 Dirk Holtwick, holtwick.it. All rights reserved. -import { tidyDOM } from "./tidy" -import { createHTMLDocument, h } from "./vdom" +import { tidyDOM } from './tidy' +import { createHTMLDocument, h } from './vdom' -// let _keepH = h +const _keepH = h -describe("Tidy", () => { - it("should look nicer", () => { - let document = createHTMLDocument() +describe('tidy', () => { + it('should look nicer', () => { + const document = createHTMLDocument() document.head?.appendChild( - + , ) document.body?.appendChild(

Hello

- This is a sample. And a link example. + This is a + {' '} + sample + . And a link + {' '} + example + .

- Some lines
line
line{" "} + Some lines + {' '} +
+ {' '} + line + {' '} +
+ {' '} + line + {' '}

  1. One
  2. @@ -30,11 +45,11 @@ describe("Tidy", () => {
               

    Do nothing

    - + , ) expect(document.render()).toEqual( - '

    Hello

    This is a sample. And a link example.

    Some lines
    line
    line

    1. One
    2. Two

    Do nothing

    ' + '

    Hello

    This is a sample. And a link example.

    Some lines
    line
    line

    1. One
    2. Two

    Do nothing

    ', ) tidyDOM(document) diff --git a/src/utils.spec.ts b/src/utils.spec.ts index c0c0bb1..838b0cd 100644 --- a/src/utils.spec.ts +++ b/src/utils.spec.ts @@ -1,20 +1,20 @@ // (C)opyright 2021-07-20 Dirk Holtwick, holtwick.it. All rights reserved. -import { removeBodyContainer } from "./utils" -import { createHTMLDocument } from "./vdom" +import { removeBodyContainer } from './utils' +import { createHTMLDocument } from './vdom' -describe("Utils", () => { - it("should remove doc stuff", () => { - let doc = createHTMLDocument() - doc.body?.appendChild(["Hello ", "world"]) - doc.title = "Hello Title" +describe('utils', () => { + it('should remove doc stuff', () => { + const doc = createHTMLDocument() + doc.body?.appendChild(['Hello ', 'world']) + doc.title = 'Hello Title' expect(doc.render()).toMatchInlineSnapshot( - `"Hello TitleHello world"` + `"Hello TitleHello world"`, ) - let body = removeBodyContainer(doc) + const body = removeBodyContainer(doc) expect(body.render()).toMatchInlineSnapshot( - `"Hello TitleHello world"` + `"Hello TitleHello world"`, ) }) }) diff --git a/src/vcss.spec.tsx b/src/vcss.spec.tsx index a81102a..8315d46 100644 --- a/src/vcss.spec.tsx +++ b/src/vcss.spec.tsx @@ -1,45 +1,45 @@ // (C)opyright 2021-07-20 Dirk Holtwick, holtwick.it. All rights reserved. -import { matchSelector } from "./vcss" -import { createHTMLDocument, h } from "./vdom" +import { matchSelector } from './vcss' +import { createHTMLDocument, h } from './vdom' -// let _keepH = h +const _keepH = h -describe("CSS", () => { - it("should parse", () => { - let element = ( +describe('cSS', () => { + it('should parse', () => { + const element = (
    ...
    ) - expect(matchSelector("#foo", element)).toBe(true) - expect(matchSelector(".foo", element)).toBe(true) - expect(matchSelector("div", element)).toBe(true) - expect(matchSelector("[id=foo]", element)).toBe(true) - expect(matchSelector("[id]", element)).toBe(true) - expect(matchSelector("div, p", element)).toBe(true) - expect(matchSelector(":not(h1)", element)).toBe(true) - expect(matchSelector("*[data-lang]", element)).toBe(true) - expect(matchSelector("#foo, #bar", element)).toBe(true) - expect(matchSelector("#bar, #foo", element)).toBe(true) + expect(matchSelector('#foo', element)).toBe(true) + expect(matchSelector('.foo', element)).toBe(true) + expect(matchSelector('div', element)).toBe(true) + expect(matchSelector('[id=foo]', element)).toBe(true) + expect(matchSelector('[id]', element)).toBe(true) + expect(matchSelector('div, p', element)).toBe(true) + expect(matchSelector(':not(h1)', element)).toBe(true) + expect(matchSelector('*[data-lang]', element)).toBe(true) + expect(matchSelector('#foo, #bar', element)).toBe(true) + expect(matchSelector('#bar, #foo', element)).toBe(true) }) - it("should parse and fail", () => { - let element =

    ...

    - expect(matchSelector("#foo", element)).toBe(false) - expect(matchSelector(".foo", element)).toBe(false) - expect(matchSelector("div", element)).toBe(false) - expect(matchSelector("[id=foo]", element)).toBe(false) - expect(matchSelector("[id]", element)).toBe(false) - expect(matchSelector("div, p", element)).toBe(false) - expect(matchSelector(":not(h1)", element)).toBe(false) - expect(matchSelector("*[data-lang]", element)).toBe(false) - expect(matchSelector("#foo, #bar", element)).toBe(false) - expect(matchSelector("#bar, #foo", element)).toBe(false) + it('should parse and fail', () => { + const element =

    ...

    + expect(matchSelector('#foo', element)).toBe(false) + expect(matchSelector('.foo', element)).toBe(false) + expect(matchSelector('div', element)).toBe(false) + expect(matchSelector('[id=foo]', element)).toBe(false) + expect(matchSelector('[id]', element)).toBe(false) + expect(matchSelector('div, p', element)).toBe(false) + expect(matchSelector(':not(h1)', element)).toBe(false) + expect(matchSelector('*[data-lang]', element)).toBe(false) + expect(matchSelector('#foo, #bar', element)).toBe(false) + expect(matchSelector('#bar, #foo', element)).toBe(false) }) - it("should handle hierarchy", () => { - let element = ( + it('should handle hierarchy', () => { + const element = ( @@ -48,15 +48,15 @@ describe("CSS", () => { ) - expect(element.querySelector("a").tagName).toBe("A") + expect(element.querySelector('a').tagName).toBe('A') // expect(element.querySelector('b c').tagName).toBe('C') }) - it("should complex attributes", () => { - let element =
    - expect(matchSelector("[title]", element)).toBe(true) - expect(matchSelector("[title=abcdefg]", element)).toBe(true) - expect(matchSelector("[title=xxx]", element)).toBe(false) + it('should complex attributes', () => { + const element =
    + expect(matchSelector('[title]', element)).toBe(true) + expect(matchSelector('[title=abcdefg]', element)).toBe(true) + expect(matchSelector('[title=xxx]', element)).toBe(false) expect(matchSelector('div[title="abcdefg"]', element)).toBe(true) expect(matchSelector('div[title="xxx"]', element)).toBe(false) expect(matchSelector('[title~="cd"]', element)).toBe(true) @@ -67,14 +67,14 @@ describe("CSS", () => { expect(matchSelector('[title$="xxx"]', element)).toBe(false) }) - it("should specific meta", () => { + it('should specific meta', () => { let element = ( ) - expect(matchSelector("meta[name=viewport]", element)).toBe(true) + expect(matchSelector('meta[name=viewport]', element)).toBe(true) element = ( { content="width=device-width, initial-scale=1, shrink-to-fit=no" /> ) - expect(matchSelector("meta[name=viewport]", element)).toBe(false) + expect(matchSelector('meta[name=viewport]', element)).toBe(false) }) - it("should query meta", () => { - let document = createHTMLDocument() + it('should query meta', () => { + const document = createHTMLDocument() document.head?.replaceWith( @@ -164,10 +164,10 @@ describe("CSS", () => { /> - + , ) - expect(!document.querySelector("meta[charset]")).toBe(false) + expect(!document.querySelector('meta[charset]')).toBe(false) }) // it('should be single fail', () => { diff --git a/src/vdom.spec.tsx b/src/vdom.spec.tsx index 0356f42..ec46893 100644 --- a/src/vdom.spec.tsx +++ b/src/vdom.spec.tsx @@ -1,65 +1,66 @@ // Copyright (c) 2020 Dirk Holtwick. All rights reserved. https://holtwick.de/copyright // import Sizzle from './sizzle' -import { createHTMLDocument, h, VDocument, VDocumentFragment, VElement } from "./vdom" -import { parseHTML } from "./vdomparser" -import { xml } from "./xml" - -describe("VDOM", () => { - it("should mimic DOM", () => { - let document = new VDocument() - document.appendChild(document.createElement("p")) - document.appendChild(document.createElement("p")) - let html = document.render() - expect(html).toBe("

    ") +import { VDocument, VDocumentFragment, VElement, createHTMLDocument, h } from './vdom' +import { parseHTML } from './vdomparser' +import { xml } from './xml' + +describe('vDOM', () => { + it('should mimic DOM', () => { + const document = new VDocument() + document.appendChild(document.createElement('p')) + document.appendChild(document.createElement('p')) + const html = document.render() + expect(html).toBe('

    ') }) - it("should mimic DOM", () => { - let document = new VDocument() - let frag = new VDocumentFragment() - let p = document.createElement("p") - p.setAttribute("class", "foo") - p.textContent = "Some" + it('should mimic DOM and class', () => { + const document = new VDocument() + const frag = new VDocumentFragment() + const p = document.createElement('p') + p.setAttribute('class', 'foo') + p.textContent = 'Some' frag.appendChild(p) - let html = frag.render() + const html = frag.render() expect(html).toBe('

    Some

    ') }) - it("should convert styles key to camel case", () => { - let document = new VDocument() - let frag = new VDocumentFragment() - let p = document.createElement("p") - p.setAttribute("style", "text-align: center; background-color: red;") + it('should convert styles key to camel case', () => { + const document = new VDocument() + const frag = new VDocumentFragment() + const p = document.createElement('p') + p.setAttribute('style', 'text-align: center; background-color: red;') frag.appendChild(p) - let html = frag.render() - expect(p.style.textAlign).toBe("center") - expect(p.style.backgroundColor).toBe("red") + const html = frag.render() + expect(p.style.textAlign).toBe('center') + expect(p.style.backgroundColor).toBe('red') expect(html).toBe( - '

    ' + '

    ', ) }) - it("should have functional factory", () => { - let doc = createHTMLDocument() + it('should have functional factory', () => { + const doc = createHTMLDocument() doc.body?.replaceChildren( - h("p", { class: "lorem" }, "Hello ", h("b", { id: "foo" }, "World")), - h("hr") + h('p', { class: 'lorem' }, 'Hello ', h('b', { id: 'foo' }, 'World')), + h('hr'), ) - let r = doc.body + const r = doc.body expect(r).not.toBeNull() - if (!r) return + if (!r) + return expect(r.render()).toBe( - '

    Hello World


    ' + '

    Hello World


    ', ) - let elements = r.flatten().map((e) => e.tagName) - expect(elements).toEqual(["BODY", "P", "B", "HR"]) + const elements = r.flatten().map(e => e.tagName) + expect(elements).toEqual(['BODY', 'P', 'B', 'HR']) - let nodes = r.flattenNodes().map((e) => e.nodeName) + const nodes = r.flattenNodes().map(e => e.nodeName) expect(nodes).toMatchInlineSnapshot(` [ "BODY", @@ -73,40 +74,40 @@ describe("VDOM", () => { expect(r.ownerDocument).toBe(doc) - expect(r.getElementsByTagName("b")[0].outerHTML).toEqual( - 'World' + expect(r.getElementsByTagName('b')[0].outerHTML).toEqual( + 'World', ) - expect(r.getElementById("foo")?.outerHTML).toEqual('World') - expect(r.getElementsByClassName("lorem")[0].outerHTML).toEqual( - '

    Hello World

    ' + expect(r.getElementById('foo')?.outerHTML).toEqual('World') + expect(r.getElementsByClassName('lorem')[0].outerHTML).toEqual( + '

    Hello World

    ', ) - expect(r.matches("body")).toBe(true) - expect(r.matches("b")).toBe(false) + expect(r.matches('body')).toBe(true) + expect(r.matches('b')).toBe(false) - expect(r.querySelector("b")?.outerHTML).toEqual('World') - expect(r.querySelector("#foo")?.outerHTML).toEqual('World') - expect(r.querySelector(".lorem")?.outerHTML).toEqual( - '

    Hello World

    ' + expect(r.querySelector('b')?.outerHTML).toEqual('World') + expect(r.querySelector('#foo')?.outerHTML).toEqual('World') + expect(r.querySelector('.lorem')?.outerHTML).toEqual( + '

    Hello World

    ', ) - r.querySelector("#foo")?.replaceWith("Surprise") + r.querySelector('#foo')?.replaceWith('Surprise') expect(r.render()).toBe( - '

    Hello Surprise


    ' + '

    Hello Surprise


    ', ) - expect(doc.body?.tagName).toBe("BODY") - expect(doc.head?.tagName).toBe("HEAD") - expect(doc.documentElement.tagName).toBe("HTML") - expect(doc.title).toBe("") + expect(doc.body?.tagName).toBe('BODY') + expect(doc.head?.tagName).toBe('HEAD') + expect(doc.documentElement.tagName).toBe('HTML') + expect(doc.title).toBe('') }) - it("should use JSX", () => { - let spread = { - title: "Hello", - id: "greeting", + it('should use JSX', () => { + const spread = { + title: 'Hello', + id: 'greeting', } - let s = ( + const s = ( { {...spread} >
    - {null && "This is invisible"} + {null && 'This is invisible'} Welcome
    ) expect(s.render()).toEqual( - '
    Welcome
    ' + '
    Welcome
    ', ) expect(s.render(xml)).toEqual( - '
    Welcome
    ' + '
    Welcome
    ', ) }) - it("should nested JSX", () => { - let content =
    Hello
    - let title = "World" + it('should nested JSX', () => { + const content =
    Hello
    + const title = 'World' - let doc = ( + const doc = (

    {title}

    {content} ) - expect(doc.render()).toBe("

    World

    Hello
    ") + expect(doc.render()).toBe('

    World

    Hello
    ') }) - it("should JSX components", () => { + it('should JSX components', () => { + // eslint-disable-next-line unused-imports/no-unused-vars function Welcome({ props, h }: any) { - return

    Hello, {props.name}

    + return ( +

    + Hello, + {' '} + {props.name} +

    + ) } - let x = - expect(x.render()).toEqual("

    Hello, Sara

    ") + const x = + expect(x.render()).toEqual('

    Hello, Sara

    ') }) - it("should JSX class magic", () => { - let x = ( + it('should JSX class magic', () => { + const x = (
    ... @@ -167,8 +175,8 @@ describe("VDOM", () => { expect(x.render()).toEqual('
    ...
    ') }) - it("should support fragments", () => { - let ff = ( + it('should support fragments', () => { + const ff = (
    One
    Middle @@ -176,11 +184,11 @@ describe("VDOM", () => {
    ) expect(ff).toBeInstanceOf(VDocumentFragment) - expect(ff.render()).toEqual("
    One
    Middle
    Two
    ") + expect(ff.render()).toEqual('
    One
    Middle
    Two
    ') }) - it("should remove", () => { - let el = ( + it('should remove', () => { + const el = (
    @@ -192,64 +200,64 @@ describe("VDOM", () => { ) expect(el.render()).toEqual( - '
    BeforeAfter
    ' + '
    BeforeAfter
    ', ) - let a = el.querySelector("#a") - el.handle("link", (e:any) => a.appendChild(e)) + const a = el.querySelector('#a') + el.handle('link', (e: any) => a.appendChild(e)) expect(el.render()).toEqual( - '
    BeforeAfter
    ' + '
    BeforeAfter
    ', ) }) - it("should handle dataSet stuff", () => { - let el =
    Test
    + it('should handle dataSet stuff', () => { + const el =
    Test
    - expect(el.attributesObject).toEqual({ "data-lang": "en" }) + expect(el.attributesObject).toEqual({ 'data-lang': 'en' }) expect(el.render()).toEqual('
    Test
    ') - expect(el.querySelector("[data-lang]").textContent).toEqual("Test") + expect(el.querySelector('[data-lang]').textContent).toEqual('Test') - let frag = parseHTML(el.render()) - expect(frag.firstChild.attributesObject).toEqual({ "data-lang": "en" }) + const frag = parseHTML(el.render()) + expect(frag.firstChild.attributesObject).toEqual({ 'data-lang': 'en' }) expect(frag.render()).toEqual('
    Test
    ') }) - it("should insert", () => { - let el = ( + it('should insert', () => { + const el = (

    Hallo

    ) - let w =

    Welcome

    + const w =

    Welcome

    el.insertBefore(w) - expect(el.render()).toEqual("

    Welcome

    Hallo

    ") + expect(el.render()).toEqual('

    Welcome

    Hallo

    ') el.insertBefore(w, w) // fail - el.insertBefore(
    Subtitle
    , el.querySelector("p")) + el.insertBefore(
    Subtitle
    , el.querySelector('p')) expect(el.render()).toEqual( - "

    Welcome

    Subtitle

    Hallo

    " + '

    Welcome

    Subtitle

    Hallo

    ', ) // Clone - expect(el.cloneNode().render()).toEqual("
    ") + expect(el.cloneNode().render()).toEqual('
    ') expect(el.cloneNode(true).render()).toEqual( - "

    Welcome

    Subtitle

    Hallo

    " + '

    Welcome

    Subtitle

    Hallo

    ', ) }) - it("should handle empty attrs", () => { - let element = new VElement("img", {"class": "avatar", "src": true, "alt": true}) - let success = !!element.getAttribute("src")?.startsWith("data:") + it('should handle empty attrs', () => { + const element = new VElement('img', { class: 'avatar', src: true, alt: true }) + const success = !!element.getAttribute('src')?.startsWith('data:') expect(success).toBe(false) - let html = element.render() + const html = element.render() expect(html).toBe('') }) }) diff --git a/src/vdom.ts b/src/vdom.ts index 5725d6c..1ea95e2 100644 --- a/src/vdom.ts +++ b/src/vdom.ts @@ -257,7 +257,7 @@ export class VNode { get ownerDocument() { if ( this.nodeType === VNode.DOCUMENT_NODE - || this.nodeType === VNode.DOCUMENT_FRAGMENT_NODE + || this.nodeType === VNode.DOCUMENT_FRAGMENT_NODE ) return this @@ -532,25 +532,23 @@ export class VElement extends VNodeQuery { } get classList() { - // eslint-disable-next-line @typescript-eslint/no-this-alias - const self = this const classNames = String(this.className ?? '').trim().split(/\s+/g) || [] // log('classList', classNames) return { contains(s: any) { return classNames.includes(s) }, - add(s: any) { + add: (s: any) => { if (!classNames.includes(s)) { classNames.push(s) - self.className = classNames + this.className = classNames } }, - remove(s: any) { + remove: (s: any) => { const index = classNames.indexOf(s) if (index >= 0) { classNames.splice(index, 1) - self.className = classNames + this.className = classNames } }, } @@ -641,7 +639,6 @@ export class VDocument extends VDocumentFragment { let content = super.render(h) if (this.docType) content = this.docType.render() + content - return content } } diff --git a/src/vdomparser.spec.ts b/src/vdomparser.spec.ts index 1a76d98..4b1e8f4 100644 --- a/src/vdomparser.spec.ts +++ b/src/vdomparser.spec.ts @@ -1,8 +1,8 @@ // Copyright (c) 2020 Dirk Holtwick. All rights reserved. https://holtwick.de/copyright -import { parseHTML } from "./vdomparser" +import { parseHTML } from './vdomparser' -describe("VDOM Parser", () => { +describe('vDOM Parser', () => { // it('should work with js', () => { // const html = 'Xyz ' // let frag = parseHTML(html) @@ -11,7 +11,7 @@ describe("VDOM Parser", () => { // expect(rhtml).toBe(html) // }) - it("should respect nested", () => { + it('should respect nested', () => { const html = ` @@ -23,8 +23,8 @@ describe("VDOM Parser", () => { ` - let frag = parseHTML(html) - let rhtml = frag.render() + const frag = parseHTML(html) + const rhtml = frag.render() // expect(rhtml).toBe('Xyz ') expect(rhtml).toEqual(html) }) diff --git a/src/vdomparser.ts b/src/vdomparser.ts index f72418c..b2ea86d 100644 --- a/src/vdomparser.ts +++ b/src/vdomparser.ts @@ -1,7 +1,6 @@ +/* eslint-disable node/prefer-global/buffer */ // Copyright (c) 2020 Dirk Holtwick. All rights reserved. https://holtwick.de/copyright -/* eslint-disable n/prefer-global/buffer */ - import { unescapeHTML } from './encoding' import { SELF_CLOSING_TAGS } from './html' import { HtmlParser } from './htmlparser' diff --git a/src/xml.spec.tsx b/src/xml.spec.tsx index 1d3a4a6..dc67efc 100644 --- a/src/xml.spec.tsx +++ b/src/xml.spec.tsx @@ -1,37 +1,37 @@ // Copyright (c) 2020 Dirk Holtwick. All rights reserved. https://holtwick.de/copyright // @tsx h -import { h } from "./xml" +import { h } from './xml' -describe("HTML", () => { - it("should xml", () => { - let s = h( - "a", +describe('hTML', () => { + it('should xml', () => { + const s = h( + 'a', { - href: "example.com", + href: 'example.com', empty: null, x: true, false: false, }, - h("hr"), - h("b", {}, "Welcome") + h('hr'), + h('b', {}, 'Welcome'), ) expect(s).toEqual('
    Welcome
    ') }) - it("should use JSX", () => { - let spread = { - title: "Hello", - id: "greeting", + it('should use JSX', () => { + const spread = { + title: 'Hello', + id: 'greeting', } - let s = ( + const s = (
    Welcome
    ) expect(s).toEqual( - '
    Welcome
    ' + '
    Welcome
    ', ) }) }) diff --git a/tsconfig.json b/tsconfig.json index 5048ff9..fdc8471 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,30 +1,30 @@ { "compilerOptions": { "target": "ES2019", + "jsx": "react", + "jsxFactory": "h", + "jsxFragmentFactory": "Fragment", "lib": [ "esnext", "dom", "dom.iterable", "scripthost" ], - "jsx": "react", - "jsxFactory": "h", - "jsxFragmentFactory": "Fragment", + "baseUrl": ".", "module": "ESNext", "moduleResolution": "Node", - "baseUrl": ".", + "resolveJsonModule": true, "types": [ "node", "vitest/globals" ], - "resolveJsonModule": true, "allowJs": true, + "strict": true, + "strictNullChecks": true, "declaration": true, "sourceMap": true, - "isolatedModules": true, "esModuleInterop": true, - "strict": true, - "strictNullChecks": true + "isolatedModules": true }, "include": [ "src/**/*",