diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
new file mode 100644
index 0000000..9259173
--- /dev/null
+++ b/.github/workflows/publish.yml
@@ -0,0 +1,19 @@
+name: Publish
+on:
+ push:
+ branches:
+ - main
+
+jobs:
+ publish:
+ runs-on: ubuntu-latest
+
+ permissions:
+ contents: read
+ id-token: write
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Publish package
+ run: npx jsr publish
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 4738c71..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,12 +0,0 @@
-.DS_Store
-node_modules
-dist
-
-# local env files
-.env.local
-.env.*.local
-
-# Log files
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
\ No newline at end of file
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..051b954
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,23 @@
+{
+ // Use IntelliSense to learn about possible attributes.
+ // Hover to view descriptions of existing attributes.
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "request": "launch",
+ "name": "Launch Program",
+ "type": "node",
+ "program": "${workspaceFolder}/main.ts",
+ "cwd": "${workspaceFolder}",
+ "env": {},
+ "runtimeExecutable": "C:\\Users\\mgamb\\.deno\\bin\\deno.EXE",
+ "runtimeArgs": [
+ "run",
+ "--inspect-wait",
+ "--allow-all"
+ ],
+ "attachSimplePort": 9229
+ }
+ ]
+}
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..cbac569
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "deno.enable": true
+}
diff --git a/README.md b/README.md
index f862b1c..ff9076b 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,13 @@
# HtmlParser
-
```html
-
+
```
```js
- const hp = new HtmlParser()
+const hp = new HtmlParser();
- let result = hp.Parse("")
+let result = hp.Parse("");
```
+
![Screenshot](docs/output-screenshot.png)
diff --git a/__tests__/__snapshots__/parser.spec.ts.snap b/__tests__/__snapshots__/parser.spec.ts.snap
new file mode 100644
index 0000000..b75387c
--- /dev/null
+++ b/__tests__/__snapshots__/parser.spec.ts.snap
@@ -0,0 +1,156 @@
+export const snapshot = {};
+
+snapshot[`HtmlParser Tests > simple test 1`] = `
+HtmlNode {
+ _outerHTML: "",
+ attributes: {
+ "/": undefined,
+ },
+ children: [],
+ content: undefined,
+ endIndex: 7,
+ endTag: undefined,
+ selfClosing: undefined,
+ startIndex: 0,
+ tag: "div",
+ type: 3,
+}
+`;
+
+snapshot[`HtmlParser Tests > attribute test 1`] = `
+HtmlNode {
+ _outerHTML: "",
+ attributes: {
+ disabled: undefined,
+ required: undefined,
+ type: "text",
+ },
+ children: [],
+ content: undefined,
+ endIndex: 39,
+ endTag: "",
+ selfClosing: true,
+ startIndex: 0,
+ tag: "input",
+ type: 3,
+}
+`;
+
+snapshot[`HtmlParser Tests > attribute test 2`] = `
+HtmlNode {
+ _outerHTML: "",
+ attributes: {},
+ children: [
+ HtmlNode {
+ _outerHTML: "",
+ attributes: {
+ disabled: undefined,
+ required: undefined,
+ type: "text",
+ },
+ children: [],
+ content: undefined,
+ endIndex: 44,
+ endTag: "",
+ selfClosing: true,
+ startIndex: 5,
+ tag: "input",
+ type: 3,
+ },
+ ],
+ content: undefined,
+ endIndex: 50,
+ endTag: "div",
+ selfClosing: undefined,
+ startIndex: 0,
+ tag: "div",
+ type: 3,
+}
+`;
+
+snapshot[`HtmlParser Tests > incomplete sample 1`] = `
+[
+ HtmlNode {
+ _outerHTML: ' jsx sample 1`] = `
+[
+ HtmlNode {
+ _outerHTML: "",
+ attributes: {},
+ children: [
+ HtmlNode {
+ _outerHTML: "",
+ attributes: {},
+ children: [
+ HtmlNode {
+ _outerHTML: undefined,
+ attributes: {},
+ children: [],
+ content: "Enter temperature in {scaleNames[scale]}:",
+ endIndex: 0,
+ endTag: undefined,
+ selfClosing: undefined,
+ startIndex: 0,
+ tag: undefined,
+ type: 4,
+ },
+ ],
+ content: undefined,
+ endIndex: 77,
+ endTag: "legend",
+ selfClosing: undefined,
+ startIndex: 19,
+ tag: "legend",
+ type: 3,
+ },
+ HtmlNode {
+ _outerHTML: "",
+ attributes: {
+ onChange: "{this.handleChange}",
+ value: "{temperature}
+",
+ },
+ children: [],
+ content: undefined,
+ endIndex: 159,
+ endTag: "",
+ selfClosing: true,
+ startIndex: 86,
+ tag: "input",
+ type: 3,
+ },
+ ],
+ content: undefined,
+ endIndex: 177,
+ endTag: "fieldset",
+ selfClosing: undefined,
+ startIndex: 0,
+ tag: "fieldset",
+ type: 3,
+ },
+]
+`;
diff --git a/__tests__/parser.spec.ts b/__tests__/parser.spec.ts
index 80bb60a..aac2b60 100644
--- a/__tests__/parser.spec.ts
+++ b/__tests__/parser.spec.ts
@@ -1,152 +1,154 @@
-import { HtmlParser } from "../src/HtmlParser";
+import { describe, test } from "jsr:@std/testing/bdd";
+import { expect } from "jsr:@std/expect";
+import { HtmlParser } from "../src/HtmlParser.ts";
+import { assertSnapshot } from "@std/testing/snapshot";
-describe.only("HtmlParser Tests", () => {
+describe("HtmlParser Tests", () => {
+ test("simple test", async (t) => {
+ const hp = new HtmlParser();
- test("simple test", () => {
- const hp = new HtmlParser()
+ const html = "";
- const html = ""
+ const result = hp.parse(html)[0];
- const result = hp.Parse(html)[0]
+ await assertSnapshot(t, result);
- console.log(result)
-
- expect(result.tag).toEqual("div")
+ expect(result.tag).toEqual("div");
expect(result.outerHTML).toEqual(html);
- })
+ });
+
+ test("attribute test", async (t) => {
+ const hp = new HtmlParser();
- test("attribute test", () => {
- const hp = new HtmlParser()
+ const html = "";
- const html = ""
+ const result = hp.parse(html)[0];
- const result = hp.Parse(html)[0]
+ await assertSnapshot(t, result);
expect(result.tag).toEqual("input");
- expect(Object.keys(result.attributes).length).toEqual(3);
+ expect(Object.keys(result.attributes as object).length).toEqual(3);
- expect(result.attributes.type).toEqual("text");
+ expect(result.attributes?.type).toEqual("text");
expect(result.outerHTML).toEqual(html);
- })
+ });
- test("attribute test", () => {
- const hp = new HtmlParser()
+ test("attribute test", async (t) => {
+ const hp = new HtmlParser();
- const innerHtml = ``
+ const innerHtml = ``;
- const html = `${innerHtml}
`
+ const html = `${innerHtml}
`;
- let result = hp.Parse(html)[0]
+ let result = hp.parse(html)[0];
- console.log(result)
+ await assertSnapshot(t, result);
expect(result.tag).toEqual("div");
- expect(Object.keys(result.attributes).length).toEqual(0);
+ expect(Object.keys(result.attributes as object).length).toEqual(0);
expect(result.outerHTML).toEqual(html);
- result = result.children[0]
+ result = result.children[0];
- expect(result.tag).toEqual("input")
+ expect(result.tag).toEqual("input");
- expect(Object.keys(result.attributes).length).toEqual(3);
+ expect(Object.keys(result.attributes as object).length).toEqual(3);
- expect(result.attributes.type).toBeTruthy();
+ expect(result.attributes?.type).toBeTruthy();
- expect(result.attributes.type).toEqual("text");
+ expect(result.attributes?.type).toEqual("text");
expect(result.outerHTML).toEqual(innerHtml);
- })
-
- test('incomplete sample', () => {
-
- const hp = new HtmlParser()
+ });
- let result = {}
+ test("incomplete sample", async (t) => {
+ const hp = new HtmlParser();
- result = hp.Parse(` {
+ test("vue sample", () => {
const vue = `
-`
+`;
- const hp = new HtmlParser()
+ const hp = new HtmlParser();
- const result = hp.Parse(vue)
+ const result = hp.parse(vue);
- let el = result[0]
- expect(el.tag).toEqual("article")
+ let el = result[0];
+ expect(el.tag).toEqual("article");
- el = result[0].children[0]
+ el = result[0].children[0];
- expect(el.tag).toEqual("textarea")
- expect(Object.values(el.attributes).length).toEqual(2)
+ expect(el.tag).toEqual("textarea");
+ expect(Object.values(el.attributes as object).length).toEqual(2);
- el = result[0].children[1]
- expect(el.tag).toEqual("div")
- expect(Object.values(el.attributes).length).toEqual(1)
+ el = result[0].children[1];
+ expect(el.tag).toEqual("div");
+ expect(Object.values(el.attributes as object).length).toEqual(1);
+ });
- })
-
- test('vue multiline sample', () => {
+ test("vue multiline sample", () => {
const vue = `
-`
-
- const hp = new HtmlParser()
+`;
- const result = hp.Parse(vue)
+ const hp = new HtmlParser();
- let el = result[0]
- expect(el.tag).toEqual("article")
+ const result = hp.parse(vue);
- el = result[0].children[0]
+ let el = result[0];
+ expect(el.tag).toEqual("article");
- expect(el.tag).toEqual("textarea")
- expect(el.children[0].content).toEqual("Some Content")
- expect(Object.values(el.attributes).length).toEqual(2)
+ el = result[0].children[0];
+ expect(el.tag).toEqual("textarea");
+ expect(el.children[0].content).toEqual("Some Content");
+ expect(Object.values(el.attributes as object).length).toEqual(2);
- el = result[0].children[1]
- expect(el.tag).toEqual("div")
- expect(Object.values(el.attributes).length).toEqual(1)
- })
+ el = result[0].children[1];
+ expect(el.tag).toEqual("div");
+ expect(Object.values(el.attributes as object).length).toEqual(1);
+ });
- test('jsx sample', () => {
+ test("jsx sample", async (t) => {
const jsx = ``
+ `;
+
+ const hp = new HtmlParser();
- const hp = new HtmlParser()
+ const result = hp.parse(jsx);
- const result = hp.Parse(jsx)
- })
+ await assertSnapshot(t, result);
+ });
- test('index.html sample', () => {
+ test("index.html sample", () => {
const html = `
@@ -167,20 +169,16 @@ html {
-`
-
- const hp = new HtmlParser()
-
- const result = hp.Parse(html)
-
- console.log(result[1])
+