xml-to-html-converter 0.2.0 → 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/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
+ });
@@ -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/package.json CHANGED
@@ -1,14 +1,16 @@
1
1
  {
2
2
  "name": "xml-to-html-converter",
3
- "version": "0.2.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.js",
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": [