xml-to-html-converter 0.1.8 → 0.3.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 +37 -5
- package/dist/index.cjs +258 -0
- package/dist/index.d.cts +26 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +25 -0
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -10,9 +10,9 @@ A zero-dependency Node.js package for converting XML to HTML. Currently in pre-1
|
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
-
## v0.
|
|
13
|
+
## v0.x.x: XML Node Extraction & Scaffolding
|
|
14
14
|
|
|
15
|
-
Version `0.
|
|
15
|
+
Version `0.2.x` is focused entirely on parsing raw XML into a structured tree of nodes. 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.
|
|
16
16
|
|
|
17
17
|
```ts
|
|
18
18
|
interface XmlAttribute {
|
|
@@ -48,12 +48,13 @@ This scaffold is the foundation everything else will be built on. No transformat
|
|
|
48
48
|
|
|
49
49
|
> **Where I am right now**
|
|
50
50
|
>
|
|
51
|
-
> `v0.x` is building the scaffold
|
|
51
|
+
> `v0.x` is building the scaffold and the first render pass.
|
|
52
52
|
>
|
|
53
53
|
> - **`scaffold(xml)`** reads any XML string and returns a nested node tree
|
|
54
54
|
> - Every node knows its `role`, its `raw` source string, its `globalIndex` in the document, and its `localIndex` within its parent
|
|
55
55
|
> - Tag nodes (`openTag`, `selfTag`) also carry `xmlTag`, `xmlInner`, and `xmlAttributes` — the parsed tag name, raw attribute string, and structured attribute array
|
|
56
|
-
> - Broken XML is never thrown
|
|
56
|
+
> - Broken XML is never thrown — malformed nodes are flagged with `malformed: true` in place and the tree is built regardless
|
|
57
|
+
> - **`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
|
|
57
58
|
>
|
|
58
59
|
> `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.
|
|
59
60
|
|
|
@@ -69,6 +70,8 @@ npm install xml-to-html-converter
|
|
|
69
70
|
|
|
70
71
|
## Usage
|
|
71
72
|
|
|
73
|
+
### Parsing XML into a node tree
|
|
74
|
+
|
|
72
75
|
```js
|
|
73
76
|
import { scaffold } from "xml-to-html-converter";
|
|
74
77
|
|
|
@@ -131,6 +134,34 @@ const tree = scaffold(`
|
|
|
131
134
|
]
|
|
132
135
|
```
|
|
133
136
|
|
|
137
|
+
### Converting the tree to HTML
|
|
138
|
+
|
|
139
|
+
```js
|
|
140
|
+
import { scaffold, render } from "xml-to-html-converter";
|
|
141
|
+
|
|
142
|
+
const html = render(
|
|
143
|
+
scaffold(`
|
|
144
|
+
<bookstore>
|
|
145
|
+
<book category="cooking">
|
|
146
|
+
<title lang="en">Everyday Italian</title>
|
|
147
|
+
</book>
|
|
148
|
+
</bookstore>
|
|
149
|
+
`),
|
|
150
|
+
);
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
`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:
|
|
154
|
+
|
|
155
|
+
```html
|
|
156
|
+
<div data-tag="bookstore">
|
|
157
|
+
<div data-tag="book" data-attrs-category="cooking">
|
|
158
|
+
<div data-tag="title" data-attrs-lang="en">Everyday Italian</div>
|
|
159
|
+
</div>
|
|
160
|
+
</div>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Processing instructions and doctypes are dropped. Comments are passed through unchanged.
|
|
164
|
+
|
|
134
165
|
---
|
|
135
166
|
|
|
136
167
|
## Node Shape
|
|
@@ -222,7 +253,7 @@ const tree = scaffold("<root><unclosed><valid>text</valid></root>");
|
|
|
222
253
|
## Exports
|
|
223
254
|
|
|
224
255
|
```ts
|
|
225
|
-
import { scaffold, isMalformed } from "xml-to-html-converter";
|
|
256
|
+
import { scaffold, render, isMalformed } from "xml-to-html-converter";
|
|
226
257
|
import type {
|
|
227
258
|
XmlNode,
|
|
228
259
|
XmlNodeRole,
|
|
@@ -234,6 +265,7 @@ import type {
|
|
|
234
265
|
| Export | Kind | Description |
|
|
235
266
|
| ------------------ | -------- | --------------------------------------------------- |
|
|
236
267
|
| `scaffold` | function | Parses an XML string and returns a node tree |
|
|
268
|
+
| `render` | function | Converts a node tree to an HTML string |
|
|
237
269
|
| `isMalformed` | function | Type guard, narrows `XmlNode` to `MalformedXmlNode` |
|
|
238
270
|
| `XmlNode` | type | The shape of every node in the tree |
|
|
239
271
|
| `XmlNodeRole` | type | Union of all valid role strings |
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
isMalformed: () => isMalformed,
|
|
24
|
+
render: () => render,
|
|
25
|
+
scaffold: () => scaffold
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(src_exports);
|
|
28
|
+
|
|
29
|
+
// src/modules/render/render.ts
|
|
30
|
+
function render(nodes) {
|
|
31
|
+
return nodes.map(renderNode).join("");
|
|
32
|
+
}
|
|
33
|
+
function renderNode(node) {
|
|
34
|
+
if (node.role === "textLeaf") return node.raw;
|
|
35
|
+
if (node.role === "comment") return node.raw;
|
|
36
|
+
if (node.role === "processingInstruction") return "";
|
|
37
|
+
if (node.role === "doctype") return "";
|
|
38
|
+
if (node.role === "closeTag") return "";
|
|
39
|
+
const tag = node.xmlTag ?? "";
|
|
40
|
+
const attrs = buildDataAttrs(node);
|
|
41
|
+
const attrsHtml = attrs ? ` ${attrs}` : "";
|
|
42
|
+
if (node.role === "selfTag") {
|
|
43
|
+
return `<div data-tag="${tag}"${attrsHtml}></div>`;
|
|
44
|
+
}
|
|
45
|
+
const children = render(node.children ?? []);
|
|
46
|
+
return `<div data-tag="${tag}"${attrsHtml}>${children}</div>`;
|
|
47
|
+
}
|
|
48
|
+
function buildDataAttrs(node) {
|
|
49
|
+
if (!node.xmlAttributes || node.xmlAttributes.length === 0) return "";
|
|
50
|
+
return node.xmlAttributes.map(({ name, value }) => `data-attrs-${name}="${value}"`).join(" ");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// src/modules/scaffold/scaffold.ts
|
|
54
|
+
function parseXmlAttributes(xmlInner) {
|
|
55
|
+
const attributes = [];
|
|
56
|
+
let i = 0;
|
|
57
|
+
const s = xmlInner.trim();
|
|
58
|
+
while (i < s.length) {
|
|
59
|
+
while (i < s.length && /\s/.test(s[i])) i++;
|
|
60
|
+
if (i >= s.length) break;
|
|
61
|
+
const nameStart = i;
|
|
62
|
+
while (i < s.length && s[i] !== "=" && !/\s/.test(s[i])) i++;
|
|
63
|
+
const name = s.slice(nameStart, i).trim();
|
|
64
|
+
if (!name) break;
|
|
65
|
+
while (i < s.length && /\s/.test(s[i])) i++;
|
|
66
|
+
if (s[i] !== "=") break;
|
|
67
|
+
i++;
|
|
68
|
+
while (i < s.length && /\s/.test(s[i])) i++;
|
|
69
|
+
const quote = s[i];
|
|
70
|
+
if (quote !== '"' && quote !== "'") break;
|
|
71
|
+
i++;
|
|
72
|
+
const valueStart = i;
|
|
73
|
+
while (i < s.length && s[i] !== quote) i++;
|
|
74
|
+
const value = s.slice(valueStart, i);
|
|
75
|
+
i++;
|
|
76
|
+
attributes.push({ name, value });
|
|
77
|
+
}
|
|
78
|
+
return attributes.length > 0 ? attributes : void 0;
|
|
79
|
+
}
|
|
80
|
+
var MAX_DEPTH = 500;
|
|
81
|
+
function scaffold(xml) {
|
|
82
|
+
const counter = { value: 0 };
|
|
83
|
+
const { xmlNodes } = collectXmlNodes(xml, 0, null, counter, 0);
|
|
84
|
+
return xmlNodes;
|
|
85
|
+
}
|
|
86
|
+
function collectXmlNodes(xml, position, parentTag, counter, depth) {
|
|
87
|
+
if (depth > MAX_DEPTH) return { xmlNodes: [], position, closed: false };
|
|
88
|
+
const xmlNodes = [];
|
|
89
|
+
while (position < xml.length) {
|
|
90
|
+
const xmlNodeData = extractXmlNodes(xml, position);
|
|
91
|
+
if (xmlNodeData.role === "textLeaf" && xmlNodeData.raw.trim() === "") {
|
|
92
|
+
position = xmlNodeData.end;
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
if (xmlNodeData.role === "closeTag") {
|
|
96
|
+
if (xmlNodeData.tag === parentTag)
|
|
97
|
+
return { xmlNodes, position: xmlNodeData.end, closed: true };
|
|
98
|
+
xmlNodes.push({
|
|
99
|
+
role: "closeTag",
|
|
100
|
+
raw: xmlNodeData.raw,
|
|
101
|
+
xmlTag: xmlNodeData.tag || void 0,
|
|
102
|
+
xmlInner: xmlNodeData.xmlInner,
|
|
103
|
+
globalIndex: counter.value++,
|
|
104
|
+
localIndex: xmlNodes.length,
|
|
105
|
+
malformed: true
|
|
106
|
+
});
|
|
107
|
+
position = xmlNodeData.end;
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (xmlNodeData.role === "openTag" && !xmlNodeData.malformed) {
|
|
111
|
+
const globalIndex = counter.value++;
|
|
112
|
+
const localIndex = xmlNodes.length;
|
|
113
|
+
const nested = collectXmlNodes(
|
|
114
|
+
xml,
|
|
115
|
+
xmlNodeData.end,
|
|
116
|
+
xmlNodeData.tag,
|
|
117
|
+
counter,
|
|
118
|
+
depth + 1
|
|
119
|
+
);
|
|
120
|
+
const xmlNode2 = {
|
|
121
|
+
role: "openTag",
|
|
122
|
+
raw: xmlNodeData.raw,
|
|
123
|
+
xmlTag: xmlNodeData.tag || void 0,
|
|
124
|
+
xmlInner: xmlNodeData.xmlInner,
|
|
125
|
+
xmlAttributes: xmlNodeData.xmlAttributes,
|
|
126
|
+
globalIndex,
|
|
127
|
+
localIndex,
|
|
128
|
+
children: nested.xmlNodes
|
|
129
|
+
};
|
|
130
|
+
if (!nested.closed) xmlNode2.malformed = true;
|
|
131
|
+
xmlNodes.push(xmlNode2);
|
|
132
|
+
position = nested.position;
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
const xmlNode = {
|
|
136
|
+
role: xmlNodeData.role,
|
|
137
|
+
raw: xmlNodeData.raw,
|
|
138
|
+
xmlTag: xmlNodeData.tag || void 0,
|
|
139
|
+
xmlInner: xmlNodeData.xmlInner,
|
|
140
|
+
xmlAttributes: xmlNodeData.xmlAttributes,
|
|
141
|
+
globalIndex: counter.value++,
|
|
142
|
+
localIndex: xmlNodes.length
|
|
143
|
+
};
|
|
144
|
+
if (xmlNodeData.malformed) xmlNode.malformed = true;
|
|
145
|
+
if (xmlNodeData.role === "openTag") xmlNode.children = [];
|
|
146
|
+
xmlNodes.push(xmlNode);
|
|
147
|
+
position = xmlNodeData.end;
|
|
148
|
+
}
|
|
149
|
+
return { xmlNodes, position, closed: parentTag === null };
|
|
150
|
+
}
|
|
151
|
+
function findTagClose(xml, position) {
|
|
152
|
+
let i = position;
|
|
153
|
+
while (i < xml.length) {
|
|
154
|
+
const ch = xml[i];
|
|
155
|
+
if (ch === '"' || ch === "'") {
|
|
156
|
+
const closeQuote = xml.indexOf(ch, i + 1);
|
|
157
|
+
i = closeQuote === -1 ? xml.length : closeQuote + 1;
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
if (ch === ">") return i;
|
|
161
|
+
i++;
|
|
162
|
+
}
|
|
163
|
+
return -1;
|
|
164
|
+
}
|
|
165
|
+
function extractXmlNodes(xml, position) {
|
|
166
|
+
if (xml[position] !== "<") {
|
|
167
|
+
const end2 = xml.indexOf("<", position);
|
|
168
|
+
return {
|
|
169
|
+
raw: xml.slice(position, end2 === -1 ? xml.length : end2),
|
|
170
|
+
role: "textLeaf",
|
|
171
|
+
tag: "",
|
|
172
|
+
end: end2 === -1 ? xml.length : end2
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
if (xml[position + 1] === "?") {
|
|
176
|
+
const end2 = xml.indexOf("?>", position + 2);
|
|
177
|
+
return end2 === -1 ? {
|
|
178
|
+
raw: xml.slice(position),
|
|
179
|
+
role: "processingInstruction",
|
|
180
|
+
tag: "",
|
|
181
|
+
end: xml.length
|
|
182
|
+
} : {
|
|
183
|
+
raw: xml.slice(position, end2 + 2),
|
|
184
|
+
role: "processingInstruction",
|
|
185
|
+
tag: "",
|
|
186
|
+
end: end2 + 2
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
if (xml[position + 1] === "!" && xml[position + 2] === "[") {
|
|
190
|
+
const end2 = xml.indexOf("]]>", position + 3);
|
|
191
|
+
return end2 === -1 ? { raw: xml.slice(position), role: "textLeaf", tag: "", end: xml.length } : {
|
|
192
|
+
raw: xml.slice(position, end2 + 3),
|
|
193
|
+
role: "textLeaf",
|
|
194
|
+
tag: "",
|
|
195
|
+
end: end2 + 3
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
if (xml[position + 1] === "!" && xml[position + 2] === "-" && xml[position + 3] === "-") {
|
|
199
|
+
const end2 = xml.indexOf("-->", position + 4);
|
|
200
|
+
return end2 === -1 ? { raw: xml.slice(position), role: "comment", tag: "", end: xml.length } : {
|
|
201
|
+
raw: xml.slice(position, end2 + 3),
|
|
202
|
+
role: "comment",
|
|
203
|
+
tag: "",
|
|
204
|
+
end: end2 + 3
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
if (xml.startsWith("<!DOCTYPE", position)) {
|
|
208
|
+
const bracketOpen = xml.indexOf("[", position);
|
|
209
|
+
const firstClose = xml.indexOf(">", position);
|
|
210
|
+
const hasBracket = bracketOpen !== -1 && bracketOpen < firstClose;
|
|
211
|
+
if (hasBracket) {
|
|
212
|
+
const bracketClose = xml.indexOf("]>", bracketOpen);
|
|
213
|
+
const end3 = bracketClose === -1 ? xml.length : bracketClose + 2;
|
|
214
|
+
return { raw: xml.slice(position, end3), role: "doctype", tag: "", end: end3 };
|
|
215
|
+
}
|
|
216
|
+
const end2 = firstClose === -1 ? xml.length : firstClose + 1;
|
|
217
|
+
return { raw: xml.slice(position, end2), role: "doctype", tag: "", end: end2 };
|
|
218
|
+
}
|
|
219
|
+
const closeAt = findTagClose(xml, position + 1);
|
|
220
|
+
if (closeAt === -1)
|
|
221
|
+
return {
|
|
222
|
+
raw: xml.slice(position),
|
|
223
|
+
role: "openTag",
|
|
224
|
+
tag: "",
|
|
225
|
+
end: xml.length,
|
|
226
|
+
malformed: true
|
|
227
|
+
};
|
|
228
|
+
const raw = xml.slice(position, closeAt + 1);
|
|
229
|
+
const end = closeAt + 1;
|
|
230
|
+
const inner = xml.slice(position + 1, closeAt).trim();
|
|
231
|
+
if (inner.startsWith("/")) {
|
|
232
|
+
const tag2 = inner.slice(1).trim().split(/\s/)[0] ?? "";
|
|
233
|
+
const xmlInner2 = inner.slice(1).trim().slice(tag2.length).trim() || void 0;
|
|
234
|
+
return { raw, role: "closeTag", tag: tag2, xmlInner: xmlInner2, end };
|
|
235
|
+
}
|
|
236
|
+
if (inner.endsWith("/")) {
|
|
237
|
+
const trimmed = inner.slice(0, -1).trim();
|
|
238
|
+
const tag2 = trimmed.split(/\s/)[0] ?? "";
|
|
239
|
+
const xmlInner2 = trimmed.slice(tag2.length).trim() || void 0;
|
|
240
|
+
const xmlAttributes2 = xmlInner2 ? parseXmlAttributes(xmlInner2) : void 0;
|
|
241
|
+
return { raw, role: "selfTag", tag: tag2, xmlInner: xmlInner2, xmlAttributes: xmlAttributes2, end };
|
|
242
|
+
}
|
|
243
|
+
const tag = inner.split(/\s/)[0] ?? "";
|
|
244
|
+
const xmlInner = inner.slice(tag.length).trim() || void 0;
|
|
245
|
+
const xmlAttributes = xmlInner ? parseXmlAttributes(xmlInner) : void 0;
|
|
246
|
+
return { raw, role: "openTag", tag, xmlInner, xmlAttributes, end };
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// src/modules/scaffold/types.ts
|
|
250
|
+
function isMalformed(node) {
|
|
251
|
+
return node.malformed === true;
|
|
252
|
+
}
|
|
253
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
254
|
+
0 && (module.exports = {
|
|
255
|
+
isMalformed,
|
|
256
|
+
render,
|
|
257
|
+
scaffold
|
|
258
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
interface XmlAttribute {
|
|
2
|
+
name: string;
|
|
3
|
+
value: string;
|
|
4
|
+
}
|
|
5
|
+
type XmlNodeRole = "closeTag" | "comment" | "doctype" | "openTag" | "processingInstruction" | "selfTag" | "textLeaf";
|
|
6
|
+
interface XmlNode {
|
|
7
|
+
role: XmlNodeRole;
|
|
8
|
+
raw: string;
|
|
9
|
+
xmlTag?: string;
|
|
10
|
+
xmlInner?: string;
|
|
11
|
+
xmlAttributes?: XmlAttribute[];
|
|
12
|
+
globalIndex: number;
|
|
13
|
+
localIndex: number;
|
|
14
|
+
children?: XmlNode[];
|
|
15
|
+
malformed?: true;
|
|
16
|
+
}
|
|
17
|
+
type MalformedXmlNode = XmlNode & {
|
|
18
|
+
malformed: true;
|
|
19
|
+
};
|
|
20
|
+
declare function isMalformed(node: XmlNode): node is MalformedXmlNode;
|
|
21
|
+
|
|
22
|
+
declare function render(nodes: XmlNode[]): string;
|
|
23
|
+
|
|
24
|
+
declare function scaffold(xml: string): XmlNode[];
|
|
25
|
+
|
|
26
|
+
export { type MalformedXmlNode, type XmlAttribute, type XmlNode, type XmlNodeRole, isMalformed, render, scaffold };
|
package/dist/index.d.ts
CHANGED
|
@@ -19,6 +19,8 @@ type MalformedXmlNode = XmlNode & {
|
|
|
19
19
|
};
|
|
20
20
|
declare function isMalformed(node: XmlNode): node is MalformedXmlNode;
|
|
21
21
|
|
|
22
|
+
declare function render(nodes: XmlNode[]): string;
|
|
23
|
+
|
|
22
24
|
declare function scaffold(xml: string): XmlNode[];
|
|
23
25
|
|
|
24
|
-
export { type MalformedXmlNode, type XmlAttribute, type XmlNode, type XmlNodeRole, isMalformed, scaffold };
|
|
26
|
+
export { type MalformedXmlNode, type XmlAttribute, type XmlNode, type XmlNodeRole, isMalformed, render, scaffold };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
// src/modules/render/render.ts
|
|
2
|
+
function render(nodes) {
|
|
3
|
+
return nodes.map(renderNode).join("");
|
|
4
|
+
}
|
|
5
|
+
function renderNode(node) {
|
|
6
|
+
if (node.role === "textLeaf") return node.raw;
|
|
7
|
+
if (node.role === "comment") return node.raw;
|
|
8
|
+
if (node.role === "processingInstruction") return "";
|
|
9
|
+
if (node.role === "doctype") return "";
|
|
10
|
+
if (node.role === "closeTag") return "";
|
|
11
|
+
const tag = node.xmlTag ?? "";
|
|
12
|
+
const attrs = buildDataAttrs(node);
|
|
13
|
+
const attrsHtml = attrs ? ` ${attrs}` : "";
|
|
14
|
+
if (node.role === "selfTag") {
|
|
15
|
+
return `<div data-tag="${tag}"${attrsHtml}></div>`;
|
|
16
|
+
}
|
|
17
|
+
const children = render(node.children ?? []);
|
|
18
|
+
return `<div data-tag="${tag}"${attrsHtml}>${children}</div>`;
|
|
19
|
+
}
|
|
20
|
+
function buildDataAttrs(node) {
|
|
21
|
+
if (!node.xmlAttributes || node.xmlAttributes.length === 0) return "";
|
|
22
|
+
return node.xmlAttributes.map(({ name, value }) => `data-attrs-${name}="${value}"`).join(" ");
|
|
23
|
+
}
|
|
24
|
+
|
|
1
25
|
// src/modules/scaffold/scaffold.ts
|
|
2
26
|
function parseXmlAttributes(xmlInner) {
|
|
3
27
|
const attributes = [];
|
|
@@ -200,5 +224,6 @@ function isMalformed(node) {
|
|
|
200
224
|
}
|
|
201
225
|
export {
|
|
202
226
|
isMalformed,
|
|
227
|
+
render,
|
|
203
228
|
scaffold
|
|
204
229
|
};
|
package/package.json
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xml-to-html-converter",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Zero dependency XML to HTML converter for Node environments",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "./dist/index.
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
7
8
|
"types": "./dist/index.d.ts",
|
|
8
9
|
"exports": {
|
|
9
10
|
".": {
|
|
10
11
|
"types": "./dist/index.d.ts",
|
|
11
|
-
"import": "./dist/index.js"
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
12
14
|
}
|
|
13
15
|
},
|
|
14
16
|
"files": [
|