xml-to-html-converter 0.3.1 → 0.4.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 CHANGED
@@ -6,72 +6,49 @@
6
6
  ![XML](https://img.shields.io/badge/input-XML-orange)
7
7
  ![HTML](https://img.shields.io/badge/output-HTML-red)
8
8
 
9
- A zero-dependency Node.js package for converting XML to HTML. Currently in pre-1.0.0 development, building the foundation one functional part at a time. Full XML-to-HTML conversion is the goal of `v1.0.0`.
9
+ A zero-dependency Node.js package for converting XML to HTML.
10
10
 
11
- ---
11
+ - **`minify(xml)`** strips inter-tag whitespace from prettified XML before parsing. Text content is left untouched
12
+ - **`scaffold(xml)`** reads any XML string and returns a nested node tree
13
+ - **`walk(nodes, visitor)`** traverses the full node tree depth-first, visiting every node
14
+ - **`render(nodes)`** converts a node tree to an HTML string. Every XML element becomes a `<div>` with `data-tag` and `data-attrs-*` attributes
12
15
 
13
- ## XML Node Extraction & Scaffolding
16
+ ---
14
17
 
15
- The `scaffold` function walks an XML string and produces an array of `XmlNode` objects, each carrying its role, its raw source text, and its position in the document, both globally across the full document and locally within its parent.
18
+ ## Install
16
19
 
17
- ```ts
18
- interface XmlAttribute {
19
- name: string;
20
- value: string;
21
- }
22
-
23
- interface XmlNode {
24
- role: XmlNodeRole;
25
- raw: string;
26
- xmlTag?: string;
27
- xmlInner?: string;
28
- xmlAttributes?: XmlAttribute[];
29
- globalIndex: number;
30
- localIndex: number;
31
- children?: XmlNode[];
32
- malformed?: true;
33
- }
34
-
35
- type XmlNodeRole =
36
- | "closeTag"
37
- | "comment"
38
- | "doctype"
39
- | "openTag"
40
- | "processingInstruction"
41
- | "selfTag"
42
- | "textLeaf";
20
+ ```bash
21
+ npm install xml-to-html-converter
43
22
  ```
44
23
 
45
- This scaffold is the foundation everything else will be built on. No transformation, no HTML output, no opinions about content, just an accurate, traversable representation of what the XML says.
46
-
47
24
  ---
48
25
 
49
- > **Where I am right now**
50
- >
51
- > `v0.x` is building the scaffold and the first render pass.
52
- >
53
- > - **`minify(xml)`** strips inter-tag whitespace from prettified XML before parsing — text content is left untouched
54
- > - **`scaffold(xml)`** reads any XML string and returns a nested node tree
55
- > - Every node knows its `role`, its `raw` source string, its `globalIndex` in the document, and its `localIndex` within its parent
56
- > - Tag nodes (`openTag`, `selfTag`) also carry `xmlTag`, `xmlInner`, and `xmlAttributes` — the parsed tag name, raw attribute string, and structured attribute array
57
- > - Broken XML is never thrown — malformed nodes are flagged with `malformed: true` in place and the tree is built regardless
58
- > - **`render(nodes)`** takes the scaffold output and converts it to an HTML string — every XML element becomes a `<div>` with `data-tag` and `data-attrs-*` attributes
59
- >
60
- > `v1.0.0` is when this package becomes what it says it is: a full XML-to-HTML converter. Everything before that is the work to get there.
26
+ ## Usage
61
27
 
62
- ---
28
+ ### minify
63
29
 
64
- ## Install
30
+ When your XML comes from a file or an API it is usually indented and line-broken. `minify` strips the whitespace between tags before parsing. Text content is left completely untouched.
65
31
 
66
- ```bash
67
- npm install xml-to-html-converter
32
+ ```js
33
+ import { minify } from "xml-to-html-converter";
34
+
35
+ const clean = minify(`
36
+ <bookstore>
37
+ <book category="cooking">
38
+ <title lang="en">Everyday Italian</title>
39
+ </book>
40
+ </bookstore>
41
+ `);
42
+ // <bookstore><book category="cooking"><title lang="en">Everyday Italian</title></book></bookstore>
68
43
  ```
69
44
 
45
+ `minify` is opt-in. Skip it if whitespace inside your content is meaningful.
46
+
70
47
  ---
71
48
 
72
- ## Usage
49
+ ### scaffold
73
50
 
74
- ### Parsing XML into a node tree
51
+ `scaffold` parses an XML string into a structured tree of `XmlNode` objects. Each node carries its role, its raw source text, and its position in the document both globally across the full document and locally within its parent.
75
52
 
76
53
  ```js
77
54
  import { scaffold } from "xml-to-html-converter";
@@ -135,7 +112,43 @@ const tree = scaffold(`
135
112
  ]
136
113
  ```
137
114
 
138
- ### Converting the tree to HTML
115
+ `scaffold` never throws. Malformed structures are flagged with `malformed: true` in place and the tree is built regardless. See [Malformed XML](#malformed-xml) for details.
116
+
117
+ ---
118
+
119
+ ### walk
120
+
121
+ `walk` traverses the full node tree depth-first, calling a visitor function on every node including all descendants. The visitor decides what to collect or do. `walk` has no opinions.
122
+
123
+ ```js
124
+ import { scaffold, walk } from "xml-to-html-converter";
125
+
126
+ const tree = scaffold(xml);
127
+
128
+ // collect all text content
129
+ const text = [];
130
+ walk(tree, (node) => {
131
+ if (node.role === "textLeaf") text.push(node.raw);
132
+ });
133
+
134
+ // find all nodes with a specific tag
135
+ const titles = [];
136
+ walk(tree, (node) => {
137
+ if (node.xmlTag === "title") titles.push(node);
138
+ });
139
+
140
+ // check for malformed nodes anywhere in the tree
141
+ const broken = [];
142
+ walk(tree, (node) => {
143
+ if (node.malformed) broken.push(node);
144
+ });
145
+ ```
146
+
147
+ ---
148
+
149
+ ### render
150
+
151
+ `render` walks the node tree and converts every XML element to a `<div>`. The original tag name is preserved in `data-tag` and each attribute becomes its own `data-attrs-*` attribute.
139
152
 
140
153
  ```js
141
154
  import { scaffold, render } from "xml-to-html-converter";
@@ -151,8 +164,6 @@ const html = render(
151
164
  );
152
165
  ```
153
166
 
154
- `render` walks the node tree and converts every XML element to a `<div>`. The original tag name is preserved in `data-tag` and each attribute becomes its own `data-attrs-*` attribute:
155
-
156
167
  ```html
157
168
  <div data-tag="bookstore">
158
169
  <div data-tag="book" data-attrs-category="cooking">
@@ -165,17 +176,19 @@ Processing instructions and doctypes are dropped. Comments are passed through un
165
176
 
166
177
  ---
167
178
 
168
- ### Minifying prettified XML
169
-
170
- When your XML comes from a file or an API it is usually indented and line-broken. `minify` strips the whitespace between tags before parsing, leaving text content completely untouched.
179
+ ### Full pipeline
171
180
 
172
181
  ```js
173
- import { minify, scaffold, render } from "xml-to-html-converter";
182
+ import { minify, scaffold, walk, render } from "xml-to-html-converter";
174
183
 
175
- const html = render(scaffold(minify(xml)));
176
- ```
184
+ const tree = scaffold(minify(xml));
177
185
 
178
- `minify` is opt-in. Skip it if whitespace inside your content is meaningful.
186
+ walk(tree, (node) => {
187
+ if (node.malformed) console.warn("malformed node", node.raw);
188
+ });
189
+
190
+ const html = render(tree);
191
+ ```
179
192
 
180
193
  ---
181
194
 
@@ -187,7 +200,7 @@ Every node in the tree has the following fields:
187
200
  | --------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------- |
188
201
  | `role` | `XmlNodeRole` | What kind of node this is |
189
202
  | `raw` | `string` | The exact source string, untouched |
190
- | `xmlTag` | `string` | Tag name only, e.g. `"book"` or `"env:Envelope"`. Present on `openTag`, `selfTag`, `closeTag` |
203
+ | `xmlTag` | `string` | Tag name only, e.g. `"book"` or `"env:Envelope"`. Present on `openTag`, `selfTag`, and `closeTag` |
191
204
  | `xmlInner` | `string` | Everything after the tag name inside the brackets, verbatim. Present on `openTag` and `selfTag` when attributes exist |
192
205
  | `xmlAttributes` | `XmlAttribute[]` | Parsed array of `{ name, value }` attribute objects. Present on `openTag` and `selfTag` when attributes exist |
193
206
  | `globalIndex` | `number` | Position in the entire document (never resets) |
@@ -268,7 +281,13 @@ const tree = scaffold("<root><unclosed><valid>text</valid></root>");
268
281
  ## Exports
269
282
 
270
283
  ```ts
271
- import { scaffold, render, minify, isMalformed } from "xml-to-html-converter";
284
+ import {
285
+ minify,
286
+ scaffold,
287
+ walk,
288
+ render,
289
+ isMalformed,
290
+ } from "xml-to-html-converter";
272
291
  import type {
273
292
  XmlNode,
274
293
  XmlNodeRole,
@@ -277,16 +296,17 @@ import type {
277
296
  } from "xml-to-html-converter";
278
297
  ```
279
298
 
280
- | Export | Kind | Description |
281
- | ------------------ | -------- | --------------------------------------------------- |
282
- | `minify` | function | Strips inter-tag whitespace from an XML string |
283
- | `scaffold` | function | Parses an XML string and returns a node tree |
284
- | `render` | function | Converts a node tree to an HTML string |
285
- | `isMalformed` | function | Type guard, narrows `XmlNode` to `MalformedXmlNode` |
286
- | `XmlNode` | type | The shape of every node in the tree |
287
- | `XmlNodeRole` | type | Union of all valid role strings |
288
- | `XmlAttribute` | type | Shape of a parsed attribute `{ name, value }` |
289
- | `MalformedXmlNode` | type | `XmlNode` narrowed to `{ malformed: true }` |
299
+ | Export | Kind | Description |
300
+ | ------------------ | -------- | ------------------------------------------------------- |
301
+ | `minify` | function | Strips inter-tag whitespace from an XML string |
302
+ | `scaffold` | function | Parses an XML string and returns a node tree |
303
+ | `walk` | function | Traverses a node tree depth-first with a visitor |
304
+ | `render` | function | Converts a node tree to an HTML string |
305
+ | `isMalformed` | function | Type guard that narrows `XmlNode` to `MalformedXmlNode` |
306
+ | `XmlNode` | type | The shape of every node in the tree |
307
+ | `XmlNodeRole` | type | Union of all valid role strings |
308
+ | `XmlAttribute` | type | Shape of a parsed attribute `{ name, value }` |
309
+ | `MalformedXmlNode` | type | `XmlNode` narrowed to nodes where `malformed` is `true` |
290
310
 
291
311
  ---
292
312
 
package/dist/index.cjs CHANGED
@@ -23,7 +23,8 @@ __export(src_exports, {
23
23
  isMalformed: () => isMalformed,
24
24
  minify: () => minify,
25
25
  render: () => render,
26
- scaffold: () => scaffold
26
+ scaffold: () => scaffold,
27
+ walk: () => walk
27
28
  });
28
29
  module.exports = __toCommonJS(src_exports);
29
30
 
@@ -256,10 +257,19 @@ function extractXmlNodes(xml, position) {
256
257
  function isMalformed(node) {
257
258
  return node.malformed === true;
258
259
  }
260
+
261
+ // src/modules/walk/walk.ts
262
+ function walk(nodes, visitor) {
263
+ for (const node of nodes) {
264
+ visitor(node);
265
+ if (node.children) walk(node.children, visitor);
266
+ }
267
+ }
259
268
  // Annotate the CommonJS export names for ESM import in node:
260
269
  0 && (module.exports = {
261
270
  isMalformed,
262
271
  minify,
263
272
  render,
264
- scaffold
273
+ scaffold,
274
+ walk
265
275
  });
package/dist/index.d.cts CHANGED
@@ -25,4 +25,6 @@ declare function render(nodes: XmlNode[]): string;
25
25
 
26
26
  declare function scaffold(xml: string): XmlNode[];
27
27
 
28
- export { type MalformedXmlNode, type XmlAttribute, type XmlNode, type XmlNodeRole, isMalformed, minify, render, scaffold };
28
+ declare function walk(nodes: XmlNode[], visitor: (node: XmlNode) => void): void;
29
+
30
+ export { type MalformedXmlNode, type XmlAttribute, type XmlNode, type XmlNodeRole, isMalformed, minify, render, scaffold, walk };
package/dist/index.d.ts CHANGED
@@ -25,4 +25,6 @@ declare function render(nodes: XmlNode[]): string;
25
25
 
26
26
  declare function scaffold(xml: string): XmlNode[];
27
27
 
28
- export { type MalformedXmlNode, type XmlAttribute, type XmlNode, type XmlNodeRole, isMalformed, minify, render, scaffold };
28
+ declare function walk(nodes: XmlNode[], visitor: (node: XmlNode) => void): void;
29
+
30
+ export { type MalformedXmlNode, type XmlAttribute, type XmlNode, type XmlNodeRole, isMalformed, minify, render, scaffold, walk };
package/dist/index.js CHANGED
@@ -227,9 +227,18 @@ function extractXmlNodes(xml, position) {
227
227
  function isMalformed(node) {
228
228
  return node.malformed === true;
229
229
  }
230
+
231
+ // src/modules/walk/walk.ts
232
+ function walk(nodes, visitor) {
233
+ for (const node of nodes) {
234
+ visitor(node);
235
+ if (node.children) walk(node.children, visitor);
236
+ }
237
+ }
230
238
  export {
231
239
  isMalformed,
232
240
  minify,
233
241
  render,
234
- scaffold
242
+ scaffold,
243
+ walk
235
244
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xml-to-html-converter",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "Zero dependency XML to HTML converter for Node environments",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",