@utilix-tech/sdk 0.64.0 → 0.66.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.
@@ -19,6 +19,7 @@
19
19
  * - csv-to-sql-insert-generator: csvToSqlInsert
20
20
  * - csv-duplicate-row-finder: findCsvDuplicateRows
21
21
  * - yaml-anchor-resolver: resolveYamlAnchors
22
+ * - markdown-table-aligner: alignMarkdownTables
22
23
  */
23
24
  interface ValidationResult {
24
25
  valid: boolean;
@@ -504,6 +505,34 @@ interface MarkdownTaskListProgressResult {
504
505
  declare function calculateMarkdownTaskListProgress(markdown: string): MarkdownTaskListProgressResult | {
505
506
  error: string;
506
507
  };
508
+ type MarkdownTableColumnAlignment = 'left' | 'center' | 'right' | 'none';
509
+ interface MarkdownTableInfo {
510
+ startLine: number;
511
+ endLine: number;
512
+ columnCount: number;
513
+ rowCount: number;
514
+ alignments: MarkdownTableColumnAlignment[];
515
+ }
516
+ interface MarkdownTableAlignResult {
517
+ output: string;
518
+ tables: MarkdownTableInfo[];
519
+ warnings: string[];
520
+ }
521
+ /**
522
+ * Reformat every GitHub-Flavored-Markdown pipe table in a document so each
523
+ * column's pipes line up visually, padding cells to the widest content in
524
+ * that column and rebuilding the delimiter row's dashes/colons to match,
525
+ * while preserving each column's declared alignment. Tables inside fenced
526
+ * code blocks are left untouched, matching how GitHub's own renderer treats
527
+ * them as literal text rather than a real table. A row with a different
528
+ * cell count than the header is padded or truncated to match, with a
529
+ * warning. Column width is measured in characters (not rendered pixel
530
+ * width), so tables with wide-character (e.g. CJK) content may not align
531
+ * pixel-perfectly even though the character counts match.
532
+ */
533
+ declare function alignMarkdownTables(markdown: string): MarkdownTableAlignResult | {
534
+ error: string;
535
+ };
507
536
 
508
537
  type data_CaptionSpeedCue = CaptionSpeedCue;
509
538
  type data_CaptionSpeedResult = CaptionSpeedResult;
@@ -525,6 +554,9 @@ type data_EnvParseResult = EnvParseResult;
525
554
  type data_FrontMatterError = FrontMatterError;
526
555
  type data_FrontMatterResult = FrontMatterResult;
527
556
  type data_IniSection = IniSection;
557
+ type data_MarkdownTableAlignResult = MarkdownTableAlignResult;
558
+ type data_MarkdownTableColumnAlignment = MarkdownTableColumnAlignment;
559
+ type data_MarkdownTableInfo = MarkdownTableInfo;
528
560
  type data_MarkdownTaskListItem = MarkdownTaskListItem;
529
561
  type data_MarkdownTaskListProgressResult = MarkdownTaskListProgressResult;
530
562
  type data_MarkdownTaskListSectionSummary = MarkdownTaskListSectionSummary;
@@ -546,6 +578,7 @@ type data_XmlToJsonOptions = XmlToJsonOptions;
546
578
  type data_YamlAnchorInfo = YamlAnchorInfo;
547
579
  type data_YamlAnchorResolveError = YamlAnchorResolveError;
548
580
  type data_YamlAnchorResolveResult = YamlAnchorResolveResult;
581
+ declare const data_alignMarkdownTables: typeof alignMarkdownTables;
549
582
  declare const data_analyzeCaptionSpeed: typeof analyzeCaptionSpeed;
550
583
  declare const data_calculateMarkdownTaskListProgress: typeof calculateMarkdownTaskListProgress;
551
584
  declare const data_convertSubtitles: typeof convertSubtitles;
@@ -599,7 +632,7 @@ declare const data_validateXml: typeof validateXml;
599
632
  declare const data_validateYaml: typeof validateYaml;
600
633
  declare const data_xmlToJson: typeof xmlToJson;
601
634
  declare namespace data {
602
- export { type data_CaptionSpeedCue as CaptionSpeedCue, type data_CaptionSpeedResult as CaptionSpeedResult, type data_ConvertedSubtitles as ConvertedSubtitles, type data_CsvColumnType as CsvColumnType, type data_CsvColumnTypeInfo as CsvColumnTypeInfo, type data_CsvColumnTypeOptions as CsvColumnTypeOptions, type data_CsvColumnTypeResult as CsvColumnTypeResult, type data_CsvDuplicateGroup as CsvDuplicateGroup, type data_CsvDuplicateOptions as CsvDuplicateOptions, type data_CsvDuplicateResult as CsvDuplicateResult, type data_CsvParseResult as CsvParseResult, type data_CsvToSqlOptions as CsvToSqlOptions, type data_CsvToSqlResult as CsvToSqlResult, 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_MarkdownTaskListItem as MarkdownTaskListItem, type data_MarkdownTaskListProgressResult as MarkdownTaskListProgressResult, type data_MarkdownTaskListSectionSummary as MarkdownTaskListSectionSummary, type data_MarkdownTocEntry as MarkdownTocEntry, type data_MarkdownTocOptions as MarkdownTocOptions, type data_MarkdownTocResult as MarkdownTocResult, type data_NdjsonDedupeResult as NdjsonDedupeResult, 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, type data_YamlAnchorInfo as YamlAnchorInfo, type data_YamlAnchorResolveError as YamlAnchorResolveError, type data_YamlAnchorResolveResult as YamlAnchorResolveResult, data_analyzeCaptionSpeed as analyzeCaptionSpeed, data_calculateMarkdownTaskListProgress as calculateMarkdownTaskListProgress, data_convertSubtitles as convertSubtitles, data_csvToJson as csvToJson, data_csvToSqlInsert as csvToSqlInsert, data_dedupeNdjson as dedupeNdjson, data_detectDelimiter as detectDelimiter, data_detectSubtitleFormat as detectSubtitleFormat, data_diffEnvExample as diffEnvExample, data_envToExport as envToExport, data_envToJson as envToJson, data_findCsvDuplicateRows as findCsvDuplicateRows, data_formatNdjson as formatNdjson, data_formatSubtitleTimestamp as formatSubtitleTimestamp, data_formatToml as formatToml, data_formatXml as formatXml, data_generateMarkdownToc as generateMarkdownToc, data_getSection as getSection, data_getSectionNames as getSectionNames, data_getTomlStats as getTomlStats, data_getXmlStats as getXmlStats, data_getYamlStats as getYamlStats, data_inferCsvColumnTypes as inferCsvColumnTypes, 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_resolveYamlAnchors as resolveYamlAnchors, 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 };
635
+ export { type data_CaptionSpeedCue as CaptionSpeedCue, type data_CaptionSpeedResult as CaptionSpeedResult, type data_ConvertedSubtitles as ConvertedSubtitles, type data_CsvColumnType as CsvColumnType, type data_CsvColumnTypeInfo as CsvColumnTypeInfo, type data_CsvColumnTypeOptions as CsvColumnTypeOptions, type data_CsvColumnTypeResult as CsvColumnTypeResult, type data_CsvDuplicateGroup as CsvDuplicateGroup, type data_CsvDuplicateOptions as CsvDuplicateOptions, type data_CsvDuplicateResult as CsvDuplicateResult, type data_CsvParseResult as CsvParseResult, type data_CsvToSqlOptions as CsvToSqlOptions, type data_CsvToSqlResult as CsvToSqlResult, 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_MarkdownTableAlignResult as MarkdownTableAlignResult, type data_MarkdownTableColumnAlignment as MarkdownTableColumnAlignment, type data_MarkdownTableInfo as MarkdownTableInfo, type data_MarkdownTaskListItem as MarkdownTaskListItem, type data_MarkdownTaskListProgressResult as MarkdownTaskListProgressResult, type data_MarkdownTaskListSectionSummary as MarkdownTaskListSectionSummary, type data_MarkdownTocEntry as MarkdownTocEntry, type data_MarkdownTocOptions as MarkdownTocOptions, type data_MarkdownTocResult as MarkdownTocResult, type data_NdjsonDedupeResult as NdjsonDedupeResult, 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, type data_YamlAnchorInfo as YamlAnchorInfo, type data_YamlAnchorResolveError as YamlAnchorResolveError, type data_YamlAnchorResolveResult as YamlAnchorResolveResult, data_alignMarkdownTables as alignMarkdownTables, data_analyzeCaptionSpeed as analyzeCaptionSpeed, data_calculateMarkdownTaskListProgress as calculateMarkdownTaskListProgress, data_convertSubtitles as convertSubtitles, data_csvToJson as csvToJson, data_csvToSqlInsert as csvToSqlInsert, data_dedupeNdjson as dedupeNdjson, data_detectDelimiter as detectDelimiter, data_detectSubtitleFormat as detectSubtitleFormat, data_diffEnvExample as diffEnvExample, data_envToExport as envToExport, data_envToJson as envToJson, data_findCsvDuplicateRows as findCsvDuplicateRows, data_formatNdjson as formatNdjson, data_formatSubtitleTimestamp as formatSubtitleTimestamp, data_formatToml as formatToml, data_formatXml as formatXml, data_generateMarkdownToc as generateMarkdownToc, data_getSection as getSection, data_getSectionNames as getSectionNames, data_getTomlStats as getTomlStats, data_getXmlStats as getXmlStats, data_getYamlStats as getYamlStats, data_inferCsvColumnTypes as inferCsvColumnTypes, 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_resolveYamlAnchors as resolveYamlAnchors, 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 };
603
636
  }
604
637
 
605
- export { findCsvDuplicateRows as $, type SubtitleFormat as A, type XmlToJsonOptions as B, type CaptionSpeedCue as C, type YamlAnchorResolveError as D, type EnvDiffError as E, type FrontMatterError as F, type YamlAnchorResolveResult as G, analyzeCaptionSpeed as H, type IniSection as I, calculateMarkdownTaskListProgress as J, convertSubtitles as K, csvToJson as L, type MarkdownTaskListItem as M, type NdjsonDedupeResult as N, csvToSqlInsert as O, type ParseOptions as P, dedupeNdjson as Q, detectDelimiter as R, type SubtitleCue as S, type TomlFormatResult as T, detectSubtitleFormat as U, type ValidationResult as V, diffEnvExample as W, type XmlFormatResult as X, type YamlAnchorInfo as Y, envToExport as Z, envToJson as _, type CaptionSpeedResult as a, formatNdjson as a0, formatSubtitleTimestamp as a1, formatToml as a2, formatXml as a3, generateMarkdownToc as a4, getSection as a5, getSectionNames as a6, getTomlStats as a7, getXmlStats as a8, getYamlStats as a9, validateToml as aA, validateXml as aB, validateYaml as aC, xmlToJson as aD, inferCsvColumnTypes as aa, iniToJson as ab, jsonArrayToNdjson as ac, jsonToIni as ad, jsonToToml as ae, jsonToXml as af, minifyNdjson as ag, minifyToml as ah, minifyXml as ai, ndjsonToJsonArray as aj, parseCsv as ak, parseEnv as al, parseFrontMatter as am, parseIni as an, parseSubtitleTimestamp as ao, parseSubtitles as ap, parseXmlToObject as aq, resolveYamlAnchors as ar, serializeSubtitles as as, shiftSubtitles as at, stringifyIni as au, toCsvString as av, tomlToJson as aw, validateEnvKey as ax, validateIni as ay, validateNdjson as az, type ConvertedSubtitles as b, type CsvColumnType as c, data as d, type CsvColumnTypeInfo as e, type CsvColumnTypeOptions as f, type CsvColumnTypeResult as g, type CsvDuplicateGroup as h, type CsvDuplicateOptions as i, type CsvDuplicateResult as j, type CsvParseResult as k, type CsvToSqlOptions as l, type CsvToSqlResult as m, type EnvDiffResult as n, type EnvEntry as o, type EnvParseResult as p, type FrontMatterResult as q, type MarkdownTaskListProgressResult as r, type MarkdownTaskListSectionSummary as s, type MarkdownTocEntry as t, type MarkdownTocOptions as u, type MarkdownTocResult as v, type NdjsonLineResult as w, type NdjsonValidateResult as x, type ParsedIni as y, type ParsedSubtitles as z };
638
+ export { detectSubtitleFormat as $, type NdjsonValidateResult as A, type ParsedIni as B, type CaptionSpeedCue as C, type ParsedSubtitles as D, type EnvDiffError as E, type FrontMatterError as F, type SubtitleFormat as G, type XmlToJsonOptions as H, type IniSection as I, type YamlAnchorResolveError as J, type YamlAnchorResolveResult as K, alignMarkdownTables as L, type MarkdownTableAlignResult as M, type NdjsonDedupeResult as N, analyzeCaptionSpeed as O, type ParseOptions as P, calculateMarkdownTaskListProgress as Q, convertSubtitles as R, type SubtitleCue as S, type TomlFormatResult as T, csvToJson as U, type ValidationResult as V, csvToSqlInsert as W, type XmlFormatResult as X, type YamlAnchorInfo as Y, dedupeNdjson as Z, detectDelimiter as _, type CaptionSpeedResult as a, diffEnvExample as a0, envToExport as a1, envToJson as a2, findCsvDuplicateRows as a3, formatNdjson as a4, formatSubtitleTimestamp as a5, formatToml as a6, formatXml as a7, generateMarkdownToc as a8, getSection as a9, tomlToJson as aA, validateEnvKey as aB, validateIni as aC, validateNdjson as aD, validateToml as aE, validateXml as aF, validateYaml as aG, xmlToJson as aH, getSectionNames as aa, getTomlStats as ab, getXmlStats as ac, getYamlStats as ad, inferCsvColumnTypes as ae, iniToJson as af, jsonArrayToNdjson as ag, jsonToIni as ah, jsonToToml as ai, jsonToXml as aj, minifyNdjson as ak, minifyToml as al, minifyXml as am, ndjsonToJsonArray as an, parseCsv as ao, parseEnv as ap, parseFrontMatter as aq, parseIni as ar, parseSubtitleTimestamp as as, parseSubtitles as at, parseXmlToObject as au, resolveYamlAnchors as av, serializeSubtitles as aw, shiftSubtitles as ax, stringifyIni as ay, toCsvString as az, type ConvertedSubtitles as b, type CsvColumnType as c, data as d, type CsvColumnTypeInfo as e, type CsvColumnTypeOptions as f, type CsvColumnTypeResult as g, type CsvDuplicateGroup as h, type CsvDuplicateOptions as i, type CsvDuplicateResult as j, type CsvParseResult as k, type CsvToSqlOptions as l, type CsvToSqlResult as m, type EnvDiffResult as n, type EnvEntry as o, type EnvParseResult as p, type FrontMatterResult as q, type MarkdownTableColumnAlignment as r, type MarkdownTableInfo as s, type MarkdownTaskListItem as t, type MarkdownTaskListProgressResult as u, type MarkdownTaskListSectionSummary as v, type MarkdownTocEntry as w, type MarkdownTocOptions as x, type MarkdownTocResult as y, type NdjsonLineResult as z };
package/dist/index.cjs CHANGED
@@ -5184,6 +5184,7 @@ function getEmojiCategories() {
5184
5184
  // src/tools/data.ts
5185
5185
  var data_exports = {};
5186
5186
  __export(data_exports, {
5187
+ alignMarkdownTables: () => alignMarkdownTables,
5187
5188
  analyzeCaptionSpeed: () => analyzeCaptionSpeed,
5188
5189
  calculateMarkdownTaskListProgress: () => calculateMarkdownTaskListProgress,
5189
5190
  convertSubtitles: () => convertSubtitles,
@@ -6986,6 +6987,141 @@ function calculateMarkdownTaskListProgress(markdown) {
6986
6987
  });
6987
6988
  return { totalItems, completedItems, percentComplete, sections, items };
6988
6989
  }
6990
+ function _splitMarkdownTableRow(line) {
6991
+ const raw = [];
6992
+ let current = "";
6993
+ for (let i = 0; i < line.length; i++) {
6994
+ const ch = line[i];
6995
+ if (ch === "\\" && line[i + 1] === "|") {
6996
+ current += "\\|";
6997
+ i++;
6998
+ continue;
6999
+ }
7000
+ if (ch === "|") {
7001
+ raw.push(current);
7002
+ current = "";
7003
+ continue;
7004
+ }
7005
+ current += ch;
7006
+ }
7007
+ raw.push(current);
7008
+ const cells = raw.map((c) => c.trim());
7009
+ if (cells.length > 1 && cells[0] === "") cells.shift();
7010
+ if (cells.length > 1 && cells[cells.length - 1] === "") cells.pop();
7011
+ return cells;
7012
+ }
7013
+ function _isMarkdownTableDelimiterRow(line) {
7014
+ const trimmed = line.trim();
7015
+ if (trimmed === "" || !trimmed.includes("-")) return false;
7016
+ const cells = _splitMarkdownTableRow(trimmed);
7017
+ if (cells.length === 0) return false;
7018
+ return cells.every((c) => /^:?-+:?$/.test(c));
7019
+ }
7020
+ function _markdownTableCellAlignment(delimCell) {
7021
+ const left = delimCell.startsWith(":");
7022
+ const right = delimCell.endsWith(":");
7023
+ if (left && right) return "center";
7024
+ if (right) return "right";
7025
+ if (left) return "left";
7026
+ return "none";
7027
+ }
7028
+ function _padMarkdownTableCell(text, width, alignment) {
7029
+ const len = [...text].length;
7030
+ const diff = Math.max(0, width - len);
7031
+ if (alignment === "right") return " ".repeat(diff) + text;
7032
+ if (alignment === "center") {
7033
+ const left = Math.floor(diff / 2);
7034
+ const right = diff - left;
7035
+ return " ".repeat(left) + text + " ".repeat(right);
7036
+ }
7037
+ return text + " ".repeat(diff);
7038
+ }
7039
+ function _markdownTableDelimiterCell(width, alignment) {
7040
+ switch (alignment) {
7041
+ case "left":
7042
+ return ":" + "-".repeat(Math.max(1, width - 1));
7043
+ case "right":
7044
+ return "-".repeat(Math.max(1, width - 1)) + ":";
7045
+ case "center":
7046
+ return ":" + "-".repeat(Math.max(1, width - 2)) + ":";
7047
+ default:
7048
+ return "-".repeat(width);
7049
+ }
7050
+ }
7051
+ function alignMarkdownTables(markdown) {
7052
+ if (typeof markdown !== "string") return { error: "markdown must be a string" };
7053
+ const lines = markdown.replace(/\r\n/g, "\n").split("\n");
7054
+ const outputLines = [...lines];
7055
+ const tables = [];
7056
+ const warnings = [];
7057
+ let inFence = false;
7058
+ let fenceMarker = "";
7059
+ let i = 0;
7060
+ while (i < lines.length) {
7061
+ const line = lines[i];
7062
+ const fenceMatch = line.match(/^\s*(```+|~~~+)/);
7063
+ if (fenceMatch) {
7064
+ if (!inFence) {
7065
+ inFence = true;
7066
+ fenceMarker = fenceMatch[1][0];
7067
+ } else if (fenceMatch[1][0] === fenceMarker) {
7068
+ inFence = false;
7069
+ }
7070
+ i++;
7071
+ continue;
7072
+ }
7073
+ if (inFence) {
7074
+ i++;
7075
+ continue;
7076
+ }
7077
+ const nextLine = lines[i + 1];
7078
+ if (line.includes("|") && nextLine !== void 0 && _isMarkdownTableDelimiterRow(nextLine)) {
7079
+ const headerCells = _splitMarkdownTableRow(line);
7080
+ const delimCells = _splitMarkdownTableRow(nextLine);
7081
+ if (headerCells.length > 0 && headerCells.length === delimCells.length) {
7082
+ const columnCount = headerCells.length;
7083
+ const alignments = delimCells.map(_markdownTableCellAlignment);
7084
+ let j = i + 2;
7085
+ const bodyRows = [];
7086
+ while (j < lines.length && lines[j].trim() !== "" && lines[j].includes("|")) {
7087
+ bodyRows.push(_splitMarkdownTableRow(lines[j]));
7088
+ j++;
7089
+ }
7090
+ const normalizedBody = [];
7091
+ for (const row of bodyRows) {
7092
+ if (row.length !== columnCount) {
7093
+ warnings.push(`Table at line ${i + 1}: a row has ${row.length} cell(s) but the header has ${columnCount}; it was padded/truncated to match.`);
7094
+ }
7095
+ normalizedBody.push(Array.from({ length: columnCount }, (_, c) => row[c] ?? ""));
7096
+ }
7097
+ const allRows = [headerCells, ...normalizedBody];
7098
+ const widths = Array.from(
7099
+ { length: columnCount },
7100
+ (_, c) => Math.max(3, ...allRows.map((r) => [...r[c] ?? ""].length))
7101
+ );
7102
+ const formattedHeader = "| " + headerCells.map((c, idx) => _padMarkdownTableCell(c, widths[idx], alignments[idx])).join(" | ") + " |";
7103
+ const formattedDelim = "| " + widths.map((w, idx) => _markdownTableDelimiterCell(w, alignments[idx])).join(" | ") + " |";
7104
+ const formattedBody = normalizedBody.map((row) => "| " + row.map((c, idx) => _padMarkdownTableCell(c, widths[idx], alignments[idx])).join(" | ") + " |");
7105
+ const formattedLines = [formattedHeader, formattedDelim, ...formattedBody];
7106
+ for (let k = 0; k < formattedLines.length; k++) {
7107
+ outputLines[i + k] = formattedLines[k];
7108
+ }
7109
+ tables.push({
7110
+ startLine: i + 1,
7111
+ endLine: i + formattedLines.length,
7112
+ columnCount,
7113
+ rowCount: normalizedBody.length,
7114
+ alignments
7115
+ });
7116
+ i = j;
7117
+ continue;
7118
+ }
7119
+ }
7120
+ i++;
7121
+ }
7122
+ if (tables.length === 0) return { error: "No Markdown tables found" };
7123
+ return { output: outputLines.join("\n"), tables, warnings };
7124
+ }
6989
7125
 
6990
7126
  // src/tools/generators.ts
6991
7127
  var generators_exports = {};
@@ -10921,6 +11057,7 @@ __export(network_exports, {
10921
11057
  buildContentDisposition: () => buildContentDisposition,
10922
11058
  buildDnsQueryUrl: () => buildDnsQueryUrl,
10923
11059
  buildGeoUrl: () => buildGeoUrl,
11060
+ buildHsts: () => buildHsts,
10924
11061
  buildLinkHeader: () => buildLinkHeader,
10925
11062
  buildMapUrl: () => buildMapUrl,
10926
11063
  buildPermissionsPolicy: () => buildPermissionsPolicy,
@@ -10931,6 +11068,7 @@ __export(network_exports, {
10931
11068
  buildRetryAfterHeader: () => buildRetryAfterHeader,
10932
11069
  buildVaryHeader: () => buildVaryHeader,
10933
11070
  buildXContentTypeOptionsHeader: () => buildXContentTypeOptionsHeader,
11071
+ buildXRobotsTag: () => buildXRobotsTag,
10934
11072
  checkSetCookieHeader: () => checkSetCookieHeader,
10935
11073
  countryCodeToFlag: () => countryCodeToFlag,
10936
11074
  extractMultipartBoundary: () => extractMultipartBoundary,
@@ -10948,7 +11086,9 @@ __export(network_exports, {
10948
11086
  isValidIpv4: () => isValidIpv42,
10949
11087
  isValidIpv6: () => isValidIpv6,
10950
11088
  listCloseCodes: () => listCloseCodes,
11089
+ listOpcodes: () => listOpcodes,
10951
11090
  lookupCloseCode: () => lookupCloseCode,
11091
+ lookupOpcode: () => lookupOpcode,
10952
11092
  parseAcceptLanguage: () => parseAcceptLanguage,
10953
11093
  parseClientHintHeaders: () => parseClientHintHeaders,
10954
11094
  parseContentDisposition: () => parseContentDisposition,
@@ -10956,6 +11096,7 @@ __export(network_exports, {
10956
11096
  parseDnsResponse: () => parseDnsResponse,
10957
11097
  parseGeoResponse: () => parseGeoResponse,
10958
11098
  parseHar: () => parseHar,
11099
+ parseHsts: () => parseHsts,
10959
11100
  parseIpv6Address: () => parseIpv6Address,
10960
11101
  parseMultipartFormData: () => parseMultipartFormData,
10961
11102
  parsePermissionsPolicy: () => parsePermissionsPolicy,
@@ -10965,6 +11106,7 @@ __export(network_exports, {
10965
11106
  parseUserAgent: () => parseUserAgent,
10966
11107
  parseVaryHeader: () => parseVaryHeader,
10967
11108
  parseXContentTypeOptionsHeader: () => parseXContentTypeOptionsHeader,
11109
+ parseXRobotsTag: () => parseXRobotsTag,
10968
11110
  searchHeaders: () => searchHeaders,
10969
11111
  searchStatusCodes: () => searchStatusCodes,
10970
11112
  splitSitemap: () => splitSitemap,
@@ -14066,6 +14208,243 @@ function parseMultipartFormData(body, boundary) {
14066
14208
  }
14067
14209
  return { boundary, parts };
14068
14210
  }
14211
+ var HSTS_ONE_YEAR_SECONDS = 31536e3;
14212
+ function _humanizeHstsMaxAge(seconds) {
14213
+ if (seconds === 0) return "0 seconds (clears HSTS)";
14214
+ if (seconds % HSTS_ONE_YEAR_SECONDS === 0) {
14215
+ const years = seconds / HSTS_ONE_YEAR_SECONDS;
14216
+ return `${years} year${years === 1 ? "" : "s"}`;
14217
+ }
14218
+ if (seconds % 86400 === 0) {
14219
+ const days = seconds / 86400;
14220
+ return `${days} day${days === 1 ? "" : "s"}`;
14221
+ }
14222
+ if (seconds % 3600 === 0) {
14223
+ const hours = seconds / 3600;
14224
+ return `${hours} hour${hours === 1 ? "" : "s"}`;
14225
+ }
14226
+ return `${seconds} second${seconds === 1 ? "" : "s"}`;
14227
+ }
14228
+ function buildHsts(options) {
14229
+ if (!options || typeof options !== "object") return { error: "maxAge is required" };
14230
+ const { maxAge, includeSubDomains = false, preload = false } = options;
14231
+ if (typeof maxAge !== "number" || !Number.isFinite(maxAge) || !Number.isInteger(maxAge) || maxAge < 0) {
14232
+ return { error: "maxAge must be a non-negative integer number of seconds" };
14233
+ }
14234
+ const warnings = [];
14235
+ const preloadEligible = maxAge >= HSTS_ONE_YEAR_SECONDS && includeSubDomains && preload;
14236
+ if (preload && !includeSubDomains) {
14237
+ warnings.push("Browser HSTS preload lists require includeSubDomains whenever preload is set; this header will not qualify for preloading as configured.");
14238
+ }
14239
+ if (preload && maxAge < HSTS_ONE_YEAR_SECONDS) {
14240
+ warnings.push(`Browser HSTS preload lists require max-age of at least ${HSTS_ONE_YEAR_SECONDS} (1 year); ${maxAge} is too low to qualify.`);
14241
+ }
14242
+ if (maxAge === 0) {
14243
+ warnings.push("max-age=0 tells the browser to forget this host supports HSTS immediately, this clears HSTS rather than enabling it.");
14244
+ } else if (maxAge < 86400) {
14245
+ warnings.push("A max-age under a day gives very little protection; most real deployments use at least 15552000 (180 days) once confident HTTPS is fully working.");
14246
+ }
14247
+ const parts = [`max-age=${maxAge}`];
14248
+ if (includeSubDomains) parts.push("includeSubDomains");
14249
+ if (preload) parts.push("preload");
14250
+ const header = parts.join("; ");
14251
+ return {
14252
+ header,
14253
+ headerName: "Strict-Transport-Security",
14254
+ snippet: `Strict-Transport-Security: ${header}`,
14255
+ maxAge,
14256
+ maxAgeHuman: _humanizeHstsMaxAge(maxAge),
14257
+ includeSubDomains,
14258
+ preload,
14259
+ preloadEligible,
14260
+ warnings
14261
+ };
14262
+ }
14263
+ function parseHsts(raw) {
14264
+ if (!raw || raw.trim() === "") return { error: "Input is empty" };
14265
+ const withoutLabel = raw.trim().replace(/^strict-transport-security:\s*/i, "");
14266
+ const tokens = withoutLabel.split(";").map((t) => t.trim()).filter((t) => t !== "");
14267
+ if (tokens.length === 0) return { error: "No directives found" };
14268
+ let maxAge = null;
14269
+ let includeSubDomains = false;
14270
+ let preload = false;
14271
+ for (const token of tokens) {
14272
+ const eq = token.indexOf("=");
14273
+ const name = (eq === -1 ? token : token.slice(0, eq)).trim().toLowerCase();
14274
+ if (name === "max-age") {
14275
+ const rawValue = eq === -1 ? "" : token.slice(eq + 1).trim();
14276
+ const n = Number(rawValue);
14277
+ if (rawValue === "" || !Number.isFinite(n) || !Number.isInteger(n) || n < 0) {
14278
+ return { error: `max-age value "${rawValue}" is not a valid non-negative integer` };
14279
+ }
14280
+ maxAge = n;
14281
+ } else if (name === "includesubdomains") {
14282
+ includeSubDomains = true;
14283
+ } else if (name === "preload") {
14284
+ preload = true;
14285
+ } else {
14286
+ return { error: `Unrecognized directive "${token}"` };
14287
+ }
14288
+ }
14289
+ if (maxAge === null) return { error: "max-age directive is required" };
14290
+ return buildHsts({ maxAge, includeSubDomains, preload });
14291
+ }
14292
+ var X_ROBOTS_TAG_FLAGS = /* @__PURE__ */ new Set(["noindex", "nofollow", "noarchive", "nosnippet", "notranslate", "noimageindex", "none", "all", "indexifembedded"]);
14293
+ var X_ROBOTS_TAG_FLAG_NOTES = {
14294
+ noindex: "Do not show this page in search results.",
14295
+ nofollow: "Do not follow, or pass ranking credit through, any links on this page.",
14296
+ noarchive: "Do not show a cached copy of this page in search results.",
14297
+ nosnippet: "Do not show a text snippet or video preview for this page in search results.",
14298
+ notranslate: "Do not offer a translation of this page in search results.",
14299
+ noimageindex: "Do not index images on this page.",
14300
+ none: "Shorthand for noindex plus nofollow combined.",
14301
+ all: "Explicitly allow indexing and following, the default with no directives at all.",
14302
+ indexifembedded: "Allow indexing of this page's content when embedded via iframe in another page, even if this page also carries noindex. Only Google supports this directive."
14303
+ };
14304
+ var X_ROBOTS_TAG_VALUED_DIRECTIVES = /* @__PURE__ */ new Set(["max-snippet", "max-image-preview", "max-video-preview", "unavailable_after"]);
14305
+ function _isXRobotsTagFlag(value) {
14306
+ return X_ROBOTS_TAG_FLAGS.has(value);
14307
+ }
14308
+ function buildXRobotsTag(options) {
14309
+ if (!options || typeof options !== "object") return { error: "At least one directive is required" };
14310
+ const { flags = [], maxSnippet, maxImagePreview, maxVideoPreview, unavailableAfter, userAgent } = options;
14311
+ if (!Array.isArray(flags)) return { error: "flags must be an array of directive names" };
14312
+ for (const flag of flags) {
14313
+ if (typeof flag !== "string" || !_isXRobotsTagFlag(flag)) return { error: `Unknown directive "${flag}"` };
14314
+ }
14315
+ if (maxSnippet !== void 0 && (typeof maxSnippet !== "number" || !Number.isInteger(maxSnippet) || maxSnippet < -1)) {
14316
+ return { error: "maxSnippet must be an integer >= -1" };
14317
+ }
14318
+ if (maxVideoPreview !== void 0 && (typeof maxVideoPreview !== "number" || !Number.isInteger(maxVideoPreview) || maxVideoPreview < -1)) {
14319
+ return { error: "maxVideoPreview must be an integer >= -1" };
14320
+ }
14321
+ if (maxImagePreview !== void 0 && !["none", "standard", "large"].includes(maxImagePreview)) {
14322
+ return { error: 'maxImagePreview must be one of "none", "standard", "large"' };
14323
+ }
14324
+ if (unavailableAfter !== void 0 && (typeof unavailableAfter !== "string" || unavailableAfter.trim() === "" || Number.isNaN(Date.parse(unavailableAfter)))) {
14325
+ return { error: "unavailableAfter must be a valid, parseable date string" };
14326
+ }
14327
+ const uniqueFlags = Array.from(new Set(flags));
14328
+ if (uniqueFlags.length === 0 && maxSnippet === void 0 && maxImagePreview === void 0 && maxVideoPreview === void 0 && unavailableAfter === void 0) {
14329
+ return { error: "At least one directive is required" };
14330
+ }
14331
+ const warnings = [];
14332
+ if (uniqueFlags.includes("none") && (uniqueFlags.includes("noindex") || uniqueFlags.includes("nofollow"))) {
14333
+ warnings.push('"none" already implies noindex and nofollow; combining it with either is redundant.');
14334
+ }
14335
+ if (uniqueFlags.includes("all") && uniqueFlags.some((f) => f !== "all" && f !== "indexifembedded")) {
14336
+ warnings.push('"all" explicitly allows indexing and following, which contradicts any restrictive directive combined with it.');
14337
+ }
14338
+ const directives = [...uniqueFlags];
14339
+ const notes = uniqueFlags.map((f) => `${f}: ${X_ROBOTS_TAG_FLAG_NOTES[f]}`);
14340
+ if (maxSnippet !== void 0) {
14341
+ directives.push(`max-snippet: ${maxSnippet}`);
14342
+ notes.push(`max-snippet: ${maxSnippet === 0 ? "Show no text snippet at all." : maxSnippet === -1 ? "No limit on snippet length." : `Limit the text snippet to at most ${maxSnippet} characters.`}`);
14343
+ }
14344
+ if (maxImagePreview !== void 0) {
14345
+ directives.push(`max-image-preview: ${maxImagePreview}`);
14346
+ notes.push(`max-image-preview: Limit any image preview shown in search results to the "${maxImagePreview}" size.`);
14347
+ }
14348
+ if (maxVideoPreview !== void 0) {
14349
+ directives.push(`max-video-preview: ${maxVideoPreview}`);
14350
+ notes.push(`max-video-preview: ${maxVideoPreview === 0 ? "Show no video preview at all, a static image only." : maxVideoPreview === -1 ? "No limit on video preview length." : `Limit the video preview to at most ${maxVideoPreview} seconds.`}`);
14351
+ }
14352
+ if (unavailableAfter !== void 0) {
14353
+ directives.push(`unavailable_after: ${unavailableAfter}`);
14354
+ notes.push(`unavailable_after: Stop showing this page in search results after this date.`);
14355
+ }
14356
+ const directivesJoined = directives.join(", ");
14357
+ const header = userAgent ? `${userAgent}: ${directivesJoined}` : directivesJoined;
14358
+ return {
14359
+ header,
14360
+ headerName: "X-Robots-Tag",
14361
+ snippet: `X-Robots-Tag: ${header}`,
14362
+ directives,
14363
+ notes,
14364
+ warnings
14365
+ };
14366
+ }
14367
+ function parseXRobotsTag(raw) {
14368
+ if (!raw || raw.trim() === "") return { error: "Input is empty" };
14369
+ let withoutLabel = raw.trim().replace(/^x-robots-tag:\s*/i, "");
14370
+ let userAgent;
14371
+ const firstColon = withoutLabel.indexOf(":");
14372
+ const firstComma = withoutLabel.indexOf(",");
14373
+ if (firstColon !== -1 && (firstComma === -1 || firstColon < firstComma)) {
14374
+ const candidate = withoutLabel.slice(0, firstColon).trim();
14375
+ const candidateLower = candidate.toLowerCase();
14376
+ if (candidate !== "" && !X_ROBOTS_TAG_VALUED_DIRECTIVES.has(candidateLower) && !_isXRobotsTagFlag(candidateLower)) {
14377
+ userAgent = candidate;
14378
+ withoutLabel = withoutLabel.slice(firstColon + 1).trim();
14379
+ }
14380
+ }
14381
+ const tokens = withoutLabel.split(",").map((t) => t.trim()).filter((t) => t !== "");
14382
+ if (tokens.length === 0) return { error: "No directives found" };
14383
+ const flags = [];
14384
+ let maxSnippet;
14385
+ let maxImagePreview;
14386
+ let maxVideoPreview;
14387
+ let unavailableAfter;
14388
+ for (const token of tokens) {
14389
+ const eq = token.indexOf(":");
14390
+ const name = (eq === -1 ? token : token.slice(0, eq)).trim().toLowerCase();
14391
+ const value = eq === -1 ? "" : token.slice(eq + 1).trim();
14392
+ if (eq === -1) {
14393
+ if (!_isXRobotsTagFlag(name)) return { error: `Unrecognized directive "${token}"` };
14394
+ flags.push(name);
14395
+ continue;
14396
+ }
14397
+ if (name === "max-snippet") {
14398
+ const n = Number(value);
14399
+ if (value === "" || !Number.isInteger(n) || n < -1) return { error: `max-snippet value "${value}" is not a valid integer >= -1` };
14400
+ maxSnippet = n;
14401
+ } else if (name === "max-image-preview") {
14402
+ if (!["none", "standard", "large"].includes(value)) return { error: `max-image-preview value "${value}" must be one of "none", "standard", "large"` };
14403
+ maxImagePreview = value;
14404
+ } else if (name === "max-video-preview") {
14405
+ const n = Number(value);
14406
+ if (value === "" || !Number.isInteger(n) || n < -1) return { error: `max-video-preview value "${value}" is not a valid integer >= -1` };
14407
+ maxVideoPreview = n;
14408
+ } else if (name === "unavailable_after") {
14409
+ if (value === "" || Number.isNaN(Date.parse(value))) return { error: `unavailable_after value "${value}" is not a valid, parseable date` };
14410
+ unavailableAfter = value;
14411
+ } else {
14412
+ return { error: `Unrecognized directive "${token}"` };
14413
+ }
14414
+ }
14415
+ return buildXRobotsTag({ flags, maxSnippet, maxImagePreview, maxVideoPreview, unavailableAfter, userAgent });
14416
+ }
14417
+ var WELL_KNOWN_OPCODES = {
14418
+ 0: { name: "Continuation Frame", description: "Continues a fragmented message whose first frame was a text or binary frame sent with the FIN bit unset.", category: "data" },
14419
+ 1: { name: "Text Frame", description: "Carries a UTF-8 encoded text payload.", category: "data" },
14420
+ 2: { name: "Binary Frame", description: "Carries an arbitrary binary payload.", category: "data" },
14421
+ 8: { name: "Connection Close", description: "Initiates or acknowledges closing the connection, optionally carrying a 2-byte close code and a UTF-8 reason in its payload.", category: "control" },
14422
+ 9: { name: "Ping", description: "A control frame used to check the connection is alive; the receiver should reply with a Pong carrying the same application data.", category: "control" },
14423
+ 10: { name: "Pong", description: "Sent in response to a Ping (or unprompted as a heartbeat), carrying the same application data as the Ping it answers.", category: "control" }
14424
+ };
14425
+ var RESERVED_NON_CONTROL_OPCODES = /* @__PURE__ */ new Set([3, 4, 5, 6, 7]);
14426
+ function _describeOpcode(opcode) {
14427
+ const known = WELL_KNOWN_OPCODES[opcode];
14428
+ const hex = `0x${opcode.toString(16).toUpperCase()}`;
14429
+ if (known) {
14430
+ return { opcode, hex, name: known.name, description: known.description, category: known.category, isControl: known.category === "control" };
14431
+ }
14432
+ if (RESERVED_NON_CONTROL_OPCODES.has(opcode)) {
14433
+ return { opcode, hex, name: "Reserved (non-control)", description: "Reserved for future non-control frame types by a later revision of the WebSocket protocol. No meaning is defined yet; a compliant endpoint must fail the connection if it receives one.", category: "reserved-non-control", isControl: false };
14434
+ }
14435
+ return { opcode, hex, name: "Reserved (control)", description: "Reserved for future control frame types by a later revision of the WebSocket protocol. No meaning is defined yet; a compliant endpoint must fail the connection if it receives one.", category: "reserved-control", isControl: true };
14436
+ }
14437
+ function listOpcodes() {
14438
+ const result = [];
14439
+ for (let opcode = 0; opcode <= 15; opcode++) result.push(_describeOpcode(opcode));
14440
+ return result;
14441
+ }
14442
+ function lookupOpcode(opcode) {
14443
+ if (typeof opcode !== "number" || !Number.isInteger(opcode) || opcode < 0 || opcode > 15) {
14444
+ return { error: "opcode must be an integer between 0 and 15 (0x0-0xF); the frame opcode is only a 4-bit field" };
14445
+ }
14446
+ return _describeOpcode(opcode);
14447
+ }
14069
14448
 
14070
14449
  // src/tools/api.ts
14071
14450
  var api_exports = {};
package/dist/index.d.cts CHANGED
@@ -2,11 +2,11 @@ export { j as json } from './json-CaiYsGDQ.cjs';
2
2
  export { e as encoding } from './encoding-Dk3wpmb3.cjs';
3
3
  export { h as hashing } from './hashing-CJjlvqS_.cjs';
4
4
  export { t as text } from './text-DWUcY8H1.cjs';
5
- export { d as data } from './data-vxXrBlWh.cjs';
5
+ export { d as data } from './data-26TALa9U.cjs';
6
6
  export { g as generators } from './generators-DAXXrMvG.cjs';
7
7
  export { t as time } from './time-KqJjdqII.cjs';
8
8
  export { u as units } from './units-DPefgzmH.cjs';
9
- export { n as network } from './network-DZTfMAk0.cjs';
9
+ export { n as network } from './network-EHkPJFoe.cjs';
10
10
  export { a as api } from './api-DmTNE4c1.cjs';
11
11
  export { c as code } from './code-CKI2Z_NM.cjs';
12
12
  export { c as color } from './color-tPwZCr9H.cjs';
package/dist/index.d.ts CHANGED
@@ -2,11 +2,11 @@ export { j as json } from './json-CaiYsGDQ.js';
2
2
  export { e as encoding } from './encoding-Dk3wpmb3.js';
3
3
  export { h as hashing } from './hashing-CJjlvqS_.js';
4
4
  export { t as text } from './text-DWUcY8H1.js';
5
- export { d as data } from './data-vxXrBlWh.js';
5
+ export { d as data } from './data-26TALa9U.js';
6
6
  export { g as generators } from './generators-DAXXrMvG.js';
7
7
  export { t as time } from './time-KqJjdqII.js';
8
8
  export { u as units } from './units-DPefgzmH.js';
9
- export { n as network } from './network-DZTfMAk0.js';
9
+ export { n as network } from './network-EHkPJFoe.js';
10
10
  export { a as api } from './api-DmTNE4c1.js';
11
11
  export { c as code } from './code-CKI2Z_NM.js';
12
12
  export { c as color } from './color-tPwZCr9H.js';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export { media_exports as media } from './chunk-226EH3ZI.js';
2
2
  export { units_exports as units } from './chunk-4HNHEOJL.js';
3
- export { network_exports as network } from './chunk-IANBS5Y3.js';
3
+ export { network_exports as network } from './chunk-TTQ2FNUG.js';
4
4
  export { api_exports as api } from './chunk-52ZDKSIX.js';
5
5
  export { code_exports as code } from './chunk-JPFHEZ4P.js';
6
6
  export { color_exports as color } from './chunk-BPVAB4P2.js';
@@ -11,7 +11,7 @@ export { json_exports as json } from './chunk-34C6GXCC.js';
11
11
  export { encoding_exports as encoding } from './chunk-DOWQZUTP.js';
12
12
  export { hashing_exports as hashing } from './chunk-PET2CGTH.js';
13
13
  export { text_exports as text } from './chunk-P7TXG7CI.js';
14
- export { data_exports as data } from './chunk-QY2M2UHJ.js';
14
+ export { data_exports as data } from './chunk-HJVSH7FQ.js';
15
15
  export { generators_exports as generators } from './chunk-422ICOZX.js';
16
16
  export { time_exports as time } from './chunk-IEPWZERQ.js';
17
17
  import './chunk-MLKGABMK.js';