@levischuck/tiny-html 0.0.1

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/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Levi Schuck
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,220 @@
1
+ # tiny-html
2
+
3
+ A minimal, dependency-free TypeScript HTML parser and renderer that is easily compatible with react, hono, preact.
4
+
5
+ ## Usage
6
+
7
+ ### Basic Parsing and Rendering
8
+
9
+ ```typescript
10
+ import { readHtml, writeHtml, awaitHtmlNode } from '@levischuck/tiny-html';
11
+
12
+ // Parse HTML into HtmlNode structure
13
+ const result = readHtml('<div class="container"><h1>Hello</h1></div>');
14
+ console.log(result.node); // HtmlNode structure
15
+ console.log(result.doctype); // DOCTYPE if present
16
+ console.log(result.xml); // XML declaration if present
17
+
18
+ // Render HtmlNode back to HTML
19
+ const html = writeHtml(result);
20
+ // Output: <div className="container"><h1>Hello</h1></div>
21
+
22
+ // Render with options
23
+ const xhtml = writeHtml(result, { voidTrailingSlash: true });
24
+
25
+ // You can also render HtmlNode directly (without parsing first)
26
+ const node = { type: 'div', props: { children: 'Hello World' } };
27
+ const output = writeHtml(node);
28
+ // Output: <div>Hello World</div>
29
+
30
+ // Handle async HtmlNode trees (with Promise children)
31
+ const asyncNode = {
32
+ type: 'div',
33
+ props: {
34
+ children: [
35
+ Promise.resolve({ type: 'span', props: { children: 'Async content' } }),
36
+ 'Regular content'
37
+ ]
38
+ }
39
+ };
40
+ const resolved = await awaitHtmlNode(asyncNode);
41
+ const asyncHtml = writeHtml(resolved);
42
+ ```
43
+
44
+ ### Converting to Framework Elements
45
+
46
+ Use `htmlNodeTo` to convert HtmlNode structures to React, Preact, or other framework elements:
47
+
48
+ ```typescript
49
+ import { createElement } from 'react';
50
+ import type { ReactNode } from 'react';
51
+ import { readHtml, htmlNodeTo } from '@levischuck/tiny-html';
52
+
53
+ const result = readHtml('<div><span>Hello React!</span></div>');
54
+ const reactElement: ReactNode = htmlNodeTo(result.node, createElement);
55
+ // Now you can render reactElement in your React component
56
+ ```
57
+
58
+ This package provides a simple HTML parser and renderer with a structure compatible with React elements, making it easy to integrate with React-based rendering pipelines.
59
+
60
+ ## API
61
+
62
+ ### `readHtml(html: string): ParseResult`
63
+
64
+ Parses an HTML string into a ParseResult containing HtmlNode elements.
65
+
66
+ **Returns:**
67
+ ```typescript
68
+ interface ParseResult {
69
+ xml?: string; // XML declaration if present
70
+ doctype?: string; // DOCTYPE declaration if present
71
+ node: HtmlNode | HtmlNode[]; // Parsed content as HtmlNode
72
+ }
73
+ ```
74
+
75
+ ### `writeHtml(input: HtmlNode | ParseResult, options?: WriterOptions): string`
76
+
77
+ Renders a HtmlNode or ParseResult back to an HTML string.
78
+
79
+ **Parameters:**
80
+ - `input: HtmlNode | ParseResult` - The content to render
81
+ - `options?: WriterOptions` - Rendering options (see WriterOptions below)
82
+
83
+ **Returns:** HTML string
84
+
85
+ ### `awaitHtmlNode(node: HtmlNode | Promise<HtmlNode>): Promise<HtmlNode>`
86
+
87
+ Recursively awaits all Promise children in a HtmlNode tree. Useful for handling async content.
88
+
89
+ **Parameters:**
90
+ - `node: HtmlNode | Promise<HtmlNode>` - The node tree to resolve
91
+
92
+ **Returns:** A new HtmlNode with all promises resolved
93
+
94
+ **Note:** Incompatible types (functions, symbols) are dropped during resolution.
95
+
96
+ ### `htmlNodeTo<T>(node: HtmlNode, createElement: CreateElementFn<T>): T | null`
97
+
98
+ Generic converter that transforms HtmlNode structures into any element type using a provided createElement function.
99
+
100
+ **Parameters:**
101
+ - `node: HtmlNode` - The HtmlNode to convert
102
+ - `createElement: CreateElementFn<T>` - Function that creates elements of type T
103
+ - Signature: `(type: string, props: CreateElementProps, ...children: T[]) => T`
104
+
105
+ **Returns:** Converted element of type T, or null
106
+
107
+ **Example with React:**
108
+ ```typescript
109
+ import { createElement } from 'react';
110
+ import type { ReactNode } from 'react';
111
+ import { readHtml, htmlNodeTo } from '@levischuck/tiny-html';
112
+
113
+ const result = readHtml('<div><span>Hello</span></div>');
114
+ const reactElement = htmlNodeTo<ReactNode>(result.node, createElement);
115
+ ```
116
+
117
+ **Example with Preact:**
118
+ ```typescript
119
+ import { h } from 'preact';
120
+ import { readHtml, htmlNodeTo } from '@levischuck/tiny-html';
121
+
122
+ const result = readHtml('<div><span>Hello</span></div>');
123
+ const preactElement = htmlNodeTo(result.node, h);
124
+ ```
125
+
126
+ ## Types
127
+
128
+ ### `HtmlNode`
129
+
130
+ The core type representing parsed HTML content:
131
+ - HTML element: `{ type: string, props: HtmlProps }`
132
+ - Primitives: `string`, `number`, `boolean`, `null`, `undefined`, `bigint`
133
+ - Arrays: `HtmlNode[]`
134
+
135
+ ### `HtmlElement`
136
+
137
+ ```typescript
138
+ interface HtmlElement {
139
+ type: string;
140
+ props: HtmlProps;
141
+ }
142
+ ```
143
+
144
+ ### `HtmlProps`
145
+
146
+ ```typescript
147
+ interface HtmlProps {
148
+ [key: string]: string | number | boolean | HtmlStyle | HtmlNode | Promise<HtmlNode>;
149
+ children?: HtmlNode | Promise<HtmlNode>;
150
+ }
151
+ ```
152
+
153
+ ### `HtmlStyle`
154
+
155
+ ```typescript
156
+ interface HtmlStyle {
157
+ [key: string]: string;
158
+ }
159
+ ```
160
+
161
+ ### `CreateElementFn<T>`
162
+
163
+ Type for createElement functions used with `htmlNodeTo`.
164
+
165
+ ```typescript
166
+ type CreateElementFn<T> = (
167
+ type: string,
168
+ props: CreateElementProps,
169
+ ...children: T[]
170
+ ) => T;
171
+ ```
172
+
173
+ ### `CreateElementProps`
174
+
175
+ Props object passed to createElement functions.
176
+
177
+ ```typescript
178
+ type CreateElementProps = Record<string, any>;
179
+ ```
180
+
181
+ ### `ParseResult`
182
+
183
+ ```typescript
184
+ interface ParseResult {
185
+ xml?: string;
186
+ doctype?: string;
187
+ node: HtmlNode | HtmlNode[];
188
+ }
189
+ ```
190
+
191
+ ### `WriterOptions`
192
+
193
+ Options for controlling HTML output formatting.
194
+
195
+ ```typescript
196
+ interface WriterOptions {
197
+ useCDataForScripts?: boolean; // Wrap <script> content in CDATA
198
+ useCDataForStyles?: boolean; // Wrap <style> content in CDATA
199
+ xml?: string; // XML declaration to prepend
200
+ doctype?: string; // DOCTYPE declaration to prepend
201
+ voidTrailingSlash?: boolean; // Add trailing slash to void elements (e.g., <br />)
202
+ }
203
+ ```
204
+
205
+ **Options:**
206
+ - `useCDataForScripts?: boolean` - When true, wraps `<script>` content in CDATA sections. Useful for XHTML output. Default: `false`
207
+ - `useCDataForStyles?: boolean` - When true, wraps `<style>` content in CDATA sections. Useful for XHTML output. Default: `false`
208
+ - `xml?: string` - XML declaration to prepend to the output (e.g., `<?xml version="1.0" encoding="UTF-8"?>`)
209
+ - `doctype?: string` - DOCTYPE declaration to prepend to the output (e.g., `<!DOCTYPE html>`)
210
+ - `voidTrailingSlash?: boolean` - When true, adds trailing slash to void elements like `<br/>`, `<img/>`. Useful for XHTML compatibility. Default: `false`
211
+
212
+ ## Why use this?
213
+
214
+ There are many other great libraries to parse HTML.
215
+ I need to process things on the edge and I can rely on this being fast and available on every platform I want to use it.
216
+ Also.. I'm tired of writing little parsers here and there just to put them into a hono-jsx like format for post-processing.
217
+
218
+ ## License
219
+
220
+ MIT Licensed.
@@ -0,0 +1,10 @@
1
+ import { HtmlNode } from './types';
2
+ /**
3
+ * Recursively awaits all Promise children in a HtmlNode tree
4
+ * Returns a new HtmlNode with all promises resolved
5
+ * Incompatible types (functions, symbols, etc.) are dropped
6
+ *
7
+ * @param node - A HtmlNode that may contain promises
8
+ * @returns An HtmlNode with all promises resolved
9
+ */
10
+ export declare function awaitReactNode(node: HtmlNode | Promise<HtmlNode>): Promise<HtmlNode>;
@@ -0,0 +1,11 @@
1
+ export declare const NAMESPACE_HTML = "http://www.w3.org/1999/xhtml";
2
+ export declare const NAMESPACE_SVG = "http://www.w3.org/2000/svg";
3
+ export declare const NAMESPACE_MATHML = "http://www.w3.org/1998/Math/MathML";
4
+ export declare const VOID_ELEMENTS: Set<string>;
5
+ export declare const NEVER_SELF_CLOSE: Set<string>;
6
+ export declare const AUTO_CLOSING_SIBLINGS: Map<string, Set<string>>;
7
+ export declare const WHITESPACE_SENSITIVE: Set<string>;
8
+ export declare const SVG_TAG_CASE_MAP: Map<string, string>;
9
+ export declare const SVG_ATTR_CASE_MAP: Map<string, string>;
10
+ export declare const HTML_ENTITIES: Record<string, string>;
11
+ export declare const CHAR_TO_ENTITY: Record<string, string>;
@@ -0,0 +1,10 @@
1
+ import { HtmlNode } from './types.ts';
2
+ export type CreateElementProps = Record<string, any>;
3
+ export type CreateElementFn<T> = (type: string, props: CreateElementProps, ...children: any[]) => T;
4
+ /**
5
+ * Generic converter from HtmlNode to any element type T
6
+ * @param node - The HtmlNode to convert
7
+ * @param createElement - Function that creates elements of type T
8
+ * @returns Converted element of type T, or null
9
+ */
10
+ export declare function htmlNodeTo<T>(node: HtmlNode, createElement: CreateElementFn<T>): T | null;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Decodes HTML entities to their UTF-8 representation
3
+ * Handles named entities (&lt;, &gt;, &amp;, etc.), decimal (&#60;), and hex (&#x3C;) entities
4
+ */
5
+ export declare function decodeHtmlEntities(text: string): string;
6
+ /**
7
+ * Encodes special characters as HTML entities
8
+ * @param text - The text to encode
9
+ * @param inAttribute - If true, also encode quotes
10
+ */
11
+ export declare function encodeHtmlEntities(text: string, inAttribute?: boolean): string;
12
+ /**
13
+ * Escape CDATA content - split ]]> into ]]]]><![CDATA[>
14
+ */
15
+ export declare function escapeCData(content: string): string;
@@ -0,0 +1,17 @@
1
+ import { ParseResult, HtmlNode, WriterOptions } from './types.ts';
2
+ /**
3
+ * Parses HTML string into a ParseResult containing HtmlNode
4
+ */
5
+ export declare function readHtml(html: string): ParseResult;
6
+ /**
7
+ * Renders HtmlNode or ParseResult to HTML string
8
+ */
9
+ export declare function writeHtml(input: HtmlNode | ParseResult, options?: WriterOptions): string;
10
+ /**
11
+ * Recursively awaits all Promise children in a HtmlNode tree
12
+ * Returns a new HtmlNode with all promises resolved
13
+ */
14
+ export declare function awaitHtmlNode(node: HtmlNode | Promise<HtmlNode>): Promise<HtmlNode>;
15
+ export { htmlNodeTo } from './convert.ts';
16
+ export type { CreateElementFn, CreateElementProps } from './convert.ts';
17
+ export type { WriterOptions, ParseResult, HtmlNode, HtmlElement, HtmlProps, HtmlStyle } from './types.ts';
package/dist/index.js ADDED
@@ -0,0 +1,733 @@
1
+ const F = /* @__PURE__ */ new Set([
2
+ "area",
3
+ "base",
4
+ "br",
5
+ "col",
6
+ "embed",
7
+ "hr",
8
+ "img",
9
+ "input",
10
+ "link",
11
+ "meta",
12
+ "param",
13
+ "source",
14
+ "track",
15
+ "wbr"
16
+ ]), Q = /* @__PURE__ */ new Set([
17
+ // Containers
18
+ "div",
19
+ "span",
20
+ "p",
21
+ "section",
22
+ "article",
23
+ "aside",
24
+ "header",
25
+ "footer",
26
+ "nav",
27
+ "main",
28
+ // Forms
29
+ "button",
30
+ "textarea",
31
+ "select",
32
+ "label",
33
+ "form",
34
+ "fieldset",
35
+ "legend",
36
+ "optgroup",
37
+ // Lists
38
+ "ul",
39
+ "ol",
40
+ "li",
41
+ "dl",
42
+ "dt",
43
+ "dd",
44
+ // Script/style
45
+ "script",
46
+ "style",
47
+ // Formatting
48
+ "a",
49
+ "b",
50
+ "i",
51
+ "strong",
52
+ "em",
53
+ "u",
54
+ "s",
55
+ "del",
56
+ "ins",
57
+ "mark",
58
+ "small",
59
+ "sub",
60
+ "sup",
61
+ "code",
62
+ "kbd",
63
+ "samp",
64
+ "var",
65
+ "abbr",
66
+ "cite",
67
+ "dfn",
68
+ "q",
69
+ "time",
70
+ // Graphics
71
+ "canvas",
72
+ "svg",
73
+ // Tables
74
+ "table",
75
+ "tr",
76
+ "td",
77
+ "th",
78
+ "thead",
79
+ "tbody",
80
+ "tfoot",
81
+ "caption",
82
+ "colgroup",
83
+ // Headings
84
+ "h1",
85
+ "h2",
86
+ "h3",
87
+ "h4",
88
+ "h5",
89
+ "h6",
90
+ // Media
91
+ "video",
92
+ "audio",
93
+ "picture",
94
+ "figure",
95
+ "figcaption",
96
+ // Interactive
97
+ "details",
98
+ "summary",
99
+ "dialog",
100
+ // Other
101
+ "blockquote",
102
+ "pre",
103
+ "address",
104
+ "noscript",
105
+ "iframe",
106
+ "object",
107
+ "map",
108
+ "html",
109
+ "head",
110
+ "body",
111
+ "title",
112
+ "meta"
113
+ ]), q = /* @__PURE__ */ new Map([
114
+ ["p", /* @__PURE__ */ new Set(["p"])],
115
+ ["li", /* @__PURE__ */ new Set(["li"])],
116
+ ["dt", /* @__PURE__ */ new Set(["dt", "dd"])],
117
+ ["dd", /* @__PURE__ */ new Set(["dt", "dd"])],
118
+ ["option", /* @__PURE__ */ new Set(["option"])],
119
+ ["optgroup", /* @__PURE__ */ new Set(["optgroup"])],
120
+ ["thead", /* @__PURE__ */ new Set(["tbody", "tfoot"])],
121
+ ["tbody", /* @__PURE__ */ new Set(["thead", "tfoot"])],
122
+ ["tfoot", /* @__PURE__ */ new Set(["thead", "tbody"])],
123
+ ["tr", /* @__PURE__ */ new Set(["tr"])],
124
+ ["td", /* @__PURE__ */ new Set(["td", "th"])],
125
+ ["th", /* @__PURE__ */ new Set(["td", "th"])]
126
+ ]), V = /* @__PURE__ */ new Map([
127
+ ["altglyph", "altGlyph"],
128
+ ["altglyphdef", "altGlyphDef"],
129
+ ["altglyphitem", "altGlyphItem"],
130
+ ["animatecolor", "animateColor"],
131
+ ["animatemotion", "animateMotion"],
132
+ ["animatetransform", "animateTransform"],
133
+ ["clippath", "clipPath"],
134
+ ["feblend", "feBlend"],
135
+ ["fecolormatrix", "feColorMatrix"],
136
+ ["fecomponenttransfer", "feComponentTransfer"],
137
+ ["fecomposite", "feComposite"],
138
+ ["feconvolvematrix", "feConvolveMatrix"],
139
+ ["fediffuselighting", "feDiffuseLighting"],
140
+ ["fedisplacementmap", "feDisplacementMap"],
141
+ ["fedistantlight", "feDistantLight"],
142
+ ["fedropshadow", "feDropShadow"],
143
+ ["feflood", "feFlood"],
144
+ ["fefunca", "feFuncA"],
145
+ ["fefuncb", "feFuncB"],
146
+ ["fefuncg", "feFuncG"],
147
+ ["fefuncr", "feFuncR"],
148
+ ["fegaussianblur", "feGaussianBlur"],
149
+ ["feimage", "feImage"],
150
+ ["femerge", "feMerge"],
151
+ ["femergenode", "feMergeNode"],
152
+ ["femorphology", "feMorphology"],
153
+ ["feoffset", "feOffset"],
154
+ ["fepointlight", "fePointLight"],
155
+ ["fespecularlighting", "feSpecularLighting"],
156
+ ["fespotlight", "feSpotLight"],
157
+ ["fetile", "feTile"],
158
+ ["feturbulence", "feTurbulence"],
159
+ ["foreignobject", "foreignObject"],
160
+ ["glyphref", "glyphRef"],
161
+ ["lineargradient", "linearGradient"],
162
+ ["radialgradient", "radialGradient"],
163
+ ["textpath", "textPath"]
164
+ ]), z = /* @__PURE__ */ new Map([
165
+ ["attributename", "attributeName"],
166
+ ["attributetype", "attributeType"],
167
+ ["basefrequency", "baseFrequency"],
168
+ ["baseprofile", "baseProfile"],
169
+ ["calcmode", "calcMode"],
170
+ ["clippathunits", "clipPathUnits"],
171
+ ["diffuseconstant", "diffuseConstant"],
172
+ ["edgemode", "edgeMode"],
173
+ ["filterunits", "filterUnits"],
174
+ ["glyphref", "glyphRef"],
175
+ ["gradienttransform", "gradientTransform"],
176
+ ["gradientunits", "gradientUnits"],
177
+ ["kernelmatrix", "kernelMatrix"],
178
+ ["kernelunitlength", "kernelUnitLength"],
179
+ ["keypoints", "keyPoints"],
180
+ ["keysplines", "keySplines"],
181
+ ["keytimes", "keyTimes"],
182
+ ["lengthadjust", "lengthAdjust"],
183
+ ["limitingconeangle", "limitingConeAngle"],
184
+ ["markerheight", "markerHeight"],
185
+ ["markerunits", "markerUnits"],
186
+ ["markerwidth", "markerWidth"],
187
+ ["maskcontentunits", "maskContentUnits"],
188
+ ["maskunits", "maskUnits"],
189
+ ["numoctaves", "numOctaves"],
190
+ ["pathlength", "pathLength"],
191
+ ["patterncontentunits", "patternContentUnits"],
192
+ ["patterntransform", "patternTransform"],
193
+ ["patternunits", "patternUnits"],
194
+ ["pointsatx", "pointsAtX"],
195
+ ["pointsaty", "pointsAtY"],
196
+ ["pointsatz", "pointsAtZ"],
197
+ ["preservealpha", "preserveAlpha"],
198
+ ["preserveaspectratio", "preserveAspectRatio"],
199
+ ["primitiveunits", "primitiveUnits"],
200
+ ["refx", "refX"],
201
+ ["refy", "refY"],
202
+ ["repeatcount", "repeatCount"],
203
+ ["repeatdur", "repeatDur"],
204
+ ["requiredextensions", "requiredExtensions"],
205
+ ["requiredfeatures", "requiredFeatures"],
206
+ ["specularconstant", "specularConstant"],
207
+ ["specularexponent", "specularExponent"],
208
+ ["spreadmethod", "spreadMethod"],
209
+ ["startoffset", "startOffset"],
210
+ ["stddeviation", "stdDeviation"],
211
+ ["stitchtiles", "stitchTiles"],
212
+ ["surfacescale", "surfaceScale"],
213
+ ["systemlanguage", "systemLanguage"],
214
+ ["tablevalues", "tableValues"],
215
+ ["targetx", "targetX"],
216
+ ["targety", "targetY"],
217
+ ["textlength", "textLength"],
218
+ ["viewbox", "viewBox"],
219
+ ["viewtarget", "viewTarget"],
220
+ ["xchannelselector", "xChannelSelector"],
221
+ ["ychannelselector", "yChannelSelector"],
222
+ ["zoomandpan", "zoomAndPan"]
223
+ ]), I = {
224
+ lt: "<",
225
+ gt: ">",
226
+ amp: "&",
227
+ quot: '"',
228
+ apos: "'",
229
+ nbsp: " ",
230
+ iexcl: "¡",
231
+ cent: "¢",
232
+ pound: "£",
233
+ curren: "¤",
234
+ yen: "¥",
235
+ brvbar: "¦",
236
+ sect: "§",
237
+ uml: "¨",
238
+ copy: "©",
239
+ ordf: "ª",
240
+ laquo: "«",
241
+ not: "¬",
242
+ shy: "­",
243
+ reg: "®",
244
+ macr: "¯",
245
+ deg: "°",
246
+ plusmn: "±",
247
+ sup2: "²",
248
+ sup3: "³",
249
+ acute: "´",
250
+ micro: "µ",
251
+ para: "¶",
252
+ middot: "·",
253
+ cedil: "¸",
254
+ sup1: "¹",
255
+ ordm: "º",
256
+ raquo: "»",
257
+ frac14: "¼",
258
+ frac12: "½",
259
+ frac34: "¾",
260
+ iquest: "¿",
261
+ times: "×",
262
+ divide: "÷",
263
+ ndash: "–",
264
+ mdash: "—",
265
+ lsquo: "‘",
266
+ rsquo: "’",
267
+ sbquo: "‚",
268
+ ldquo: "“",
269
+ rdquo: "”",
270
+ bdquo: "„",
271
+ dagger: "†",
272
+ Dagger: "‡",
273
+ bull: "•",
274
+ hellip: "…",
275
+ permil: "‰",
276
+ prime: "′",
277
+ Prime: "″",
278
+ lsaquo: "‹",
279
+ rsaquo: "›",
280
+ oline: "‾",
281
+ frasl: "⁄",
282
+ euro: "€",
283
+ trade: "™",
284
+ larr: "←",
285
+ uarr: "↑",
286
+ rarr: "→",
287
+ darr: "↓",
288
+ harr: "↔",
289
+ lArr: "⇐",
290
+ uArr: "⇑",
291
+ rArr: "⇒",
292
+ dArr: "⇓",
293
+ hArr: "⇔"
294
+ }, B = {};
295
+ for (const [e, r] of Object.entries(I))
296
+ B[r] || (B[r] = e);
297
+ function v(e) {
298
+ return !e || typeof e != "string" || !e.includes("&") ? e : e.replace(/&(?:#[xX]([0-9a-fA-F]+)|#(\d+)|([a-zA-Z][a-zA-Z0-9]*));/g, (r, n, u, f) => {
299
+ if (n) {
300
+ const a = parseInt(n, 16);
301
+ return String.fromCodePoint(a);
302
+ } else if (u) {
303
+ const a = parseInt(u, 10);
304
+ return String.fromCodePoint(a);
305
+ } else if (f && I[f])
306
+ return I[f];
307
+ return r;
308
+ });
309
+ }
310
+ function G(e, r = !1) {
311
+ if (!e || typeof e != "string")
312
+ return e;
313
+ let n = e;
314
+ return n = n.replace(/&/g, "&amp;"), n = n.replace(/</g, "&lt;"), n = n.replace(/>/g, "&gt;"), r && (n = n.replace(/"/g, "&quot;")), n;
315
+ }
316
+ function Z(e) {
317
+ return e.replace(/\]\]>/g, "]]]]><![CDATA[>");
318
+ }
319
+ function k(e) {
320
+ return e.replace(/[-_]([a-z])/g, (r, n) => n.toUpperCase());
321
+ }
322
+ function $(e) {
323
+ return e.replace(/[A-Z]/g, (r) => `-${r.toLowerCase()}`);
324
+ }
325
+ function y(e, r, n) {
326
+ return new TextDecoder("utf-8").decode(e.slice(r, n));
327
+ }
328
+ function S(e) {
329
+ return e === 32 || e === 9 || e === 10 || e === 13;
330
+ }
331
+ function N(e) {
332
+ return e >= 97 && e <= 122 || // a-z
333
+ e >= 65 && e <= 90 || // A-Z
334
+ e >= 48 && e <= 57 || // 0-9
335
+ e === 45 || // -
336
+ e === 95 || // _
337
+ e === 58;
338
+ }
339
+ function K(e) {
340
+ const n = new TextEncoder().encode(e), u = {
341
+ node: []
342
+ }, f = [], a = [];
343
+ let c = "HTML", i = "TEXT", t = 0, p = 0, g = 0, A = 0, E = 0, d = "", P = 0, h = null;
344
+ function M() {
345
+ return a.length > 0 ? a[a.length - 1].children : f;
346
+ }
347
+ function X(s, o) {
348
+ if (s >= o) return;
349
+ const l = y(n, s, o), T = v(l);
350
+ T.length > 0 && M().push(T);
351
+ }
352
+ function U(s, o) {
353
+ if (s >= o) return;
354
+ const l = y(n, s, o);
355
+ l.length > 0 && M().push(l);
356
+ }
357
+ function C(s, o) {
358
+ const l = s.toLowerCase();
359
+ return o === "SVG" && V.has(l) ? V.get(l) : l;
360
+ }
361
+ function _(s, o) {
362
+ const l = s.toLowerCase();
363
+ if (l === "class") return "className";
364
+ if (l === "for") return "htmlFor";
365
+ if (o === "SVG")
366
+ return z.has(l) ? z.get(l) : s;
367
+ if (o === "HTML") {
368
+ const T = k(l);
369
+ return l === "class" || l === "for" ? l === "class" ? "className" : "htmlFor" : T;
370
+ }
371
+ return l;
372
+ }
373
+ function R(s) {
374
+ const o = C(s, c);
375
+ for (let l = a.length - 1; l >= 0; l--)
376
+ if (a[l].type === o) {
377
+ for (let T = a.length - 1; T >= l; T--) {
378
+ const m = a.pop(), b = {
379
+ type: m.type,
380
+ props: {
381
+ ...m.props,
382
+ children: m.children.length === 1 ? m.children[0] : m.children
383
+ }
384
+ };
385
+ a.length > 0 ? a[a.length - 1].children.push(b) : f.push(b), (m.type === "svg" || m.type === "math") && (c = "HTML");
386
+ }
387
+ return;
388
+ }
389
+ }
390
+ function w(s, o, l) {
391
+ const T = C(s, c);
392
+ if (a.length > 0 && q.has(T)) {
393
+ const b = q.get(T), j = a[a.length - 1].type;
394
+ b.has(j) && R(j);
395
+ }
396
+ let m = c;
397
+ if (T === "svg" ? m = "SVG" : T === "math" && (m = "MATHML"), F.has(T) || l) {
398
+ const b = {
399
+ type: T,
400
+ props: o
401
+ };
402
+ M().push(b);
403
+ } else {
404
+ const b = {
405
+ type: T,
406
+ props: o,
407
+ children: [],
408
+ namespace: m
409
+ };
410
+ a.push(b), c = m;
411
+ }
412
+ }
413
+ for (; t < n.length; ) {
414
+ const s = n[t];
415
+ switch (i) {
416
+ case "TEXT":
417
+ s === 60 && (X(p, t), i = "TAG_OPEN"), t++;
418
+ break;
419
+ case "TAG_OPEN":
420
+ s === 33 ? n[t + 1] === 45 && n[t + 2] === 45 ? (i = "COMMENT", t += 3) : n[t + 1] === 68 || n[t + 1] === 100 ? y(n, t, Math.min(t + 20, n.length)).toLowerCase().startsWith("!doctype") ? (i = "DOCTYPE", g = t, t++) : (p = t - 1, i = "TEXT") : n[t + 1] === 91 && n[t + 2] === 67 && y(n, t, Math.min(t + 9, n.length)).startsWith("![CDATA[") ? (i = "CDATA", p = t + 8, t += 8) : (p = t - 1, i = "TEXT") : s === 63 ? (i = "PROCESSING_INSTRUCTION", g = t - 1, t++) : s === 47 ? (i = "TAG_CLOSE_START", t++) : N(s) ? (g = t, i = "TAG_NAME", h = null, t++) : (p = t - 1, i = "TEXT");
421
+ break;
422
+ case "TAG_NAME":
423
+ if (S(s)) {
424
+ const o = y(n, g, t), l = o.toLowerCase();
425
+ h = {
426
+ type: o,
427
+ props: {},
428
+ children: [],
429
+ namespace: l === "svg" ? "SVG" : l === "math" ? "MATHML" : c
430
+ }, i = "ATTRIBUTES", t++;
431
+ } else if (s === 62) {
432
+ const o = y(n, g, t);
433
+ w(o, {}, !1);
434
+ const l = C(o, c);
435
+ l === "script" ? (i = "SCRIPT_CONTENT", p = t + 1) : l === "style" ? (i = "STYLE_CONTENT", p = t + 1) : (i = "TEXT", p = t + 1), t++;
436
+ } else s === 47 ? (i = "TAG_CLOSE_SELF", t++) : N(s) ? t++ : (p = g - 1, i = "TEXT");
437
+ break;
438
+ case "ATTRIBUTES":
439
+ if (S(s))
440
+ t++;
441
+ else if (s === 62) {
442
+ const o = h.type;
443
+ w(o, h.props, !1);
444
+ const l = C(o, c);
445
+ l === "script" ? (i = "SCRIPT_CONTENT", p = t + 1) : l === "style" ? (i = "STYLE_CONTENT", p = t + 1) : (i = "TEXT", p = t + 1), t++;
446
+ } else s === 47 ? (i = "TAG_CLOSE_SELF", t++) : N(s) ? (A = t, i = "ATTRIBUTE_NAME", t++) : (p = g - 1, i = "TEXT");
447
+ break;
448
+ case "ATTRIBUTE_NAME":
449
+ if (S(s)) {
450
+ d = y(n, A, t);
451
+ const o = _(d, h.namespace);
452
+ h.props[o] = !0, d = "", i = "ATTRIBUTES", t++;
453
+ } else if (s === 61)
454
+ d = y(n, A, t), i = "ATTRIBUTE_VALUE_START", t++;
455
+ else if (s === 62) {
456
+ d = y(n, A, t);
457
+ const o = _(d, h.namespace);
458
+ h.props[o] = !0, d = "";
459
+ const l = h.type;
460
+ w(l, h.props, !1);
461
+ const T = C(l, c);
462
+ T === "script" ? (i = "SCRIPT_CONTENT", p = t + 1) : T === "style" ? (i = "STYLE_CONTENT", p = t + 1) : (i = "TEXT", p = t + 1), t++;
463
+ } else if (s === 47) {
464
+ d = y(n, A, t);
465
+ const o = _(d, h.namespace);
466
+ h.props[o] = !0, d = "", i = "TAG_CLOSE_SELF", t++;
467
+ } else N(s) ? t++ : (p = g - 1, i = "TEXT");
468
+ break;
469
+ case "ATTRIBUTE_VALUE_START":
470
+ S(s) ? t++ : s === 34 || s === 39 ? (P = s, E = t + 1, i = "ATTRIBUTE_VALUE_QUOTED", t++) : (E = t, i = "ATTRIBUTE_VALUE_UNQUOTED");
471
+ break;
472
+ case "ATTRIBUTE_VALUE_QUOTED":
473
+ if (s === P) {
474
+ const o = y(n, E, t), l = v(o), T = _(d, h.namespace);
475
+ T === "style" ? h.props[T] = D(l) : h.props[T] = l, d = "", i = "ATTRIBUTES", t++;
476
+ } else
477
+ t++;
478
+ break;
479
+ case "ATTRIBUTE_VALUE_UNQUOTED":
480
+ if (S(s) || s === 62 || s === 47) {
481
+ const o = y(n, E, t), l = v(o), T = _(d, h.namespace);
482
+ T === "style" ? h.props[T] = D(l) : h.props[T] = l, d = "", i = "ATTRIBUTES";
483
+ } else
484
+ t++;
485
+ break;
486
+ case "TAG_CLOSE_SELF":
487
+ if (s === 62) {
488
+ const o = h.type;
489
+ w(o, h.props, !0), i = "TEXT", p = t + 1, t++;
490
+ } else
491
+ p = g - 1, i = "TEXT";
492
+ break;
493
+ case "TAG_CLOSE_START":
494
+ N(s) ? (g = t, i = "TAG_CLOSE_NAME", t++) : (p = t - 2, i = "TEXT");
495
+ break;
496
+ case "TAG_CLOSE_NAME":
497
+ if (s === 62) {
498
+ const o = y(n, g, t);
499
+ R(o), i = "TEXT", p = t + 1, t++;
500
+ } else S(s) || N(s) ? t++ : (p = g - 2, i = "TEXT");
501
+ break;
502
+ case "COMMENT":
503
+ s === 45 && n[t + 1] === 45 && n[t + 2] === 62 ? (i = "TEXT", p = t + 3, t += 3) : t++;
504
+ break;
505
+ case "DOCTYPE":
506
+ if (s === 62) {
507
+ const o = y(n, g, t + 1);
508
+ u.doctype = "<" + o, i = "TEXT", p = t + 1, t++;
509
+ } else
510
+ t++;
511
+ break;
512
+ case "CDATA":
513
+ s === 93 && n[t + 1] === 93 && n[t + 2] === 62 ? (U(p, t), i = "TEXT", p = t + 3, t += 3) : t++;
514
+ break;
515
+ case "PROCESSING_INSTRUCTION":
516
+ if (s === 63 && n[t + 1] === 62) {
517
+ const o = y(n, g, t + 2);
518
+ u.xml = o, i = "TEXT", p = t + 2, t += 2;
519
+ } else
520
+ t++;
521
+ break;
522
+ case "SCRIPT_CONTENT":
523
+ case "STYLE_CONTENT":
524
+ if (s === 60 && n[t + 1] === 47) {
525
+ const o = i === "SCRIPT_CONTENT" ? "script" : "style", l = "</" + o, T = y(n, t, Math.min(t + l.length + 1, n.length)).toLowerCase();
526
+ if (T.startsWith(l) && (T[l.length] === ">" || S(T.charCodeAt(l.length)))) {
527
+ U(p, t);
528
+ let m = t + l.length;
529
+ for (; m < n.length && n[m] !== 62; ) m++;
530
+ R(o), i = "TEXT", p = m + 1, t = m + 1;
531
+ } else
532
+ t++;
533
+ } else
534
+ t++;
535
+ break;
536
+ default:
537
+ t++;
538
+ }
539
+ }
540
+ for (i === "TEXT" ? X(p, t) : (i === "SCRIPT_CONTENT" || i === "STYLE_CONTENT") && U(p, t); a.length > 0; ) {
541
+ const s = a.pop(), o = {
542
+ type: s.type,
543
+ props: {
544
+ ...s.props,
545
+ children: s.children.length === 1 ? s.children[0] : s.children
546
+ }
547
+ };
548
+ a.length > 0 ? a[a.length - 1].children.push(o) : f.push(o);
549
+ }
550
+ return f.length === 0 ? u.node = null : f.length === 1 ? u.node = f[0] : u.node = f, u;
551
+ }
552
+ function D(e) {
553
+ const r = {}, u = v(e).split(/;(?![^(]*\))/);
554
+ for (const f of u) {
555
+ const a = f.indexOf(":");
556
+ if (a === -1) continue;
557
+ const c = f.substring(0, a).trim(), i = f.substring(a + 1).trim();
558
+ c && i && (r[k(c)] = i);
559
+ }
560
+ return r;
561
+ }
562
+ function H(e, r = {}) {
563
+ const n = [];
564
+ let u, f, a;
565
+ if (e && typeof e == "object" && "node" in e) {
566
+ const p = e;
567
+ u = p.node, f = p.xml ?? r.xml, a = p.doctype ?? r.doctype;
568
+ } else
569
+ u = e, f = r.xml, a = r.doctype;
570
+ f && (n.push(f), f.endsWith(`
571
+ `) || n.push(`
572
+ `)), a && (n.push(a), a.endsWith(`
573
+ `) || n.push(`
574
+ `));
575
+ const c = r.useCDataForScripts ?? !1, i = r.useCDataForStyles ?? !1, t = r.voidTrailingSlash ?? !0;
576
+ return O(u, n, "HTML", c, i, t), n.join("");
577
+ }
578
+ function O(e, r, n, u, f, a) {
579
+ if (e != null) {
580
+ if (typeof e == "string") {
581
+ r.push(G(e, !1));
582
+ return;
583
+ }
584
+ if (typeof e == "number" || typeof e == "bigint") {
585
+ r.push(String(e));
586
+ return;
587
+ }
588
+ if (typeof e == "boolean") {
589
+ r.push(String(e));
590
+ return;
591
+ }
592
+ if (Array.isArray(e)) {
593
+ for (const c of e)
594
+ O(c, r, n, u, f, a);
595
+ return;
596
+ }
597
+ if (typeof e != "function" && typeof e != "symbol" && !(e && typeof e == "object" && "then" in e && typeof e.then == "function") && e && typeof e == "object" && "type" in e && "props" in e) {
598
+ J(e, r, n, u, f, a);
599
+ return;
600
+ }
601
+ }
602
+ }
603
+ function J(e, r, n, u, f, a) {
604
+ var g;
605
+ const c = e.type;
606
+ let i = n;
607
+ if (c === "svg" ? i = "SVG" : c === "math" && (i = "MATHML"), r.push("<"), r.push(c), e.props) {
608
+ for (const [A, E] of Object.entries(e.props))
609
+ if (A !== "children" && !(E === !1 || E === null || E === void 0))
610
+ if (E === !0)
611
+ r.push(" "), r.push(A);
612
+ else if (A === "style" && typeof E == "object") {
613
+ const d = ee(E);
614
+ d && (r.push(' style="'), r.push(G(d, !0)), r.push('"'));
615
+ } else
616
+ r.push(" "), r.push(A), r.push('="'), r.push(G(String(E), !0)), r.push('"');
617
+ }
618
+ const t = (g = e.props) == null ? void 0 : g.children;
619
+ let p;
620
+ if (t && typeof t == "object" && "then" in t && typeof t.then == "function" ? p = !1 : p = t != null && (Array.isArray(t) && t.length > 0 || !Array.isArray(t) && t !== !1), F.has(c))
621
+ a ? r.push(" />") : r.push(">");
622
+ else if (p) {
623
+ r.push(">");
624
+ const A = t;
625
+ c === "script" && u || c === "style" && f ? (r.push("<![CDATA["), x(A, r, i, u, f, a), r.push("]]>")) : c === "script" || c === "style" ? W(A, r) : O(A, r, i, u, f, a), r.push("</"), r.push(c), r.push(">");
626
+ } else Q.has(c), r.push("></"), r.push(c), r.push(">");
627
+ }
628
+ function x(e, r, n, u, f, a, c) {
629
+ if (e != null) {
630
+ if (typeof e == "string") {
631
+ r.push(Z(e));
632
+ return;
633
+ }
634
+ if (typeof e == "number" || typeof e == "bigint" || typeof e == "boolean") {
635
+ r.push(String(e));
636
+ return;
637
+ }
638
+ if (Array.isArray(e)) {
639
+ for (const i of e)
640
+ x(i, r, n, u, f, a);
641
+ return;
642
+ }
643
+ O(e, r, n, u, f, a);
644
+ }
645
+ }
646
+ function W(e, r) {
647
+ if (e != null) {
648
+ if (typeof e == "string") {
649
+ r.push(e);
650
+ return;
651
+ }
652
+ if (typeof e == "number" || typeof e == "bigint" || typeof e == "boolean") {
653
+ r.push(String(e));
654
+ return;
655
+ }
656
+ if (Array.isArray(e)) {
657
+ for (const n of e)
658
+ W(n, r);
659
+ return;
660
+ }
661
+ }
662
+ }
663
+ function ee(e) {
664
+ const r = [];
665
+ for (const [n, u] of Object.entries(e))
666
+ if (u) {
667
+ const f = $(n);
668
+ r.push(`${f}: ${u}`);
669
+ }
670
+ return r.join("; ");
671
+ }
672
+ async function L(e) {
673
+ if (e == null)
674
+ return e;
675
+ if (e && typeof e == "object" && "then" in e && typeof e.then == "function") {
676
+ const r = await e;
677
+ return L(r);
678
+ }
679
+ if (typeof e == "string" || typeof e == "number" || typeof e == "boolean" || typeof e == "bigint")
680
+ return e;
681
+ if (typeof e != "function" && typeof e != "symbol") {
682
+ if (Array.isArray(e))
683
+ return await Promise.all(
684
+ e.filter((n) => !(n == null || typeof n == "function" || typeof n == "symbol")).map((n) => L(n))
685
+ );
686
+ if (e && typeof e == "object" && "type" in e && "props" in e) {
687
+ const r = e, n = {};
688
+ for (const [u, f] of Object.entries(r.props))
689
+ if (u === "children") {
690
+ const a = await L(f);
691
+ a != null && (n.children = a);
692
+ } else {
693
+ if (typeof f == "function" || typeof f == "symbol")
694
+ continue;
695
+ f != null && (n[u] = f);
696
+ }
697
+ return {
698
+ type: r.type,
699
+ props: n
700
+ };
701
+ }
702
+ }
703
+ }
704
+ function Y(e, r) {
705
+ if (e == null || typeof e == "string" || typeof e == "number" || typeof e == "boolean" || typeof e == "bigint")
706
+ return e;
707
+ if (Array.isArray(e))
708
+ return e.map((n) => Y(n, r));
709
+ if (typeof e == "object" && "type" in e && "props" in e) {
710
+ const { type: n, props: u } = e, { children: f, ...a } = u;
711
+ if (f !== void 0) {
712
+ const c = Y(f, r);
713
+ return c === null ? r(n, a) : Array.isArray(c) ? r(n, a, ...c) : r(n, a, c);
714
+ }
715
+ return r(n, a);
716
+ }
717
+ return null;
718
+ }
719
+ function te(e) {
720
+ return K(e);
721
+ }
722
+ function re(e, r = {}) {
723
+ return e && typeof e == "object" && "node" in e ? H(e, r) : e === void 0 ? "" : H(e, r);
724
+ }
725
+ async function ne(e) {
726
+ return await L(e);
727
+ }
728
+ export {
729
+ ne as awaitHtmlNode,
730
+ Y as htmlNodeTo,
731
+ te as readHtml,
732
+ re as writeHtml
733
+ };
@@ -0,0 +1,2 @@
1
+ import { ParseResult } from './types.ts';
2
+ export declare function parseHtml(html: string): ParseResult;
@@ -0,0 +1,54 @@
1
+ export interface HtmlStyle {
2
+ [key: string]: string;
3
+ }
4
+ export interface HtmlElement {
5
+ type: string;
6
+ props: HtmlProps;
7
+ }
8
+ export interface HtmlProps {
9
+ [key: string]: string | number | boolean | HtmlStyle | HtmlNode | Promise<HtmlNode>;
10
+ children?: HtmlNode | Promise<HtmlNode>;
11
+ }
12
+ export type HtmlNode = HtmlElement | string | number | bigint | boolean | null | undefined | HtmlNode[];
13
+ export declare enum ParserState {
14
+ TEXT = "TEXT",
15
+ TAG_OPEN = "TAG_OPEN",
16
+ TAG_NAME = "TAG_NAME",
17
+ ATTRIBUTES = "ATTRIBUTES",
18
+ ATTRIBUTE_NAME = "ATTRIBUTE_NAME",
19
+ ATTRIBUTE_VALUE_START = "ATTRIBUTE_VALUE_START",
20
+ ATTRIBUTE_VALUE_QUOTED = "ATTRIBUTE_VALUE_QUOTED",
21
+ ATTRIBUTE_VALUE_UNQUOTED = "ATTRIBUTE_VALUE_UNQUOTED",
22
+ TAG_CLOSE_SELF = "TAG_CLOSE_SELF",
23
+ TAG_CLOSE_START = "TAG_CLOSE_START",
24
+ TAG_CLOSE_NAME = "TAG_CLOSE_NAME",
25
+ COMMENT = "COMMENT",
26
+ DOCTYPE = "DOCTYPE",
27
+ CDATA = "CDATA",
28
+ PROCESSING_INSTRUCTION = "PROCESSING_INSTRUCTION",
29
+ SCRIPT_CONTENT = "SCRIPT_CONTENT",
30
+ STYLE_CONTENT = "STYLE_CONTENT"
31
+ }
32
+ export declare enum Namespace {
33
+ HTML = "HTML",
34
+ SVG = "SVG",
35
+ MATHML = "MATHML"
36
+ }
37
+ export interface ElementStackEntry {
38
+ type: string;
39
+ props: Partial<HtmlProps>;
40
+ children: HtmlNode[];
41
+ namespace: Namespace;
42
+ }
43
+ export interface ParseResult {
44
+ xml?: string;
45
+ doctype?: string;
46
+ node: HtmlNode | HtmlNode[];
47
+ }
48
+ export interface WriterOptions {
49
+ useCDataForScripts?: boolean;
50
+ useCDataForStyles?: boolean;
51
+ xml?: string;
52
+ doctype?: string;
53
+ voidTrailingSlash?: boolean;
54
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Converts a kebab-case or snake_case string to camelCase
3
+ * @example toCamelCase("foo-bar") => "fooBar"
4
+ * @example toCamelCase("background-color") => "backgroundColor"
5
+ */
6
+ export declare function toCamelCase(str: string): string;
7
+ /**
8
+ * Converts a camelCase string to kebab-case
9
+ * @example toKebabCase("fooBar") => "foo-bar"
10
+ * @example toKebabCase("backgroundColor") => "background-color"
11
+ */
12
+ export declare function toKebabCase(str: string): string;
13
+ /**
14
+ * Efficient string builder using array accumulation
15
+ */
16
+ export declare class StringBuilder {
17
+ private chunks;
18
+ append(str: string): void;
19
+ toString(): string;
20
+ clear(): void;
21
+ get length(): number;
22
+ }
23
+ /**
24
+ * Decodes a UTF-8 byte sequence to a string
25
+ */
26
+ export declare function decodeUtf8(bytes: Uint8Array, start: number, end: number): string;
27
+ /**
28
+ * Checks if a character code is whitespace
29
+ */
30
+ export declare function isWhitespace(code: number): boolean;
31
+ /**
32
+ * Checks if a character code is valid for tag/attribute names
33
+ */
34
+ export declare function isNameChar(code: number): boolean;
@@ -0,0 +1,2 @@
1
+ import { HtmlNode, WriterOptions, ParseResult } from './types.ts';
2
+ export declare function renderHtml(input: HtmlNode | ParseResult, options?: WriterOptions): string;
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@levischuck/tiny-html",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "license": "MIT",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/index.js",
12
+ "types": "./dist/index.d.ts"
13
+ }
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/LeviSchuck/tiny-packages",
18
+ "directory": "packages/tiny-html"
19
+ },
20
+ "publishConfig": {
21
+ "access": "public"
22
+ },
23
+ "files": [
24
+ "dist",
25
+ "README.md",
26
+ "LICENSE.txt"
27
+ ],
28
+ "keywords": [
29
+ "html",
30
+ "parser",
31
+ "react"
32
+ ],
33
+ "scripts": {
34
+ "build": "vite build",
35
+ "type-check": "bunx tsc --noEmit",
36
+ "build:jsr": "echo Nothing to build",
37
+ "lint": "oxlint -c ../../.oxlintrc.json"
38
+ },
39
+ "devDependencies": {
40
+ "@types/bun": "latest"
41
+ },
42
+ "peerDependencies": {
43
+ "typescript": "^5"
44
+ }
45
+ }