@utilix-tech/sdk 0.29.0 → 0.31.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 (35) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +25 -11
  3. package/dist/{chunk-2CJSLYWI.js → chunk-3TYWIX3B.js} +107 -1
  4. package/dist/{chunk-66QHV5KW.js → chunk-6FIB72KX.js} +66 -1
  5. package/dist/{chunk-I63BCOAG.js → chunk-GDIZWDBY.js} +57 -1
  6. package/dist/{chunk-WO3LJMVV.js → chunk-WVEKRKGU.js} +101 -1
  7. package/dist/{data-XRb0D7Zn.d.cts → data-C4lCByXw.d.cts} +24 -2
  8. package/dist/{data-XRb0D7Zn.d.ts → data-C4lCByXw.d.ts} +24 -2
  9. package/dist/{generators-BGtRGpJZ.d.ts → generators-Du8cBesn.d.cts} +45 -2
  10. package/dist/{generators-BGtRGpJZ.d.cts → generators-Du8cBesn.d.ts} +45 -2
  11. package/dist/index.cjs +327 -0
  12. package/dist/index.d.cts +4 -4
  13. package/dist/index.d.ts +4 -4
  14. package/dist/index.js +4 -4
  15. package/dist/{json-DEVFIpsC.d.cts → json-Ta9JykSB.d.cts} +36 -2
  16. package/dist/{json-DEVFIpsC.d.ts → json-Ta9JykSB.d.ts} +36 -2
  17. package/dist/tools/data.cjs +65 -0
  18. package/dist/tools/data.d.cts +1 -1
  19. package/dist/tools/data.d.ts +1 -1
  20. package/dist/tools/data.js +1 -1
  21. package/dist/tools/generators.cjs +106 -0
  22. package/dist/tools/generators.d.cts +1 -1
  23. package/dist/tools/generators.d.ts +1 -1
  24. package/dist/tools/generators.js +1 -1
  25. package/dist/tools/json.cjs +100 -0
  26. package/dist/tools/json.d.cts +1 -1
  27. package/dist/tools/json.d.ts +1 -1
  28. package/dist/tools/json.js +1 -1
  29. package/dist/tools/units.cjs +56 -0
  30. package/dist/tools/units.d.cts +1 -1
  31. package/dist/tools/units.d.ts +1 -1
  32. package/dist/tools/units.js +1 -1
  33. package/dist/{units-COt5uI20.d.cts → units-DQYLZd1n.d.cts} +33 -2
  34. package/dist/{units-COt5uI20.d.ts → units-DQYLZd1n.d.ts} +33 -2
  35. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  Full release notes for all Utilix surfaces (browser tools, REST API, SDKs, MCP server) live at [utilix.tech/changelog](https://utilix.tech/changelog). This file tracks just this package.
4
4
 
5
+ ## 0.31.0
6
+ - Add `calculateEmi` (emi-calculator): equated monthly installment, total interest, and a year-by-year principal/interest breakdown from principal, annual rate, and tenure in years or months.
7
+ - Add `parseFrontMatter` (markdown-front-matter-parser): split a Markdown document into its YAML front matter fields and body content, parsing scalars, inline arrays, and block lists.
8
+
9
+ ## 0.30.0
10
+ - Add `jsonSchemaToTypescript` (json-schema-to-typescript): convert a JSON Schema document into TypeScript interfaces/types, reading `required`/`enum`/`oneOf`/`anyOf`/`allOf`/`$ref` directly instead of inferring from an example payload.
11
+ - Add `estimatePasswordEntropy` (password-entropy-estimator): bits of entropy from a password's character pool, a strength label, and crack-time estimates across four guess-rate scenarios.
12
+
5
13
  ## 0.29.0
6
14
  - Add `readPdfPageDimensions` (pdf-page-dimensions): each page's MediaBox width/height (points and inches), rotation, and orientation, walking the Root -> Pages -> Kids tree and inheriting from ancestor nodes, plus a common paper size match (Letter, A4, etc.).
7
15
  - Add `parseIpv6Address` (ipv6-compressor): expand an IPv6 address to its full 8-group form or compress it to its RFC 5952 canonical shortest form, classify its address type, and handle an embedded IPv4 suffix or zone ID.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @utilix-tech/sdk
2
2
 
3
- **581 developer utility functions for Node.js: runs locally, no API key required.**
3
+ **585 developer utility functions for Node.js: runs locally, no API key required.**
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/@utilix-tech/sdk?style=flat-square&color=cb3837)](https://www.npmjs.com/package/@utilix-tech/sdk)
6
6
  [![npm downloads](https://img.shields.io/npm/dm/@utilix-tech/sdk?style=flat-square)](https://www.npmjs.com/package/@utilix-tech/sdk)
@@ -65,7 +65,7 @@ const { formatJson } = require("@utilix-tech/sdk/json");
65
65
  ### `/json`: JSON Tools
66
66
 
67
67
  ```ts
68
- import { formatJson, minifyJson, diffJson, jsonToTypescript, validateJson,
68
+ import { formatJson, minifyJson, diffJson, jsonToTypescript, jsonSchemaToTypescript, validateJson,
69
69
  evaluateJsonPath, resolveJsonPointer, jsonToCsv, yamlToJson, jsonToYaml, getJsonStats } from "@utilix-tech/sdk/json";
70
70
 
71
71
  // Format with 2-space indent
@@ -77,6 +77,9 @@ diffJson(jsonA, jsonB);
77
77
  // Generate TypeScript interface from JSON
78
78
  jsonToTypescript('{"id":1,"name":"Alice"}', { rootName: "User" });
79
79
 
80
+ // Generate TypeScript interfaces from a JSON Schema (reads required/enum/$ref directly)
81
+ jsonSchemaToTypescript('{"type":"object","properties":{"name":{"type":"string"}},"required":["name"]}', { rootName: "User" });
82
+
80
83
  // Query with JSONPath
81
84
  evaluateJsonPath(obj, "$.users[*].name");
82
85
 
@@ -174,13 +177,13 @@ calculateStringDistance("kitten", "sitting");
174
177
 
175
178
  ---
176
179
 
177
- ### `/data`: CSV / YAML / TOML / XML / INI / NDJSON / .env diff / subtitles
180
+ ### `/data`: CSV / YAML / TOML / XML / INI / NDJSON / .env diff / subtitles / Markdown front matter
178
181
 
179
182
  ```ts
180
183
  import { parseCsv, csvToJson, validateYaml, tomlToJson, jsonToToml,
181
184
  formatXml, xmlToJson, jsonToXml, parseIni,
182
185
  validateNdjson, formatNdjson, ndjsonToJsonArray, diffEnvExample,
183
- parseSubtitles, convertSubtitles, shiftSubtitles } from "@utilix-tech/sdk/data";
186
+ parseSubtitles, convertSubtitles, shiftSubtitles, parseFrontMatter } from "@utilix-tech/sdk/data";
184
187
 
185
188
  // CSV
186
189
  const rows = parseCsv("name,age\nalice,30\nbob,25");
@@ -214,6 +217,10 @@ convertSubtitles("1\n00:00:01,000 --> 00:00:04,000\nHello there.\n", "vtt");
214
217
  // { format: "vtt", sourceFormat: "srt", output: "WEBVTT\n\n00:00:01.000 --> ...", cueCount: 1, ... }
215
218
  shiftSubtitles("1\n00:00:01,000 --> 00:00:04,000\nHi\n", -2.5);
216
219
  // shifts every cue 2.5s earlier, clamping anything below zero to 00:00:00
220
+
221
+ // Markdown front matter: split a document into its YAML front matter and body
222
+ parseFrontMatter("---\ntitle: Hello World\ntags: [foo, bar]\n---\n# Body");
223
+ // { frontMatter: { title: "Hello World", tags: ["foo", "bar"] }, body: "# Body", hasFrontMatter: true, ... }
217
224
  ```
218
225
 
219
226
  ---
@@ -222,14 +229,17 @@ shiftSubtitles("1\n00:00:01,000 --> 00:00:04,000\nHi\n", -2.5);
222
229
 
223
230
  ```ts
224
231
  import { generateUuid, generateV4, generateV7, generateUlid,
225
- generatePassword, checkStrength, generateData } from "@utilix-tech/sdk/generators";
232
+ generatePassword, checkStrength, estimatePasswordEntropy, generateData } from "@utilix-tech/sdk/generators";
226
233
 
227
234
  generateUuid(); // "f47ac10b-58cc-4372-a567-0e02b2c3d479" (v4)
228
235
  generateV7(); // time-ordered UUID v7
229
236
  generateUlid(); // "01ARZ3NDEKTSV4RRFFQ69G5FAV"
230
237
 
231
238
  generatePassword({ length: 16, symbols: true, numbers: true });
232
- checkStrength("P@ssw0rd!"); // { score: 4, label: "Strong", entropy: 52.4 }
239
+ checkStrength("P@ssw0rd!"); // { score: 4, label: "Strong", color: "#16a34a" }
240
+
241
+ // Actual bits of entropy from the character pool, plus crack-time estimates
242
+ estimatePasswordEntropy("Tr0ub4dor&3xyzKL9!"); // { entropyBits: 118.26, strength: "strong", crackTimes: [...] }
233
243
 
234
244
  // Generate fake data rows
235
245
  generateData([
@@ -272,7 +282,7 @@ formatIso8601Duration(90061); // { iso: "P1DT1H1M1S", ... }
272
282
  ### `/units`: Conversions
273
283
 
274
284
  ```ts
275
- import { convertBytes, pxToAll, convert, formatValue, validateCardNumber, validateIban, calculateLoan, validateBarcode, calculateTax, calculateCompoundInterest, validateIsbn, calculateTipSplit, calculateSimpleInterest, calculateTimeValue, calculatePercentageChange, convertAprApy, calculateMarginMarkup, calculateDiscount, applySuccessiveDiscounts, calculateBreakEven, calculateVideoBitrate, calculateRuleOf72 } from "@utilix-tech/sdk/units";
285
+ import { convertBytes, pxToAll, convert, formatValue, validateCardNumber, validateIban, calculateLoan, validateBarcode, calculateTax, calculateCompoundInterest, validateIsbn, calculateTipSplit, calculateSimpleInterest, calculateTimeValue, calculatePercentageChange, convertAprApy, calculateMarginMarkup, calculateDiscount, applySuccessiveDiscounts, calculateBreakEven, calculateVideoBitrate, calculateRuleOf72, calculateEmi } from "@utilix-tech/sdk/units";
276
286
 
277
287
  // File sizes
278
288
  convertBytes(1073741824, "GB"); // 1
@@ -362,6 +372,10 @@ calculateVideoBitrate({ mode: "size-from-bitrate", durationSeconds: 600, videoBi
362
372
  // Rule of 72: years to double from a rate, or the rate needed to double in N years
363
373
  calculateRuleOf72(8, "rate-to-years");
364
374
  // { ruleOf72Estimate: 9, exactValue: 9.0065, errorPercent: -0.0718, ... }
375
+
376
+ // EMI: equated monthly installment with a year-by-year principal/interest breakdown
377
+ calculateEmi(500000, 8.5, 5, "years");
378
+ // { emi: 10258.27, totalInterest: 115495.89, tenureMonths: 60, yearlyBreakdown: [...] }
365
379
  ```
366
380
 
367
381
  ---
@@ -637,14 +651,14 @@ readVideoInfo(new Uint8Array(videoBytes));
637
651
 
638
652
  | Import | What it does |
639
653
  |---|---|
640
- | `@utilix-tech/sdk/json` | Format, minify, diff, validate, JSONPath, CSV↔JSON, YAML↔JSON, TS types |
654
+ | `@utilix-tech/sdk/json` | Format, minify, diff, validate, JSONPath, CSV↔JSON, YAML↔JSON, TS types from data or from a JSON Schema |
641
655
  | `@utilix-tech/sdk/encoding` | Base64, URL, HTML entities, Base32/Base58/Base62 encode/decode |
642
656
  | `@utilix-tech/sdk/hashing` | MD5, SHA-1/256/512, bcrypt, HMAC, .htpasswd |
643
657
  | `@utilix-tech/sdk/text` | Case convert, slugify, word count, lorem ipsum, line ops, HTML→Markdown, Levenshtein/Damerau string distance |
644
- | `@utilix-tech/sdk/data` | CSV, YAML, TOML, XML, INI, NDJSON parse and convert, SRT/WebVTT subtitles |
645
- | `@utilix-tech/sdk/generators` | UUID v4/v7, ULID, passwords, strength check, fake data |
658
+ | `@utilix-tech/sdk/data` | CSV, YAML, TOML, XML, INI, NDJSON parse and convert, SRT/WebVTT subtitles, Markdown front matter parser |
659
+ | `@utilix-tech/sdk/generators` | UUID v4/v7, ULID, passwords, strength check, entropy estimator, fake data |
646
660
  | `@utilix-tech/sdk/time` | Date diff, timezone convert, cron parse, relative time |
647
- | `@utilix-tech/sdk/units` | Bytes, CSS px/rem, number bases, currency format, credit card/IBAN/barcode/ISBN validation, loan calculator, compound/simple interest calculators, VAT/sales tax calculator, tip/bill split calculator, break-even point calculator, Rule of 72 calculator |
661
+ | `@utilix-tech/sdk/units` | Bytes, CSS px/rem, number bases, currency format, credit card/IBAN/barcode/ISBN validation, loan calculator, EMI calculator, compound/simple interest calculators, VAT/sales tax calculator, tip/bill split calculator, break-even point calculator, Rule of 72 calculator |
648
662
  | `@utilix-tech/sdk/network` | HTTP status codes, IP validation, country flags, geolocation URLs, HAR file parsing, User-Agent parsing, IPv6 address compress/expand |
649
663
  | `@utilix-tech/sdk/api` | cURL build/parse, JWT decode/sign, JWKS parse, CORS headers, CSP header |
650
664
  | `@utilix-tech/sdk/code` | SQL format/minify, HTML format/minify, regex tester, GraphQL format, MIME type lookup, GitHub URL parsing |
@@ -12,6 +12,7 @@ __export(generators_exports, {
12
12
  SYMBOL_CHARS: () => SYMBOL_CHARS,
13
13
  ULID_REGEX: () => ULID_REGEX,
14
14
  checkStrength: () => checkStrength,
15
+ estimatePasswordEntropy: () => estimatePasswordEntropy,
15
16
  generateBulk: () => generateBulk,
16
17
  generateBulkPasswords: () => generateBulkPasswords,
17
18
  generateBulkUlids: () => generateBulkUlids,
@@ -228,6 +229,111 @@ function checkStrength(password) {
228
229
  color: levels[score].color
229
230
  };
230
231
  }
232
+ var _SYMBOL_POOL_CHARS = " !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
233
+ var _SYMBOL_POOL_SET = new Set(_SYMBOL_POOL_CHARS.split(""));
234
+ function _hasSymbolChar(password) {
235
+ for (const ch of password) {
236
+ if (_SYMBOL_POOL_SET.has(ch)) return true;
237
+ }
238
+ return false;
239
+ }
240
+ function _hasSequentialRun(password, minRun) {
241
+ let ascRun = 1;
242
+ let descRun = 1;
243
+ for (let i = 1; i < password.length; i++) {
244
+ const prev = password.charCodeAt(i - 1);
245
+ const curr = password.charCodeAt(i);
246
+ if (curr === prev + 1) {
247
+ ascRun++;
248
+ descRun = 1;
249
+ } else if (curr === prev - 1) {
250
+ descRun++;
251
+ ascRun = 1;
252
+ } else {
253
+ ascRun = 1;
254
+ descRun = 1;
255
+ }
256
+ if (ascRun >= minRun || descRun >= minRun) return true;
257
+ }
258
+ return false;
259
+ }
260
+ function _formatCrackDuration(seconds) {
261
+ if (!isFinite(seconds)) return "effectively never";
262
+ if (seconds < 1) return "instantly";
263
+ const units = [
264
+ ["century", 315576e4],
265
+ ["year", 31557600],
266
+ ["month", 2629800],
267
+ ["day", 86400],
268
+ ["hour", 3600],
269
+ ["minute", 60],
270
+ ["second", 1]
271
+ ];
272
+ for (const [name, unitSeconds] of units) {
273
+ if (seconds >= unitSeconds) {
274
+ const value = seconds / unitSeconds;
275
+ if (name === "century" && value > 1e3) return "longer than the age of the universe";
276
+ const rounded = value >= 100 ? Math.round(value) : Math.round(value * 10) / 10;
277
+ const plural = name === "century" ? "centuries" : `${name}s`;
278
+ return `${rounded} ${rounded === 1 ? name : plural}`;
279
+ }
280
+ }
281
+ return "instantly";
282
+ }
283
+ function estimatePasswordEntropy(password) {
284
+ if (!password) return { error: "Password is required" };
285
+ const hasLowercase = /[a-z]/.test(password);
286
+ const hasUppercase = /[A-Z]/.test(password);
287
+ const hasDigits = /[0-9]/.test(password);
288
+ const hasSymbols = _hasSymbolChar(password);
289
+ const hasOther = /[^\x20-\x7e]/.test(password);
290
+ let poolSize = 0;
291
+ if (hasLowercase) poolSize += 26;
292
+ if (hasUppercase) poolSize += 26;
293
+ if (hasDigits) poolSize += 10;
294
+ if (hasSymbols) poolSize += _SYMBOL_POOL_CHARS.length;
295
+ if (hasOther) poolSize += 100;
296
+ const entropyBits = Math.round(password.length * Math.log2(poolSize) * 100) / 100;
297
+ let strength;
298
+ if (entropyBits < 28) strength = "very-weak";
299
+ else if (entropyBits < 36) strength = "weak";
300
+ else if (entropyBits < 60) strength = "fair";
301
+ else if (entropyBits < 128) strength = "strong";
302
+ else strength = "very-strong";
303
+ const averageGuesses = Math.pow(2, entropyBits) / 2;
304
+ const scenarios = [
305
+ { scenario: "Online, throttled (100 guesses/hour)", guessesPerSecond: 100 / 3600 },
306
+ { scenario: "Online, unthrottled (10 guesses/sec)", guessesPerSecond: 10 },
307
+ { scenario: "Offline, slow hash e.g. bcrypt (10k guesses/sec)", guessesPerSecond: 1e4 },
308
+ { scenario: "Offline, fast hash / GPU cluster (10B guesses/sec)", guessesPerSecond: 1e10 }
309
+ ];
310
+ const crackTimes = scenarios.map((s) => ({
311
+ scenario: s.scenario,
312
+ guessesPerSecond: s.guessesPerSecond,
313
+ humanReadable: _formatCrackDuration(averageGuesses / s.guessesPerSecond)
314
+ }));
315
+ const warnings = [];
316
+ if (password.length < 8) {
317
+ warnings.push("Shorter than 8 characters \u2014 most sites and cracking tools treat this as trivially weak regardless of entropy.");
318
+ }
319
+ if (/(.)\1{2,}/.test(password)) {
320
+ warnings.push('Contains a repeated character run (e.g. "aaa"), which is easier to guess than the entropy figure implies.');
321
+ }
322
+ if (_hasSequentialRun(password, 3)) {
323
+ warnings.push('Contains a sequential run (e.g. "abc" or "321"), which is easier to guess than the entropy figure implies.');
324
+ }
325
+ if (poolSize <= 26) {
326
+ warnings.push("Uses only one character class \u2014 mixing in uppercase, digits, or symbols raises the character pool and entropy.");
327
+ }
328
+ return {
329
+ length: password.length,
330
+ charset: { hasLowercase, hasUppercase, hasDigits, hasSymbols, hasOther, poolSize },
331
+ entropyBits,
332
+ strength,
333
+ crackTimes,
334
+ warnings
335
+ };
336
+ }
231
337
  var DATA_TYPES = [
232
338
  { value: "name", label: "Full Name", example: "John Smith" },
233
339
  { value: "email", label: "Email Address", example: "john.smith@gmail.com" },
@@ -517,4 +623,4 @@ async function generateQrDataUrl(text, options) {
517
623
  });
518
624
  }
519
625
 
520
- export { AMBIGUOUS_CHARS, DATA_TYPES, DEFAULT_OPTIONS, DEFAULT_QR_OPTIONS, SYMBOL_CHARS, ULID_REGEX, checkStrength, generateBulk, generateBulkPasswords, generateBulkUlids, generateData, generatePassword, generateQrDataUrl, generateQrSvg, generateSingle, generateUlid, generateUuid, generateV4, generateV7, generators_exports, isValidUlid, isValidUuid, parseUlid, parseUuidVersion };
626
+ export { AMBIGUOUS_CHARS, DATA_TYPES, DEFAULT_OPTIONS, DEFAULT_QR_OPTIONS, SYMBOL_CHARS, ULID_REGEX, checkStrength, estimatePasswordEntropy, generateBulk, generateBulkPasswords, generateBulkUlids, generateData, generatePassword, generateQrDataUrl, generateQrSvg, generateSingle, generateUlid, generateUuid, generateV4, generateV7, generators_exports, isValidUlid, isValidUuid, parseUlid, parseUuidVersion };
@@ -32,6 +32,7 @@ __export(data_exports, {
32
32
  ndjsonToJsonArray: () => ndjsonToJsonArray,
33
33
  parseCsv: () => parseCsv,
34
34
  parseEnv: () => parseEnv,
35
+ parseFrontMatter: () => parseFrontMatter,
35
36
  parseIni: () => parseIni,
36
37
  parseSubtitleTimestamp: () => parseSubtitleTimestamp,
37
38
  parseSubtitles: () => parseSubtitles,
@@ -1334,5 +1335,69 @@ function shiftSubtitles(input, offsetSeconds, target) {
1334
1335
  warnings
1335
1336
  };
1336
1337
  }
1338
+ function parseFrontMatterScalar(value) {
1339
+ if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
1340
+ return value.slice(1, -1);
1341
+ }
1342
+ if (value === "true") return true;
1343
+ if (value === "false") return false;
1344
+ if (value === "null" || value === "~") return null;
1345
+ if (value !== "" && !Number.isNaN(Number(value))) return Number(value);
1346
+ return value;
1347
+ }
1348
+ function parseFrontMatter(input) {
1349
+ if (typeof input !== "string" || input.length === 0) return { error: "input is required" };
1350
+ const normalized = input.replace(/\r\n/g, "\n");
1351
+ if (!normalized.startsWith("---\n") && normalized !== "---") {
1352
+ return { frontMatter: {}, body: input, hasFrontMatter: false, raw: "" };
1353
+ }
1354
+ const closingIdx = normalized.indexOf("\n---", 4);
1355
+ if (closingIdx === -1) {
1356
+ return { error: 'Front matter opening delimiter found but no closing "---" delimiter' };
1357
+ }
1358
+ const raw = normalized.slice(4, closingIdx);
1359
+ let afterClose = normalized.slice(closingIdx + 4);
1360
+ if (afterClose.startsWith("\n")) afterClose = afterClose.slice(1);
1361
+ const frontMatter = {};
1362
+ const rawLines = raw.split("\n");
1363
+ let i = 0;
1364
+ while (i < rawLines.length) {
1365
+ const line = rawLines[i];
1366
+ if (line.trim() === "" || line.trim().startsWith("#")) {
1367
+ i++;
1368
+ continue;
1369
+ }
1370
+ const colonIdx = line.indexOf(":");
1371
+ if (colonIdx === -1) return { error: `Invalid front matter line ${i + 1}: expected "key: value"` };
1372
+ const key = line.slice(0, colonIdx).trim();
1373
+ if (!key) return { error: `Invalid front matter line ${i + 1}: empty key` };
1374
+ const rest = line.slice(colonIdx + 1).trim();
1375
+ if (rest === "") {
1376
+ const listItems = [];
1377
+ let j = i + 1;
1378
+ while (j < rawLines.length && /^\s*-\s+/.test(rawLines[j])) {
1379
+ listItems.push(rawLines[j].replace(/^\s*-\s+/, "").trim());
1380
+ j++;
1381
+ }
1382
+ if (listItems.length > 0) {
1383
+ frontMatter[key] = listItems.map(parseFrontMatterScalar);
1384
+ i = j;
1385
+ continue;
1386
+ }
1387
+ frontMatter[key] = null;
1388
+ i++;
1389
+ continue;
1390
+ }
1391
+ if (rest.startsWith("[") && rest.endsWith("]")) {
1392
+ const inner = rest.slice(1, -1).trim();
1393
+ frontMatter[key] = inner === "" ? [] : inner.split(",").map((s) => parseFrontMatterScalar(s.trim()));
1394
+ i++;
1395
+ continue;
1396
+ }
1397
+ frontMatter[key] = parseFrontMatterScalar(rest);
1398
+ i++;
1399
+ }
1400
+ return { frontMatter, body: afterClose, hasFrontMatter: true, raw };
1401
+ }
1337
1402
 
1338
- export { convertSubtitles, csvToJson, data_exports, detectDelimiter, detectSubtitleFormat, diffEnvExample, envToExport, envToJson, formatNdjson, formatSubtitleTimestamp, formatToml, formatXml, getSection, getSectionNames, getTomlStats, getXmlStats, getYamlStats, iniToJson, jsonArrayToNdjson, jsonToIni, jsonToToml, jsonToXml, minifyNdjson, minifyToml, minifyXml, ndjsonToJsonArray, parseCsv, parseEnv, parseIni, parseSubtitleTimestamp, parseSubtitles, parseXmlToObject, serializeSubtitles, shiftSubtitles, stringifyIni, toCsvString, tomlToJson, validateEnvKey, validateIni, validateNdjson, validateToml, validateXml, validateYaml, xmlToJson };
1403
+ export { convertSubtitles, csvToJson, data_exports, detectDelimiter, detectSubtitleFormat, diffEnvExample, envToExport, envToJson, formatNdjson, formatSubtitleTimestamp, formatToml, formatXml, getSection, getSectionNames, getTomlStats, getXmlStats, getYamlStats, iniToJson, jsonArrayToNdjson, jsonToIni, jsonToToml, jsonToXml, minifyNdjson, minifyToml, minifyXml, ndjsonToJsonArray, parseCsv, parseEnv, parseFrontMatter, parseIni, parseSubtitleTimestamp, parseSubtitles, parseXmlToObject, serializeSubtitles, shiftSubtitles, stringifyIni, toCsvString, tomlToJson, validateEnvKey, validateIni, validateNdjson, validateToml, validateXml, validateYaml, xmlToJson };
@@ -22,6 +22,7 @@ __export(units_exports, {
22
22
  calculateBreakEven: () => calculateBreakEven,
23
23
  calculateCompoundInterest: () => calculateCompoundInterest,
24
24
  calculateDiscount: () => calculateDiscount,
25
+ calculateEmi: () => calculateEmi,
25
26
  calculateLoan: () => calculateLoan,
26
27
  calculateMarginMarkup: () => calculateMarginMarkup,
27
28
  calculatePercentageChange: () => calculatePercentageChange,
@@ -1676,5 +1677,60 @@ function calculateRuleOf72(value, direction) {
1676
1677
  errorPercent: round4(errorPercent)
1677
1678
  };
1678
1679
  }
1680
+ function calculateEmi(principal, annualRatePercent, tenure, tenureUnit = "years") {
1681
+ if (!Number.isFinite(principal) || principal <= 0) return { error: "Principal must be a positive number" };
1682
+ if (!Number.isFinite(annualRatePercent) || annualRatePercent < 0) {
1683
+ return { error: "Annual interest rate must be zero or a positive number" };
1684
+ }
1685
+ if (tenureUnit !== "years" && tenureUnit !== "months") {
1686
+ return { error: 'tenureUnit must be "years" or "months"' };
1687
+ }
1688
+ if (!Number.isFinite(tenure) || tenure <= 0) return { error: "Tenure must be a positive number" };
1689
+ const tenureMonths = Math.round(tenureUnit === "years" ? tenure * 12 : tenure);
1690
+ if (tenureMonths <= 0) return { error: "Tenure must resolve to at least 1 month" };
1691
+ const monthlyRate = annualRatePercent / 100 / 12;
1692
+ let emi;
1693
+ if (monthlyRate === 0) {
1694
+ emi = principal / tenureMonths;
1695
+ } else {
1696
+ const factor = Math.pow(1 + monthlyRate, tenureMonths);
1697
+ emi = principal * monthlyRate * factor / (factor - 1);
1698
+ }
1699
+ const yearlyBreakdown = [];
1700
+ let balance = round2(principal);
1701
+ let totalPayment = 0;
1702
+ let yearPrincipal = 0;
1703
+ let yearInterest = 0;
1704
+ let year = 1;
1705
+ for (let month = 1; month <= tenureMonths; month++) {
1706
+ const interest = monthlyRate === 0 ? 0 : round2(balance * monthlyRate);
1707
+ let principalPortion = round2(emi) - interest;
1708
+ if (month === tenureMonths || principalPortion > balance) principalPortion = balance;
1709
+ const payment = round2(principalPortion + interest);
1710
+ balance = Math.max(round2(balance - principalPortion), 0);
1711
+ totalPayment += payment;
1712
+ yearPrincipal += principalPortion;
1713
+ yearInterest += interest;
1714
+ const isYearEnd = month % 12 === 0 || month === tenureMonths;
1715
+ if (isYearEnd) {
1716
+ yearlyBreakdown.push({
1717
+ year,
1718
+ principalPaid: round2(yearPrincipal),
1719
+ interestPaid: round2(yearInterest),
1720
+ balance
1721
+ });
1722
+ year += 1;
1723
+ yearPrincipal = 0;
1724
+ yearInterest = 0;
1725
+ }
1726
+ }
1727
+ return {
1728
+ emi: round2(emi),
1729
+ totalInterest: round2(totalPayment - principal),
1730
+ totalPayment: round2(totalPayment),
1731
+ tenureMonths,
1732
+ yearlyBreakdown
1733
+ };
1734
+ }
1679
1735
 
1680
- export { BASE_LABELS, BASE_PREFIXES, BYTE_UNITS, COMMON_CURRENCIES, COMMON_LOCALES, COMMON_PERMISSIONS, COMMON_RATIOS, COMMON_SIZES, COMMON_TAX_RATES, COMMON_TIP_PERCENTAGES, COMMON_VIEWPORTS, applySuccessiveDiscounts, autoFormat, bumpVersion, calcAspectRatio, calcSubnet, calculateBreakEven, calculateCompoundInterest, calculateDiscount, calculateLoan, calculateMarginMarkup, calculatePercentageChange, calculateRuleOf72, calculateSimpleInterest, calculateTax, calculateTimeValue, calculateTipSplit, calculateVideoBitrate, compareSemver, convert, convertAprApy, convertBytes, convertIp, coverBox, decimalToIp, decimalToIpCidr, describePermissions, fitIntoBox, formatNumber, formatValue, formatVwValue, formatWithSeparator, gcd, ipFromBinary, ipFromDecimal, ipFromHex, ipToBinary, ipToDecimal, ipToDecimalCidr, ipToHex, ipToOctal, isValid, isValidCidr, isValidIp, isValidIpv4, marginToMarkup, markupToMargin, octalToPermissions, parseFileSize, parseInput, parseNumberString, parseSemver, permissionsToChmod, permissionsToOctal, permissionsToSymbolic, ptToPx, pxToAll, pxToViewport, remToPx, satisfiesRange, scaleByHeight, scaleByWidth, sortVersions, splitSubnet, symbolicToPermissions, units_exports, validateBarcode, validateCardNumber, validateIban, validateIsbn, viewportToPx };
1736
+ export { BASE_LABELS, BASE_PREFIXES, BYTE_UNITS, COMMON_CURRENCIES, COMMON_LOCALES, COMMON_PERMISSIONS, COMMON_RATIOS, COMMON_SIZES, COMMON_TAX_RATES, COMMON_TIP_PERCENTAGES, COMMON_VIEWPORTS, applySuccessiveDiscounts, autoFormat, bumpVersion, calcAspectRatio, calcSubnet, calculateBreakEven, calculateCompoundInterest, calculateDiscount, calculateEmi, calculateLoan, calculateMarginMarkup, calculatePercentageChange, calculateRuleOf72, calculateSimpleInterest, calculateTax, calculateTimeValue, calculateTipSplit, calculateVideoBitrate, compareSemver, convert, convertAprApy, convertBytes, convertIp, coverBox, decimalToIp, decimalToIpCidr, describePermissions, fitIntoBox, formatNumber, formatValue, formatVwValue, formatWithSeparator, gcd, ipFromBinary, ipFromDecimal, ipFromHex, ipToBinary, ipToDecimal, ipToDecimalCidr, ipToHex, ipToOctal, isValid, isValidCidr, isValidIp, isValidIpv4, marginToMarkup, markupToMargin, octalToPermissions, parseFileSize, parseInput, parseNumberString, parseSemver, permissionsToChmod, permissionsToOctal, permissionsToSymbolic, ptToPx, pxToAll, pxToViewport, remToPx, satisfiesRange, scaleByHeight, scaleByWidth, sortVersions, splitSubnet, symbolicToPermissions, units_exports, validateBarcode, validateCardNumber, validateIban, validateIsbn, viewportToPx };
@@ -15,6 +15,7 @@ __export(json_exports, {
15
15
  inferGoType: () => inferGoType,
16
16
  inferPythonType: () => inferPythonType,
17
17
  inferType: () => inferType,
18
+ jsonSchemaToTypescript: () => jsonSchemaToTypescript,
18
19
  jsonToCsv: () => jsonToCsv,
19
20
  jsonToGo: () => jsonToGo,
20
21
  jsonToPython: () => jsonToPython,
@@ -1302,5 +1303,104 @@ function resolveJsonPointer(json, pointer) {
1302
1303
  }
1303
1304
  return { pointer, found: true, value: current, tokens };
1304
1305
  }
1306
+ function _schemaRefName(ref) {
1307
+ const parts = ref.split("/");
1308
+ return _capitalize(parts[parts.length - 1] || "Ref");
1309
+ }
1310
+ function _schemaLiteralType(value) {
1311
+ if (typeof value === "string") return JSON.stringify(value);
1312
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
1313
+ if (value === null) return "null";
1314
+ return JSON.stringify(value);
1315
+ }
1316
+ function _safePropertyKey(key) {
1317
+ return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key) ? key : JSON.stringify(key);
1318
+ }
1319
+ function _schemaToTsType(schema, name, interfaces) {
1320
+ if (schema.$ref) return _schemaRefName(schema.$ref);
1321
+ if (schema.const !== void 0) return _schemaLiteralType(schema.const);
1322
+ if (schema.enum) return schema.enum.map(_schemaLiteralType).join(" | ");
1323
+ if (schema.oneOf) return schema.oneOf.map((s, i) => _schemaToTsType(s, `${name}Variant${i}`, interfaces)).join(" | ");
1324
+ if (schema.anyOf) return schema.anyOf.map((s, i) => _schemaToTsType(s, `${name}Variant${i}`, interfaces)).join(" | ");
1325
+ if (schema.allOf) return schema.allOf.map((s, i) => _schemaToTsType(s, `${name}Part${i}`, interfaces)).join(" & ");
1326
+ const types = Array.isArray(schema.type) ? schema.type : schema.type ? [schema.type] : [];
1327
+ const nullable = types.includes("null");
1328
+ const nonNullTypes = types.filter((t) => t !== "null");
1329
+ const primaryType = nonNullTypes[0] ?? (schema.properties || schema.additionalProperties !== void 0 ? "object" : void 0);
1330
+ let result;
1331
+ switch (primaryType) {
1332
+ case "string":
1333
+ result = "string";
1334
+ break;
1335
+ case "number":
1336
+ case "integer":
1337
+ result = "number";
1338
+ break;
1339
+ case "boolean":
1340
+ result = "boolean";
1341
+ break;
1342
+ case "array": {
1343
+ const itemsSchema = Array.isArray(schema.items) ? schema.items[0] : schema.items;
1344
+ const itemType = itemsSchema ? _schemaToTsType(itemsSchema, `${name}Item`, interfaces) : "unknown";
1345
+ result = `${itemType}[]`;
1346
+ break;
1347
+ }
1348
+ case "object": {
1349
+ _buildSchemaInterface(schema, name, interfaces);
1350
+ result = name;
1351
+ break;
1352
+ }
1353
+ default:
1354
+ result = "unknown";
1355
+ }
1356
+ return nullable ? `${result} | null` : result;
1357
+ }
1358
+ function _buildSchemaInterface(schema, name, interfaces) {
1359
+ if (interfaces.has(name)) return;
1360
+ const required = new Set(schema.required ?? []);
1361
+ const lines = [`interface ${name} {`];
1362
+ for (const [key, propSchema] of Object.entries(schema.properties ?? {})) {
1363
+ if (propSchema.description) lines.push(` /** ${propSchema.description} */`);
1364
+ const optional = required.has(key) ? "" : "?";
1365
+ const propType = _schemaToTsType(propSchema, _capitalize(key), interfaces);
1366
+ lines.push(` ${_safePropertyKey(key)}${optional}: ${propType};`);
1367
+ }
1368
+ if (schema.additionalProperties === true) {
1369
+ lines.push(" [key: string]: unknown;");
1370
+ } else if (schema.additionalProperties && typeof schema.additionalProperties === "object") {
1371
+ const addType = _schemaToTsType(schema.additionalProperties, `${name}Value`, interfaces);
1372
+ lines.push(` [key: string]: ${addType};`);
1373
+ }
1374
+ lines.push("}");
1375
+ interfaces.set(name, lines.join("\n"));
1376
+ }
1377
+ function jsonSchemaToTypescript(schemaJson, options) {
1378
+ let schema;
1379
+ try {
1380
+ schema = JSON.parse(schemaJson);
1381
+ } catch {
1382
+ return { error: "Invalid JSON input" };
1383
+ }
1384
+ if (typeof schema !== "object" || schema === null || Array.isArray(schema)) {
1385
+ return { error: "Schema must be a JSON object" };
1386
+ }
1387
+ const rootName = options?.rootName ?? "Root";
1388
+ const typedSchema = schema;
1389
+ const interfaces = /* @__PURE__ */ new Map();
1390
+ const defs = { ...typedSchema.$defs ?? {}, ...typedSchema.definitions ?? {} };
1391
+ for (const [defName, defSchema] of Object.entries(defs)) {
1392
+ const defTypeName = _capitalize(defName);
1393
+ const defType = _schemaToTsType(defSchema, defTypeName, interfaces);
1394
+ if (!interfaces.has(defTypeName)) {
1395
+ interfaces.set(defTypeName, `type ${defTypeName} = ${defType};`);
1396
+ }
1397
+ }
1398
+ const rootType = _schemaToTsType(typedSchema, rootName, interfaces);
1399
+ const parts = [...interfaces.values()];
1400
+ if (!interfaces.has(rootName)) {
1401
+ parts.push(`type ${rootName} = ${rootType};`);
1402
+ }
1403
+ return parts.join("\n\n");
1404
+ }
1305
1405
 
1306
- export { csvToJson, detectFormat, diffJson, evaluateJsonPath, formatDiffLine, formatJson, generateExample, getJsonStats, inferGoType, inferPythonType, inferType, jsonToCsv, jsonToGo, jsonToPython, jsonToTypescript, jsonToYaml, jsonToZod, json_exports, minifyJson, parseJson, parseStructs, resolveJsonPointer, toPascalCase, toSnakeCase, validateJson, validateJsonPath, validateJsonString, yamlToJson };
1406
+ export { csvToJson, detectFormat, diffJson, evaluateJsonPath, formatDiffLine, formatJson, generateExample, getJsonStats, inferGoType, inferPythonType, inferType, jsonSchemaToTypescript, jsonToCsv, jsonToGo, jsonToPython, jsonToTypescript, jsonToYaml, jsonToZod, json_exports, minifyJson, parseJson, parseStructs, resolveJsonPointer, toPascalCase, toSnakeCase, validateJson, validateJsonPath, validateJsonString, yamlToJson };
@@ -13,6 +13,7 @@
13
13
  * - env-diff-checker: diffEnvExample
14
14
  * - ndjson-formatter: validateNdjson, minifyNdjson, formatNdjson, ndjsonToJsonArray, jsonArrayToNdjson
15
15
  * - subtitle-converter: parseSubtitleTimestamp, formatSubtitleTimestamp, detectSubtitleFormat, parseSubtitles, serializeSubtitles, convertSubtitles, shiftSubtitles
16
+ * - markdown-front-matter-parser: parseFrontMatter
16
17
  */
17
18
  interface ValidationResult {
18
19
  valid: boolean;
@@ -272,6 +273,24 @@ declare function convertSubtitles(input: string, target: SubtitleFormat, sourceF
272
273
  declare function shiftSubtitles(input: string, offsetSeconds: number, target?: SubtitleFormat): ConvertedSubtitles | {
273
274
  error: string;
274
275
  };
276
+ interface FrontMatterResult {
277
+ frontMatter: Record<string, unknown>;
278
+ body: string;
279
+ hasFrontMatter: boolean;
280
+ raw: string;
281
+ }
282
+ interface FrontMatterError {
283
+ error: string;
284
+ }
285
+ /**
286
+ * Split a Markdown document into its YAML front matter (delimited by --- lines
287
+ * at the top) and body content. Parses simple scalar values (strings, quoted
288
+ * strings, booleans, numbers, null), inline arrays (`tags: [a, b]`), and YAML
289
+ * block lists (`tags:\n - a\n - b`). Not a full YAML parser: nested mappings
290
+ * and multi-line block scalars are not supported. A document with no opening
291
+ * "---" delimiter is returned as-is with `hasFrontMatter: false`.
292
+ */
293
+ declare function parseFrontMatter(input: string): FrontMatterResult | FrontMatterError;
275
294
 
276
295
  type data_ConvertedSubtitles = ConvertedSubtitles;
277
296
  type data_CsvParseResult = CsvParseResult;
@@ -279,6 +298,8 @@ type data_EnvDiffError = EnvDiffError;
279
298
  type data_EnvDiffResult = EnvDiffResult;
280
299
  type data_EnvEntry = EnvEntry;
281
300
  type data_EnvParseResult = EnvParseResult;
301
+ type data_FrontMatterError = FrontMatterError;
302
+ type data_FrontMatterResult = FrontMatterResult;
282
303
  type data_IniSection = IniSection;
283
304
  type data_NdjsonLineResult = NdjsonLineResult;
284
305
  type data_NdjsonValidateResult = NdjsonValidateResult;
@@ -318,6 +339,7 @@ declare const data_minifyXml: typeof minifyXml;
318
339
  declare const data_ndjsonToJsonArray: typeof ndjsonToJsonArray;
319
340
  declare const data_parseCsv: typeof parseCsv;
320
341
  declare const data_parseEnv: typeof parseEnv;
342
+ declare const data_parseFrontMatter: typeof parseFrontMatter;
321
343
  declare const data_parseIni: typeof parseIni;
322
344
  declare const data_parseSubtitleTimestamp: typeof parseSubtitleTimestamp;
323
345
  declare const data_parseSubtitles: typeof parseSubtitles;
@@ -335,7 +357,7 @@ declare const data_validateXml: typeof validateXml;
335
357
  declare const data_validateYaml: typeof validateYaml;
336
358
  declare const data_xmlToJson: typeof xmlToJson;
337
359
  declare namespace data {
338
- export { type data_ConvertedSubtitles as ConvertedSubtitles, type data_CsvParseResult as CsvParseResult, type data_EnvDiffError as EnvDiffError, type data_EnvDiffResult as EnvDiffResult, type data_EnvEntry as EnvEntry, type data_EnvParseResult as EnvParseResult, type data_IniSection as IniSection, type data_NdjsonLineResult as NdjsonLineResult, type data_NdjsonValidateResult as NdjsonValidateResult, type data_ParseOptions as ParseOptions, type data_ParsedIni as ParsedIni, type data_ParsedSubtitles as ParsedSubtitles, type data_SubtitleCue as SubtitleCue, type data_SubtitleFormat as SubtitleFormat, type data_TomlFormatResult as TomlFormatResult, type data_ValidationResult as ValidationResult, type data_XmlFormatResult as XmlFormatResult, type data_XmlToJsonOptions as XmlToJsonOptions, data_convertSubtitles as convertSubtitles, data_csvToJson as csvToJson, data_detectDelimiter as detectDelimiter, data_detectSubtitleFormat as detectSubtitleFormat, data_diffEnvExample as diffEnvExample, data_envToExport as envToExport, data_envToJson as envToJson, data_formatNdjson as formatNdjson, data_formatSubtitleTimestamp as formatSubtitleTimestamp, data_formatToml as formatToml, data_formatXml as formatXml, data_getSection as getSection, data_getSectionNames as getSectionNames, data_getTomlStats as getTomlStats, data_getXmlStats as getXmlStats, data_getYamlStats as getYamlStats, data_iniToJson as iniToJson, data_jsonArrayToNdjson as jsonArrayToNdjson, data_jsonToIni as jsonToIni, data_jsonToToml as jsonToToml, data_jsonToXml as jsonToXml, data_minifyNdjson as minifyNdjson, data_minifyToml as minifyToml, data_minifyXml as minifyXml, data_ndjsonToJsonArray as ndjsonToJsonArray, data_parseCsv as parseCsv, data_parseEnv as parseEnv, data_parseIni as parseIni, data_parseSubtitleTimestamp as parseSubtitleTimestamp, data_parseSubtitles as parseSubtitles, data_parseXmlToObject as parseXmlToObject, data_serializeSubtitles as serializeSubtitles, data_shiftSubtitles as shiftSubtitles, data_stringifyIni as stringifyIni, data_toCsvString as toCsvString, data_tomlToJson as tomlToJson, data_validateEnvKey as validateEnvKey, data_validateIni as validateIni, data_validateNdjson as validateNdjson, data_validateToml as validateToml, data_validateXml as validateXml, data_validateYaml as validateYaml, data_xmlToJson as xmlToJson };
360
+ export { type data_ConvertedSubtitles as ConvertedSubtitles, type data_CsvParseResult as CsvParseResult, type data_EnvDiffError as EnvDiffError, type data_EnvDiffResult as EnvDiffResult, type data_EnvEntry as EnvEntry, type data_EnvParseResult as EnvParseResult, type data_FrontMatterError as FrontMatterError, type data_FrontMatterResult as FrontMatterResult, type data_IniSection as IniSection, type data_NdjsonLineResult as NdjsonLineResult, type data_NdjsonValidateResult as NdjsonValidateResult, type data_ParseOptions as ParseOptions, type data_ParsedIni as ParsedIni, type data_ParsedSubtitles as ParsedSubtitles, type data_SubtitleCue as SubtitleCue, type data_SubtitleFormat as SubtitleFormat, type data_TomlFormatResult as TomlFormatResult, type data_ValidationResult as ValidationResult, type data_XmlFormatResult as XmlFormatResult, type data_XmlToJsonOptions as XmlToJsonOptions, data_convertSubtitles as convertSubtitles, data_csvToJson as csvToJson, data_detectDelimiter as detectDelimiter, data_detectSubtitleFormat as detectSubtitleFormat, data_diffEnvExample as diffEnvExample, data_envToExport as envToExport, data_envToJson as envToJson, data_formatNdjson as formatNdjson, data_formatSubtitleTimestamp as formatSubtitleTimestamp, data_formatToml as formatToml, data_formatXml as formatXml, data_getSection as getSection, data_getSectionNames as getSectionNames, data_getTomlStats as getTomlStats, data_getXmlStats as getXmlStats, data_getYamlStats as getYamlStats, data_iniToJson as iniToJson, data_jsonArrayToNdjson as jsonArrayToNdjson, data_jsonToIni as jsonToIni, data_jsonToToml as jsonToToml, data_jsonToXml as jsonToXml, data_minifyNdjson as minifyNdjson, data_minifyToml as minifyToml, data_minifyXml as minifyXml, data_ndjsonToJsonArray as ndjsonToJsonArray, data_parseCsv as parseCsv, data_parseEnv as parseEnv, data_parseFrontMatter as parseFrontMatter, data_parseIni as parseIni, data_parseSubtitleTimestamp as parseSubtitleTimestamp, data_parseSubtitles as parseSubtitles, data_parseXmlToObject as parseXmlToObject, data_serializeSubtitles as serializeSubtitles, data_shiftSubtitles as shiftSubtitles, data_stringifyIni as stringifyIni, data_toCsvString as toCsvString, data_tomlToJson as tomlToJson, data_validateEnvKey as validateEnvKey, data_validateIni as validateIni, data_validateNdjson as validateNdjson, data_validateToml as validateToml, data_validateXml as validateXml, data_validateYaml as validateYaml, data_xmlToJson as xmlToJson };
339
361
  }
340
362
 
341
- export { toCsvString as $, iniToJson as A, jsonArrayToNdjson as B, type ConvertedSubtitles as C, jsonToIni as D, type EnvDiffError as E, jsonToToml as F, jsonToXml as G, minifyNdjson as H, type IniSection as I, minifyToml as J, minifyXml as K, ndjsonToJsonArray as L, parseCsv as M, type NdjsonLineResult as N, parseEnv as O, type ParseOptions as P, parseIni as Q, parseSubtitleTimestamp as R, type SubtitleCue as S, type TomlFormatResult as T, parseSubtitles as U, type ValidationResult as V, parseXmlToObject as W, type XmlFormatResult as X, serializeSubtitles as Y, shiftSubtitles as Z, stringifyIni as _, type CsvParseResult as a, tomlToJson as a0, validateEnvKey as a1, validateIni as a2, validateNdjson as a3, validateToml as a4, validateXml as a5, validateYaml as a6, xmlToJson as a7, type EnvDiffResult as b, type EnvEntry as c, data as d, type EnvParseResult as e, type NdjsonValidateResult as f, type ParsedIni as g, type ParsedSubtitles as h, type SubtitleFormat as i, type XmlToJsonOptions as j, convertSubtitles as k, csvToJson as l, detectDelimiter as m, detectSubtitleFormat as n, diffEnvExample as o, envToExport as p, envToJson as q, formatNdjson as r, formatSubtitleTimestamp as s, formatToml as t, formatXml as u, getSection as v, getSectionNames as w, getTomlStats as x, getXmlStats as y, getYamlStats as z };
363
+ export { serializeSubtitles as $, getYamlStats as A, iniToJson as B, type ConvertedSubtitles as C, jsonArrayToNdjson as D, type EnvDiffError as E, type FrontMatterError as F, jsonToIni as G, jsonToToml as H, type IniSection as I, jsonToXml as J, minifyNdjson as K, minifyToml as L, minifyXml as M, type NdjsonLineResult as N, ndjsonToJsonArray as O, type ParseOptions as P, parseCsv as Q, parseEnv as R, type SubtitleCue as S, type TomlFormatResult as T, parseFrontMatter as U, type ValidationResult as V, parseIni as W, type XmlFormatResult as X, parseSubtitleTimestamp as Y, parseSubtitles as Z, parseXmlToObject as _, type CsvParseResult as a, shiftSubtitles as a0, stringifyIni as a1, toCsvString as a2, tomlToJson as a3, validateEnvKey as a4, validateIni as a5, validateNdjson as a6, validateToml as a7, validateXml as a8, validateYaml as a9, xmlToJson as aa, type EnvDiffResult as b, type EnvEntry as c, data as d, type EnvParseResult as e, type FrontMatterResult as f, type NdjsonValidateResult as g, type ParsedIni as h, type ParsedSubtitles as i, type SubtitleFormat as j, type XmlToJsonOptions as k, convertSubtitles as l, csvToJson as m, detectDelimiter as n, detectSubtitleFormat as o, diffEnvExample as p, envToExport as q, envToJson as r, formatNdjson as s, formatSubtitleTimestamp as t, formatToml as u, formatXml as v, getSection as w, getSectionNames as x, getTomlStats as y, getXmlStats as z };