@utilix-tech/sdk 0.1.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.
Files changed (106) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +199 -0
  3. package/dist/api-8aZtWhSj.d.cts +308 -0
  4. package/dist/api-8aZtWhSj.d.ts +308 -0
  5. package/dist/chunk-2CJSLYWI.js +520 -0
  6. package/dist/chunk-3BAHSW4C.js +1385 -0
  7. package/dist/chunk-6YPV2AB5.js +1246 -0
  8. package/dist/chunk-BPVAB4P2.js +1126 -0
  9. package/dist/chunk-FL53T24A.js +257 -0
  10. package/dist/chunk-L6KCTHUW.js +1086 -0
  11. package/dist/chunk-MLKGABMK.js +7 -0
  12. package/dist/chunk-ROTPLW7T.js +265 -0
  13. package/dist/chunk-TSAGO3XP.js +1253 -0
  14. package/dist/chunk-UC656APA.js +1080 -0
  15. package/dist/chunk-W4UBLYFU.js +1219 -0
  16. package/dist/chunk-XST6X3HT.js +896 -0
  17. package/dist/chunk-XXYZLLHI.js +2227 -0
  18. package/dist/chunk-ZKL2VX2G.js +2215 -0
  19. package/dist/chunk-ZPQZEIXP.js +685 -0
  20. package/dist/code-QNrdLIR3.d.cts +327 -0
  21. package/dist/code-QNrdLIR3.d.ts +327 -0
  22. package/dist/color-tPwZCr9H.d.cts +229 -0
  23. package/dist/color-tPwZCr9H.d.ts +229 -0
  24. package/dist/css-Cf7AMGM-.d.cts +318 -0
  25. package/dist/css-Cf7AMGM-.d.ts +318 -0
  26. package/dist/data-rMjWNiOJ.d.cts +215 -0
  27. package/dist/data-rMjWNiOJ.d.ts +215 -0
  28. package/dist/encoding-7gmq-vkV.d.cts +108 -0
  29. package/dist/encoding-7gmq-vkV.d.ts +108 -0
  30. package/dist/generators-BGtRGpJZ.d.cts +118 -0
  31. package/dist/generators-BGtRGpJZ.d.ts +118 -0
  32. package/dist/hashing-CnetQFD_.d.cts +76 -0
  33. package/dist/hashing-CnetQFD_.d.ts +76 -0
  34. package/dist/index.cjs +15466 -0
  35. package/dist/index.d.cts +18 -0
  36. package/dist/index.d.ts +18 -0
  37. package/dist/index.js +20 -0
  38. package/dist/json-BjSoIS1h.d.cts +198 -0
  39. package/dist/json-BjSoIS1h.d.ts +198 -0
  40. package/dist/misc-DcVBManm.d.cts +201 -0
  41. package/dist/misc-DcVBManm.d.ts +201 -0
  42. package/dist/network-CNtmrDeN.d.cts +170 -0
  43. package/dist/network-CNtmrDeN.d.ts +170 -0
  44. package/dist/text-DqAjPtQ0.d.cts +319 -0
  45. package/dist/text-DqAjPtQ0.d.ts +319 -0
  46. package/dist/time-DbT8fjaF.d.cts +145 -0
  47. package/dist/time-DbT8fjaF.d.ts +145 -0
  48. package/dist/tools/api.cjs +1216 -0
  49. package/dist/tools/api.d.cts +1 -0
  50. package/dist/tools/api.d.ts +1 -0
  51. package/dist/tools/api.js +2 -0
  52. package/dist/tools/code.cjs +2212 -0
  53. package/dist/tools/code.d.cts +1 -0
  54. package/dist/tools/code.d.ts +1 -0
  55. package/dist/tools/code.js +2 -0
  56. package/dist/tools/color.cjs +1122 -0
  57. package/dist/tools/color.d.cts +1 -0
  58. package/dist/tools/color.d.ts +1 -0
  59. package/dist/tools/color.js +2 -0
  60. package/dist/tools/css.cjs +1242 -0
  61. package/dist/tools/css.d.cts +1 -0
  62. package/dist/tools/css.d.ts +1 -0
  63. package/dist/tools/css.js +2 -0
  64. package/dist/tools/data.cjs +1097 -0
  65. package/dist/tools/data.d.cts +1 -0
  66. package/dist/tools/data.d.ts +1 -0
  67. package/dist/tools/data.js +2 -0
  68. package/dist/tools/encoding.cjs +261 -0
  69. package/dist/tools/encoding.d.cts +1 -0
  70. package/dist/tools/encoding.d.ts +1 -0
  71. package/dist/tools/encoding.js +2 -0
  72. package/dist/tools/generators.cjs +521 -0
  73. package/dist/tools/generators.d.cts +1 -0
  74. package/dist/tools/generators.d.ts +1 -0
  75. package/dist/tools/generators.js +2 -0
  76. package/dist/tools/hashing.cjs +259 -0
  77. package/dist/tools/hashing.d.cts +1 -0
  78. package/dist/tools/hashing.d.ts +1 -0
  79. package/dist/tools/hashing.js +2 -0
  80. package/dist/tools/json.cjs +1270 -0
  81. package/dist/tools/json.d.cts +1 -0
  82. package/dist/tools/json.d.ts +1 -0
  83. package/dist/tools/json.js +2 -0
  84. package/dist/tools/misc.cjs +1082 -0
  85. package/dist/tools/misc.d.cts +1 -0
  86. package/dist/tools/misc.d.ts +1 -0
  87. package/dist/tools/misc.js +2 -0
  88. package/dist/tools/network.cjs +1381 -0
  89. package/dist/tools/network.d.cts +1 -0
  90. package/dist/tools/network.d.ts +1 -0
  91. package/dist/tools/network.js +2 -0
  92. package/dist/tools/text.cjs +2224 -0
  93. package/dist/tools/text.d.cts +1 -0
  94. package/dist/tools/text.d.ts +1 -0
  95. package/dist/tools/text.js +2 -0
  96. package/dist/tools/time.cjs +681 -0
  97. package/dist/tools/time.d.cts +1 -0
  98. package/dist/tools/time.d.ts +1 -0
  99. package/dist/tools/time.js +2 -0
  100. package/dist/tools/units.cjs +892 -0
  101. package/dist/tools/units.d.cts +1 -0
  102. package/dist/tools/units.d.ts +1 -0
  103. package/dist/tools/units.js +2 -0
  104. package/dist/units-6lwDYBvX.d.cts +302 -0
  105. package/dist/units-6lwDYBvX.d.ts +302 -0
  106. package/package.json +148 -0
@@ -0,0 +1,2224 @@
1
+ 'use strict';
2
+
3
+ var marked = require('marked');
4
+
5
+ // src/tools/text.ts
6
+ var WORDS_PER_MINUTE = 200;
7
+ function countWords(text) {
8
+ if (!text) {
9
+ return { words: 0, chars: 0, charsNoSpaces: 0, lines: 0, sentences: 0, paragraphs: 0, readingTimeSec: 0 };
10
+ }
11
+ const chars = text.length;
12
+ const charsNoSpaces = text.replace(/\s/g, "").length;
13
+ const lines = text.split("\n").length;
14
+ const words = text.trim() === "" ? 0 : text.trim().split(/\s+/).length;
15
+ const sentences = text.split(/[.!?]+/).filter((s) => s.trim().length > 0).length;
16
+ const paragraphs = text.split(/\n\s*\n/).filter((p) => p.trim().length > 0).length || (text.trim() ? 1 : 0);
17
+ const readingTimeSec = Math.ceil(words / WORDS_PER_MINUTE * 60);
18
+ return { words, chars, charsNoSpaces, lines, sentences, paragraphs, readingTimeSec };
19
+ }
20
+ function formatReadingTime(seconds) {
21
+ if (seconds < 60) return `${seconds}s`;
22
+ const minutes = Math.floor(seconds / 60);
23
+ const remainingSec = seconds % 60;
24
+ return remainingSec > 0 ? `${minutes}m ${remainingSec}s` : `${minutes}m`;
25
+ }
26
+ var CASE_FORMATS = [
27
+ "camelCase",
28
+ "PascalCase",
29
+ "snake_case",
30
+ "kebab-case",
31
+ "SCREAMING_SNAKE",
32
+ "Title Case",
33
+ "lowercase",
34
+ "UPPERCASE",
35
+ "dot.case",
36
+ "path/case"
37
+ ];
38
+ function tokenize(input) {
39
+ return input.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").split(/[\s\-_./\\]+/).map((w) => w.trim()).filter(Boolean);
40
+ }
41
+ function capitalize(word) {
42
+ if (!word) return "";
43
+ return word[0].toUpperCase() + word.slice(1).toLowerCase();
44
+ }
45
+ function convertCase(input, format) {
46
+ if (!input.trim()) return "";
47
+ const words = tokenize(input);
48
+ if (!words.length) return "";
49
+ switch (format) {
50
+ case "camelCase":
51
+ return words.map((w, i) => i === 0 ? w.toLowerCase() : capitalize(w)).join("");
52
+ case "PascalCase":
53
+ return words.map(capitalize).join("");
54
+ case "snake_case":
55
+ return words.map((w) => w.toLowerCase()).join("_");
56
+ case "kebab-case":
57
+ return words.map((w) => w.toLowerCase()).join("-");
58
+ case "SCREAMING_SNAKE":
59
+ return words.map((w) => w.toUpperCase()).join("_");
60
+ case "Title Case":
61
+ return words.map(capitalize).join(" ");
62
+ case "lowercase":
63
+ return words.join(" ").toLowerCase();
64
+ case "UPPERCASE":
65
+ return words.join(" ").toUpperCase();
66
+ case "dot.case":
67
+ return words.map((w) => w.toLowerCase()).join(".");
68
+ case "path/case":
69
+ return words.map((w) => w.toLowerCase()).join("/");
70
+ }
71
+ }
72
+ function convertAll(input) {
73
+ return Object.fromEntries(
74
+ CASE_FORMATS.map((f) => [f, convertCase(input, f)])
75
+ );
76
+ }
77
+ var LOREM_WORDS = [
78
+ "lorem",
79
+ "ipsum",
80
+ "dolor",
81
+ "sit",
82
+ "amet",
83
+ "consectetur",
84
+ "adipiscing",
85
+ "elit",
86
+ "sed",
87
+ "do",
88
+ "eiusmod",
89
+ "tempor",
90
+ "incididunt",
91
+ "ut",
92
+ "labore",
93
+ "et",
94
+ "dolore",
95
+ "magna",
96
+ "aliqua",
97
+ "enim",
98
+ "ad",
99
+ "minim",
100
+ "veniam",
101
+ "quis",
102
+ "nostrud",
103
+ "exercitation",
104
+ "ullamco",
105
+ "laboris",
106
+ "nisi",
107
+ "aliquip",
108
+ "ex",
109
+ "ea",
110
+ "commodo",
111
+ "consequat",
112
+ "duis",
113
+ "aute",
114
+ "irure",
115
+ "in",
116
+ "reprehenderit",
117
+ "voluptate",
118
+ "velit",
119
+ "esse",
120
+ "cillum",
121
+ "eu",
122
+ "fugiat",
123
+ "nulla",
124
+ "pariatur",
125
+ "excepteur",
126
+ "sint",
127
+ "occaecat",
128
+ "cupidatat",
129
+ "non",
130
+ "proident",
131
+ "sunt",
132
+ "culpa",
133
+ "qui",
134
+ "officia",
135
+ "deserunt",
136
+ "mollit",
137
+ "anim",
138
+ "id",
139
+ "est",
140
+ "laborum",
141
+ "curabitur",
142
+ "pretium",
143
+ "tincidunt",
144
+ "lacus",
145
+ "nunc",
146
+ "pulvinar",
147
+ "sapien",
148
+ "ligula",
149
+ "egestas",
150
+ "feugiat",
151
+ "viverra",
152
+ "nisl",
153
+ "ultrices",
154
+ "metus",
155
+ "malesuada",
156
+ "facilisis",
157
+ "venenatis",
158
+ "porttitor",
159
+ "quam",
160
+ "luctus",
161
+ "accumsan",
162
+ "tortor",
163
+ "posuere",
164
+ "ac",
165
+ "ut",
166
+ "consequat",
167
+ "semper",
168
+ "viverra",
169
+ "nam",
170
+ "libero",
171
+ "justo",
172
+ "laoreet",
173
+ "sit",
174
+ "amet",
175
+ "cursus",
176
+ "magna",
177
+ "ac",
178
+ "placerat"
179
+ ];
180
+ var LOREM_CLASSIC = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";
181
+ function loremWord(index) {
182
+ return LOREM_WORDS[index % LOREM_WORDS.length];
183
+ }
184
+ function makeSentence(startIndex, length = 8) {
185
+ const count = length + startIndex % 4;
186
+ const words = [];
187
+ for (let i = 0; i < count; i++) {
188
+ words.push(loremWord(startIndex + i));
189
+ }
190
+ const sentence = words[0].charAt(0).toUpperCase() + words[0].slice(1) + " " + words.slice(1).join(" ") + ".";
191
+ return { text: sentence, nextIndex: startIndex + count };
192
+ }
193
+ function makeParagraph(startIndex, sentenceCount2 = 4) {
194
+ const sentences = [];
195
+ let idx = startIndex;
196
+ const count = sentenceCount2 + startIndex % 3;
197
+ for (let i = 0; i < count; i++) {
198
+ const { text, nextIndex } = makeSentence(idx, 8 + i % 4);
199
+ sentences.push(text);
200
+ idx = nextIndex;
201
+ }
202
+ return { text: sentences.join(" "), nextIndex: idx };
203
+ }
204
+ function generateWords(count, startClassic = true) {
205
+ if (count <= 0) return "";
206
+ const words = [];
207
+ if (startClassic) {
208
+ const classicWords = LOREM_CLASSIC.replace(/[^a-z\s]/gi, "").split(/\s+/);
209
+ words.push(...classicWords.slice(0, Math.min(count, classicWords.length)));
210
+ }
211
+ let idx = words.length;
212
+ while (words.length < count) {
213
+ words.push(loremWord(idx++));
214
+ }
215
+ return words.slice(0, count).join(" ");
216
+ }
217
+ function generateSentences(count) {
218
+ if (count <= 0) return "";
219
+ const sentences = [LOREM_CLASSIC];
220
+ let idx = 20;
221
+ while (sentences.length < count) {
222
+ const { text, nextIndex } = makeSentence(idx, 8);
223
+ sentences.push(text);
224
+ idx = nextIndex;
225
+ }
226
+ return sentences.slice(0, count).join(" ");
227
+ }
228
+ function generateParagraphs(count) {
229
+ if (count <= 0) return "";
230
+ const paragraphs = [LOREM_CLASSIC + " " + makeSentence(20, 10).text + " " + makeSentence(32, 9).text];
231
+ let idx = 44;
232
+ while (paragraphs.length < count) {
233
+ const { text, nextIndex } = makeParagraph(idx, 4);
234
+ paragraphs.push(text);
235
+ idx = nextIndex;
236
+ }
237
+ return paragraphs.slice(0, count).join("\n\n");
238
+ }
239
+ function generate(unit, count) {
240
+ switch (unit) {
241
+ case "words":
242
+ return generateWords(count);
243
+ case "sentences":
244
+ return generateSentences(count);
245
+ case "paragraphs":
246
+ return generateParagraphs(count);
247
+ }
248
+ }
249
+ function slugify(input, separator = "-") {
250
+ return input.toLowerCase().normalize("NFD").replace(/[̀-ͯ]/g, "").replace(/[^a-z0-9]+/g, separator).replace(new RegExp(`\\${separator}+`, "g"), separator).replace(new RegExp(`^\\${separator}|\\${separator}$`, "g"), "");
251
+ }
252
+ function slugifyAll(input) {
253
+ return {
254
+ "-": slugify(input, "-"),
255
+ "_": slugify(input, "_"),
256
+ ".": slugify(input, ".")
257
+ };
258
+ }
259
+ var ESCAPE_MODES = ["json", "javascript", "html", "url", "csv"];
260
+ function escapeString(input, mode) {
261
+ switch (mode) {
262
+ case "json":
263
+ return input.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\t/g, "\\t").replace(/\r/g, "\\r").replace(/\0/g, "\\0");
264
+ case "javascript":
265
+ return input.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\t/g, "\\t").replace(/\r/g, "\\r").replace(/\0/g, "\\0").replace(/`/g, "\\`");
266
+ case "html":
267
+ return input.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
268
+ case "url":
269
+ return encodeURIComponent(input);
270
+ case "csv": {
271
+ if (/[,\n"]/.test(input)) {
272
+ return '"' + input.replace(/"/g, '""') + '"';
273
+ }
274
+ return input;
275
+ }
276
+ }
277
+ }
278
+ function unescapeString(input, mode) {
279
+ switch (mode) {
280
+ case "json":
281
+ return input.replace(/\\0/g, "\0").replace(/\\r/g, "\r").replace(/\\t/g, " ").replace(/\\n/g, "\n").replace(/\\"/g, '"').replace(/\\\\/g, "\\");
282
+ case "javascript":
283
+ return input.replace(/\\0/g, "\0").replace(/\\r/g, "\r").replace(/\\t/g, " ").replace(/\\n/g, "\n").replace(/\\`/g, "`").replace(/\\"/g, '"').replace(/\\\\/g, "\\");
284
+ case "html":
285
+ return input.replace(/&#39;/g, "'").replace(/&quot;/g, '"').replace(/&gt;/g, ">").replace(/&lt;/g, "<").replace(/&amp;/g, "&");
286
+ case "url":
287
+ return decodeURIComponent(input);
288
+ case "csv": {
289
+ if (input.startsWith('"') && input.endsWith('"')) {
290
+ return input.slice(1, -1).replace(/""/g, '"');
291
+ }
292
+ return input;
293
+ }
294
+ }
295
+ }
296
+ function escapeAll(input) {
297
+ return {
298
+ json: escapeString(input, "json"),
299
+ javascript: escapeString(input, "javascript"),
300
+ html: escapeString(input, "html"),
301
+ url: escapeString(input, "url"),
302
+ csv: escapeString(input, "csv")
303
+ };
304
+ }
305
+ var LINE_OPS = [
306
+ "sort-asc",
307
+ "sort-desc",
308
+ "sort-natural",
309
+ "reverse",
310
+ "dedupe",
311
+ "dedupe-ci",
312
+ "shuffle",
313
+ "trim",
314
+ "remove-empty",
315
+ "number-lines"
316
+ ];
317
+ function applyOp(input, op) {
318
+ if (input === "") return "";
319
+ const lines = input.split("\n");
320
+ switch (op) {
321
+ case "sort-asc":
322
+ return [...lines].sort((a, b) => a.localeCompare(b)).join("\n");
323
+ case "sort-desc":
324
+ return [...lines].sort((a, b) => b.localeCompare(a)).join("\n");
325
+ case "sort-natural":
326
+ return [...lines].sort((a, b) => a.localeCompare(b, void 0, { numeric: true, sensitivity: "base" })).join("\n");
327
+ case "reverse":
328
+ return [...lines].reverse().join("\n");
329
+ case "dedupe": {
330
+ const seen = /* @__PURE__ */ new Set();
331
+ return lines.filter((line) => {
332
+ if (seen.has(line)) return false;
333
+ seen.add(line);
334
+ return true;
335
+ }).join("\n");
336
+ }
337
+ case "dedupe-ci": {
338
+ const seen = /* @__PURE__ */ new Set();
339
+ return lines.filter((line) => {
340
+ const key = line.toLowerCase();
341
+ if (seen.has(key)) return false;
342
+ seen.add(key);
343
+ return true;
344
+ }).join("\n");
345
+ }
346
+ case "shuffle": {
347
+ const arr = [...lines];
348
+ for (let i = arr.length - 1; i > 0; i--) {
349
+ const j = Math.floor(Math.random() * (i + 1));
350
+ [arr[i], arr[j]] = [arr[j], arr[i]];
351
+ }
352
+ return arr.join("\n");
353
+ }
354
+ case "trim":
355
+ return lines.map((line) => line.trim()).join("\n");
356
+ case "remove-empty":
357
+ return lines.filter((line) => line.trim() !== "").join("\n");
358
+ case "number-lines":
359
+ return lines.map((line, i) => `${i + 1}. ${line}`).join("\n");
360
+ default:
361
+ return input;
362
+ }
363
+ }
364
+ function applyOps(input, ops) {
365
+ return ops.reduce((current, op) => applyOp(current, op), input);
366
+ }
367
+ var DEFAULT_CONVERT_OPTIONS = {
368
+ headingStyle: "atx",
369
+ bulletStyle: "-",
370
+ codeBlockStyle: "fenced",
371
+ linkStyle: "inline"
372
+ };
373
+ function parseHtml(html) {
374
+ let i = 0;
375
+ function parseAttrs(attrStr) {
376
+ const attrs = {};
377
+ const re = /([a-zA-Z][a-zA-Z0-9-]*)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]*)))?/g;
378
+ let m;
379
+ while ((m = re.exec(attrStr)) !== null) {
380
+ if (m[1]) {
381
+ attrs[m[1].toLowerCase()] = m[2] ?? m[3] ?? m[4] ?? "";
382
+ }
383
+ }
384
+ return attrs;
385
+ }
386
+ function parseNodes(endTag) {
387
+ const result = [];
388
+ while (i < html.length) {
389
+ if (html[i] === "<") {
390
+ if (html.startsWith("<!--", i)) {
391
+ const end = html.indexOf("-->", i);
392
+ i = end === -1 ? html.length : end + 3;
393
+ continue;
394
+ }
395
+ const tagMatch = html.slice(i).match(/^<\/([a-zA-Z][a-zA-Z0-9]*)\s*>/);
396
+ if (tagMatch) {
397
+ if (endTag && tagMatch[1].toLowerCase() === endTag.toLowerCase()) {
398
+ i += tagMatch[0].length;
399
+ return result;
400
+ }
401
+ i += tagMatch[0].length;
402
+ continue;
403
+ }
404
+ const selfClosingMatch = html.slice(i).match(/^<([a-zA-Z][a-zA-Z0-9]*)([^>]*)\/\s*>/);
405
+ if (selfClosingMatch) {
406
+ const tag = selfClosingMatch[1].toLowerCase();
407
+ const attrs = parseAttrs(selfClosingMatch[2]);
408
+ result.push({ type: "element", tag, attrs, children: [] });
409
+ i += selfClosingMatch[0].length;
410
+ continue;
411
+ }
412
+ const openMatch = html.slice(i).match(/^<([a-zA-Z][a-zA-Z0-9]*)([^>]*)>/);
413
+ if (openMatch) {
414
+ const tag = openMatch[1].toLowerCase();
415
+ const attrs = parseAttrs(openMatch[2]);
416
+ i += openMatch[0].length;
417
+ const voidTags = /* @__PURE__ */ new Set(["br", "hr", "img", "input", "meta", "link"]);
418
+ if (voidTags.has(tag)) {
419
+ result.push({ type: "element", tag, attrs, children: [] });
420
+ continue;
421
+ }
422
+ if (tag === "script" || tag === "style") {
423
+ const closeIdx = html.toLowerCase().indexOf(`</${tag}>`, i);
424
+ i = closeIdx === -1 ? html.length : closeIdx + tag.length + 3;
425
+ continue;
426
+ }
427
+ const children = parseNodes(tag);
428
+ result.push({ type: "element", tag, attrs, children });
429
+ continue;
430
+ }
431
+ result.push({ type: "text", text: "<" });
432
+ i++;
433
+ } else {
434
+ let j = i;
435
+ while (j < html.length && html[j] !== "<") j++;
436
+ const raw = html.slice(i, j);
437
+ result.push({ type: "text", text: decodeHtmlEntities(raw) });
438
+ i = j;
439
+ }
440
+ }
441
+ return result;
442
+ }
443
+ i = 0;
444
+ return parseNodes();
445
+ }
446
+ function decodeHtmlEntities(str) {
447
+ return str.replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&#39;/g, "'").replace(/&nbsp;/g, " ").replace(/&#(\d+);/g, (_, code) => String.fromCharCode(parseInt(code, 10))).replace(/&#x([0-9a-fA-F]+);/g, (_, code) => String.fromCharCode(parseInt(code, 16)));
448
+ }
449
+ function getTextContent(nodes) {
450
+ return nodes.map((n) => {
451
+ if (n.type === "text") return n.text ?? "";
452
+ return getTextContent(n.children ?? []);
453
+ }).join("");
454
+ }
455
+ function convertNodes(nodes, ctx, inline = false) {
456
+ return nodes.map((n) => convertNode(n, ctx, inline)).join("");
457
+ }
458
+ function convertNode(node, ctx, inline = false) {
459
+ if (node.type === "text") {
460
+ return node.text ?? "";
461
+ }
462
+ const tag = node.tag ?? "";
463
+ const children = node.children ?? [];
464
+ const attrs = node.attrs ?? {};
465
+ switch (tag) {
466
+ case "h1":
467
+ case "h2":
468
+ case "h3":
469
+ case "h4":
470
+ case "h5":
471
+ case "h6": {
472
+ const level = parseInt(tag[1], 10);
473
+ const text = convertNodes(children, ctx, true).trim();
474
+ if (ctx.options.headingStyle === "setext" && level <= 2) {
475
+ const underline = level === 1 ? "=".repeat(text.length) : "-".repeat(text.length);
476
+ return `
477
+
478
+ ${text}
479
+ ${underline}
480
+
481
+ `;
482
+ }
483
+ const hashes = "#".repeat(level);
484
+ return `
485
+
486
+ ${hashes} ${text}
487
+
488
+ `;
489
+ }
490
+ case "p": {
491
+ const content = convertNodes(children, ctx, true).trim();
492
+ if (!content) return "";
493
+ return `
494
+
495
+ ${content}
496
+
497
+ `;
498
+ }
499
+ case "strong":
500
+ case "b": {
501
+ const content = convertNodes(children, ctx, true);
502
+ return `**${content}**`;
503
+ }
504
+ case "em":
505
+ case "i": {
506
+ const content = convertNodes(children, ctx, true);
507
+ return `*${content}*`;
508
+ }
509
+ case "del":
510
+ case "s": {
511
+ const content = convertNodes(children, ctx, true);
512
+ return `~~${content}~~`;
513
+ }
514
+ case "a": {
515
+ const href = attrs["href"] ?? "";
516
+ const text = convertNodes(children, ctx, true);
517
+ if (ctx.options.linkStyle === "reference") {
518
+ const existing = ctx.refs.find((r) => r.url === href);
519
+ const idx = existing ? existing.index : (() => {
520
+ const refIdx = ctx.refs.length + 1;
521
+ ctx.refs.push({ url: href, index: refIdx });
522
+ return refIdx;
523
+ })();
524
+ return `[${text}][${idx}]`;
525
+ }
526
+ return `[${text}](${href})`;
527
+ }
528
+ case "img": {
529
+ const src = attrs["src"] ?? "";
530
+ const alt = attrs["alt"] ?? "";
531
+ return `![${alt}](${src})`;
532
+ }
533
+ case "code": {
534
+ const text = getTextContent(children);
535
+ if (text.includes("`")) {
536
+ return `\`\`${text}\`\``;
537
+ }
538
+ return `\`${text}\``;
539
+ }
540
+ case "pre": {
541
+ const codeChild = children.find((c) => c.type === "element" && c.tag === "code");
542
+ const raw = codeChild ? getTextContent(codeChild.children ?? []) : getTextContent(children);
543
+ const lang = codeChild ? (codeChild.attrs?.["class"] ?? "").replace(/language-/, "").trim() : "";
544
+ const trimmed = raw.replace(/^\n/, "").replace(/\n$/, "");
545
+ if (ctx.options.codeBlockStyle === "indented") {
546
+ const indented = trimmed.split("\n").map((l) => ` ${l}`).join("\n");
547
+ return `
548
+
549
+ ${indented}
550
+
551
+ `;
552
+ }
553
+ return `
554
+
555
+ \`\`\`${lang}
556
+ ${trimmed}
557
+ \`\`\`
558
+
559
+ `;
560
+ }
561
+ case "blockquote": {
562
+ const inner = convertNodes(children, ctx).trim();
563
+ const quoted = inner.split("\n").map((l) => `> ${l}`).join("\n");
564
+ return `
565
+
566
+ ${quoted}
567
+
568
+ `;
569
+ }
570
+ case "ul": {
571
+ ctx.listStack.push({ ordered: false, counter: 0 });
572
+ const items = convertNodes(children, ctx).replace(/\n$/, "");
573
+ ctx.listStack.pop();
574
+ const depth = ctx.listStack.length;
575
+ return depth === 0 ? `
576
+
577
+ ${items}
578
+
579
+ ` : `
580
+ ${items}`;
581
+ }
582
+ case "ol": {
583
+ ctx.listStack.push({ ordered: true, counter: 0 });
584
+ const items = convertNodes(children, ctx).replace(/\n$/, "");
585
+ ctx.listStack.pop();
586
+ const depth = ctx.listStack.length;
587
+ return depth === 0 ? `
588
+
589
+ ${items}
590
+
591
+ ` : `
592
+ ${items}`;
593
+ }
594
+ case "li": {
595
+ const current = ctx.listStack[ctx.listStack.length - 1];
596
+ const indent = " ".repeat(Math.max(0, ctx.listStack.length - 1));
597
+ let prefix;
598
+ if (current?.ordered) {
599
+ current.counter++;
600
+ prefix = `${current.counter}.`;
601
+ } else {
602
+ prefix = ctx.options.bulletStyle;
603
+ }
604
+ const content = convertNodes(children, ctx, false).trim();
605
+ return `${indent}${prefix} ${content}
606
+ `;
607
+ }
608
+ case "br": {
609
+ return " \n";
610
+ }
611
+ case "hr": {
612
+ return "\n\n---\n\n";
613
+ }
614
+ case "table": {
615
+ return `
616
+
617
+ ${convertHtmlTable(children, ctx)}
618
+
619
+ `;
620
+ }
621
+ case "thead":
622
+ case "tbody":
623
+ case "tfoot": {
624
+ return convertNodes(children, ctx);
625
+ }
626
+ case "tr": {
627
+ const cells = children.filter((c) => c.type === "element" && (c.tag === "th" || c.tag === "td")).map((c) => convertNodes(c.children ?? [], ctx, true).trim());
628
+ return `| ${cells.join(" | ")} |
629
+ `;
630
+ }
631
+ case "th":
632
+ case "td": {
633
+ return convertNodes(children, ctx, true).trim();
634
+ }
635
+ case "div":
636
+ case "section":
637
+ case "article":
638
+ case "main":
639
+ case "header":
640
+ case "footer":
641
+ case "nav":
642
+ case "aside": {
643
+ return convertNodes(children, ctx);
644
+ }
645
+ case "span": {
646
+ return convertNodes(children, ctx, inline);
647
+ }
648
+ default: {
649
+ return convertNodes(children, ctx, inline);
650
+ }
651
+ }
652
+ }
653
+ function convertHtmlTable(nodes, ctx) {
654
+ const rows = [];
655
+ let headerRowIndex = -1;
656
+ function collectRows(nodes2, fromHead) {
657
+ for (const node of nodes2) {
658
+ if (node.type !== "element") continue;
659
+ if (node.tag === "thead") {
660
+ collectRows(node.children ?? [], true);
661
+ } else if (node.tag === "tbody" || node.tag === "tfoot") {
662
+ collectRows(node.children ?? [], false);
663
+ } else if (node.tag === "tr") {
664
+ const cells = (node.children ?? []).filter((c) => c.type === "element" && (c.tag === "th" || c.tag === "td")).map((c) => convertNodes(c.children ?? [], ctx, true).trim());
665
+ if (fromHead && headerRowIndex === -1) {
666
+ headerRowIndex = rows.length;
667
+ }
668
+ rows.push(cells);
669
+ }
670
+ }
671
+ }
672
+ collectRows(nodes, false);
673
+ if (rows.length === 0) return "";
674
+ const colCount = Math.max(...rows.map((r) => r.length));
675
+ const normalizeRow = (r) => {
676
+ while (r.length < colCount) r.push("");
677
+ return r;
678
+ };
679
+ const lines = [];
680
+ const effectiveHeaderIdx = headerRowIndex >= 0 ? headerRowIndex : 0;
681
+ rows.forEach((row, idx) => {
682
+ const normalized = normalizeRow([...row]);
683
+ lines.push(`| ${normalized.join(" | ")} |`);
684
+ if (idx === effectiveHeaderIdx) {
685
+ lines.push(`| ${normalized.map(() => "---").join(" | ")} |`);
686
+ }
687
+ });
688
+ return lines.join("\n");
689
+ }
690
+ function cleanupOutput(str) {
691
+ return str.replace(/\n{3,}/g, "\n\n").replace(/^\n+/, "").replace(/\n+$/, "");
692
+ }
693
+ function htmlToMarkdown(html, options) {
694
+ if (!html || !html.trim()) return "";
695
+ const opts = { ...DEFAULT_CONVERT_OPTIONS, ...options };
696
+ const ctx = {
697
+ options: opts,
698
+ refs: [],
699
+ listStack: []
700
+ };
701
+ const nodes = parseHtml(html.trim());
702
+ const raw = convertNodes(nodes, ctx);
703
+ let result = cleanupOutput(raw);
704
+ if (opts.linkStyle === "reference" && ctx.refs.length > 0) {
705
+ const refBlock = ctx.refs.map((r) => `[${r.index}]: ${r.url}`).join("\n");
706
+ result = `${result}
707
+
708
+ ${refBlock}`;
709
+ }
710
+ return result;
711
+ }
712
+ function markdownToHtml(markdown) {
713
+ if (!markdown || !markdown.trim()) return "";
714
+ const lines = markdown.split("\n");
715
+ const output = [];
716
+ let i = 0;
717
+ function processInline(text) {
718
+ let result = text;
719
+ result = result.replace(/!\[([^\]]*)\]\(([^)]*)\)/g, '<img alt="$1" src="$2">');
720
+ result = result.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>');
721
+ result = result.replace(/~~([^~]+)~~/g, "<del>$1</del>");
722
+ result = result.replace(/\*\*([^*]+)\*\*/g, "<strong>$1</strong>");
723
+ result = result.replace(/__([^_]+)__/g, "<strong>$1</strong>");
724
+ result = result.replace(/\*([^*]+)\*/g, "<em>$1</em>");
725
+ result = result.replace(/_([^_]+)_/g, "<em>$1</em>");
726
+ result = result.replace(/`([^`]+)`/g, "<code>$1</code>");
727
+ return result;
728
+ }
729
+ while (i < lines.length) {
730
+ const line = lines[i];
731
+ const fenceMatch = line.match(/^```(\w*)$/);
732
+ if (fenceMatch) {
733
+ const lang = fenceMatch[1];
734
+ const codeLines = [];
735
+ i++;
736
+ while (i < lines.length && !lines[i].startsWith("```")) {
737
+ codeLines.push(lines[i]);
738
+ i++;
739
+ }
740
+ i++;
741
+ const langAttr = lang ? ` class="language-${lang}"` : "";
742
+ output.push(`<pre><code${langAttr}>${codeLines.join("\n")}</code></pre>`);
743
+ continue;
744
+ }
745
+ const hrMatch = line.match(/^[-*_]{3,}\s*$/);
746
+ if (hrMatch && line.replace(/\s/g, "").split("").every((c) => c === line.trim()[0])) {
747
+ output.push("<hr>");
748
+ i++;
749
+ continue;
750
+ }
751
+ const headingMatch = line.match(/^(#{1,6})\s+(.+)$/);
752
+ if (headingMatch) {
753
+ const level = headingMatch[1].length;
754
+ const text = processInline(headingMatch[2].trim());
755
+ output.push(`<h${level}>${text}</h${level}>`);
756
+ i++;
757
+ continue;
758
+ }
759
+ if (i < lines.length - 1) {
760
+ const nextLine = lines[i + 1];
761
+ if (/^=+\s*$/.test(nextLine) && line.trim()) {
762
+ output.push(`<h1>${processInline(line.trim())}</h1>`);
763
+ i += 2;
764
+ continue;
765
+ }
766
+ if (/^-+\s*$/.test(nextLine) && line.trim() && !line.match(/^[-*+]\s/)) {
767
+ output.push(`<h2>${processInline(line.trim())}</h2>`);
768
+ i += 2;
769
+ continue;
770
+ }
771
+ }
772
+ if (line.startsWith(">")) {
773
+ const bqLines = [];
774
+ while (i < lines.length && lines[i].startsWith(">")) {
775
+ bqLines.push(lines[i].replace(/^>\s?/, ""));
776
+ i++;
777
+ }
778
+ const inner = markdownToHtml(bqLines.join("\n"));
779
+ output.push(`<blockquote>${inner}</blockquote>`);
780
+ continue;
781
+ }
782
+ if (/^(\s*)[-*+]\s/.test(line)) {
783
+ const ulLines = [];
784
+ while (i < lines.length && (/^(\s*)[-*+]\s/.test(lines[i]) || /^\s{2,}/.test(lines[i]))) {
785
+ ulLines.push(lines[i]);
786
+ i++;
787
+ }
788
+ output.push(parseMarkdownList(ulLines, false));
789
+ continue;
790
+ }
791
+ if (/^(\s*)\d+\.\s/.test(line)) {
792
+ const olLines = [];
793
+ while (i < lines.length && (/^(\s*)\d+\.\s/.test(lines[i]) || /^\s{2,}/.test(lines[i]))) {
794
+ olLines.push(lines[i]);
795
+ i++;
796
+ }
797
+ output.push(parseMarkdownList(olLines, true));
798
+ continue;
799
+ }
800
+ if (line.trim() === "") {
801
+ i++;
802
+ continue;
803
+ }
804
+ output.push(`<p>${processInline(line.trim())}</p>`);
805
+ i++;
806
+ }
807
+ return output.join("\n");
808
+ }
809
+ function parseMarkdownList(lines, ordered) {
810
+ const tag = ordered ? "ol" : "ul";
811
+ const items = [];
812
+ for (let i = 0; i < lines.length; i++) {
813
+ const line = lines[i];
814
+ const match = ordered ? line.match(/^(\s*)\d+\.\s(.*)$/) : line.match(/^(\s*)[-*+]\s(.*)$/);
815
+ if (match) {
816
+ let content = match[2];
817
+ const subLines = [];
818
+ while (i + 1 < lines.length && (lines[i + 1].match(/^\s{2,}[-*+\d]/) || lines[i + 1].match(/^\s{4,}/))) {
819
+ i++;
820
+ subLines.push(lines[i].replace(/^ /, ""));
821
+ }
822
+ if (subLines.length > 0) {
823
+ const subOrdered = /^\s*\d+\./.test(subLines[0]);
824
+ content += parseMarkdownList(subLines, subOrdered);
825
+ }
826
+ items.push(`<li>${content}</li>`);
827
+ }
828
+ }
829
+ return `<${tag}>${items.join("")}</${tag}>`;
830
+ }
831
+ var ONES = [
832
+ "",
833
+ "one",
834
+ "two",
835
+ "three",
836
+ "four",
837
+ "five",
838
+ "six",
839
+ "seven",
840
+ "eight",
841
+ "nine",
842
+ "ten",
843
+ "eleven",
844
+ "twelve",
845
+ "thirteen",
846
+ "fourteen",
847
+ "fifteen",
848
+ "sixteen",
849
+ "seventeen",
850
+ "eighteen",
851
+ "nineteen"
852
+ ];
853
+ var TENS = [
854
+ "",
855
+ "",
856
+ "twenty",
857
+ "thirty",
858
+ "forty",
859
+ "fifty",
860
+ "sixty",
861
+ "seventy",
862
+ "eighty",
863
+ "ninety"
864
+ ];
865
+ var SCALES = [
866
+ "",
867
+ "thousand",
868
+ "million",
869
+ "billion",
870
+ "trillion",
871
+ "quadrillion"
872
+ ];
873
+ function convertHundreds(n) {
874
+ if (n === 0) return "";
875
+ if (n < 20) return ONES[n];
876
+ if (n < 100) {
877
+ const ten = TENS[Math.floor(n / 10)];
878
+ const one = ONES[n % 10];
879
+ return one ? `${ten}-${one}` : ten;
880
+ }
881
+ const hundred = ONES[Math.floor(n / 100)];
882
+ const rest = convertHundreds(n % 100);
883
+ return rest ? `${hundred} hundred ${rest}` : `${hundred} hundred`;
884
+ }
885
+ function numberToWords(n) {
886
+ if (!isFinite(n) || isNaN(n)) {
887
+ return { error: "Input must be a finite number" };
888
+ }
889
+ const MAX = 999999999999999;
890
+ if (Math.abs(Math.trunc(n)) > MAX) {
891
+ return { error: `Number out of range (max \xB1${MAX})` };
892
+ }
893
+ if (n === 0) return "zero";
894
+ const isNegative = n < 0;
895
+ const absVal = Math.abs(n);
896
+ const decimalIndex = absVal.toString().indexOf(".");
897
+ let intPart = Math.trunc(absVal);
898
+ let decimalWords = "";
899
+ if (decimalIndex !== -1) {
900
+ const decStr = absVal.toString().slice(decimalIndex + 1);
901
+ const decDigits = decStr.split("").map(Number);
902
+ decimalWords = " point " + decDigits.map((d) => ONES[d] || "zero").join(" ");
903
+ }
904
+ if (intPart === 0 && decimalWords) {
905
+ const prefix2 = isNegative ? "negative " : "";
906
+ return `${prefix2}zero${decimalWords}`;
907
+ }
908
+ let result = "";
909
+ let scaleIndex = 0;
910
+ while (intPart > 0) {
911
+ const chunk = intPart % 1e3;
912
+ if (chunk !== 0) {
913
+ const chunkWords = convertHundreds(chunk);
914
+ const scale = SCALES[scaleIndex];
915
+ result = scale ? `${chunkWords} ${scale}${result ? " " + result : ""}` : chunkWords;
916
+ }
917
+ intPart = Math.floor(intPart / 1e3);
918
+ scaleIndex++;
919
+ }
920
+ const prefix = isNegative ? "negative " : "";
921
+ return `${prefix}${result}${decimalWords}`;
922
+ }
923
+ function numberToOrdinal(n) {
924
+ if (!Number.isInteger(n) || !isFinite(n)) {
925
+ return { error: "Input must be a finite integer" };
926
+ }
927
+ const abs = Math.abs(n);
928
+ const lastTwo = abs % 100;
929
+ const lastOne = abs % 10;
930
+ let suffix;
931
+ if (lastTwo >= 11 && lastTwo <= 13) {
932
+ suffix = "th";
933
+ } else if (lastOne === 1) {
934
+ suffix = "st";
935
+ } else if (lastOne === 2) {
936
+ suffix = "nd";
937
+ } else if (lastOne === 3) {
938
+ suffix = "rd";
939
+ } else {
940
+ suffix = "th";
941
+ }
942
+ return `${n}${suffix}`;
943
+ }
944
+ var ORDINAL_ONES = [
945
+ "",
946
+ "first",
947
+ "second",
948
+ "third",
949
+ "fourth",
950
+ "fifth",
951
+ "sixth",
952
+ "seventh",
953
+ "eighth",
954
+ "ninth",
955
+ "tenth",
956
+ "eleventh",
957
+ "twelfth",
958
+ "thirteenth",
959
+ "fourteenth",
960
+ "fifteenth",
961
+ "sixteenth",
962
+ "seventeenth",
963
+ "eighteenth",
964
+ "nineteenth"
965
+ ];
966
+ var ORDINAL_TENS = [
967
+ "",
968
+ "",
969
+ "twentieth",
970
+ "thirtieth",
971
+ "fortieth",
972
+ "fiftieth",
973
+ "sixtieth",
974
+ "seventieth",
975
+ "eightieth",
976
+ "ninetieth"
977
+ ];
978
+ function convertOrdinalHundreds(n) {
979
+ if (n < 20) return ORDINAL_ONES[n];
980
+ if (n < 100) {
981
+ const tenIndex = Math.floor(n / 10);
982
+ const one = n % 10;
983
+ if (one === 0) return ORDINAL_TENS[tenIndex];
984
+ return `${TENS[tenIndex]}-${ORDINAL_ONES[one]}`;
985
+ }
986
+ const hundred = ONES[Math.floor(n / 100)];
987
+ const rest = n % 100;
988
+ if (rest === 0) return `${hundred} hundredth`;
989
+ return `${hundred} hundred ${convertOrdinalHundreds(rest)}`;
990
+ }
991
+ function ordinalWords(n) {
992
+ if (!Number.isInteger(n) || !isFinite(n) || n < 0) {
993
+ return { error: "Input must be a non-negative finite integer" };
994
+ }
995
+ if (n === 0) return "zeroth";
996
+ const MAX = 999999999999999;
997
+ if (n > MAX) return { error: `Number out of range (max ${MAX})` };
998
+ const wordsResult = numberToWords(n);
999
+ if (typeof wordsResult !== "string") return wordsResult;
1000
+ if (n <= 999) {
1001
+ return convertOrdinalHundreds(n);
1002
+ }
1003
+ const lastChunk = n % 1e3;
1004
+ if (lastChunk === 0) {
1005
+ const parts = wordsResult.split(" ");
1006
+ const lastWord = parts[parts.length - 1];
1007
+ const ordinalScale = {
1008
+ thousand: "thousandth",
1009
+ million: "millionth",
1010
+ billion: "billionth",
1011
+ trillion: "trillionth",
1012
+ quadrillion: "quadrillionth"
1013
+ };
1014
+ if (ordinalScale[lastWord]) {
1015
+ parts[parts.length - 1] = ordinalScale[lastWord];
1016
+ return parts.join(" ");
1017
+ }
1018
+ return wordsResult + "th";
1019
+ }
1020
+ const lastChunkCardinal = convertHundreds(lastChunk);
1021
+ const lastChunkOrdinal = convertOrdinalHundreds(lastChunk);
1022
+ const idx = wordsResult.lastIndexOf(lastChunkCardinal);
1023
+ if (idx !== -1) {
1024
+ return wordsResult.slice(0, idx) + lastChunkOrdinal;
1025
+ }
1026
+ return wordsResult + "th";
1027
+ }
1028
+ var ROMAN_VALUES = [
1029
+ [1e3, "M"],
1030
+ [900, "CM"],
1031
+ [500, "D"],
1032
+ [400, "CD"],
1033
+ [100, "C"],
1034
+ [90, "XC"],
1035
+ [50, "L"],
1036
+ [40, "XL"],
1037
+ [10, "X"],
1038
+ [9, "IX"],
1039
+ [5, "V"],
1040
+ [4, "IV"],
1041
+ [1, "I"]
1042
+ ];
1043
+ function numberToRoman(n) {
1044
+ if (!Number.isInteger(n) || n < 1 || n > 3999) {
1045
+ return { error: "Input must be an integer between 1 and 3999" };
1046
+ }
1047
+ let result = "";
1048
+ let remaining = n;
1049
+ for (const [value, numeral] of ROMAN_VALUES) {
1050
+ while (remaining >= value) {
1051
+ result += numeral;
1052
+ remaining -= value;
1053
+ }
1054
+ }
1055
+ return result;
1056
+ }
1057
+ var ROMAN_MAP = {
1058
+ I: 1,
1059
+ V: 5,
1060
+ X: 10,
1061
+ L: 50,
1062
+ C: 100,
1063
+ D: 500,
1064
+ M: 1e3
1065
+ };
1066
+ function romanToNumber(roman) {
1067
+ if (!roman || !/^[IVXLCDM]+$/i.test(roman)) {
1068
+ return { error: `Invalid Roman numeral: ${roman}` };
1069
+ }
1070
+ const upper = roman.toUpperCase();
1071
+ let result = 0;
1072
+ for (let i = 0; i < upper.length; i++) {
1073
+ const curr = ROMAN_MAP[upper[i]];
1074
+ const next = ROMAN_MAP[upper[i + 1]];
1075
+ if (curr === void 0) return { error: `Invalid Roman numeral character: ${upper[i]}` };
1076
+ if (next && curr < next) {
1077
+ result -= curr;
1078
+ } else {
1079
+ result += curr;
1080
+ }
1081
+ }
1082
+ const roundTrip = numberToRoman(result);
1083
+ if (typeof roundTrip !== "string" || roundTrip !== upper) {
1084
+ return { error: `Invalid Roman numeral: ${roman}` };
1085
+ }
1086
+ return result;
1087
+ }
1088
+ var STOP_WORDS = /* @__PURE__ */ new Set([
1089
+ "a",
1090
+ "an",
1091
+ "the",
1092
+ "and",
1093
+ "or",
1094
+ "but",
1095
+ "in",
1096
+ "on",
1097
+ "at",
1098
+ "to",
1099
+ "for",
1100
+ "of",
1101
+ "with",
1102
+ "by",
1103
+ "from",
1104
+ "is",
1105
+ "it",
1106
+ "its",
1107
+ "this",
1108
+ "that",
1109
+ "was",
1110
+ "are",
1111
+ "be",
1112
+ "been",
1113
+ "being",
1114
+ "have",
1115
+ "has",
1116
+ "had",
1117
+ "do",
1118
+ "does",
1119
+ "did",
1120
+ "will",
1121
+ "would",
1122
+ "could",
1123
+ "should",
1124
+ "may",
1125
+ "might",
1126
+ "shall",
1127
+ "can",
1128
+ "not",
1129
+ "no",
1130
+ "nor",
1131
+ "so",
1132
+ "yet",
1133
+ "both",
1134
+ "either",
1135
+ "neither",
1136
+ "each",
1137
+ "few",
1138
+ "more",
1139
+ "most",
1140
+ "other",
1141
+ "some",
1142
+ "such",
1143
+ "than",
1144
+ "then",
1145
+ "too",
1146
+ "very",
1147
+ "as",
1148
+ "if",
1149
+ "into",
1150
+ "through",
1151
+ "during",
1152
+ "before",
1153
+ "after",
1154
+ "above",
1155
+ "below",
1156
+ "up",
1157
+ "down",
1158
+ "out",
1159
+ "off",
1160
+ "over",
1161
+ "under",
1162
+ "again",
1163
+ "further",
1164
+ "once",
1165
+ "i",
1166
+ "me",
1167
+ "my",
1168
+ "we",
1169
+ "our",
1170
+ "you",
1171
+ "your",
1172
+ "he",
1173
+ "him",
1174
+ "his",
1175
+ "she",
1176
+ "her",
1177
+ "they",
1178
+ "them",
1179
+ "their",
1180
+ "what",
1181
+ "which",
1182
+ "who",
1183
+ "whom",
1184
+ "when",
1185
+ "where",
1186
+ "why",
1187
+ "how",
1188
+ "all",
1189
+ "any",
1190
+ "while"
1191
+ ]);
1192
+ function sentenceCount(text) {
1193
+ if (!text.trim()) return 0;
1194
+ const matches = text.match(/[^.!?]*[.!?]+/g);
1195
+ return matches ? matches.length : text.trim().length > 0 ? 1 : 0;
1196
+ }
1197
+ function syllableCount(word) {
1198
+ const cleaned = word.toLowerCase().replace(/[^a-z]/g, "");
1199
+ if (!cleaned) return 0;
1200
+ if (cleaned.length <= 3) return 1;
1201
+ let count = 0;
1202
+ let prevWasVowel = false;
1203
+ const vowels = /[aeiouy]/;
1204
+ for (let i = 0; i < cleaned.length; i++) {
1205
+ const isVowel = vowels.test(cleaned[i]);
1206
+ if (isVowel && !prevWasVowel) {
1207
+ count++;
1208
+ }
1209
+ prevWasVowel = isVowel;
1210
+ }
1211
+ if (cleaned.endsWith("e") && count > 1) {
1212
+ count--;
1213
+ }
1214
+ if (cleaned.endsWith("le") && cleaned.length > 2 && !vowels.test(cleaned[cleaned.length - 3])) {
1215
+ count++;
1216
+ }
1217
+ if ((cleaned.endsWith("es") || cleaned.endsWith("ed")) && count > 1) {
1218
+ count--;
1219
+ }
1220
+ return Math.max(1, count);
1221
+ }
1222
+ function extractWords(text) {
1223
+ return text.match(/\b[a-zA-Z']+\b/g) ?? [];
1224
+ }
1225
+ function analyzeText(text) {
1226
+ const charCount = text.length;
1227
+ const charCountNoSpaces = text.replace(/\s/g, "").length;
1228
+ const words = extractWords(text);
1229
+ const wordCount = words.length;
1230
+ const sentences = sentenceCount(text);
1231
+ const paragraphCount = text.trim() ? text.trim().split(/\n\s*\n+/).filter((p) => p.trim().length > 0).length : 0;
1232
+ const lineCount = text.trim() ? text.split(/\n/).filter((l) => l.trim().length > 0).length : 0;
1233
+ const totalWordLength = words.reduce((sum, w) => sum + w.replace(/'/g, "").length, 0);
1234
+ const avgWordLength = wordCount > 0 ? Math.round(totalWordLength / wordCount * 100) / 100 : 0;
1235
+ const avgWordsPerSentence = sentences > 0 ? Math.round(wordCount / sentences * 100) / 100 : 0;
1236
+ const longestWord = words.reduce((longest, w) => w.length > longest.length ? w : longest, "");
1237
+ const freq = {};
1238
+ for (const w of words) {
1239
+ const lower = w.toLowerCase();
1240
+ freq[lower] = (freq[lower] ?? 0) + 1;
1241
+ }
1242
+ const mostFrequentWord = Object.entries(freq).sort((a, b) => b[1] - a[1])[0]?.[0] ?? "";
1243
+ const uniqueWordCount = Object.keys(freq).length;
1244
+ const estimatedReadTime = Math.max(1, Math.ceil(wordCount / 200));
1245
+ return {
1246
+ charCount,
1247
+ charCountNoSpaces,
1248
+ wordCount,
1249
+ sentenceCount: sentences,
1250
+ paragraphCount,
1251
+ lineCount,
1252
+ avgWordLength,
1253
+ avgWordsPerSentence,
1254
+ longestWord,
1255
+ mostFrequentWord,
1256
+ uniqueWordCount,
1257
+ estimatedReadTime
1258
+ };
1259
+ }
1260
+ function readabilityScore(text) {
1261
+ const words = extractWords(text);
1262
+ const wordCount = words.length;
1263
+ const sentences = sentenceCount(text);
1264
+ if (sentences < 1 || wordCount < 1) {
1265
+ return { error: "Requires at least 1 sentence and 1 word to compute" };
1266
+ }
1267
+ const totalSyllables = words.reduce((sum, w) => sum + syllableCount(w), 0);
1268
+ const fleschReadingEase = Math.round(
1269
+ (206.835 - 1.015 * (wordCount / sentences) - 84.6 * (totalSyllables / wordCount)) * 10
1270
+ ) / 10;
1271
+ const fleschKincaidGrade = Math.round(
1272
+ (0.39 * (wordCount / sentences) + 11.8 * (totalSyllables / wordCount) - 15.59) * 10
1273
+ ) / 10;
1274
+ let readingLevel;
1275
+ const grade = fleschKincaidGrade;
1276
+ if (grade <= 5) readingLevel = "Elementary";
1277
+ else if (grade <= 8) readingLevel = "Middle School";
1278
+ else if (grade <= 12) readingLevel = "High School";
1279
+ else if (grade <= 16) readingLevel = "College";
1280
+ else readingLevel = "Expert";
1281
+ return { fleschReadingEase, fleschKincaidGrade, readingLevel };
1282
+ }
1283
+ function wordFrequency(text, limit = 20) {
1284
+ const words = extractWords(text);
1285
+ const total = words.length;
1286
+ if (total === 0) return [];
1287
+ const freq = {};
1288
+ for (const w of words) {
1289
+ const lower = w.toLowerCase();
1290
+ if (!STOP_WORDS.has(lower)) {
1291
+ freq[lower] = (freq[lower] ?? 0) + 1;
1292
+ }
1293
+ }
1294
+ return Object.entries(freq).sort((a, b) => b[1] - a[1]).slice(0, limit).map(([word, count]) => ({
1295
+ word,
1296
+ count,
1297
+ percent: Math.round(count / total * 1e4) / 100
1298
+ }));
1299
+ }
1300
+ function lcsTextDiff(a, b) {
1301
+ const m = a.length;
1302
+ const n = b.length;
1303
+ const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));
1304
+ for (let i2 = 1; i2 <= m; i2++) {
1305
+ for (let j2 = 1; j2 <= n; j2++) {
1306
+ if (a[i2 - 1] === b[j2 - 1]) {
1307
+ dp[i2][j2] = dp[i2 - 1][j2 - 1] + 1;
1308
+ } else {
1309
+ dp[i2][j2] = Math.max(dp[i2 - 1][j2], dp[i2][j2 - 1]);
1310
+ }
1311
+ }
1312
+ }
1313
+ const inLCS = Array.from({ length: m }, () => new Array(n).fill(false));
1314
+ let i = m, j = n;
1315
+ while (i > 0 && j > 0) {
1316
+ if (a[i - 1] === b[j - 1]) {
1317
+ inLCS[i - 1][j - 1] = true;
1318
+ i--;
1319
+ j--;
1320
+ } else if (dp[i - 1][j] > dp[i][j - 1]) {
1321
+ i--;
1322
+ } else {
1323
+ j--;
1324
+ }
1325
+ }
1326
+ return inLCS;
1327
+ }
1328
+ function diffLines(left, right) {
1329
+ const leftLines = left.split("\n");
1330
+ const rightLines = right.split("\n");
1331
+ const m = leftLines.length;
1332
+ const n = rightLines.length;
1333
+ const inLCS = lcsTextDiff(leftLines, rightLines);
1334
+ const lines = [];
1335
+ let li = 0, ri = 0;
1336
+ let leftNum = 1, rightNum = 1;
1337
+ let addedCount = 0, removedCount = 0, unchangedCount = 0;
1338
+ while (li < m || ri < n) {
1339
+ if (li < m && ri < n && inLCS[li]?.[ri]) {
1340
+ lines.push({ type: "equal", text: leftLines[li], lineNumLeft: leftNum++, lineNumRight: rightNum++ });
1341
+ unchangedCount++;
1342
+ li++;
1343
+ ri++;
1344
+ } else if (li < m && (ri >= n || !inLCS[li]?.[ri])) {
1345
+ const consumed = ri < n && inLCS[li] && Object.values(inLCS[li]).some(Boolean);
1346
+ if (consumed) {
1347
+ lines.push({ type: "removed", text: leftLines[li], lineNumLeft: leftNum++ });
1348
+ removedCount++;
1349
+ li++;
1350
+ } else {
1351
+ lines.push({ type: "removed", text: leftLines[li], lineNumLeft: leftNum++ });
1352
+ removedCount++;
1353
+ li++;
1354
+ }
1355
+ } else {
1356
+ lines.push({ type: "added", text: rightLines[ri], lineNumRight: rightNum++ });
1357
+ addedCount++;
1358
+ ri++;
1359
+ }
1360
+ }
1361
+ return { lines, addedCount, removedCount, unchangedCount };
1362
+ }
1363
+ function diffLinesSimple(left, right) {
1364
+ const leftLines = left === "" ? [] : left.split("\n");
1365
+ const rightLines = right === "" ? [] : right.split("\n");
1366
+ const m = leftLines.length;
1367
+ const n = rightLines.length;
1368
+ const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));
1369
+ for (let i = 1; i <= m; i++)
1370
+ for (let j = 1; j <= n; j++)
1371
+ dp[i][j] = leftLines[i - 1] === rightLines[j - 1] ? dp[i - 1][j - 1] + 1 : Math.max(dp[i - 1][j], dp[i][j - 1]);
1372
+ const lines = [];
1373
+ let addedCount = 0, removedCount = 0, unchangedCount = 0;
1374
+ let leftNum = 1, rightNum = 1;
1375
+ function backtrack(i, j) {
1376
+ if (i === 0 && j === 0) return;
1377
+ if (i > 0 && j > 0 && leftLines[i - 1] === rightLines[j - 1]) {
1378
+ backtrack(i - 1, j - 1);
1379
+ lines.push({ type: "equal", text: leftLines[i - 1], lineNumLeft: leftNum++, lineNumRight: rightNum++ });
1380
+ unchangedCount++;
1381
+ } else if (j > 0 && (i === 0 || dp[i][j - 1] >= dp[i - 1][j])) {
1382
+ backtrack(i, j - 1);
1383
+ lines.push({ type: "added", text: rightLines[j - 1], lineNumRight: rightNum++ });
1384
+ addedCount++;
1385
+ } else {
1386
+ backtrack(i - 1, j);
1387
+ lines.push({ type: "removed", text: leftLines[i - 1], lineNumLeft: leftNum++ });
1388
+ removedCount++;
1389
+ }
1390
+ }
1391
+ backtrack(m, n);
1392
+ return { lines, addedCount, removedCount, unchangedCount };
1393
+ }
1394
+ function parseDiff(unifiedDiff) {
1395
+ if (typeof unifiedDiff !== "string") {
1396
+ return { error: "Input must be a string" };
1397
+ }
1398
+ if (unifiedDiff.trim() === "") {
1399
+ return {
1400
+ files: [],
1401
+ totalAdded: 0,
1402
+ totalRemoved: 0,
1403
+ stats: "0 files changed, 0 insertions(+), 0 deletions(-)"
1404
+ };
1405
+ }
1406
+ const lines = unifiedDiff.split("\n");
1407
+ const files = [];
1408
+ let currentFile = null;
1409
+ let currentHunk = null;
1410
+ let oldLineNum = 0;
1411
+ let newLineNum = 0;
1412
+ for (const line of lines) {
1413
+ if (line.startsWith("diff --git")) {
1414
+ if (currentFile) {
1415
+ if (currentHunk) {
1416
+ currentFile.hunks.push(currentHunk);
1417
+ currentHunk = null;
1418
+ }
1419
+ files.push(currentFile);
1420
+ }
1421
+ currentFile = {
1422
+ oldPath: "",
1423
+ newPath: "",
1424
+ hunks: [],
1425
+ added: 0,
1426
+ removed: 0,
1427
+ isBinary: false,
1428
+ isNew: false,
1429
+ isDeleted: false
1430
+ };
1431
+ continue;
1432
+ }
1433
+ if (line.startsWith("Binary files")) {
1434
+ if (currentFile) {
1435
+ currentFile.isBinary = true;
1436
+ }
1437
+ continue;
1438
+ }
1439
+ if (line.startsWith("--- ")) {
1440
+ if (!currentFile) {
1441
+ currentFile = {
1442
+ oldPath: "",
1443
+ newPath: "",
1444
+ hunks: [],
1445
+ added: 0,
1446
+ removed: 0,
1447
+ isBinary: false,
1448
+ isNew: false,
1449
+ isDeleted: false
1450
+ };
1451
+ }
1452
+ const path = line.slice(4);
1453
+ currentFile.oldPath = path;
1454
+ if (path === "/dev/null") {
1455
+ currentFile.isNew = true;
1456
+ }
1457
+ continue;
1458
+ }
1459
+ if (line.startsWith("+++ ")) {
1460
+ if (currentFile) {
1461
+ const path = line.slice(4);
1462
+ currentFile.newPath = path;
1463
+ if (path === "/dev/null") {
1464
+ currentFile.isDeleted = true;
1465
+ }
1466
+ }
1467
+ continue;
1468
+ }
1469
+ if (line.startsWith("@@ ")) {
1470
+ if (currentFile) {
1471
+ if (currentHunk) {
1472
+ currentFile.hunks.push(currentHunk);
1473
+ }
1474
+ const match = line.match(/@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/);
1475
+ if (match) {
1476
+ const oldStart = parseInt(match[1], 10);
1477
+ const oldCount = match[2] !== void 0 ? parseInt(match[2], 10) : 1;
1478
+ const newStart = parseInt(match[3], 10);
1479
+ const newCount = match[4] !== void 0 ? parseInt(match[4], 10) : 1;
1480
+ oldLineNum = oldStart;
1481
+ newLineNum = newStart;
1482
+ currentHunk = {
1483
+ header: line,
1484
+ lines: [],
1485
+ oldStart,
1486
+ oldCount,
1487
+ newStart,
1488
+ newCount
1489
+ };
1490
+ }
1491
+ }
1492
+ continue;
1493
+ }
1494
+ if (currentHunk && currentFile) {
1495
+ if (line.startsWith("+")) {
1496
+ const content = line.slice(1);
1497
+ currentHunk.lines.push({
1498
+ type: "added",
1499
+ content,
1500
+ lineNumber: { new: newLineNum }
1501
+ });
1502
+ currentFile.added++;
1503
+ newLineNum++;
1504
+ } else if (line.startsWith("-")) {
1505
+ const content = line.slice(1);
1506
+ currentHunk.lines.push({
1507
+ type: "removed",
1508
+ content,
1509
+ lineNumber: { old: oldLineNum }
1510
+ });
1511
+ currentFile.removed++;
1512
+ oldLineNum++;
1513
+ } else if (line.startsWith(" ")) {
1514
+ const content = line.slice(1);
1515
+ currentHunk.lines.push({
1516
+ type: "context",
1517
+ content,
1518
+ lineNumber: { old: oldLineNum, new: newLineNum }
1519
+ });
1520
+ oldLineNum++;
1521
+ newLineNum++;
1522
+ }
1523
+ }
1524
+ }
1525
+ if (currentFile) {
1526
+ if (currentHunk) {
1527
+ currentFile.hunks.push(currentHunk);
1528
+ }
1529
+ files.push(currentFile);
1530
+ }
1531
+ const totalAdded = files.reduce((sum, f) => sum + f.added, 0);
1532
+ const totalRemoved = files.reduce((sum, f) => sum + f.removed, 0);
1533
+ const fileCount = files.length;
1534
+ const filePart = `${fileCount} ${fileCount === 1 ? "file" : "files"} changed`;
1535
+ const addPart = `${totalAdded} ${totalAdded === 1 ? "insertion" : "insertions"}(+)`;
1536
+ const delPart = `${totalRemoved} ${totalRemoved === 1 ? "deletion" : "deletions"}(-)`;
1537
+ const stats = `${filePart}, ${addPart}, ${delPart}`;
1538
+ return { files, totalAdded, totalRemoved, stats };
1539
+ }
1540
+ function lcsDiffViewer(a, b) {
1541
+ const m = a.length;
1542
+ const n = b.length;
1543
+ const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));
1544
+ for (let i = 1; i <= m; i++) {
1545
+ for (let j = 1; j <= n; j++) {
1546
+ dp[i][j] = a[i - 1] === b[j - 1] ? dp[i - 1][j - 1] + 1 : Math.max(dp[i - 1][j], dp[i][j - 1]);
1547
+ }
1548
+ }
1549
+ return dp;
1550
+ }
1551
+ function backtrackDiff(dp, a, b) {
1552
+ const result = [];
1553
+ let i = a.length;
1554
+ let j = b.length;
1555
+ while (i > 0 || j > 0) {
1556
+ if (i > 0 && j > 0 && a[i - 1] === b[j - 1]) {
1557
+ result.push({ type: "equal", line: a[i - 1] });
1558
+ i--;
1559
+ j--;
1560
+ } else if (j > 0 && (i === 0 || dp[i][j - 1] >= dp[i - 1][j])) {
1561
+ result.push({ type: "insert", line: b[j - 1] });
1562
+ j--;
1563
+ } else {
1564
+ result.push({ type: "delete", line: a[i - 1] });
1565
+ i--;
1566
+ }
1567
+ }
1568
+ return result.reverse();
1569
+ }
1570
+ function generateDiff(original, modified, filename = "file") {
1571
+ const originalLines = original === "" ? [] : original.split("\n");
1572
+ const modifiedLines = modified === "" ? [] : modified.split("\n");
1573
+ const dp = lcsDiffViewer(originalLines, modifiedLines);
1574
+ const ops = backtrackDiff(dp, originalLines, modifiedLines);
1575
+ const CONTEXT = 3;
1576
+ const changes = [];
1577
+ ops.forEach((op, idx) => {
1578
+ if (op.type !== "equal") {
1579
+ changes.push(idx);
1580
+ }
1581
+ });
1582
+ if (changes.length === 0) {
1583
+ return "";
1584
+ }
1585
+ const hunks = [];
1586
+ let hunkStart = Math.max(0, changes[0] - CONTEXT);
1587
+ let hunkEnd = Math.min(ops.length - 1, changes[0] + CONTEXT);
1588
+ for (let ci = 1; ci < changes.length; ci++) {
1589
+ const changeIdx = changes[ci];
1590
+ const contextStart = Math.max(0, changeIdx - CONTEXT);
1591
+ if (contextStart <= hunkEnd + 1) {
1592
+ hunkEnd = Math.min(ops.length - 1, changeIdx + CONTEXT);
1593
+ } else {
1594
+ hunks.push({ start: hunkStart, end: hunkEnd });
1595
+ hunkStart = contextStart;
1596
+ hunkEnd = Math.min(ops.length - 1, changeIdx + CONTEXT);
1597
+ }
1598
+ }
1599
+ hunks.push({ start: hunkStart, end: hunkEnd });
1600
+ const outputLines = [
1601
+ `--- a/${filename}`,
1602
+ `+++ b/${filename}`
1603
+ ];
1604
+ for (const hunk of hunks) {
1605
+ let oldStart = 1;
1606
+ let newStart = 1;
1607
+ let oldCount = 0;
1608
+ let newCount = 0;
1609
+ let oldLineAt = 0;
1610
+ let newLineAt = 0;
1611
+ for (let i = 0; i < hunk.start; i++) {
1612
+ if (ops[i].type === "equal" || ops[i].type === "delete") oldLineAt++;
1613
+ if (ops[i].type === "equal" || ops[i].type === "insert") newLineAt++;
1614
+ }
1615
+ oldStart = oldLineAt + 1;
1616
+ newStart = newLineAt + 1;
1617
+ const hunkLines = [];
1618
+ for (let i = hunk.start; i <= hunk.end; i++) {
1619
+ const op = ops[i];
1620
+ if (op.type === "equal") {
1621
+ hunkLines.push(` ${op.line}`);
1622
+ oldCount++;
1623
+ newCount++;
1624
+ } else if (op.type === "delete") {
1625
+ hunkLines.push(`-${op.line}`);
1626
+ oldCount++;
1627
+ } else {
1628
+ hunkLines.push(`+${op.line}`);
1629
+ newCount++;
1630
+ }
1631
+ }
1632
+ outputLines.push(`@@ -${oldStart},${oldCount} +${newStart},${newCount} @@`);
1633
+ outputLines.push(...hunkLines);
1634
+ }
1635
+ return outputLines.join("\n");
1636
+ }
1637
+ function diffStats(diff) {
1638
+ return {
1639
+ files: diff.files.length,
1640
+ added: diff.totalAdded,
1641
+ removed: diff.totalRemoved
1642
+ };
1643
+ }
1644
+ function extractHeadings(markdown) {
1645
+ const headings = [];
1646
+ const lines = markdown.split("\n");
1647
+ for (const line of lines) {
1648
+ const match = line.match(/^(#{1,6}) (.+)/);
1649
+ if (match) {
1650
+ headings.push({ level: match[1].length, text: match[2].trim() });
1651
+ }
1652
+ }
1653
+ return headings;
1654
+ }
1655
+ function renderMarkdown(input) {
1656
+ const html = marked.marked.parse(input);
1657
+ const headings = extractHeadings(input);
1658
+ const stripped = input.replace(/#{1,6} /g, "").replace(/[*_~`]/g, "").replace(/\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/<[^>]+>/g, "").trim();
1659
+ const wordCount = stripped.length === 0 ? 0 : stripped.split(/\s+/).filter((w) => w.length > 0).length;
1660
+ return { html, wordCount, headings };
1661
+ }
1662
+ function detectDelimiter(csv) {
1663
+ const delimiters = [",", " ", ";", "|"];
1664
+ const lines = csv.split("\n").filter((l) => l.trim() !== "").slice(0, 10);
1665
+ if (lines.length === 0) return ",";
1666
+ const counts = { ",": [], " ": [], ";": [], "|": [] };
1667
+ for (const line of lines) {
1668
+ for (const d of delimiters) {
1669
+ const count = line.split(d).length - 1;
1670
+ counts[d].push(count);
1671
+ }
1672
+ }
1673
+ let bestDelimiter = ",";
1674
+ let bestScore = -1;
1675
+ for (const d of delimiters) {
1676
+ const arr = counts[d];
1677
+ if (arr.length === 0) continue;
1678
+ const avg = arr.reduce((a, b) => a + b, 0) / arr.length;
1679
+ if (avg === 0) continue;
1680
+ const variance = arr.reduce((a, b) => a + Math.pow(b - avg, 2), 0) / arr.length;
1681
+ const score = avg - variance;
1682
+ if (score > bestScore) {
1683
+ bestScore = score;
1684
+ bestDelimiter = d;
1685
+ }
1686
+ }
1687
+ return bestDelimiter;
1688
+ }
1689
+ function parseTableData(input, options) {
1690
+ if (!input || input.trim() === "") return { error: "Input is empty" };
1691
+ const delimiter = options?.delimiter ?? detectDelimiter(input);
1692
+ const hasHeader = options?.hasHeader !== false;
1693
+ const lines = input.split(/\r?\n/).map((l) => l.trimEnd()).filter((l) => l.trim() !== "");
1694
+ if (lines.length === 0) return { error: "No data found" };
1695
+ const allRows = lines.map((line) => line.split(delimiter));
1696
+ const colCount = Math.max(...allRows.map((r) => r.length));
1697
+ let headers;
1698
+ let rows;
1699
+ if (hasHeader) {
1700
+ headers = allRows[0].map((h) => h.trim());
1701
+ rows = allRows.slice(1);
1702
+ } else {
1703
+ headers = Array.from({ length: colCount }, (_, i) => `Column ${i + 1}`);
1704
+ rows = allRows;
1705
+ }
1706
+ return {
1707
+ headers,
1708
+ rows,
1709
+ delimiter,
1710
+ rowCount: rows.length,
1711
+ colCount
1712
+ };
1713
+ }
1714
+ function escapeHtmlTable(str) {
1715
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
1716
+ }
1717
+ function generateHtmlTable(data, options) {
1718
+ const classes = [];
1719
+ if (options?.striped) classes.push("striped");
1720
+ if (options?.sortable) classes.push("sortable");
1721
+ const attrs = ["<table"];
1722
+ if (options?.id) attrs.push(` id="${escapeHtmlTable(options.id)}"`);
1723
+ if (options?.bordered) attrs.push(' border="1"');
1724
+ if (classes.length > 0) attrs.push(` class="${classes.join(" ")}"`);
1725
+ if (options?.sortable) attrs.push(" data-sortable");
1726
+ attrs.push(">");
1727
+ const parts = [attrs.join("")];
1728
+ if (options?.caption) {
1729
+ parts.push(` <caption>${escapeHtmlTable(options.caption)}</caption>`);
1730
+ }
1731
+ parts.push(" <thead>");
1732
+ parts.push(" <tr>");
1733
+ for (const header of data.headers) {
1734
+ parts.push(` <th>${escapeHtmlTable(header)}</th>`);
1735
+ }
1736
+ parts.push(" </tr>");
1737
+ parts.push(" </thead>");
1738
+ parts.push(" <tbody>");
1739
+ for (const row of data.rows) {
1740
+ parts.push(" <tr>");
1741
+ for (let i = 0; i < data.colCount; i++) {
1742
+ const cell = row[i] ?? "";
1743
+ parts.push(` <td>${escapeHtmlTable(cell)}</td>`);
1744
+ }
1745
+ parts.push(" </tr>");
1746
+ }
1747
+ parts.push(" </tbody>");
1748
+ parts.push("</table>");
1749
+ return parts.join("\n");
1750
+ }
1751
+ function generateMarkdownTable(data) {
1752
+ const lines = [];
1753
+ const headerRow = "| " + data.headers.map((h) => h.trim()).join(" | ") + " |";
1754
+ lines.push(headerRow);
1755
+ const separatorRow = "| " + data.headers.map(() => "---").join(" | ") + " |";
1756
+ lines.push(separatorRow);
1757
+ for (const row of data.rows) {
1758
+ const cells = Array.from({ length: data.colCount }, (_, i) => (row[i] ?? "").trim());
1759
+ lines.push("| " + cells.join(" | ") + " |");
1760
+ }
1761
+ return lines.join("\n");
1762
+ }
1763
+ function csvToHtml(input, options) {
1764
+ const result = parseTableData(input, options);
1765
+ if (typeof result === "object" && "error" in result) return result;
1766
+ return generateHtmlTable(result, options);
1767
+ }
1768
+ function csvToMarkdown(input, options) {
1769
+ const result = parseTableData(input, options);
1770
+ if (typeof result === "object" && "error" in result) return result;
1771
+ return generateMarkdownTable(result);
1772
+ }
1773
+ var BLOCK_FONT = {
1774
+ "A": ["\u2588\u2588\u2588\u2588\u2588", "\u2588 \u2588", "\u2588\u2588\u2588\u2588\u2588", "\u2588 \u2588", "\u2588 \u2588"],
1775
+ "B": ["\u2588\u2588\u2588\u2588 ", "\u2588 \u2588", "\u2588\u2588\u2588\u2588 ", "\u2588 \u2588", "\u2588\u2588\u2588\u2588 "],
1776
+ "C": [" \u2588\u2588\u2588\u2588", "\u2588 ", "\u2588 ", "\u2588 ", " \u2588\u2588\u2588\u2588"],
1777
+ "D": ["\u2588\u2588\u2588\u2588 ", "\u2588 \u2588", "\u2588 \u2588", "\u2588 \u2588", "\u2588\u2588\u2588\u2588 "],
1778
+ "E": ["\u2588\u2588\u2588\u2588\u2588", "\u2588 ", "\u2588\u2588\u2588\u2588 ", "\u2588 ", "\u2588\u2588\u2588\u2588\u2588"],
1779
+ "F": ["\u2588\u2588\u2588\u2588\u2588", "\u2588 ", "\u2588\u2588\u2588\u2588 ", "\u2588 ", "\u2588 "],
1780
+ "G": [" \u2588\u2588\u2588\u2588", "\u2588 ", "\u2588 \u2588\u2588", "\u2588 \u2588", " \u2588\u2588\u2588\u2588"],
1781
+ "H": ["\u2588 \u2588", "\u2588 \u2588", "\u2588\u2588\u2588\u2588\u2588", "\u2588 \u2588", "\u2588 \u2588"],
1782
+ "I": ["\u2588\u2588\u2588\u2588\u2588", " \u2588 ", " \u2588 ", " \u2588 ", "\u2588\u2588\u2588\u2588\u2588"],
1783
+ "J": ["\u2588\u2588\u2588\u2588\u2588", " \u2588 ", " \u2588 ", "\u2588 \u2588 ", " \u2588\u2588 "],
1784
+ "K": ["\u2588 \u2588", "\u2588 \u2588 ", "\u2588\u2588\u2588 ", "\u2588 \u2588 ", "\u2588 \u2588"],
1785
+ "L": ["\u2588 ", "\u2588 ", "\u2588 ", "\u2588 ", "\u2588\u2588\u2588\u2588\u2588"],
1786
+ "M": ["\u2588 \u2588", "\u2588\u2588 \u2588\u2588", "\u2588 \u2588 \u2588", "\u2588 \u2588", "\u2588 \u2588"],
1787
+ "N": ["\u2588 \u2588", "\u2588\u2588 \u2588", "\u2588 \u2588 \u2588", "\u2588 \u2588\u2588", "\u2588 \u2588"],
1788
+ "O": [" \u2588\u2588\u2588 ", "\u2588 \u2588", "\u2588 \u2588", "\u2588 \u2588", " \u2588\u2588\u2588 "],
1789
+ "P": ["\u2588\u2588\u2588\u2588 ", "\u2588 \u2588", "\u2588\u2588\u2588\u2588 ", "\u2588 ", "\u2588 "],
1790
+ "Q": [" \u2588\u2588\u2588 ", "\u2588 \u2588", "\u2588 \u2588", "\u2588 \u2588\u2588", " \u2588\u2588\u2588\u2588"],
1791
+ "R": ["\u2588\u2588\u2588\u2588 ", "\u2588 \u2588", "\u2588\u2588\u2588\u2588 ", "\u2588 \u2588 ", "\u2588 \u2588"],
1792
+ "S": [" \u2588\u2588\u2588\u2588", "\u2588 ", " \u2588\u2588\u2588 ", " \u2588", "\u2588\u2588\u2588\u2588 "],
1793
+ "T": ["\u2588\u2588\u2588\u2588\u2588", " \u2588 ", " \u2588 ", " \u2588 ", " \u2588 "],
1794
+ "U": ["\u2588 \u2588", "\u2588 \u2588", "\u2588 \u2588", "\u2588 \u2588", " \u2588\u2588\u2588 "],
1795
+ "V": ["\u2588 \u2588", "\u2588 \u2588", "\u2588 \u2588", " \u2588 \u2588 ", " \u2588 "],
1796
+ "W": ["\u2588 \u2588", "\u2588 \u2588", "\u2588 \u2588 \u2588", "\u2588\u2588 \u2588\u2588", "\u2588 \u2588"],
1797
+ "X": ["\u2588 \u2588", " \u2588 \u2588 ", " \u2588 ", " \u2588 \u2588 ", "\u2588 \u2588"],
1798
+ "Y": ["\u2588 \u2588", " \u2588 \u2588 ", " \u2588 ", " \u2588 ", " \u2588 "],
1799
+ "Z": ["\u2588\u2588\u2588\u2588\u2588", " \u2588 ", " \u2588 ", " \u2588 ", "\u2588\u2588\u2588\u2588\u2588"],
1800
+ "0": [" \u2588\u2588\u2588 ", "\u2588 \u2588\u2588", "\u2588 \u2588 \u2588", "\u2588\u2588 \u2588", " \u2588\u2588\u2588 "],
1801
+ "1": [" \u2588 ", " \u2588\u2588 ", " \u2588 ", " \u2588 ", "\u2588\u2588\u2588\u2588\u2588"],
1802
+ "2": [" \u2588\u2588\u2588 ", "\u2588 \u2588", " \u2588\u2588 ", " \u2588 ", "\u2588\u2588\u2588\u2588\u2588"],
1803
+ "3": ["\u2588\u2588\u2588\u2588 ", " \u2588", " \u2588\u2588\u2588 ", " \u2588", "\u2588\u2588\u2588\u2588 "],
1804
+ "4": ["\u2588 \u2588", "\u2588 \u2588", "\u2588\u2588\u2588\u2588\u2588", " \u2588", " \u2588"],
1805
+ "5": ["\u2588\u2588\u2588\u2588\u2588", "\u2588 ", "\u2588\u2588\u2588\u2588 ", " \u2588", "\u2588\u2588\u2588\u2588 "],
1806
+ "6": [" \u2588\u2588\u2588 ", "\u2588 ", "\u2588\u2588\u2588\u2588 ", "\u2588 \u2588", " \u2588\u2588\u2588 "],
1807
+ "7": ["\u2588\u2588\u2588\u2588\u2588", " \u2588", " \u2588 ", " \u2588 ", " \u2588 "],
1808
+ "8": [" \u2588\u2588\u2588 ", "\u2588 \u2588", " \u2588\u2588\u2588 ", "\u2588 \u2588", " \u2588\u2588\u2588 "],
1809
+ "9": [" \u2588\u2588\u2588 ", "\u2588 \u2588", " \u2588\u2588\u2588\u2588", " \u2588", " \u2588\u2588\u2588 "],
1810
+ " ": [" ", " ", " ", " ", " "],
1811
+ "!": [" \u2588 ", " \u2588 ", " \u2588 ", " ", " \u2588 "],
1812
+ "?": [" \u2588\u2588\u2588 ", " \u2588", " \u2588\u2588 ", " ", " \u2588 "],
1813
+ ".": [" ", " ", " ", " ", " \u2588 "],
1814
+ ",": [" ", " ", " ", " \u2588 ", " \u2588 "],
1815
+ "-": [" ", " ", "\u2588\u2588\u2588\u2588\u2588", " ", " "],
1816
+ ":": [" ", " \u2588 ", " ", " \u2588 ", " "]
1817
+ };
1818
+ var BANNER_FONT = {
1819
+ "A": [" /\\ ", "/--\\", "/ \\"],
1820
+ "B": ["|-- ", "|-- ", "|__/"],
1821
+ "C": [" /-", "| ", " \\-"],
1822
+ "D": ["|\\ ", "| \\", "|_/"],
1823
+ "E": ["|--", "|- ", "|__"],
1824
+ "F": ["|--", "|- ", "| "],
1825
+ "G": [" /-", "| -", " \\-"],
1826
+ "H": ["| |", "|-|", "| |"],
1827
+ "I": ["---", " | ", "---"],
1828
+ "J": [" |", " |", "\\_/"],
1829
+ "K": ["| /", "|-/", "| \\"],
1830
+ "L": ["| ", "| ", "|__"],
1831
+ "M": ["|\\/|", "| |", "| |"],
1832
+ "N": ["|\\ |", "| \\|", "| |"],
1833
+ "O": [" _ ", "| |", " - "],
1834
+ "P": ["|- ", "|- ", "| "],
1835
+ "Q": [" _ ", "|_|", " -\\"],
1836
+ "R": ["|- ", "|-/", "| \\"],
1837
+ "S": [" /-", " --", "__/"],
1838
+ "T": ["---", " | ", " | "],
1839
+ "U": ["| |", "| |", "\\_/"],
1840
+ "V": ["\\ /", " \\/ ", " "],
1841
+ "W": ["| |", "|/\\|", "| |"],
1842
+ "X": ["\\ /", " X ", "/ \\"],
1843
+ "Y": ["\\/", " |", " |"],
1844
+ "Z": ["--/", " / ", "/--"],
1845
+ "0": [" 0 ", "|0|", " 0 "],
1846
+ "1": ["/1 ", " 1 ", "_1_"],
1847
+ "2": ["-2-", " 2/", "2--"],
1848
+ "3": ["-3-", " 3 ", "-3-"],
1849
+ "4": ["4 4", "444", " 4"],
1850
+ "5": ["5--", "5- ", "--5"],
1851
+ "6": [" 6 ", "6- ", " 6 "],
1852
+ "7": ["77/", " 7", " 7"],
1853
+ "8": ["888", "8 8", "888"],
1854
+ "9": ["999", " 9 ", " 9"],
1855
+ " ": [" ", " ", " "],
1856
+ "!": [" ! ", " ! ", " . "],
1857
+ "?": ["-?-", " ? ", " . "],
1858
+ ".": [" ", " ", " . "],
1859
+ ",": [" ", " ", ", "],
1860
+ "-": [" ", "---", " "],
1861
+ ":": [" : ", " ", " : "]
1862
+ };
1863
+ var SMALL_FONT = {
1864
+ "A": ["/-\\", "|_|"],
1865
+ "B": ["|_)", "|_)"],
1866
+ "C": ["/-", "\\_"],
1867
+ "D": ["|\\ ", "|_/"],
1868
+ "E": ["|-", "|_"],
1869
+ "F": ["|-", "| "],
1870
+ "G": ["/-", "\\_|"],
1871
+ "H": ["|_|", "| |"],
1872
+ "I": ["-|-", "-|-"],
1873
+ "J": [" |", "\\_|"],
1874
+ "K": ["|/ ", "|\\ "],
1875
+ "L": ["| ", "|__"],
1876
+ "M": ["|\\/|", "| |"],
1877
+ "N": ["|\\ ", "| \\"],
1878
+ "O": ["(_)", "(_)"],
1879
+ "P": ["|_)", "| "],
1880
+ "Q": ["(_)", "(_\\"],
1881
+ "R": ["|_)", "| \\"],
1882
+ "S": ["/_", "\\_"],
1883
+ "T": ["-|-", " | "],
1884
+ "U": ["| |", "\\_/"],
1885
+ "V": ["\\/", " v "],
1886
+ "W": ["| |", "|_|"],
1887
+ "X": ["\\ /", " X "],
1888
+ "Y": ["\\/", " | "],
1889
+ "Z": ["_/", "/_ "],
1890
+ "0": ["0", "0"],
1891
+ "1": ["1", "1"],
1892
+ "2": ["2", "2"],
1893
+ "3": ["3", "3"],
1894
+ "4": ["4", "4"],
1895
+ "5": ["5", "5"],
1896
+ "6": ["6", "6"],
1897
+ "7": ["7", "7"],
1898
+ "8": ["8", "8"],
1899
+ "9": ["9", "9"],
1900
+ " ": [" ", " "],
1901
+ "!": ["!", "."],
1902
+ "?": ["?", "."],
1903
+ ".": [" ", "."],
1904
+ ",": [" ", ","],
1905
+ "-": ["-", " "],
1906
+ ":": [":", ":"]
1907
+ };
1908
+ var DOTS_FONT = {
1909
+ "A": [".::.", ":..:", "::::", ": :"],
1910
+ "B": ["::. ", "::.:", "::. ", ":::,"],
1911
+ "C": [".:::", ": ", ": ", ".:::"],
1912
+ "D": ["::. ", ": :", ": :", "::. "],
1913
+ "E": ["::::", "::: ", "::: ", "::::"],
1914
+ "F": ["::::", "::: ", "::: ", ": "],
1915
+ "G": [".:::", ": ", ": ::", ".:::"],
1916
+ "H": [": :", "::::", ": :", ": :"],
1917
+ "I": ["::::", " : ", " : ", "::::"],
1918
+ "J": ["::::", " : ", " : ", ".:. "],
1919
+ "K": [": :", ": . ", ":.. ", ": :"],
1920
+ "L": [": ", ": ", ": ", "::::"],
1921
+ "M": [": :", ":: ::", ": : :", ": :"],
1922
+ "N": [": :", ":: :", ": : :", ": ::"],
1923
+ "O": [".::.", ": :", ": :", ".::."],
1924
+ "P": ["::. ", ": :", "::. ", ": "],
1925
+ "Q": [".::.", ": :", ": .:", ".:.."],
1926
+ "R": ["::. ", ": :", ":.. ", ": :"],
1927
+ "S": [".:::", ": ", " :::", ":::."],
1928
+ "T": ["::::", " : ", " : ", " : "],
1929
+ "U": [": :", ": :", ": :", ".::."],
1930
+ "V": [": :", ": :", " :: ", " : "],
1931
+ "W": [": :", ": :", ": : :", " :.: "],
1932
+ "X": [": :", " :: ", " :: ", ": :"],
1933
+ "Y": [": :", " :: ", " : ", " : "],
1934
+ "Z": ["::::", " : ", " : ", "::::"],
1935
+ "0": [".::.", ": :", ": :", ".::."],
1936
+ "1": [" : ", " : ", " : ", " : "],
1937
+ "2": [".::.", " ::", ".::.", "::.."],
1938
+ "3": [".::.", " ..:", " .:", ".::."],
1939
+ "4": [": :", "::::", " :", " :"],
1940
+ "5": ["::::", ":::.", " :", ":::."],
1941
+ "6": [".::.", ":::.", ": :", ".::."],
1942
+ "7": ["::::", " :", " : ", " : "],
1943
+ "8": [".::.", ".::.", ".::.", ".::."],
1944
+ "9": [".::.", ": :", " :::", ".::."],
1945
+ " ": [" ", " ", " ", " "],
1946
+ "!": [" :: ", " :: ", " ", " :: "],
1947
+ "?": [".::.", " ::", " ", " : "],
1948
+ ".": [" ", " ", " ", " :: "],
1949
+ ",": [" ", " ", " : ", ": "],
1950
+ "-": [" ", "::::", " ", " "],
1951
+ ":": [" ", " :: ", " ", " :: "]
1952
+ };
1953
+ var ASCII_FONTS = {
1954
+ block: BLOCK_FONT,
1955
+ banner: BANNER_FONT,
1956
+ small: SMALL_FONT,
1957
+ dots: DOTS_FONT
1958
+ };
1959
+ function getCharData(font, char) {
1960
+ const upper = char.toUpperCase();
1961
+ if (font[upper]) return font[upper];
1962
+ if (font[char]) return font[char];
1963
+ return font[" "] || [" ", " ", " "];
1964
+ }
1965
+ function textToAscii(text, options) {
1966
+ const font = options?.font ?? "block";
1967
+ const maxWidth = options?.width ?? 80;
1968
+ const align = options?.align ?? "left";
1969
+ const fontData = ASCII_FONTS[font];
1970
+ if (!text) return "";
1971
+ const chars = text.split("");
1972
+ const charDataList = chars.map((c) => getCharData(fontData, c));
1973
+ const height = charDataList[0]?.length ?? 0;
1974
+ const lines = [];
1975
+ for (let row = 0; row < height; row++) {
1976
+ const rowParts = charDataList.map((cd) => cd[row] ?? " ".repeat((cd[0] ?? "").length));
1977
+ let line = rowParts.join(" ");
1978
+ if (line.length > maxWidth) {
1979
+ line = line.slice(0, maxWidth);
1980
+ }
1981
+ lines.push(line);
1982
+ }
1983
+ if (align === "center" || align === "right") {
1984
+ const maxLen = Math.max(...lines.map((l) => l.length));
1985
+ return lines.map((line) => {
1986
+ const pad = maxLen - line.length;
1987
+ if (align === "center") {
1988
+ const left = Math.floor(pad / 2);
1989
+ const right = pad - left;
1990
+ return " ".repeat(left) + line + " ".repeat(right);
1991
+ }
1992
+ return " ".repeat(pad) + line;
1993
+ }).join("\n");
1994
+ }
1995
+ return lines.join("\n");
1996
+ }
1997
+ function getAvailableFonts() {
1998
+ return [
1999
+ { value: "block", label: "Block", preview: textToAscii("Hi", { font: "block" }) },
2000
+ { value: "banner", label: "Banner", preview: textToAscii("Hi", { font: "banner" }) },
2001
+ { value: "small", label: "Small", preview: textToAscii("Hi", { font: "small" }) },
2002
+ { value: "dots", label: "Dots", preview: textToAscii("Hi", { font: "dots" }) }
2003
+ ];
2004
+ }
2005
+ function addBorder(text, style) {
2006
+ const lines = text.split("\n");
2007
+ const maxLen = Math.max(...lines.map((l) => l.length));
2008
+ const chars = {
2009
+ box: { tl: "\u250C", tr: "\u2510", bl: "\u2514", br: "\u2518", h: "\u2500", v: "\u2502" },
2010
+ double: { tl: "\u2554", tr: "\u2557", bl: "\u255A", br: "\u255D", h: "\u2550", v: "\u2551" },
2011
+ rounded: { tl: "\u256D", tr: "\u256E", bl: "\u2570", br: "\u256F", h: "\u2500", v: "\u2502" },
2012
+ stars: { tl: "*", tr: "*", bl: "*", br: "*", h: "*", v: "*" }
2013
+ }[style];
2014
+ const top = chars.tl + chars.h.repeat(maxLen + 2) + chars.tr;
2015
+ const bottom = chars.bl + chars.h.repeat(maxLen + 2) + chars.br;
2016
+ const middle = lines.map((l) => chars.v + " " + l.padEnd(maxLen) + " " + chars.v);
2017
+ return [top, ...middle, bottom].join("\n");
2018
+ }
2019
+ function centerText(text, width) {
2020
+ const lines = text.split("\n");
2021
+ return lines.map((line) => {
2022
+ if (line.length >= width) return line;
2023
+ const pad = width - line.length;
2024
+ const left = Math.floor(pad / 2);
2025
+ const right = pad - left;
2026
+ return " ".repeat(left) + line + " ".repeat(right);
2027
+ }).join("\n");
2028
+ }
2029
+ var MORSE_CODE = {
2030
+ "A": ".-",
2031
+ "B": "-...",
2032
+ "C": "-.-.",
2033
+ "D": "-..",
2034
+ "E": ".",
2035
+ "F": "..-.",
2036
+ "G": "--.",
2037
+ "H": "....",
2038
+ "I": "..",
2039
+ "J": ".---",
2040
+ "K": "-.-",
2041
+ "L": ".-..",
2042
+ "M": "--",
2043
+ "N": "-.",
2044
+ "O": "---",
2045
+ "P": ".--.",
2046
+ "Q": "--.-",
2047
+ "R": ".-.",
2048
+ "S": "...",
2049
+ "T": "-",
2050
+ "U": "..-",
2051
+ "V": "...-",
2052
+ "W": ".--",
2053
+ "X": "-..-",
2054
+ "Y": "-.--",
2055
+ "Z": "--..",
2056
+ "0": "-----",
2057
+ "1": ".----",
2058
+ "2": "..---",
2059
+ "3": "...--",
2060
+ "4": "....-",
2061
+ "5": ".....",
2062
+ "6": "-....",
2063
+ "7": "--...",
2064
+ "8": "---..",
2065
+ "9": "----.",
2066
+ ".": ".-.-.-",
2067
+ ",": "--..--",
2068
+ "?": "..--..",
2069
+ "'": ".----.",
2070
+ "!": "-.-.--",
2071
+ "/": "-..-.",
2072
+ "(": "-.--.",
2073
+ ")": "-.--.-",
2074
+ "&": ".-...",
2075
+ ";": "-.-.-.",
2076
+ "=": "-...-",
2077
+ "+": ".-.-.",
2078
+ "-": "-....-",
2079
+ "_": "..--.-",
2080
+ '"': ".-..-.",
2081
+ "$": "...-..-",
2082
+ "@": ".--.-."
2083
+ };
2084
+ var MORSE_TO_TEXT = Object.fromEntries(
2085
+ Object.entries(MORSE_CODE).map(([k, v]) => [v, k])
2086
+ );
2087
+ function applyDotDash(morse, dotChar, dashChar) {
2088
+ return morse.replace(/\./g, dotChar).replace(/-/g, dashChar);
2089
+ }
2090
+ function normalizeDotDash(morse, dotChar, dashChar) {
2091
+ if (dotChar === "." && dashChar === "-") return morse;
2092
+ const escapedDot = dotChar.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2093
+ const escapedDash = dashChar.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2094
+ return morse.replace(new RegExp(escapedDash, "g"), "-").replace(new RegExp(escapedDot, "g"), ".");
2095
+ }
2096
+ function textToMorse(text, options) {
2097
+ const separator = options?.separator ?? " ";
2098
+ const wordSeparator = options?.wordSeparator ?? " / ";
2099
+ const dotChar = options?.dotChar ?? ".";
2100
+ const dashChar = options?.dashChar ?? "-";
2101
+ const words = text.trim().toUpperCase().split(/\s+/);
2102
+ const morseWords = words.map((word) => {
2103
+ const chars = word.split("");
2104
+ const morseChars = chars.map((c) => MORSE_CODE[c]).filter((m) => m !== void 0);
2105
+ return morseChars.map((m) => applyDotDash(m, dotChar, dashChar)).join(separator);
2106
+ });
2107
+ return morseWords.join(wordSeparator);
2108
+ }
2109
+ function morseToText(morse, options) {
2110
+ const separator = options?.separator ?? " ";
2111
+ const wordSeparator = options?.wordSeparator ?? " / ";
2112
+ const dotChar = options?.dotChar ?? ".";
2113
+ const dashChar = options?.dashChar ?? "-";
2114
+ const normalized = normalizeDotDash(morse.trim(), dotChar, dashChar);
2115
+ const wordSepNormalized = normalizeDotDash(wordSeparator, dotChar, dashChar);
2116
+ const sepNormalized = normalizeDotDash(separator, dotChar, dashChar);
2117
+ const wordSepEscaped = wordSepNormalized.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2118
+ const words = normalized.split(new RegExp(wordSepEscaped));
2119
+ const result = [];
2120
+ for (const word of words) {
2121
+ const sepEscaped = sepNormalized.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2122
+ const chars = word.trim().split(new RegExp(sepEscaped)).filter(Boolean);
2123
+ const decoded = [];
2124
+ for (const c of chars) {
2125
+ const letter = MORSE_TO_TEXT[c];
2126
+ if (!letter) return { error: `Unknown morse sequence: ${c}` };
2127
+ decoded.push(letter);
2128
+ }
2129
+ result.push(decoded.join(""));
2130
+ }
2131
+ return result.join(" ");
2132
+ }
2133
+ function isValidMorse(morse) {
2134
+ const tokens = morse.trim().split(/\s+/);
2135
+ for (const token of tokens) {
2136
+ if (token === "/") continue;
2137
+ if (!/^[.\-]+$/.test(token)) return false;
2138
+ if (!MORSE_TO_TEXT[token]) return false;
2139
+ }
2140
+ return true;
2141
+ }
2142
+ function getMorseForChar(char) {
2143
+ return MORSE_CODE[char.toUpperCase()] ?? null;
2144
+ }
2145
+ function getMorseTiming(morse) {
2146
+ const result = [];
2147
+ const tokens = morse.trim().split(" ");
2148
+ for (let i = 0; i < tokens.length; i++) {
2149
+ const token = tokens[i];
2150
+ if (token === "/") {
2151
+ result.push({ type: "wordgap", duration: 700 });
2152
+ continue;
2153
+ }
2154
+ for (let j = 0; j < token.length; j++) {
2155
+ if (token[j] === ".") {
2156
+ result.push({ type: "dot", duration: 100 });
2157
+ } else if (token[j] === "-") {
2158
+ result.push({ type: "dash", duration: 300 });
2159
+ }
2160
+ if (j < token.length - 1) {
2161
+ result.push({ type: "gap", duration: 100 });
2162
+ }
2163
+ }
2164
+ if (i < tokens.length - 1 && tokens[i + 1] !== "/") {
2165
+ result.push({ type: "gap", duration: 100 });
2166
+ }
2167
+ }
2168
+ return result;
2169
+ }
2170
+
2171
+ exports.CASE_FORMATS = CASE_FORMATS;
2172
+ exports.DEFAULT_CONVERT_OPTIONS = DEFAULT_CONVERT_OPTIONS;
2173
+ exports.ESCAPE_MODES = ESCAPE_MODES;
2174
+ exports.LINE_OPS = LINE_OPS;
2175
+ exports.MORSE_CODE = MORSE_CODE;
2176
+ exports.addBorder = addBorder;
2177
+ exports.analyzeText = analyzeText;
2178
+ exports.applyOp = applyOp;
2179
+ exports.applyOps = applyOps;
2180
+ exports.centerText = centerText;
2181
+ exports.convertAll = convertAll;
2182
+ exports.convertCase = convertCase;
2183
+ exports.countWords = countWords;
2184
+ exports.csvToHtml = csvToHtml;
2185
+ exports.csvToMarkdown = csvToMarkdown;
2186
+ exports.detectDelimiter = detectDelimiter;
2187
+ exports.diffLines = diffLines;
2188
+ exports.diffLinesSimple = diffLinesSimple;
2189
+ exports.diffStats = diffStats;
2190
+ exports.escapeAll = escapeAll;
2191
+ exports.escapeString = escapeString;
2192
+ exports.extractHeadings = extractHeadings;
2193
+ exports.formatReadingTime = formatReadingTime;
2194
+ exports.generate = generate;
2195
+ exports.generateDiff = generateDiff;
2196
+ exports.generateHtmlTable = generateHtmlTable;
2197
+ exports.generateMarkdownTable = generateMarkdownTable;
2198
+ exports.generateParagraphs = generateParagraphs;
2199
+ exports.generateSentences = generateSentences;
2200
+ exports.generateWords = generateWords;
2201
+ exports.getAvailableFonts = getAvailableFonts;
2202
+ exports.getMorseForChar = getMorseForChar;
2203
+ exports.getMorseTiming = getMorseTiming;
2204
+ exports.htmlToMarkdown = htmlToMarkdown;
2205
+ exports.isValidMorse = isValidMorse;
2206
+ exports.markdownToHtml = markdownToHtml;
2207
+ exports.morseToText = morseToText;
2208
+ exports.numberToOrdinal = numberToOrdinal;
2209
+ exports.numberToRoman = numberToRoman;
2210
+ exports.numberToWords = numberToWords;
2211
+ exports.ordinalWords = ordinalWords;
2212
+ exports.parseDiff = parseDiff;
2213
+ exports.parseTableData = parseTableData;
2214
+ exports.readabilityScore = readabilityScore;
2215
+ exports.renderMarkdown = renderMarkdown;
2216
+ exports.romanToNumber = romanToNumber;
2217
+ exports.sentenceCount = sentenceCount;
2218
+ exports.slugify = slugify;
2219
+ exports.slugifyAll = slugifyAll;
2220
+ exports.syllableCount = syllableCount;
2221
+ exports.textToAscii = textToAscii;
2222
+ exports.textToMorse = textToMorse;
2223
+ exports.unescapeString = unescapeString;
2224
+ exports.wordFrequency = wordFrequency;