@cj-tech-master/excelts 7.6.0 → 8.0.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 (79) hide show
  1. package/README.md +99 -577
  2. package/README_zh.md +101 -577
  3. package/dist/browser/index.browser.d.ts +3 -0
  4. package/dist/browser/index.browser.js +2 -0
  5. package/dist/browser/index.d.ts +3 -0
  6. package/dist/browser/index.js +2 -0
  7. package/dist/browser/modules/archive/compression/compress.browser.js +4 -4
  8. package/dist/browser/modules/archive/compression/deflate-fallback.d.ts +24 -22
  9. package/dist/browser/modules/archive/compression/deflate-fallback.js +664 -360
  10. package/dist/browser/modules/archive/compression/streaming-compress.browser.d.ts +7 -0
  11. package/dist/browser/modules/archive/compression/streaming-compress.browser.js +15 -3
  12. package/dist/browser/modules/archive/compression/streaming-compress.d.ts +5 -0
  13. package/dist/browser/modules/archive/compression/streaming-compress.js +7 -0
  14. package/dist/browser/modules/archive/zip/stream.js +27 -3
  15. package/dist/browser/modules/excel/workbook.browser.d.ts +72 -0
  16. package/dist/browser/modules/excel/workbook.browser.js +226 -0
  17. package/dist/browser/modules/excel/workbook.d.ts +32 -1
  18. package/dist/browser/modules/excel/workbook.js +47 -2
  19. package/dist/browser/modules/excel/xlsx/xlsx.browser.js +42 -4
  20. package/dist/browser/modules/markdown/constants.d.ts +30 -0
  21. package/dist/browser/modules/markdown/constants.js +30 -0
  22. package/dist/browser/modules/markdown/errors.d.ts +21 -0
  23. package/dist/browser/modules/markdown/errors.js +23 -0
  24. package/dist/browser/modules/markdown/format/index.d.ts +54 -0
  25. package/dist/browser/modules/markdown/format/index.js +307 -0
  26. package/dist/browser/modules/markdown/index.d.ts +15 -0
  27. package/dist/browser/modules/markdown/index.js +22 -0
  28. package/dist/browser/modules/markdown/parse/index.d.ts +70 -0
  29. package/dist/browser/modules/markdown/parse/index.js +428 -0
  30. package/dist/browser/modules/markdown/types.d.ts +130 -0
  31. package/dist/browser/modules/markdown/types.js +6 -0
  32. package/dist/cjs/index.js +5 -1
  33. package/dist/cjs/modules/archive/compression/compress.browser.js +4 -4
  34. package/dist/cjs/modules/archive/compression/deflate-fallback.js +664 -360
  35. package/dist/cjs/modules/archive/compression/streaming-compress.browser.js +15 -2
  36. package/dist/cjs/modules/archive/compression/streaming-compress.js +8 -0
  37. package/dist/cjs/modules/archive/zip/stream.js +26 -2
  38. package/dist/cjs/modules/excel/workbook.browser.js +226 -0
  39. package/dist/cjs/modules/excel/workbook.js +46 -1
  40. package/dist/cjs/modules/excel/xlsx/xlsx.browser.js +42 -4
  41. package/dist/cjs/modules/markdown/constants.js +33 -0
  42. package/dist/cjs/modules/markdown/errors.js +28 -0
  43. package/dist/cjs/modules/markdown/format/index.js +310 -0
  44. package/dist/cjs/modules/markdown/index.js +30 -0
  45. package/dist/cjs/modules/markdown/parse/index.js +432 -0
  46. package/dist/cjs/modules/markdown/types.js +7 -0
  47. package/dist/esm/index.browser.js +2 -0
  48. package/dist/esm/index.js +2 -0
  49. package/dist/esm/modules/archive/compression/compress.browser.js +4 -4
  50. package/dist/esm/modules/archive/compression/deflate-fallback.js +664 -360
  51. package/dist/esm/modules/archive/compression/streaming-compress.browser.js +15 -3
  52. package/dist/esm/modules/archive/compression/streaming-compress.js +7 -0
  53. package/dist/esm/modules/archive/zip/stream.js +27 -3
  54. package/dist/esm/modules/excel/workbook.browser.js +226 -0
  55. package/dist/esm/modules/excel/workbook.js +47 -2
  56. package/dist/esm/modules/excel/xlsx/xlsx.browser.js +42 -4
  57. package/dist/esm/modules/markdown/constants.js +30 -0
  58. package/dist/esm/modules/markdown/errors.js +23 -0
  59. package/dist/esm/modules/markdown/format/index.js +307 -0
  60. package/dist/esm/modules/markdown/index.js +22 -0
  61. package/dist/esm/modules/markdown/parse/index.js +428 -0
  62. package/dist/esm/modules/markdown/types.js +6 -0
  63. package/dist/iife/excelts.iife.js +1342 -283
  64. package/dist/iife/excelts.iife.js.map +1 -1
  65. package/dist/iife/excelts.iife.min.js +38 -34
  66. package/dist/types/index.browser.d.ts +3 -0
  67. package/dist/types/index.d.ts +3 -0
  68. package/dist/types/modules/archive/compression/deflate-fallback.d.ts +24 -22
  69. package/dist/types/modules/archive/compression/streaming-compress.browser.d.ts +7 -0
  70. package/dist/types/modules/archive/compression/streaming-compress.d.ts +5 -0
  71. package/dist/types/modules/excel/workbook.browser.d.ts +72 -0
  72. package/dist/types/modules/excel/workbook.d.ts +32 -1
  73. package/dist/types/modules/markdown/constants.d.ts +30 -0
  74. package/dist/types/modules/markdown/errors.d.ts +21 -0
  75. package/dist/types/modules/markdown/format/index.d.ts +54 -0
  76. package/dist/types/modules/markdown/index.d.ts +15 -0
  77. package/dist/types/modules/markdown/parse/index.d.ts +70 -0
  78. package/dist/types/modules/markdown/types.d.ts +130 -0
  79. package/package.json +56 -32
@@ -0,0 +1,307 @@
1
+ /**
2
+ * Markdown Table Formatter
3
+ *
4
+ * Formats data into well-formed Markdown table strings.
5
+ *
6
+ * Features:
7
+ * - Auto column width calculation with padding
8
+ * - Column alignment (left, center, right, none)
9
+ * - Proper escaping of pipe characters and backslashes
10
+ * - Compact mode (disable column-width alignment) for minimal output
11
+ * - Configurable column definitions
12
+ * - Multiline cell content (newlines converted to `<br>`)
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * // Simple array data with headers
17
+ * formatMarkdown(["Name", "Age"], [["Alice", "30"], ["Bob", "25"]]);
18
+ * // | Name | Age |
19
+ * // | ----- | --- |
20
+ * // | Alice | 30 |
21
+ * // | Bob | 25 |
22
+ *
23
+ * // With alignment
24
+ * formatMarkdown(["Left", "Center", "Right"], data, {
25
+ * alignment: "left",
26
+ * columns: [
27
+ * { header: "Left", alignment: "left" },
28
+ * { header: "Center", alignment: "center" },
29
+ * { header: "Right", alignment: "right" }
30
+ * ]
31
+ * });
32
+ * ```
33
+ */
34
+ import { ESCAPE_AND_NEWLINE, NEWLINE_IN_CELL } from "../constants.js";
35
+ // =============================================================================
36
+ // Unicode Display Width
37
+ // =============================================================================
38
+ /**
39
+ * Calculate the display width of a string in a monospace terminal.
40
+ * CJK characters, fullwidth forms, and most emoji are 2 columns wide.
41
+ * This enables proper column alignment in tables containing these characters.
42
+ */
43
+ function displayWidth(str) {
44
+ let width = 0;
45
+ for (let i = 0; i < str.length; i++) {
46
+ const code = str.charCodeAt(i);
47
+ // Handle surrogate pairs (emoji and supplementary plane characters)
48
+ if (code >= 0xd800 && code <= 0xdbff && i + 1 < str.length) {
49
+ const low = str.charCodeAt(i + 1);
50
+ if (low >= 0xdc00 && low <= 0xdfff) {
51
+ width += 2;
52
+ i++;
53
+ continue;
54
+ }
55
+ }
56
+ // Zero-width characters
57
+ if (code === 0x200b || // zero-width space
58
+ code === 0x200c || // zero-width non-joiner
59
+ code === 0x200d || // zero-width joiner
60
+ code === 0xfeff // BOM / zero-width no-break space
61
+ ) {
62
+ continue;
63
+ }
64
+ // Combining marks (general categories Mn, Mc, Me)
65
+ if ((code >= 0x0300 && code <= 0x036f) || // Combining Diacritical Marks
66
+ (code >= 0x1ab0 && code <= 0x1aff) || // Combining Diacritical Marks Extended
67
+ (code >= 0x1dc0 && code <= 0x1dff) || // Combining Diacritical Marks Supplement
68
+ (code >= 0x20d0 && code <= 0x20ff) || // Combining Diacritical Marks for Symbols
69
+ (code >= 0xfe20 && code <= 0xfe2f) // Combining Half Marks
70
+ ) {
71
+ continue;
72
+ }
73
+ // Fullwidth and wide characters: CJK, Hangul, Katakana/Hiragana, etc.
74
+ if ((code >= 0x1100 && code <= 0x115f) || // Hangul Jamo
75
+ (code >= 0x2e80 && code <= 0x303e) || // CJK Radicals, Kangxi, CJK Symbols
76
+ (code >= 0x3040 && code <= 0x33bf) || // Hiragana, Katakana, Bopomofo, CJK Compat
77
+ (code >= 0x3400 && code <= 0x4dbf) || // CJK Unified Ideographs Extension A
78
+ (code >= 0x4e00 && code <= 0xa4cf) || // CJK Unified Ideographs, Yi
79
+ (code >= 0xa960 && code <= 0xa97f) || // Hangul Jamo Extended-A
80
+ (code >= 0xac00 && code <= 0xd7af) || // Hangul Syllables
81
+ (code >= 0xf900 && code <= 0xfaff) || // CJK Compatibility Ideographs
82
+ (code >= 0xfe10 && code <= 0xfe19) || // Vertical forms
83
+ (code >= 0xfe30 && code <= 0xfe6f) || // CJK Compatibility Forms
84
+ (code >= 0xff01 && code <= 0xff60) || // Fullwidth ASCII/Latin
85
+ (code >= 0xffe0 && code <= 0xffe6) // Fullwidth Signs
86
+ ) {
87
+ width += 2;
88
+ continue;
89
+ }
90
+ width += 1;
91
+ }
92
+ return width;
93
+ }
94
+ // =============================================================================
95
+ // Internal Helpers
96
+ // =============================================================================
97
+ /**
98
+ * Default value-to-string converter.
99
+ */
100
+ function defaultStringify(value) {
101
+ if (value === null || value === undefined) {
102
+ return "";
103
+ }
104
+ if (value instanceof Date) {
105
+ return value.toISOString();
106
+ }
107
+ if (typeof value === "object") {
108
+ try {
109
+ return JSON.stringify(value);
110
+ }
111
+ catch {
112
+ return "[object Object]";
113
+ }
114
+ }
115
+ return String(value);
116
+ }
117
+ /**
118
+ * Escape pipe characters, backslashes, and convert newlines to `<br>` in a single pass.
119
+ * `|` → `\|`, `\` → `\\`, `\r\n`/`\r`/`\n` → `<br>`
120
+ */
121
+ function escapeCell(value) {
122
+ return value.replace(ESCAPE_AND_NEWLINE, ch => (ch === "|" || ch === "\\" ? "\\" + ch : "<br>"));
123
+ }
124
+ /**
125
+ * Convert literal newlines to `<br>` without escaping pipes/backslashes.
126
+ */
127
+ function convertNewlines(value) {
128
+ if (value.indexOf("\n") !== -1 || value.indexOf("\r") !== -1) {
129
+ return value.replace(NEWLINE_IN_CELL, "<br>");
130
+ }
131
+ return value;
132
+ }
133
+ /**
134
+ * Build the separator cell for a column based on alignment and width.
135
+ *
136
+ * Examples (width=5):
137
+ * - none: `-----`
138
+ * - left: `:----`
139
+ * - right: `----:`
140
+ * - center: `:---:`
141
+ */
142
+ function buildSeparator(alignment, width) {
143
+ switch (alignment) {
144
+ case "left":
145
+ return ":" + "-".repeat(width - 1);
146
+ case "right":
147
+ return "-".repeat(width - 1) + ":";
148
+ case "center":
149
+ return ":" + "-".repeat(Math.max(width - 2, 1)) + ":";
150
+ default: // "none"
151
+ return "-".repeat(width);
152
+ }
153
+ }
154
+ /**
155
+ * Pad a cell value to the target display width with alignment.
156
+ * Uses displayWidth() for proper CJK/emoji handling.
157
+ */
158
+ function padCell(value, targetWidth, alignment) {
159
+ const len = displayWidth(value);
160
+ if (len >= targetWidth) {
161
+ return value;
162
+ }
163
+ const diff = targetWidth - len;
164
+ switch (alignment) {
165
+ case "right":
166
+ return " ".repeat(diff) + value;
167
+ case "center": {
168
+ const left = Math.floor(diff / 2);
169
+ const right = diff - left;
170
+ return " ".repeat(left) + value + " ".repeat(right);
171
+ }
172
+ default: // "left" or "none"
173
+ return value + " ".repeat(diff);
174
+ }
175
+ }
176
+ /**
177
+ * Resolve column configuration from options.
178
+ */
179
+ function resolveColumns(headers, options) {
180
+ const columnCount = headers.length;
181
+ const defaultAlignment = options.alignment ?? "left";
182
+ const displayHeaders = new Array(columnCount);
183
+ const alignments = new Array(columnCount);
184
+ const minWidths = new Array(columnCount);
185
+ if (options.columns && options.columns.length > 0) {
186
+ for (let i = 0; i < columnCount; i++) {
187
+ const col = i < options.columns.length ? options.columns[i] : undefined;
188
+ if (typeof col === "string") {
189
+ displayHeaders[i] = col;
190
+ alignments[i] = defaultAlignment;
191
+ minWidths[i] = 3;
192
+ }
193
+ else if (col) {
194
+ displayHeaders[i] = col.header;
195
+ alignments[i] = col.alignment ?? defaultAlignment;
196
+ minWidths[i] = col.minWidth ?? 3;
197
+ }
198
+ else {
199
+ displayHeaders[i] = headers[i] ?? "";
200
+ alignments[i] = defaultAlignment;
201
+ minWidths[i] = 3;
202
+ }
203
+ }
204
+ }
205
+ else {
206
+ for (let i = 0; i < columnCount; i++) {
207
+ displayHeaders[i] = headers[i] ?? "";
208
+ alignments[i] = defaultAlignment;
209
+ minWidths[i] = 3;
210
+ }
211
+ }
212
+ return { displayHeaders, alignments, minWidths };
213
+ }
214
+ // =============================================================================
215
+ // Main Formatter
216
+ // =============================================================================
217
+ /**
218
+ * Format data as a Markdown table string.
219
+ *
220
+ * @param headers - Column header strings
221
+ * @param rows - Data rows (each row is an array of cell values)
222
+ * @param options - Formatting options
223
+ * @returns Formatted Markdown table string
224
+ *
225
+ * @example
226
+ * ```ts
227
+ * formatMarkdown(
228
+ * ["Name", "Age", "City"],
229
+ * [
230
+ * ["Alice", 30, "New York"],
231
+ * ["Bob", 25, "London"]
232
+ * ]
233
+ * );
234
+ * ```
235
+ */
236
+ export function formatMarkdown(headers, rows, options = {}) {
237
+ const { padding = true, trailingNewline = true, escapeContent = true, stringify = defaultStringify } = options;
238
+ const columnCount = headers.length;
239
+ if (columnCount === 0) {
240
+ return "";
241
+ }
242
+ // Resolve column configs
243
+ const { displayHeaders, alignments, minWidths } = resolveColumns(headers, options);
244
+ // Single-pass: convert all cell values to strings, apply escaping,
245
+ // and compute column widths simultaneously.
246
+ const headerStrings = new Array(columnCount);
247
+ const widths = new Array(columnCount);
248
+ // Initialize widths from headers
249
+ for (let i = 0; i < columnCount; i++) {
250
+ const h = escapeContent ? escapeCell(displayHeaders[i]) : convertNewlines(displayHeaders[i]);
251
+ headerStrings[i] = h;
252
+ widths[i] = padding ? Math.max(displayWidth(h), minWidths[i]) : Math.max(minWidths[i], 3);
253
+ }
254
+ // Convert rows and update widths in a single pass
255
+ const rowStrings = new Array(rows.length);
256
+ for (let r = 0; r < rows.length; r++) {
257
+ const row = rows[r];
258
+ const cells = new Array(columnCount);
259
+ for (let c = 0; c < columnCount; c++) {
260
+ const raw = c < row.length ? stringify(row[c]) : "";
261
+ const cell = escapeContent ? escapeCell(raw) : convertNewlines(raw);
262
+ cells[c] = cell;
263
+ if (padding) {
264
+ const cellWidth = displayWidth(cell);
265
+ if (cellWidth > widths[c]) {
266
+ widths[c] = cellWidth;
267
+ }
268
+ }
269
+ }
270
+ rowStrings[r] = cells;
271
+ }
272
+ // Build the complete table output
273
+ // Pre-calculate total line count: header + separator + data rows
274
+ const totalLines = 2 + rowStrings.length;
275
+ const lines = new Array(totalLines);
276
+ // Header row
277
+ const headerParts = new Array(columnCount);
278
+ for (let c = 0; c < columnCount; c++) {
279
+ headerParts[c] = padding
280
+ ? " " + padCell(headerStrings[c], widths[c], alignments[c]) + " "
281
+ : " " + headerStrings[c] + " ";
282
+ }
283
+ lines[0] = "|" + headerParts.join("|") + "|";
284
+ // Separator row
285
+ // In both modes, cell content has 1 space padding on each side (" value "),
286
+ // so separator width must be widths[c] + 2 to match.
287
+ const sepParts = new Array(columnCount);
288
+ for (let c = 0; c < columnCount; c++) {
289
+ sepParts[c] = buildSeparator(alignments[c], widths[c] + 2);
290
+ }
291
+ lines[1] = "|" + sepParts.join("|") + "|";
292
+ // Data rows
293
+ for (let r = 0; r < rowStrings.length; r++) {
294
+ const rowParts = new Array(columnCount);
295
+ for (let c = 0; c < columnCount; c++) {
296
+ rowParts[c] = padding
297
+ ? " " + padCell(rowStrings[r][c], widths[c], alignments[c]) + " "
298
+ : " " + rowStrings[r][c] + " ";
299
+ }
300
+ lines[r + 2] = "|" + rowParts.join("|") + "|";
301
+ }
302
+ let result = lines.join("\n");
303
+ if (trailingNewline) {
304
+ result += "\n";
305
+ }
306
+ return result;
307
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Markdown Module - Public API
3
+ *
4
+ * Pure Markdown table parsing/formatting functionality with no Excel dependencies.
5
+ * For Markdown-Worksheet integration, use Workbook.readMarkdown/writeMarkdown methods instead.
6
+ *
7
+ * Design principles:
8
+ * - Only export types and functions that are part of the PUBLIC API
9
+ * - Internal utilities are used internally but not exported
10
+ * - This reduces bundle size and simplifies the public interface
11
+ */
12
+ // =============================================================================
13
+ // Core Functions
14
+ // =============================================================================
15
+ // Parser
16
+ export { parseMarkdown, parseMarkdownAll } from "./parse/index.js";
17
+ // Formatter
18
+ export { formatMarkdown } from "./format/index.js";
19
+ // =============================================================================
20
+ // Errors
21
+ // =============================================================================
22
+ export { MarkdownError, MarkdownParseError } from "./errors.js";