formatferry 0.1.3 → 1.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.
- package/dist/commands/auth.d.ts +17 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +102 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/batch.d.ts +10 -0
- package/dist/commands/batch.d.ts.map +1 -0
- package/dist/commands/batch.js +92 -0
- package/dist/commands/batch.js.map +1 -0
- package/dist/commands/convert.d.ts +26 -0
- package/dist/commands/convert.d.ts.map +1 -0
- package/dist/commands/convert.js +198 -0
- package/dist/commands/convert.js.map +1 -0
- package/dist/config-store.d.ts +27 -0
- package/dist/config-store.d.ts.map +1 -0
- package/dist/config-store.js +58 -0
- package/dist/config-store.js.map +1 -0
- package/dist/entitlement.d.ts +11 -0
- package/dist/entitlement.d.ts.map +1 -0
- package/dist/entitlement.js +91 -0
- package/dist/entitlement.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -11
- package/dist/index.js.map +1 -0
- package/dist/packages/cli/src/commands/auth.d.ts +17 -0
- package/dist/packages/cli/src/commands/auth.d.ts.map +1 -0
- package/dist/packages/cli/src/commands/auth.js +102 -0
- package/dist/packages/cli/src/commands/auth.js.map +1 -0
- package/dist/packages/cli/src/commands/batch.d.ts +10 -0
- package/dist/packages/cli/src/commands/batch.d.ts.map +1 -0
- package/dist/packages/cli/src/commands/batch.js +92 -0
- package/dist/packages/cli/src/commands/batch.js.map +1 -0
- package/dist/packages/cli/src/commands/convert.d.ts +26 -0
- package/dist/packages/cli/src/commands/convert.d.ts.map +1 -0
- package/dist/packages/cli/src/commands/convert.js +198 -0
- package/dist/packages/cli/src/commands/convert.js.map +1 -0
- package/dist/packages/cli/src/config-store.d.ts +27 -0
- package/dist/packages/cli/src/config-store.d.ts.map +1 -0
- package/dist/packages/cli/src/config-store.js +58 -0
- package/dist/packages/cli/src/config-store.js.map +1 -0
- package/dist/packages/cli/src/entitlement.d.ts +11 -0
- package/dist/packages/cli/src/entitlement.d.ts.map +1 -0
- package/dist/packages/cli/src/entitlement.js +91 -0
- package/dist/packages/cli/src/entitlement.js.map +1 -0
- package/dist/packages/cli/src/index.d.ts +2 -0
- package/dist/packages/cli/src/index.d.ts.map +1 -0
- package/dist/packages/cli/src/index.js +28 -0
- package/dist/packages/cli/src/index.js.map +1 -0
- package/dist/packages/cli/src/shim.d.ts +2 -0
- package/dist/packages/cli/src/shim.d.ts.map +1 -0
- package/dist/packages/cli/src/shim.js +21 -0
- package/dist/packages/cli/src/shim.js.map +1 -0
- package/dist/shim.d.ts +2 -0
- package/dist/shim.d.ts.map +1 -0
- package/dist/shim.js +21 -0
- package/dist/shim.js.map +1 -0
- package/dist/src/shared/adapters/docx-adapter.d.ts +85 -0
- package/dist/src/shared/adapters/docx-adapter.d.ts.map +1 -0
- package/dist/src/shared/adapters/docx-adapter.js +164 -0
- package/dist/src/shared/adapters/docx-adapter.js.map +1 -0
- package/dist/src/shared/adapters/pdf-adapter.d.ts +94 -0
- package/dist/src/shared/adapters/pdf-adapter.d.ts.map +1 -0
- package/dist/src/shared/adapters/pdf-adapter.js +322 -0
- package/dist/src/shared/adapters/pdf-adapter.js.map +1 -0
- package/dist/src/shared/adapters/spreadsheet-adapter.d.ts +98 -0
- package/dist/src/shared/adapters/spreadsheet-adapter.d.ts.map +1 -0
- package/dist/src/shared/adapters/spreadsheet-adapter.js +424 -0
- package/dist/src/shared/adapters/spreadsheet-adapter.js.map +1 -0
- package/dist/src/shared/atlassian-detector.d.ts +6 -0
- package/dist/src/shared/atlassian-detector.d.ts.map +1 -0
- package/dist/src/shared/atlassian-detector.js +23 -0
- package/dist/src/shared/atlassian-detector.js.map +1 -0
- package/dist/src/shared/conversion-engine.d.ts +114 -0
- package/dist/src/shared/conversion-engine.d.ts.map +1 -0
- package/dist/src/shared/conversion-engine.js +790 -0
- package/dist/src/shared/conversion-engine.js.map +1 -0
- package/dist/src/shared/entitlement-service.d.ts +42 -0
- package/dist/src/shared/entitlement-service.d.ts.map +1 -0
- package/dist/src/shared/entitlement-service.js +38 -0
- package/dist/src/shared/entitlement-service.js.map +1 -0
- package/dist/src/shared/input-sanitizer.d.ts +93 -0
- package/dist/src/shared/input-sanitizer.d.ts.map +1 -0
- package/dist/src/shared/input-sanitizer.js +527 -0
- package/dist/src/shared/input-sanitizer.js.map +1 -0
- package/package.json +6 -2
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spreadsheet Adapter Module
|
|
3
|
+
*
|
|
4
|
+
* Converts XLSX and CSV files to HTML using SheetJS for processing through
|
|
5
|
+
* the existing ConversionEngine pipeline.
|
|
6
|
+
*
|
|
7
|
+
* Requirements: 2.1, 2.2, 2.7, 2.8, 2.9, 2.14, 2.15, 2.16
|
|
8
|
+
*/
|
|
9
|
+
/** Sheet information extracted from spreadsheet */
|
|
10
|
+
export interface SheetInfo {
|
|
11
|
+
/** Sheet name */
|
|
12
|
+
name: string;
|
|
13
|
+
/** Number of rows in the sheet */
|
|
14
|
+
rowCount: number;
|
|
15
|
+
/** Number of columns in the sheet */
|
|
16
|
+
columnCount: number;
|
|
17
|
+
}
|
|
18
|
+
/** Result of parsing a spreadsheet file */
|
|
19
|
+
export interface SpreadsheetParseResult {
|
|
20
|
+
/** HTML table representation of the spreadsheet */
|
|
21
|
+
html: string;
|
|
22
|
+
/** Information about all sheets in the workbook */
|
|
23
|
+
sheets: SheetInfo[];
|
|
24
|
+
/** Index of the currently active/converted sheet */
|
|
25
|
+
activeSheetIndex: number;
|
|
26
|
+
/** Any warnings generated during parsing */
|
|
27
|
+
warnings: string[];
|
|
28
|
+
}
|
|
29
|
+
/** Error thrown when spreadsheet parsing fails */
|
|
30
|
+
export declare class SpreadsheetParseError extends Error {
|
|
31
|
+
readonly code: 'CORRUPTED' | 'INVALID_FORMAT' | 'PARSE_ERROR' | 'EMPTY_FILE';
|
|
32
|
+
readonly originalError?: Error | undefined;
|
|
33
|
+
constructor(message: string, code: 'CORRUPTED' | 'INVALID_FORMAT' | 'PARSE_ERROR' | 'EMPTY_FILE', originalError?: Error | undefined);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Spreadsheet Adapter class
|
|
37
|
+
*
|
|
38
|
+
* Handles conversion of XLSX and CSV files to HTML using SheetJS.
|
|
39
|
+
* The HTML output is then processed through the ConversionEngine pipeline.
|
|
40
|
+
*/
|
|
41
|
+
export declare class SpreadsheetAdapter {
|
|
42
|
+
private xlsx;
|
|
43
|
+
private currentWorkbook;
|
|
44
|
+
/**
|
|
45
|
+
* Load the SheetJS library if not already loaded
|
|
46
|
+
*/
|
|
47
|
+
private ensureXlsxLoaded;
|
|
48
|
+
/**
|
|
49
|
+
* Parse a spreadsheet file and convert it to HTML
|
|
50
|
+
*
|
|
51
|
+
* @param arrayBuffer - The file content as an ArrayBuffer
|
|
52
|
+
* @param format - The file format ('xlsx' or 'csv')
|
|
53
|
+
* @param sheetIndex - Optional sheet index to convert (default: 0)
|
|
54
|
+
* @returns Promise resolving to the parse result with HTML and metadata
|
|
55
|
+
* @throws SpreadsheetParseError if the file cannot be parsed
|
|
56
|
+
*/
|
|
57
|
+
parseToHtml(arrayBuffer: ArrayBuffer, format?: 'xlsx' | 'csv', sheetIndex?: number): Promise<SpreadsheetParseResult>;
|
|
58
|
+
/**
|
|
59
|
+
* Convert a worksheet to HTML table format
|
|
60
|
+
*
|
|
61
|
+
* Requirements:
|
|
62
|
+
* - 2.7: Handle merged cells by repeating content
|
|
63
|
+
* - 2.9: Preserve empty rows/columns in table structure
|
|
64
|
+
* - 2.14: Use pipe (|) syntax for Markdown tables (via HTML table)
|
|
65
|
+
*/
|
|
66
|
+
private worksheetToHtml;
|
|
67
|
+
/**
|
|
68
|
+
* Build a map of merged cells with their values repeated
|
|
69
|
+
*
|
|
70
|
+
* Requirement 2.7: Handle merged cells by repeating content
|
|
71
|
+
*/
|
|
72
|
+
private buildMergedCellsMap;
|
|
73
|
+
/**
|
|
74
|
+
* Get the names of all sheets in the current workbook
|
|
75
|
+
*
|
|
76
|
+
* Requirement 2.4: Display sheet selector with sheet names
|
|
77
|
+
*/
|
|
78
|
+
getSheetNames(): string[];
|
|
79
|
+
/**
|
|
80
|
+
* Get the number of sheets in the current workbook
|
|
81
|
+
*/
|
|
82
|
+
getSheetCount(): number;
|
|
83
|
+
/**
|
|
84
|
+
* Re-parse the current workbook with a different sheet selected
|
|
85
|
+
*
|
|
86
|
+
* Requirement 2.5: Re-convert when user selects different sheet
|
|
87
|
+
*/
|
|
88
|
+
selectSheet(sheetIndex: number): Promise<SpreadsheetParseResult>;
|
|
89
|
+
/**
|
|
90
|
+
* Clear the current workbook from memory
|
|
91
|
+
*/
|
|
92
|
+
clearWorkbook(): void;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Singleton instance for convenience
|
|
96
|
+
*/
|
|
97
|
+
export declare const spreadsheetAdapter: SpreadsheetAdapter;
|
|
98
|
+
//# sourceMappingURL=spreadsheet-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spreadsheet-adapter.d.ts","sourceRoot":"","sources":["../../../../../../src/shared/adapters/spreadsheet-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,mDAAmD;AACnD,MAAM,WAAW,SAAS;IACxB,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,qCAAqC;IACrC,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,2CAA2C;AAC3C,MAAM,WAAW,sBAAsB;IACrC,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,oDAAoD;IACpD,gBAAgB,EAAE,MAAM,CAAC;IACzB,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,kDAAkD;AAClD,qBAAa,qBAAsB,SAAQ,KAAK;aAG5B,IAAI,EAAE,WAAW,GAAG,gBAAgB,GAAG,aAAa,GAAG,YAAY;aACnE,aAAa,CAAC,EAAE,KAAK;gBAFrC,OAAO,EAAE,MAAM,EACC,IAAI,EAAE,WAAW,GAAG,gBAAgB,GAAG,aAAa,GAAG,YAAY,EACnE,aAAa,CAAC,EAAE,KAAK,YAAA;CAKxC;AAyND;;;;;GAKG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,IAAI,CAAwB;IACpC,OAAO,CAAC,eAAe,CAA6B;IAEpD;;OAEG;YACW,gBAAgB;IAO9B;;;;;;;;OAQG;IACG,WAAW,CACf,WAAW,EAAE,WAAW,EACxB,MAAM,GAAE,MAAM,GAAG,KAAc,EAC/B,UAAU,GAAE,MAAU,GACrB,OAAO,CAAC,sBAAsB,CAAC;IAsGlC;;;;;;;OAOG;IACH,OAAO,CAAC,eAAe;IAkDvB;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IA6B3B;;;;OAIG;IACH,aAAa,IAAI,MAAM,EAAE;IASzB;;OAEG;IACH,aAAa,IAAI,MAAM;IAIvB;;;;OAIG;IACG,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC;IA4CtE;;OAEG;IACH,aAAa,IAAI,IAAI;CAGtB;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB,oBAA2B,CAAC"}
|
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spreadsheet Adapter Module
|
|
3
|
+
*
|
|
4
|
+
* Converts XLSX and CSV files to HTML using SheetJS for processing through
|
|
5
|
+
* the existing ConversionEngine pipeline.
|
|
6
|
+
*
|
|
7
|
+
* Requirements: 2.1, 2.2, 2.7, 2.8, 2.9, 2.14, 2.15, 2.16
|
|
8
|
+
*/
|
|
9
|
+
import { loadLibrary } from '@/shared/dynamic-loader';
|
|
10
|
+
/** Error thrown when spreadsheet parsing fails */
|
|
11
|
+
export class SpreadsheetParseError extends Error {
|
|
12
|
+
code;
|
|
13
|
+
originalError;
|
|
14
|
+
constructor(message, code, originalError) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.code = code;
|
|
17
|
+
this.originalError = originalError;
|
|
18
|
+
this.name = 'SpreadsheetParseError';
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Parse a cell reference like "A1" into column and row indices
|
|
23
|
+
*/
|
|
24
|
+
function parseCellRef(ref) {
|
|
25
|
+
const match = ref.match(/^([A-Z]+)(\d+)$/);
|
|
26
|
+
if (!match)
|
|
27
|
+
return null;
|
|
28
|
+
const colStr = match[1];
|
|
29
|
+
const rowStr = match[2];
|
|
30
|
+
// Convert column letters to index (A=0, B=1, ..., Z=25, AA=26, etc.)
|
|
31
|
+
let col = 0;
|
|
32
|
+
for (let i = 0; i < colStr.length; i++) {
|
|
33
|
+
col = col * 26 + (colStr.charCodeAt(i) - 64);
|
|
34
|
+
}
|
|
35
|
+
col -= 1; // Make 0-indexed
|
|
36
|
+
const row = parseInt(rowStr, 10) - 1; // Make 0-indexed
|
|
37
|
+
return { col, row };
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Get the range of a worksheet
|
|
41
|
+
*/
|
|
42
|
+
function getWorksheetRange(ws) {
|
|
43
|
+
const ref = ws['!ref'];
|
|
44
|
+
if (!ref)
|
|
45
|
+
return null;
|
|
46
|
+
const parts = ref.split(':');
|
|
47
|
+
const start = parseCellRef(parts[0]);
|
|
48
|
+
const end = parts[1] ? parseCellRef(parts[1]) : start;
|
|
49
|
+
if (!start || !end)
|
|
50
|
+
return null;
|
|
51
|
+
return {
|
|
52
|
+
startRow: start.row,
|
|
53
|
+
endRow: end.row,
|
|
54
|
+
startCol: start.col,
|
|
55
|
+
endCol: end.col,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Convert column index to Excel-style column letter (0=A, 1=B, ..., 25=Z, 26=AA)
|
|
60
|
+
*/
|
|
61
|
+
function colIndexToLetter(col) {
|
|
62
|
+
let result = '';
|
|
63
|
+
let n = col + 1;
|
|
64
|
+
while (n > 0) {
|
|
65
|
+
n--;
|
|
66
|
+
result = String.fromCharCode(65 + (n % 26)) + result;
|
|
67
|
+
n = Math.floor(n / 26);
|
|
68
|
+
}
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Format a cell value for display
|
|
73
|
+
*
|
|
74
|
+
* Requirements:
|
|
75
|
+
* - 2.8: Display formula calculated values (not formula text)
|
|
76
|
+
* - 2.15: Format dates as ISO 8601
|
|
77
|
+
* - 2.16: Preserve currency symbols
|
|
78
|
+
*/
|
|
79
|
+
function formatCellValue(cell) {
|
|
80
|
+
if (!cell)
|
|
81
|
+
return '';
|
|
82
|
+
// Use the raw value (v) which contains calculated formula results (Req 2.8)
|
|
83
|
+
const value = cell.v;
|
|
84
|
+
if (value === null || value === undefined) {
|
|
85
|
+
return '';
|
|
86
|
+
}
|
|
87
|
+
// Handle dates (Req 2.15)
|
|
88
|
+
if (cell.t === 'd' && value instanceof Date) {
|
|
89
|
+
return formatDateISO8601(value);
|
|
90
|
+
}
|
|
91
|
+
// Check if it's a date stored as number (Excel serial date)
|
|
92
|
+
if (cell.t === 'n' && typeof value === 'number' && isDateFormat(cell.z)) {
|
|
93
|
+
const date = excelSerialToDate(value);
|
|
94
|
+
return formatDateISO8601(date);
|
|
95
|
+
}
|
|
96
|
+
// For currency and other formatted numbers, use the formatted text if available (Req 2.16)
|
|
97
|
+
// This preserves currency symbols like $, €, £
|
|
98
|
+
if (cell.w && cell.t === 'n' && isCurrencyFormat(cell.z)) {
|
|
99
|
+
return cell.w;
|
|
100
|
+
}
|
|
101
|
+
// For other values, convert to string
|
|
102
|
+
if (typeof value === 'boolean') {
|
|
103
|
+
return value ? 'TRUE' : 'FALSE';
|
|
104
|
+
}
|
|
105
|
+
if (typeof value === 'number') {
|
|
106
|
+
// Use formatted text if available for better display
|
|
107
|
+
return cell.w || String(value);
|
|
108
|
+
}
|
|
109
|
+
return String(value);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Check if a number format string indicates a date format
|
|
113
|
+
*/
|
|
114
|
+
function isDateFormat(format) {
|
|
115
|
+
if (!format)
|
|
116
|
+
return false;
|
|
117
|
+
// Common date format patterns
|
|
118
|
+
const datePatterns = [
|
|
119
|
+
/[ymd]/i, // Contains y, m, or d
|
|
120
|
+
/\d{1,2}\/\d{1,2}/, // Contains date-like pattern
|
|
121
|
+
/mmm/i, // Month abbreviation
|
|
122
|
+
/ddd/i, // Day abbreviation
|
|
123
|
+
];
|
|
124
|
+
// Exclude time-only formats
|
|
125
|
+
const isTimeOnly = /^[hms:]+$/i.test(format.replace(/[[\]]/g, ''));
|
|
126
|
+
if (isTimeOnly)
|
|
127
|
+
return false;
|
|
128
|
+
return datePatterns.some(pattern => pattern.test(format));
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Check if a number format string indicates a currency format
|
|
132
|
+
*/
|
|
133
|
+
function isCurrencyFormat(format) {
|
|
134
|
+
if (!format)
|
|
135
|
+
return false;
|
|
136
|
+
// Common currency symbols and patterns
|
|
137
|
+
const currencyPatterns = [
|
|
138
|
+
/[$€£¥₹₽₩]/, // Currency symbols
|
|
139
|
+
/\[[$€£¥₹₽₩]/, // Currency in brackets
|
|
140
|
+
/"[$€£¥₹₽₩]"/, // Currency in quotes
|
|
141
|
+
];
|
|
142
|
+
return currencyPatterns.some(pattern => pattern.test(format));
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Convert Excel serial date number to JavaScript Date
|
|
146
|
+
*/
|
|
147
|
+
function excelSerialToDate(serial) {
|
|
148
|
+
// Excel's epoch is December 30, 1899
|
|
149
|
+
// But there's a bug where Excel thinks 1900 was a leap year
|
|
150
|
+
const excelEpoch = new Date(Date.UTC(1899, 11, 30));
|
|
151
|
+
const msPerDay = 24 * 60 * 60 * 1000;
|
|
152
|
+
// Adjust for Excel's leap year bug (dates after Feb 28, 1900)
|
|
153
|
+
const adjustedSerial = serial > 60 ? serial - 1 : serial;
|
|
154
|
+
return new Date(excelEpoch.getTime() + adjustedSerial * msPerDay);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Format a Date as ISO 8601 (Req 2.15)
|
|
158
|
+
* YYYY-MM-DD for dates, YYYY-MM-DD HH:MM:SS for datetimes
|
|
159
|
+
*/
|
|
160
|
+
function formatDateISO8601(date) {
|
|
161
|
+
const year = date.getUTCFullYear();
|
|
162
|
+
const month = String(date.getUTCMonth() + 1).padStart(2, '0');
|
|
163
|
+
const day = String(date.getUTCDate()).padStart(2, '0');
|
|
164
|
+
const hours = date.getUTCHours();
|
|
165
|
+
const minutes = date.getUTCMinutes();
|
|
166
|
+
const seconds = date.getUTCSeconds();
|
|
167
|
+
// If there's a time component, include it
|
|
168
|
+
if (hours !== 0 || minutes !== 0 || seconds !== 0) {
|
|
169
|
+
const h = String(hours).padStart(2, '0');
|
|
170
|
+
const m = String(minutes).padStart(2, '0');
|
|
171
|
+
const s = String(seconds).padStart(2, '0');
|
|
172
|
+
return `${year}-${month}-${day} ${h}:${m}:${s}`;
|
|
173
|
+
}
|
|
174
|
+
return `${year}-${month}-${day}`;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Escape HTML special characters
|
|
178
|
+
*/
|
|
179
|
+
function escapeHtml(str) {
|
|
180
|
+
return str
|
|
181
|
+
.replace(/&/g, '&')
|
|
182
|
+
.replace(/</g, '<')
|
|
183
|
+
.replace(/>/g, '>')
|
|
184
|
+
.replace(/"/g, '"')
|
|
185
|
+
.replace(/'/g, ''');
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Spreadsheet Adapter class
|
|
189
|
+
*
|
|
190
|
+
* Handles conversion of XLSX and CSV files to HTML using SheetJS.
|
|
191
|
+
* The HTML output is then processed through the ConversionEngine pipeline.
|
|
192
|
+
*/
|
|
193
|
+
export class SpreadsheetAdapter {
|
|
194
|
+
xlsx = null;
|
|
195
|
+
currentWorkbook = null;
|
|
196
|
+
/**
|
|
197
|
+
* Load the SheetJS library if not already loaded
|
|
198
|
+
*/
|
|
199
|
+
async ensureXlsxLoaded() {
|
|
200
|
+
if (!this.xlsx) {
|
|
201
|
+
this.xlsx = await loadLibrary('xlsx');
|
|
202
|
+
}
|
|
203
|
+
return this.xlsx;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Parse a spreadsheet file and convert it to HTML
|
|
207
|
+
*
|
|
208
|
+
* @param arrayBuffer - The file content as an ArrayBuffer
|
|
209
|
+
* @param format - The file format ('xlsx' or 'csv')
|
|
210
|
+
* @param sheetIndex - Optional sheet index to convert (default: 0)
|
|
211
|
+
* @returns Promise resolving to the parse result with HTML and metadata
|
|
212
|
+
* @throws SpreadsheetParseError if the file cannot be parsed
|
|
213
|
+
*/
|
|
214
|
+
async parseToHtml(arrayBuffer, format = 'xlsx', sheetIndex = 0) {
|
|
215
|
+
const xlsx = await this.ensureXlsxLoaded();
|
|
216
|
+
const warnings = [];
|
|
217
|
+
try {
|
|
218
|
+
// Parse the workbook with options for proper value handling
|
|
219
|
+
// cellDates: true - Parse dates as Date objects (Req 2.15)
|
|
220
|
+
// cellFormula: false - We want calculated values, not formulas (Req 2.8)
|
|
221
|
+
// cellNF: true - Preserve number formats for currency detection (Req 2.16)
|
|
222
|
+
this.currentWorkbook = xlsx.read(arrayBuffer, {
|
|
223
|
+
type: 'array',
|
|
224
|
+
cellDates: true,
|
|
225
|
+
cellFormula: false,
|
|
226
|
+
cellNF: true,
|
|
227
|
+
cellStyles: false,
|
|
228
|
+
});
|
|
229
|
+
// Format is used for future format-specific handling if needed
|
|
230
|
+
void format;
|
|
231
|
+
const workbook = this.currentWorkbook;
|
|
232
|
+
// Check for empty workbook
|
|
233
|
+
if (!workbook.SheetNames || workbook.SheetNames.length === 0) {
|
|
234
|
+
throw new SpreadsheetParseError('This spreadsheet appears to be empty.', 'EMPTY_FILE');
|
|
235
|
+
}
|
|
236
|
+
// Validate sheet index
|
|
237
|
+
const validSheetIndex = Math.min(Math.max(0, sheetIndex), workbook.SheetNames.length - 1);
|
|
238
|
+
if (validSheetIndex !== sheetIndex) {
|
|
239
|
+
warnings.push(`Sheet index ${sheetIndex} is out of range. Using sheet ${validSheetIndex + 1}.`);
|
|
240
|
+
}
|
|
241
|
+
// Get sheet info for all sheets
|
|
242
|
+
const sheets = workbook.SheetNames.map((name, idx) => {
|
|
243
|
+
const ws = workbook.Sheets[name];
|
|
244
|
+
const range = getWorksheetRange(ws);
|
|
245
|
+
return {
|
|
246
|
+
name: name || `Sheet ${idx + 1}`,
|
|
247
|
+
rowCount: range ? range.endRow - range.startRow + 1 : 0,
|
|
248
|
+
columnCount: range ? range.endCol - range.startCol + 1 : 0,
|
|
249
|
+
};
|
|
250
|
+
});
|
|
251
|
+
// Convert the selected sheet to HTML
|
|
252
|
+
const sheetName = workbook.SheetNames[validSheetIndex];
|
|
253
|
+
const worksheet = workbook.Sheets[sheetName];
|
|
254
|
+
const html = this.worksheetToHtml(worksheet, warnings);
|
|
255
|
+
return {
|
|
256
|
+
html,
|
|
257
|
+
sheets,
|
|
258
|
+
activeSheetIndex: validSheetIndex,
|
|
259
|
+
warnings,
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
catch (error) {
|
|
263
|
+
// Handle SpreadsheetParseError as-is
|
|
264
|
+
if (error instanceof SpreadsheetParseError) {
|
|
265
|
+
throw error;
|
|
266
|
+
}
|
|
267
|
+
// Handle specific SheetJS errors
|
|
268
|
+
const errorMessage = error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase();
|
|
269
|
+
if (errorMessage.includes('not a valid') ||
|
|
270
|
+
errorMessage.includes('unsupported') ||
|
|
271
|
+
errorMessage.includes('unrecognized')) {
|
|
272
|
+
throw new SpreadsheetParseError('This file does not appear to be a valid spreadsheet.', 'INVALID_FORMAT', error instanceof Error ? error : undefined);
|
|
273
|
+
}
|
|
274
|
+
if (errorMessage.includes('corrupted') ||
|
|
275
|
+
errorMessage.includes('invalid') ||
|
|
276
|
+
errorMessage.includes('unexpected') ||
|
|
277
|
+
errorMessage.includes('end of data') ||
|
|
278
|
+
errorMessage.includes('cfb')) {
|
|
279
|
+
throw new SpreadsheetParseError('Unable to read this spreadsheet. It may be corrupted or in an unsupported format.', 'CORRUPTED', error instanceof Error ? error : undefined);
|
|
280
|
+
}
|
|
281
|
+
// Generic parse error
|
|
282
|
+
throw new SpreadsheetParseError(`Failed to parse spreadsheet: ${error instanceof Error ? error.message : String(error)}`, 'PARSE_ERROR', error instanceof Error ? error : undefined);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Convert a worksheet to HTML table format
|
|
287
|
+
*
|
|
288
|
+
* Requirements:
|
|
289
|
+
* - 2.7: Handle merged cells by repeating content
|
|
290
|
+
* - 2.9: Preserve empty rows/columns in table structure
|
|
291
|
+
* - 2.14: Use pipe (|) syntax for Markdown tables (via HTML table)
|
|
292
|
+
*/
|
|
293
|
+
worksheetToHtml(ws, warnings) {
|
|
294
|
+
const range = getWorksheetRange(ws);
|
|
295
|
+
if (!range) {
|
|
296
|
+
return '<table><tr><td></td></tr></table>';
|
|
297
|
+
}
|
|
298
|
+
const { startRow, endRow, startCol, endCol } = range;
|
|
299
|
+
const colCount = endCol - startCol + 1;
|
|
300
|
+
// Warn about wide tables (Req 2.17)
|
|
301
|
+
if (colCount > 100) {
|
|
302
|
+
warnings.push('This spreadsheet has many columns and may be difficult to read in Markdown format.');
|
|
303
|
+
}
|
|
304
|
+
// Build merged cells map for content repetition (Req 2.7)
|
|
305
|
+
const mergedCells = this.buildMergedCellsMap(ws);
|
|
306
|
+
let html = '<table>\n';
|
|
307
|
+
for (let r = startRow; r <= endRow; r++) {
|
|
308
|
+
html += ' <tr>\n';
|
|
309
|
+
for (let c = startCol; c <= endCol; c++) {
|
|
310
|
+
const cellRef = colIndexToLetter(c) + (r + 1);
|
|
311
|
+
const cell = ws[cellRef];
|
|
312
|
+
// Check if this cell is part of a merged region
|
|
313
|
+
const mergedValue = mergedCells.get(cellRef);
|
|
314
|
+
// Get cell value - use merged value if available, otherwise format the cell
|
|
315
|
+
let value;
|
|
316
|
+
if (mergedValue !== undefined) {
|
|
317
|
+
value = mergedValue;
|
|
318
|
+
}
|
|
319
|
+
else {
|
|
320
|
+
value = formatCellValue(cell);
|
|
321
|
+
}
|
|
322
|
+
// Use th for first row (header), td for data rows
|
|
323
|
+
const tag = r === startRow ? 'th' : 'td';
|
|
324
|
+
html += ` <${tag}>${escapeHtml(value)}</${tag}>\n`;
|
|
325
|
+
}
|
|
326
|
+
html += ' </tr>\n';
|
|
327
|
+
}
|
|
328
|
+
html += '</table>';
|
|
329
|
+
return html;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Build a map of merged cells with their values repeated
|
|
333
|
+
*
|
|
334
|
+
* Requirement 2.7: Handle merged cells by repeating content
|
|
335
|
+
*/
|
|
336
|
+
buildMergedCellsMap(ws) {
|
|
337
|
+
const mergedMap = new Map();
|
|
338
|
+
const merges = ws['!merges'];
|
|
339
|
+
if (!merges || merges.length === 0) {
|
|
340
|
+
return mergedMap;
|
|
341
|
+
}
|
|
342
|
+
for (const merge of merges) {
|
|
343
|
+
// Get the value from the top-left cell of the merge
|
|
344
|
+
const topLeftRef = colIndexToLetter(merge.s.c) + (merge.s.r + 1);
|
|
345
|
+
const topLeftCell = ws[topLeftRef];
|
|
346
|
+
const value = formatCellValue(topLeftCell);
|
|
347
|
+
// Fill all cells in the merge range with the same value
|
|
348
|
+
for (let r = merge.s.r; r <= merge.e.r; r++) {
|
|
349
|
+
for (let c = merge.s.c; c <= merge.e.c; c++) {
|
|
350
|
+
const cellRef = colIndexToLetter(c) + (r + 1);
|
|
351
|
+
// Skip the top-left cell (it already has the value)
|
|
352
|
+
if (cellRef !== topLeftRef) {
|
|
353
|
+
mergedMap.set(cellRef, value);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
return mergedMap;
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Get the names of all sheets in the current workbook
|
|
362
|
+
*
|
|
363
|
+
* Requirement 2.4: Display sheet selector with sheet names
|
|
364
|
+
*/
|
|
365
|
+
getSheetNames() {
|
|
366
|
+
if (!this.currentWorkbook) {
|
|
367
|
+
return [];
|
|
368
|
+
}
|
|
369
|
+
return this.currentWorkbook.SheetNames.map((name, idx) => name || `Sheet ${idx + 1}`);
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Get the number of sheets in the current workbook
|
|
373
|
+
*/
|
|
374
|
+
getSheetCount() {
|
|
375
|
+
return this.currentWorkbook?.SheetNames.length || 0;
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Re-parse the current workbook with a different sheet selected
|
|
379
|
+
*
|
|
380
|
+
* Requirement 2.5: Re-convert when user selects different sheet
|
|
381
|
+
*/
|
|
382
|
+
async selectSheet(sheetIndex) {
|
|
383
|
+
if (!this.currentWorkbook) {
|
|
384
|
+
throw new SpreadsheetParseError('No workbook is currently loaded. Please upload a file first.', 'PARSE_ERROR');
|
|
385
|
+
}
|
|
386
|
+
const warnings = [];
|
|
387
|
+
const workbook = this.currentWorkbook;
|
|
388
|
+
// Validate sheet index
|
|
389
|
+
if (sheetIndex < 0 || sheetIndex >= workbook.SheetNames.length) {
|
|
390
|
+
throw new SpreadsheetParseError(`Invalid sheet index: ${sheetIndex}. Workbook has ${workbook.SheetNames.length} sheets.`, 'PARSE_ERROR');
|
|
391
|
+
}
|
|
392
|
+
// Get sheet info for all sheets
|
|
393
|
+
const sheets = workbook.SheetNames.map((name, idx) => {
|
|
394
|
+
const ws = workbook.Sheets[name];
|
|
395
|
+
const range = getWorksheetRange(ws);
|
|
396
|
+
return {
|
|
397
|
+
name: name || `Sheet ${idx + 1}`,
|
|
398
|
+
rowCount: range ? range.endRow - range.startRow + 1 : 0,
|
|
399
|
+
columnCount: range ? range.endCol - range.startCol + 1 : 0,
|
|
400
|
+
};
|
|
401
|
+
});
|
|
402
|
+
// Convert the selected sheet to HTML
|
|
403
|
+
const sheetName = workbook.SheetNames[sheetIndex];
|
|
404
|
+
const worksheet = workbook.Sheets[sheetName];
|
|
405
|
+
const html = this.worksheetToHtml(worksheet, warnings);
|
|
406
|
+
return {
|
|
407
|
+
html,
|
|
408
|
+
sheets,
|
|
409
|
+
activeSheetIndex: sheetIndex,
|
|
410
|
+
warnings,
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Clear the current workbook from memory
|
|
415
|
+
*/
|
|
416
|
+
clearWorkbook() {
|
|
417
|
+
this.currentWorkbook = null;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Singleton instance for convenience
|
|
422
|
+
*/
|
|
423
|
+
export const spreadsheetAdapter = new SpreadsheetAdapter();
|
|
424
|
+
//# sourceMappingURL=spreadsheet-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spreadsheet-adapter.js","sourceRoot":"","sources":["../../../../../../src/shared/adapters/spreadsheet-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atlassian-detector.d.ts","sourceRoot":"","sources":["../../../../../src/shared/atlassian-detector.ts"],"names":[],"mappings":"AAgBA;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGrD"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// src/shared/atlassian-detector.ts
|
|
2
|
+
// Detects Atlassian (Confluence/Jira) HTML by checking for known proprietary markers.
|
|
3
|
+
// See Design §5.1
|
|
4
|
+
const ATLASSIAN_MARKERS = [
|
|
5
|
+
'ac:structured-macro',
|
|
6
|
+
'ac:parameter',
|
|
7
|
+
'ac:rich-text-body',
|
|
8
|
+
'ac:plain-text-body',
|
|
9
|
+
'confluenceTable',
|
|
10
|
+
'confluence-information-macro',
|
|
11
|
+
'jira-macro',
|
|
12
|
+
'user-hover',
|
|
13
|
+
'jira-issue-macro',
|
|
14
|
+
];
|
|
15
|
+
/**
|
|
16
|
+
* Returns true if the given HTML string contains Atlassian (Confluence/Jira) markers.
|
|
17
|
+
* Detection is case-insensitive.
|
|
18
|
+
*/
|
|
19
|
+
export function isAtlassianHTML(html) {
|
|
20
|
+
const lower = html.toLowerCase();
|
|
21
|
+
return ATLASSIAN_MARKERS.some(marker => lower.includes(marker.toLowerCase()));
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=atlassian-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atlassian-detector.js","sourceRoot":"","sources":["../../../../../src/shared/atlassian-detector.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,sFAAsF;AACtF,kBAAkB;AAElB,MAAM,iBAAiB,GAAG;IACxB,qBAAqB;IACrB,cAAc;IACd,mBAAmB;IACnB,oBAAoB;IACpB,iBAAiB;IACjB,8BAA8B;IAC9B,YAAY;IACZ,YAAY;IACZ,kBAAkB;CACV,CAAC;AAEX;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACjC,OAAO,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;AAChF,CAAC"}
|