xlkit 1.0.5 → 1.2.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/engine/writer.ts","../src/engine/sheet-writer.ts","../src/styles/converter.ts","../src/styles/merger.ts","../src/styles/presets.ts","../src/types/text.ts","../src/types/workbook.ts","../src/types/column.ts","../src/utils/column.ts","../src/engine/cell-writer.ts","../src/engine/width-calculator.ts","../src/output/browser.ts","../src/output/node.ts","../src/validators/excel-constraints.ts","../src/schemas/image.ts","../src/schemas/table.ts","../src/schemas/column.ts","../src/schemas/style.ts","../src/schemas/text.ts","../src/core/sheet-builder.ts","../src/core/workbook-builder.ts","../src/reader/workbook-reader.ts","../src/reader/cell-reader.ts","../src/reader/sheet-reader.ts"],"sourcesContent":["// xlkit - Declarative Excel generation library\n\nexport { xlkit } from \"./core/workbook-builder\";\nexport type { CellBorder, CellReader } from \"./reader/cell-reader\";\nexport type { SheetReader } from \"./reader/sheet-reader\";\n// 読み取りAPI用の型\nexport type { WorkbookReader } from \"./reader/workbook-reader\";\nexport { read } from \"./reader/workbook-reader\";\nexport type { Column, LeafColumn, ParentColumn } from \"./types/column\";\nexport type { ImageOptions, ImageSource } from \"./types/image\";\n// 型定義をエクスポート(ユーザーが使用できるように)\nexport type { AlignType, BorderStyle, CellStyle, FormatType, LineStyle, TableStyle } from \"./types/style\";\nexport type { AutoWidthOption, TableOptions, TablePreset } from \"./types/table\";\nexport type { StyledCell, TextInput } from \"./types/text\";\nexport type { Block, BlockType, SheetState, WorkbookState } from \"./types/workbook\";\n","import ExcelJS from \"exceljs\";\nimport type { WorkbookState } from \"../types/workbook\";\nimport { SheetWriter } from \"./sheet-writer\";\n\n/**\n * ワークブックを書き込む\n * @param state ワークブック状態\n * @returns ExcelJSのWorkbookオブジェクト\n */\nexport async function writeWorkbook(state: WorkbookState): Promise<ExcelJS.Workbook> {\n const workbook = new ExcelJS.Workbook();\n\n for (const sheetState of state.sheets) {\n const worksheet = workbook.addWorksheet(sheetState.name);\n const writer = new SheetWriter(workbook, worksheet);\n writer.writeSheet(sheetState);\n }\n\n return workbook;\n}\n","import { readFileSync } from \"node:fs\";\nimport type { Workbook, Worksheet } from \"exceljs\";\nimport { createBodyCellBorder, createHeaderCellBorder } from \"../styles/converter\";\nimport { mergeStyles } from \"../styles/merger\";\nimport type { TablePresetConfig } from \"../styles/presets\";\nimport { getPreset } from \"../styles/presets\";\nimport type { Column, LeafColumn } from \"../types/column\";\nimport type { ImageOptions } from \"../types/image\";\nimport type { BorderStyle, CellStyle, TableStyle } from \"../types/style\";\nimport type { TableOptions } from \"../types/table\";\nimport type { TextInput } from \"../types/text\";\nimport { isStyledCell } from \"../types/text\";\nimport type { Block, SheetState } from \"../types/workbook\";\nimport { isImageBlock, isSpaceBlock, isTableBlock, isTextBlock } from \"../types/workbook\";\nimport { buildHeaderRows, flattenColumns, getHeaderDepth } from \"../utils/column\";\nimport { getOrCreateRow, mergeCells, writeCell } from \"./cell-writer\";\nimport { calculateColumnWidths } from \"./width-calculator\";\n\n/**\n * シートにブロックを書き込む\n */\nexport class SheetWriter {\n private workbook: Workbook;\n private worksheet: Worksheet;\n private currentRow: number;\n\n constructor(workbook: Workbook, worksheet: Worksheet) {\n this.workbook = workbook;\n this.worksheet = worksheet;\n this.currentRow = 1; // 1行目から開始(1-indexed)\n }\n\n /**\n * SheetStateを書き込む\n */\n writeSheet(sheetState: SheetState): void {\n for (const block of sheetState.blocks) {\n this.writeBlock(block);\n }\n }\n\n /**\n * ブロックを書き込む\n */\n private writeBlock(block: Block): void {\n if (isTableBlock(block)) {\n this.writeTable(block.options);\n } else if (isTextBlock(block)) {\n this.writeText(block.input);\n } else if (isImageBlock(block)) {\n this.writeImage(block.options);\n } else if (isSpaceBlock(block)) {\n this.writeSpace(block.lines);\n }\n }\n\n /**\n * テーブルを書き込む\n */\n private writeTable<T>(options: TableOptions<T>): void {\n const { preset, columns, data, autoWidth, style, border, mergeSameValues } = options;\n\n // プリセット取得\n const presetConfig = preset ? getPreset(preset) : undefined;\n\n // 罫線の優先度: options.border > presetConfig.border\n const effectiveBorder = border ?? presetConfig?.border;\n\n // リーフカラムをフラット化\n const leafColumns = flattenColumns(columns);\n\n // 列幅計算\n if (autoWidth !== false && autoWidth !== undefined) {\n this.setColumnWidths(leafColumns, data, autoWidth);\n }\n\n // ヘッダー書き込み(マルチヘッダー対応)\n const headerDepth = getHeaderDepth(columns);\n this.writeHeaders(columns, leafColumns, headerDepth, presetConfig, style, effectiveBorder);\n\n // データ行書き込み\n this.writeDataRows(leafColumns, data, presetConfig, style, effectiveBorder, mergeSameValues);\n }\n\n /**\n * ヘッダーを書き込む(マルチヘッダー対応)\n */\n private writeHeaders<T>(\n columns: Column<T>[],\n leafColumns: LeafColumn<T>[],\n depth: number,\n presetConfig: TablePresetConfig | undefined,\n tableStyle: TableStyle | undefined,\n borderStyle: BorderStyle | undefined,\n ): void {\n const headerRows = buildHeaderRows(columns, depth);\n const colCount = leafColumns.length;\n const startRow = this.currentRow;\n\n // 各ヘッダー行を書き込む\n for (let rowIndex = 0; rowIndex < headerRows.length; rowIndex++) {\n const headerRow = headerRows[rowIndex];\n const row = getOrCreateRow(this.worksheet, this.currentRow);\n\n let colPosition = 1; // 現在の列位置(1-indexed)\n\n for (const headerCell of headerRow) {\n const cell = row.getCell(colPosition);\n\n // スタイルのカスケーディング\n const finalStyle = mergeStyles(presetConfig?.style?.header, headerCell.style, tableStyle?.header);\n\n writeCell(cell, headerCell.label, finalStyle);\n\n // マージ処理\n if (headerCell.colSpan > 1 || headerCell.rowSpan > 1) {\n const endCol = colPosition + headerCell.colSpan - 1;\n const endRow = this.currentRow + headerCell.rowSpan - 1;\n mergeCells(this.worksheet, this.currentRow, colPosition, endRow, endCol);\n }\n\n // 罫線を適用(マージされたセルの左上に設定)\n const isLastHeaderRow = rowIndex === headerRows.length - 1;\n const border = createHeaderCellBorder(\n borderStyle,\n {\n isFirstCol: colPosition === 1,\n isLastCol: colPosition + headerCell.colSpan - 1 === colCount,\n isFirstRow: rowIndex === 0,\n },\n isLastHeaderRow && headerCell.rowSpan === 1,\n );\n if (border) {\n cell.border = border;\n }\n\n // 次の列位置に移動\n colPosition += headerCell.colSpan;\n }\n\n this.currentRow++;\n }\n\n // マージされたセルの罫線を補完(rowSpan > 1 のセルの下端)\n this.applyMergedCellBorders(headerRows, startRow, colCount, borderStyle);\n }\n\n /**\n * マージされたセルの罫線を補完\n */\n private applyMergedCellBorders(\n headerRows: ReturnType<typeof buildHeaderRows>,\n startRow: number,\n colCount: number,\n borderStyle: BorderStyle | undefined,\n ): void {\n const totalRows = headerRows.length;\n\n for (let rowIndex = 0; rowIndex < totalRows; rowIndex++) {\n const headerRow = headerRows[rowIndex];\n let colPosition = 1;\n\n for (const headerCell of headerRow) {\n // rowSpan > 1 のセルは、マージ範囲の最後の行に罫線を適用\n if (headerCell.rowSpan > 1) {\n const lastRowOfMerge = startRow + rowIndex + headerCell.rowSpan - 1;\n const isLastHeaderRow = lastRowOfMerge === startRow + totalRows - 1;\n\n // マージ範囲内の各列に罫線を設定(見える辺のみ)\n for (let col = colPosition; col < colPosition + headerCell.colSpan; col++) {\n const targetCell = this.worksheet.getCell(lastRowOfMerge, col);\n const border = createHeaderCellBorder(\n borderStyle,\n {\n isFirstCol: col === 1,\n isLastCol: col === colCount,\n isFirstRow: false, // マージ補完は常に2行目以降\n },\n isLastHeaderRow,\n );\n if (border) {\n // top は見えない辺なので削除(マージ範囲の内部)\n delete border.top;\n if (Object.keys(border).length > 0) {\n // 既存の罫線設定を保持しつつ、必要な辺のみ追加\n targetCell.border = { ...targetCell.border, ...border };\n }\n }\n }\n }\n\n colPosition += headerCell.colSpan;\n }\n }\n }\n\n /**\n * データ行を書き込む\n */\n private writeDataRows<T>(\n leafColumns: LeafColumn<T>[],\n data: (T & { _style?: Partial<Record<keyof T, CellStyle>> })[],\n presetConfig: TablePresetConfig | undefined,\n tableStyle: TableStyle | undefined,\n borderStyle: BorderStyle | undefined,\n tableMergeSameValues?: boolean,\n ): void {\n const dataLength = data.length;\n const colCount = leafColumns.length;\n const startRow = this.currentRow;\n\n // マージ範囲を記録: 各列ごとに { startRow, endRow, value } のリスト\n const mergeRanges: { colIndex: number; startRow: number; endRow: number }[][] = leafColumns.map(() => []);\n\n // 各列でマージが有効かどうかを判定\n const shouldMergeColumn = leafColumns.map((col) => tableMergeSameValues === true || col.mergeSameValues === true);\n\n // マージ範囲をトラッキングするための変数\n const currentMergeStart: number[] = leafColumns.map(() => 0);\n const currentMergeValue: unknown[] = leafColumns.map(() => undefined);\n\n for (const [rowIndex, rowData] of data.entries()) {\n const row = getOrCreateRow(this.worksheet, this.currentRow);\n\n for (let colIndex = 0; colIndex < colCount; colIndex++) {\n const col = leafColumns[colIndex];\n const cell = row.getCell(colIndex + 1);\n const value = rowData[col.key];\n\n // スタイルのカスケーディング\n const baseStyle = presetConfig?.style?.body;\n const columnStyle = col.style;\n const rowStyle = tableStyle?.body;\n const cellStyle = rowData._style?.[col.key];\n\n // ストライプ\n const isOddRow = rowIndex % 2 === 0;\n const stripeStyle =\n isOddRow && presetConfig?.stripedRowColor ? { fill: presetConfig.stripedRowColor } : undefined;\n\n const finalStyle = mergeStyles(baseStyle, stripeStyle, columnStyle, rowStyle, cellStyle);\n\n writeCell(cell, value, finalStyle);\n\n // 罫線を適用\n const border = createBodyCellBorder(borderStyle, {\n isFirstCol: colIndex === 0,\n isLastCol: colIndex === colCount - 1,\n isFirstRow: rowIndex === 0,\n isLastRow: rowIndex === dataLength - 1,\n });\n if (border) {\n cell.border = border;\n }\n\n // マージ範囲のトラッキング\n if (shouldMergeColumn[colIndex]) {\n if (rowIndex === 0) {\n // 最初の行:開始位置を記録\n currentMergeStart[colIndex] = rowIndex;\n currentMergeValue[colIndex] = value;\n } else if (value !== currentMergeValue[colIndex]) {\n // 値が変わった:前のマージ範囲を確定\n const start = currentMergeStart[colIndex];\n if (rowIndex - 1 > start) {\n mergeRanges[colIndex].push({\n colIndex,\n startRow: startRow + start,\n endRow: startRow + rowIndex - 1,\n });\n }\n // 新しいマージ範囲を開始\n currentMergeStart[colIndex] = rowIndex;\n currentMergeValue[colIndex] = value;\n }\n // 最後の行:現在のマージ範囲を確定\n if (rowIndex === dataLength - 1) {\n const start = currentMergeStart[colIndex];\n if (rowIndex > start) {\n mergeRanges[colIndex].push({\n colIndex,\n startRow: startRow + start,\n endRow: startRow + rowIndex,\n });\n }\n }\n }\n }\n\n this.currentRow++;\n }\n\n // マージを適用\n for (let colIndex = 0; colIndex < colCount; colIndex++) {\n for (const range of mergeRanges[colIndex]) {\n mergeCells(this.worksheet, range.startRow, colIndex + 1, range.endRow, colIndex + 1);\n }\n }\n\n // マージセルの罫線を補完\n this.applyBodyMergedCellBorders(mergeRanges, colCount, dataLength, startRow, borderStyle);\n }\n\n /**\n * ボディのマージセルの罫線を補完\n * マージ範囲内の各行に「見える辺のみ」罫線を設定\n */\n private applyBodyMergedCellBorders(\n mergeRanges: { colIndex: number; startRow: number; endRow: number }[][],\n colCount: number,\n dataLength: number,\n dataStartRow: number,\n borderStyle: BorderStyle | undefined,\n ): void {\n if (!borderStyle) return;\n\n for (let colIndex = 0; colIndex < colCount; colIndex++) {\n for (const range of mergeRanges[colIndex]) {\n // マージ範囲の各行に罫線を設定(見える辺のみ)\n for (let row = range.startRow; row <= range.endRow; row++) {\n const cell = this.worksheet.getCell(row, colIndex + 1);\n const isLastRow = row === dataStartRow + dataLength - 1;\n const isFirstRowOfMerge = row === range.startRow;\n const isLastRowOfMerge = row === range.endRow;\n\n const border = createBodyCellBorder(borderStyle, {\n isFirstCol: colIndex === 0,\n isLastCol: colIndex === colCount - 1,\n isFirstRow: row === dataStartRow,\n isLastRow: isLastRow,\n });\n\n if (border) {\n // マージ範囲内で見えない辺を削除\n if (!isFirstRowOfMerge) {\n delete border.top; // マージ範囲の最初の行以外は top が見えない\n }\n if (!isLastRowOfMerge) {\n delete border.bottom; // マージ範囲の最後の行以外は bottom が見えない\n }\n\n if (Object.keys(border).length > 0) {\n // 既存の罫線設定を保持しつつ、必要な辺のみ追加\n cell.border = { ...cell.border, ...border };\n }\n }\n }\n }\n }\n }\n\n /**\n * 列幅を設定\n */\n private setColumnWidths<T>(leafColumns: LeafColumn<T>[], data: T[], autoWidth: \"all\" | \"body\"): void {\n const rows: unknown[][] = [];\n\n // ヘッダー行\n if (autoWidth === \"all\") {\n rows.push(leafColumns.map((col) => col.label));\n }\n\n // データ行\n for (const rowData of data) {\n const row = leafColumns.map((col) => rowData[col.key]);\n rows.push(row);\n }\n\n // 幅を計算\n const widths = calculateColumnWidths(leafColumns.length, rows);\n\n // 列幅を設定\n for (let i = 0; i < widths.length; i++) {\n this.worksheet.getColumn(i + 1).width = widths[i];\n }\n }\n\n /**\n * テキストを書き込む\n */\n private writeText(input: TextInput): void {\n const row = getOrCreateRow(this.worksheet, this.currentRow);\n const cell = row.getCell(1);\n\n if (isStyledCell(input)) {\n writeCell(cell, input.value, input.style);\n } else {\n writeCell(cell, input);\n }\n\n this.currentRow++;\n }\n\n /**\n * 画像を書き込む\n */\n private writeImage(options: ImageOptions): void {\n const { source, width = 100, height = 100, row, col = 0 } = options;\n\n // 画像ソースの処理\n let imageBuffer: Buffer;\n if (Buffer.isBuffer(source)) {\n imageBuffer = source;\n } else {\n // ファイルパスとして読み込み\n imageBuffer = readFileSync(source);\n }\n\n // ExcelJSで画像追加(ExcelJSの型定義との互換性のためキャスト)\n const imageId = this.workbook.addImage({\n buffer: imageBuffer,\n extension: \"png\",\n } as unknown as Parameters<typeof this.workbook.addImage>[0]);\n\n // 配置位置(row指定がなければ現在行を使用)\n const targetRow = row ?? this.currentRow;\n\n this.worksheet.addImage(imageId, {\n tl: { col, row: targetRow - 1 }, // 0-indexedに変換\n ext: { width, height },\n });\n\n // 行位置の更新(画像の高さに応じて概算、約20pxで1行)\n const rowsToSkip = Math.ceil(height / 20);\n this.currentRow += rowsToSkip;\n }\n\n /**\n * 空行を追加\n */\n private writeSpace(lines: number): void {\n this.currentRow += lines;\n }\n}\n","import type { Alignment, Border, Borders, Fill, Font, Style } from \"exceljs\";\nimport type { BorderStyle, CellStyle, LineStyle } from \"../types/style\";\n\n/**\n * xlkitのCellStyleをExcelJSのStyleに変換\n */\nexport function convertToExcelJSStyle(style: CellStyle | undefined): Partial<Style> {\n if (!style) return {};\n\n const excelStyle: Partial<Style> = {};\n\n // フォント\n if (hasFont(style)) {\n excelStyle.font = convertFont(style);\n }\n\n // 塗りつぶし\n if (style.fill) {\n excelStyle.fill = convertFill(style.fill);\n }\n\n // 配置\n if (style.align) {\n excelStyle.alignment = convertAlignment(style.align);\n }\n\n // 数値フォーマット\n if (style.format) {\n excelStyle.numFmt = convertNumFmt(style);\n }\n\n return excelStyle;\n}\n\n/**\n * フォント関連のプロパティがあるかチェック\n */\nfunction hasFont(style: CellStyle): boolean {\n return !!(\n style.fontFamily ||\n style.fontSize ||\n style.bold ||\n style.italic ||\n style.underline ||\n style.strike ||\n style.color\n );\n}\n\n/**\n * フォントを変換\n */\nfunction convertFont(style: CellStyle): Partial<Font> {\n const font: Partial<Font> = {};\n\n if (style.fontFamily) font.name = style.fontFamily;\n if (style.fontSize) font.size = style.fontSize;\n if (style.bold) font.bold = true;\n if (style.italic) font.italic = true;\n if (style.underline) font.underline = true;\n if (style.strike) font.strike = true;\n\n if (style.color) {\n // #RRGGBB → ARGB形式に変換\n font.color = { argb: hexToArgb(style.color) };\n }\n\n return font;\n}\n\n/**\n * 塗りつぶしを変換\n */\nfunction convertFill(hexColor: string): Fill {\n return {\n type: \"pattern\",\n pattern: \"solid\",\n fgColor: { argb: hexToArgb(hexColor) },\n };\n}\n\n/**\n * 配置を変換\n */\nfunction convertAlignment(align: \"left\" | \"center\" | \"right\"): Partial<Alignment> {\n return {\n horizontal: align,\n vertical: \"middle\", // 垂直方向は常に中央\n };\n}\n\n/**\n * 数値フォーマットを変換\n */\nfunction convertNumFmt(style: CellStyle): string {\n if (style.format === \"date\") {\n return \"yyyy-mm-dd\"; // 日付フォーマット\n }\n\n if (style.format === \"number\") {\n const { decimalPlaces = 0, thousandsSeparator = false } = style;\n\n // 桁区切りカンマ\n const base = thousandsSeparator ? \"#,##0\" : \"#0\";\n\n // 小数点以下\n if (decimalPlaces > 0) {\n const decimals = \"0\".repeat(decimalPlaces);\n return `${base}.${decimals}`;\n }\n\n return base;\n }\n\n // \"string\" or 未指定\n return \"@\"; // テキスト形式\n}\n\n/**\n * #RRGGBB → AARRGGBB (ARGB形式) に変換\n * 不透明度は常に100% (FF)\n */\nfunction hexToArgb(hex: string): string {\n // \"#RRGGBB\" → \"FFRRGGBB\"\n return `FF${hex.slice(1).toUpperCase()}`;\n}\n\n/**\n * ARGB → #RRGGBB に変換(読み取りAPI用)\n */\nexport function argbToHex(argb: string): string {\n // \"FFRRGGBB\" → \"#RRGGBB\"\n return `#${argb.slice(2).toUpperCase()}`;\n}\n\n/**\n * ExcelJS Border オブジェクトを生成\n */\nfunction createBorder(style: LineStyle, color?: string): Partial<Border> {\n const border: Partial<Border> = { style };\n if (color) {\n border.color = { argb: hexToArgb(color) };\n }\n return border;\n}\n\n/**\n * ヘッダーセル用のボーダーを生成\n */\nexport function createHeaderCellBorder(\n border: BorderStyle | undefined,\n position: { isFirstCol: boolean; isLastCol: boolean; isFirstRow: boolean },\n isLastHeaderRow: boolean,\n): Partial<Borders> | undefined {\n if (!border) return undefined;\n\n const { outline, headerBody, headerInner, borderColor } = border;\n const borders: Partial<Borders> = {};\n\n // 上罫線(最初の行 → outline、それ以外 → headerInner)\n if (position.isFirstRow && outline) {\n borders.top = createBorder(outline, borderColor);\n } else if (!position.isFirstRow && headerInner) {\n borders.top = createBorder(headerInner, borderColor);\n }\n\n // 下罫線(最後のヘッダー行 → headerBody、それ以外 → headerInner)\n if (isLastHeaderRow && headerBody) {\n borders.bottom = createBorder(headerBody, borderColor);\n } else if (!isLastHeaderRow && headerInner) {\n borders.bottom = createBorder(headerInner, borderColor);\n }\n\n // 左罫線\n if (position.isFirstCol && outline) {\n borders.left = createBorder(outline, borderColor);\n } else if (!position.isFirstCol && headerInner) {\n borders.left = createBorder(headerInner, borderColor);\n }\n\n // 右罫線\n if (position.isLastCol && outline) {\n borders.right = createBorder(outline, borderColor);\n } else if (!position.isLastCol && headerInner) {\n borders.right = createBorder(headerInner, borderColor);\n }\n\n return Object.keys(borders).length > 0 ? borders : undefined;\n}\n\n/**\n * ボディセル用のボーダーを生成\n */\nexport function createBodyCellBorder(\n border: BorderStyle | undefined,\n position: { isFirstCol: boolean; isLastCol: boolean; isFirstRow: boolean; isLastRow: boolean },\n): Partial<Borders> | undefined {\n if (!border) return undefined;\n\n const { outline, bodyInner, borderColor } = border;\n const borders: Partial<Borders> = {};\n\n // 上罫線(最初の行はheaderBodyで対応済みなのでbodyInnerのみ)\n if (!position.isFirstRow && bodyInner) {\n borders.top = createBorder(bodyInner, borderColor);\n }\n\n // 下罫線\n if (position.isLastRow && outline) {\n borders.bottom = createBorder(outline, borderColor);\n } else if (!position.isLastRow && bodyInner) {\n borders.bottom = createBorder(bodyInner, borderColor);\n }\n\n // 左罫線\n if (position.isFirstCol && outline) {\n borders.left = createBorder(outline, borderColor);\n } else if (!position.isFirstCol && bodyInner) {\n borders.left = createBorder(bodyInner, borderColor);\n }\n\n // 右罫線\n if (position.isLastCol && outline) {\n borders.right = createBorder(outline, borderColor);\n } else if (!position.isLastCol && bodyInner) {\n borders.right = createBorder(bodyInner, borderColor);\n }\n\n return Object.keys(borders).length > 0 ? borders : undefined;\n}\n","import type { CellStyle } from \"../types/style\";\n\n/**\n * スタイルをマージする(後のスタイルが優先)\n */\nexport function mergeStyles(...styles: (CellStyle | undefined)[]): CellStyle {\n const merged: CellStyle = {};\n\n for (const style of styles) {\n if (!style) continue;\n\n // すべてのプロパティをマージ\n Object.assign(merged, style);\n }\n\n return merged;\n}\n\n/**\n * スタイル配列をディープコピー\n */\nexport function cloneStyle(style: CellStyle | undefined): CellStyle | undefined {\n if (!style) return undefined;\n return { ...style };\n}\n\n/**\n * 空のスタイルかチェック\n */\nexport function isEmptyStyle(style: CellStyle | undefined): boolean {\n if (!style) return true;\n return Object.keys(style).length === 0;\n}\n","import type { BorderStyle, TableStyle } from \"../types/style\";\n\n/**\n * テーブルプリセットの型定義\n */\nexport type TablePresetConfig = {\n style?: TableStyle;\n border?: BorderStyle;\n stripedRowColor?: string; // striped用の奇数行背景色\n};\n\n/**\n * プリセット定義\n */\nexport const TABLE_PRESETS: Record<string, TablePresetConfig> = {\n basic: {\n style: {\n header: {\n bold: true,\n fill: \"#4472C4\", // Excelの標準青\n color: \"#FFFFFF\", // 白文字\n align: \"center\",\n },\n body: {\n align: \"left\",\n },\n },\n border: {\n outline: \"thin\",\n headerBody: \"thin\",\n headerInner: \"thin\",\n bodyInner: \"thin\",\n },\n },\n\n minimal: {\n style: {\n header: {\n bold: true,\n align: \"left\",\n },\n body: {\n align: \"left\",\n },\n },\n // 罫線なし\n },\n\n striped: {\n style: {\n header: {\n bold: true,\n fill: \"#4472C4\",\n color: \"#FFFFFF\",\n align: \"center\",\n },\n body: {\n align: \"left\",\n },\n },\n border: {\n outline: \"thin\",\n headerBody: \"thin\",\n headerInner: \"thin\",\n bodyInner: \"thin\",\n },\n stripedRowColor: \"#F2F2F2\", // 奇数行の背景色(薄いグレー)\n },\n};\n\n/**\n * プリセット名からプリセット設定を取得\n */\nexport function getPreset(presetName: string): TablePresetConfig {\n const preset = TABLE_PRESETS[presetName];\n if (!preset) {\n throw new Error(`不明なプリセット名: ${presetName}`);\n }\n return preset;\n}\n\n/**\n * プリセットが存在するかチェック\n */\nexport function hasPreset(presetName: string): boolean {\n return presetName in TABLE_PRESETS;\n}\n","import type { CellStyle } from \"./style\";\n\n// スタイル付きセル\nexport type StyledCell = {\n value: string | number | boolean;\n style?: CellStyle;\n};\n\n// テキスト入力(文字列 or スタイル付きセル)\nexport type TextInput = string | StyledCell;\n\n// 型ガード関数\nexport function isStyledCell(input: TextInput): input is StyledCell {\n return typeof input === \"object\" && \"value\" in input;\n}\n","import type { ImageOptions } from \"./image\";\nimport type { TableOptions } from \"./table\";\nimport type { TextInput } from \"./text\";\n\n// ブロックの種類\nexport type BlockType = \"table\" | \"text\" | \"image\" | \"space\";\n\n// ブロック(Union型)\nexport type Block =\n | { type: \"table\"; options: TableOptions<Record<string, unknown>> }\n | { type: \"text\"; input: TextInput }\n | { type: \"image\"; options: ImageOptions }\n | { type: \"space\"; lines: number };\n\n// シートの状態\nexport type SheetState = {\n name: string;\n blocks: Block[];\n};\n\n// ワークブック全体の状態\nexport type WorkbookState = {\n sheets: SheetState[];\n};\n\n// 型ガード関数\nexport function isTableBlock(block: Block): block is { type: \"table\"; options: TableOptions<Record<string, unknown>> } {\n return block.type === \"table\";\n}\n\nexport function isTextBlock(block: Block): block is { type: \"text\"; input: TextInput } {\n return block.type === \"text\";\n}\n\nexport function isImageBlock(block: Block): block is { type: \"image\"; options: ImageOptions } {\n return block.type === \"image\";\n}\n\nexport function isSpaceBlock(block: Block): block is { type: \"space\"; lines: number } {\n return block.type === \"space\";\n}\n","import type { CellStyle } from \"./style\";\n\n// リーフカラム(末端のカラム、実際のデータを持つ)\nexport type LeafColumn<T> = {\n key: keyof T & string;\n label: string;\n style?: CellStyle;\n mergeSameValues?: boolean; // 同じ値を縦マージするか\n};\n\n// 親カラム(子カラムを持つ、マルチヘッダー用)\nexport type ParentColumn<T> = {\n label: string;\n children: Column<T>[]; // 再帰的な定義\n};\n\n// カラム型(Union型)\nexport type Column<T> = LeafColumn<T> | ParentColumn<T>;\n\n// 型ガード関数\nexport function isLeafColumn<T>(column: Column<T>): column is LeafColumn<T> {\n return \"key\" in column;\n}\n\nexport function isParentColumn<T>(column: Column<T>): column is ParentColumn<T> {\n return \"children\" in column;\n}\n","import type { Column, LeafColumn } from \"../types/column\";\nimport { isLeafColumn } from \"../types/column\";\nimport type { CellStyle } from \"../types/style\";\n\n/**\n * ヘッダーセルの情報(マージ情報を含む)\n */\nexport type HeaderCell = {\n label: string;\n colSpan: number; // 水平マージ\n rowSpan: number; // 垂直マージ\n style?: CellStyle;\n};\n\n/**\n * カラムツリーをフラット化(リーフカラムのみ抽出)\n */\nexport function flattenColumns<T>(columns: Column<T>[]): LeafColumn<T>[] {\n const result: LeafColumn<T>[] = [];\n\n for (const col of columns) {\n if (isLeafColumn(col)) {\n result.push(col);\n } else {\n result.push(...flattenColumns(col.children));\n }\n }\n\n return result;\n}\n\n/**\n * カラムの水平スパン(リーフ数)を計算\n */\nexport function getColumnSpan<T>(column: Column<T>): number {\n if (isLeafColumn(column)) {\n return 1;\n }\n return column.children.reduce((sum, child) => sum + getColumnSpan(child), 0);\n}\n\n/**\n * ヘッダーの深さを計算\n */\nexport function getHeaderDepth<T>(columns: Column<T>[]): number {\n let maxDepth = 1;\n for (const col of columns) {\n if (!isLeafColumn(col)) {\n const childDepth = getHeaderDepth(col.children);\n maxDepth = Math.max(maxDepth, childDepth + 1);\n }\n }\n return maxDepth;\n}\n\n/**\n * ヘッダー行ごとのセル情報を構築\n * @param columns カラム定義\n * @param totalDepth ヘッダーの総深さ\n * @returns 行ごとのHeaderCell配列\n */\nexport function buildHeaderRows<T>(columns: Column<T>[], totalDepth: number): HeaderCell[][] {\n const rows: HeaderCell[][] = Array.from({ length: totalDepth }, () => []);\n\n function processColumn(col: Column<T>, currentDepth: number): void {\n if (isLeafColumn(col)) {\n // リーフカラム: 残りの深さ分だけ縦にマージ\n const rowSpan = totalDepth - currentDepth;\n rows[currentDepth].push({\n label: col.label,\n colSpan: 1,\n rowSpan,\n style: col.style,\n });\n } else {\n // 親カラム: 子の数だけ横にマージ\n const colSpan = getColumnSpan(col);\n rows[currentDepth].push({\n label: col.label,\n colSpan,\n rowSpan: 1,\n style: undefined, // ParentColumnにはstyleがない\n });\n // 子カラムを次の深さで処理\n for (const child of col.children) {\n processColumn(child, currentDepth + 1);\n }\n }\n }\n\n for (const col of columns) {\n processColumn(col, 0);\n }\n\n return rows;\n}\n","import type { Cell, CellValue, Row, Worksheet } from \"exceljs\";\nimport { convertToExcelJSStyle } from \"../styles/converter\";\nimport type { CellStyle } from \"../types/style\";\n\n/**\n * セルに値とスタイルを設定\n */\nexport function writeCell(cell: Cell, value: unknown, style?: CellStyle): void {\n // 値を設定\n cell.value = value as CellValue;\n\n // スタイルを適用\n if (style) {\n const excelStyle = convertToExcelJSStyle(style);\n cell.style = excelStyle;\n }\n}\n\n/**\n * セル範囲をマージ\n * @param worksheet ワークシート\n * @param startRow 開始行(1-indexed)\n * @param startCol 開始列(1-indexed)\n * @param endRow 終了行(1-indexed)\n * @param endCol 終了列(1-indexed)\n */\nexport function mergeCells(\n worksheet: Worksheet,\n startRow: number,\n startCol: number,\n endRow: number,\n endCol: number,\n): void {\n worksheet.mergeCells(startRow, startCol, endRow, endCol);\n}\n\n/**\n * 行を作成して返す(存在する場合は既存の行を返す)\n */\nexport function getOrCreateRow(worksheet: Worksheet, rowNumber: number): Row {\n const row = worksheet.getRow(rowNumber);\n return row;\n}\n\n/**\n * セル参照(A1形式)を取得\n */\nexport function getCellAddress(row: number, col: number): string {\n const colLetter = numberToColumnLetter(col);\n return `${colLetter}${row}`;\n}\n\n/**\n * 列番号をA1形式の列名に変換(1 → A, 2 → B, ...)\n */\nfunction numberToColumnLetter(num: number): string {\n let letter = \"\";\n let n = num;\n\n while (n > 0) {\n const remainder = (n - 1) % 26;\n letter = String.fromCharCode(65 + remainder) + letter;\n n = Math.floor((n - 1) / 26);\n }\n\n return letter;\n}\n","/**\n * テキストの幅を計算(文字数ベース)\n * 全角文字: 2幅、半角文字: 1幅\n */\nexport function calculateTextWidth(text: string): number {\n let width = 0;\n\n for (const char of text) {\n const code = char.charCodeAt(0);\n\n // 全角文字の判定\n const isFullWidth =\n (code >= 0x3000 && code <= 0x9fff) || // CJK統合漢字、ひらがな、カタカナ\n (code >= 0xff00 && code <= 0xffef); // 全角英数字\n\n width += isFullWidth ? 2 : 1;\n }\n\n return width;\n}\n\n/**\n * 値から表示幅を計算(ExcelJS単位)\n */\nexport function calculateCellWidth(value: unknown): number {\n // null, undefined\n if (value == null) return 0;\n\n // 文字列\n if (typeof value === \"string\") {\n const textWidth = calculateTextWidth(value);\n // ExcelJSの列幅単位に変換(1文字 ≒ 1.2単位 + パディング)\n return textWidth * 1.2 + 2;\n }\n\n // 数値\n if (typeof value === \"number\") {\n const str = value.toString();\n return calculateTextWidth(str) * 1.2 + 2;\n }\n\n // 真偽値\n if (typeof value === \"boolean\") {\n return 6; // \"TRUE\" or \"FALSE\"\n }\n\n // その他\n return 10; // デフォルト幅\n}\n\n/**\n * 列ごとの最大幅を計算\n * @param columnCount 列数\n * @param rows 行データ配列\n */\nexport function calculateColumnWidths(columnCount: number, rows: unknown[][]): number[] {\n const widths = new Array(columnCount).fill(0);\n\n for (const row of rows) {\n for (let col = 0; col < columnCount; col++) {\n const cellValue = row[col];\n const width = calculateCellWidth(cellValue);\n\n // 最大幅を保持\n if (width > widths[col]) {\n widths[col] = width;\n }\n }\n }\n\n // 最小幅と最大幅を設定\n return widths.map((w) => Math.max(8, Math.min(w, 60)));\n}\n","import type ExcelJS from \"exceljs\";\n\nexport class BrowserOutput {\n constructor(private workbook: ExcelJS.Workbook) {}\n\n /**\n * ブラウザでダウンロード\n */\n async download(fileName: string): Promise<void> {\n const buffer = await this.workbook.xlsx.writeBuffer();\n const blob = new Blob([buffer], {\n type: \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n });\n\n const url = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = fileName;\n a.click();\n\n URL.revokeObjectURL(url);\n }\n}\n","import type ExcelJS from \"exceljs\";\n\nexport class NodeOutput {\n constructor(private workbook: ExcelJS.Workbook) {}\n\n /**\n * ファイルに保存\n */\n async saveToFile(filePath: string): Promise<void> {\n await this.workbook.xlsx.writeFile(filePath);\n }\n\n /**\n * Bufferとして取得\n */\n async toBuffer(): Promise<Buffer> {\n const buffer = await this.workbook.xlsx.writeBuffer();\n return Buffer.from(buffer);\n }\n}\n","// Excel制約の定数\nexport const EXCEL_LIMITS = {\n SHEET_NAME_MAX_LENGTH: 31,\n SHEET_NAME_INVALID_CHARS: [\":\", \"\\\\\", \"/\", \"?\", \"*\", \"[\", \"]\"],\n MAX_ROWS: 1_048_576,\n MAX_COLUMNS: 16_384,\n} as const;\n\n/**\n * シート名のバリデーション\n */\nexport function validateSheetName(name: string): void {\n // 文字数チェック\n if (name.length > EXCEL_LIMITS.SHEET_NAME_MAX_LENGTH) {\n throw new Error(\"シート名は31文字以内である必要があります\");\n }\n\n // 禁止文字チェック\n for (const char of EXCEL_LIMITS.SHEET_NAME_INVALID_CHARS) {\n if (name.includes(char)) {\n throw new Error(`シート名に使用できない文字が含まれています: ${char}`);\n }\n }\n\n // 空白のみチェック\n if (name.trim().length === 0) {\n throw new Error(\"シート名を空白のみにすることはできません\");\n }\n}\n\n/**\n * データサイズのバリデーション\n */\nexport function validateDataSize(rowCount: number, columnCount: number): void {\n if (rowCount > EXCEL_LIMITS.MAX_ROWS) {\n throw new Error(\"データ行数がExcelの上限(1,048,576行)を超えています\");\n }\n\n if (columnCount > EXCEL_LIMITS.MAX_COLUMNS) {\n throw new Error(\"列数がExcelの上限(16,384列)を超えています\");\n }\n}\n","import { z } from \"zod\";\n\n// ImageSource(Buffer or string)\nconst imageSourceSchema = z.union([\n z.instanceof(Buffer),\n z\n .string()\n .url(), // URL形式\n z\n .string()\n .min(1), // ファイルパス\n]);\n\n// ImageOptions\nexport const imageOptionsSchema = z\n .object({\n source: imageSourceSchema,\n width: z.number().positive().optional(),\n height: z.number().positive().optional(),\n row: z.number().int().min(0).optional(),\n col: z.number().int().min(0).optional(),\n })\n .strict();\n","import { z } from \"zod\";\nimport { columnsSchema } from \"./column\";\nimport { borderStyleSchema, tableStyleSchema } from \"./style\";\n\n// TablePreset\nconst tablePresetSchema = z.enum([\"basic\", \"minimal\", \"striped\"]);\n\n// AutoWidthOption\nconst autoWidthOptionSchema = z.union([z.enum([\"all\", \"body\"]), z.literal(false)]);\n\n// TableOptions(ジェネリック型を外す)\nexport const tableOptionsSchema = z\n .object({\n preset: tablePresetSchema.optional(),\n columns: columnsSchema,\n data: z.array(z.record(z.string(), z.any())),\n autoWidth: autoWidthOptionSchema.optional(),\n mergeSameValues: z.boolean().optional(),\n style: tableStyleSchema.optional(),\n border: borderStyleSchema.optional(),\n conditionalStyle: z.function().optional(),\n })\n .strict();\n","import { z } from \"zod\";\nimport { cellStyleSchema } from \"./style\";\n\n// LeafColumn(ジェネリック型パラメータを外す)\nconst leafColumnSchema = z\n .object({\n key: z.string(),\n label: z.string(),\n style: cellStyleSchema.optional(),\n mergeSameValues: z.boolean().optional(),\n })\n .strict();\n\n// 再帰型の定義\nexport type ColumnShape = {\n key?: string;\n label: string;\n children?: ColumnShape[];\n};\n\n// ParentColumn(再帰的な定義)\nconst parentColumnSchema: z.ZodType<{\n label: string;\n children: ColumnShape[];\n}> = z.lazy(() =>\n z\n .object({\n label: z.string(),\n children: z.array(columnSchema).nonempty(),\n })\n .strict(),\n);\n\n// Column(Union型)\nexport const columnSchema = z.union([leafColumnSchema, parentColumnSchema]);\n\n// 配列のバリデーション\nexport const columnsSchema = z.array(columnSchema).nonempty();\n","import { z } from \"zod\";\n\n// 色の16進数形式を検証\nconst hexColorRegex = /^#[\\dA-Fa-f]{6}$/;\n\nconst hexColorSchema = z.string().regex(hexColorRegex, \"色は #RRGGBB 形式で指定してください\");\n\n// AlignType\nconst alignTypeSchema = z.enum([\"left\", \"center\", \"right\"]);\n\n// FormatType\nconst formatTypeSchema = z.enum([\"string\", \"number\", \"date\"]);\n\n// CellStyle\nexport const cellStyleSchema = z\n .object({\n fontFamily: z.string().optional(),\n fontSize: z.number().positive().optional(),\n bold: z.boolean().optional(),\n italic: z.boolean().optional(),\n underline: z.boolean().optional(),\n strike: z.boolean().optional(),\n color: hexColorSchema.optional(),\n fill: hexColorSchema.optional(),\n align: alignTypeSchema.optional(),\n format: formatTypeSchema.optional(),\n decimalPlaces: z.number().int().min(0).optional(),\n thousandsSeparator: z.boolean().optional(),\n })\n .strict();\n\n// LineStyle\nconst lineStyleSchema = z.enum([\"thin\", \"medium\", \"thick\", \"dotted\", \"dashed\", \"double\"]);\n\n// BorderStyle\nexport const borderStyleSchema = z\n .object({\n outline: lineStyleSchema.optional(),\n headerBody: lineStyleSchema.optional(),\n headerInner: lineStyleSchema.optional(),\n bodyInner: lineStyleSchema.optional(),\n borderColor: hexColorSchema.optional(),\n })\n .strict();\n\n// TableStyle\nexport const tableStyleSchema = z\n .object({\n header: cellStyleSchema.optional(),\n body: cellStyleSchema.optional(),\n })\n .strict();\n","import { z } from \"zod\";\nimport { cellStyleSchema } from \"./style\";\n\n// StyledCell\nconst styledCellSchema = z\n .object({\n value: z.union([z.string(), z.number(), z.boolean()]),\n style: cellStyleSchema.optional(),\n })\n .strict();\n\n// TextInput(Union型)\nexport const textInputSchema = z.union([z.string(), styledCellSchema]);\n","import { imageOptionsSchema } from \"../schemas/image\";\nimport { tableOptionsSchema } from \"../schemas/table\";\nimport { textInputSchema } from \"../schemas/text\";\nimport type { ImageOptions } from \"../types/image\";\nimport type { TableOptions } from \"../types/table\";\nimport type { TextInput } from \"../types/text\";\nimport type { Block, SheetState } from \"../types/workbook\";\nimport { flattenColumns } from \"../utils/column\";\nimport { validateDataSize } from \"../validators/excel-constraints\";\nimport type { WorkbookBuilder } from \"./workbook-builder\";\n\nexport class SheetBuilder {\n private workbook: WorkbookBuilder;\n private sheetState: SheetState;\n\n constructor(workbook: WorkbookBuilder, sheetState: SheetState) {\n this.workbook = workbook;\n this.sheetState = sheetState;\n }\n\n /**\n * テーブルを追加\n */\n table<T>(options: TableOptions<T>): this {\n // バリデーション\n const result = tableOptionsSchema.safeParse(options);\n if (!result.success) {\n throw new Error(`Invalid table options: ${result.error.message}`);\n }\n\n // データサイズのExcel制約チェック\n const leafColumns = flattenColumns(options.columns);\n validateDataSize(options.data.length, leafColumns.length);\n\n // ブロックを追加\n const block: Block = { type: \"table\", options: options as TableOptions<Record<string, unknown>> };\n this.sheetState.blocks.push(block);\n\n return this;\n }\n\n /**\n * テキストを追加\n */\n text(input: TextInput): this {\n // バリデーション\n const result = textInputSchema.safeParse(input);\n if (!result.success) {\n throw new Error(`Invalid text input: ${result.error.message}`);\n }\n\n // ブロックを追加\n const block: Block = { type: \"text\", input };\n this.sheetState.blocks.push(block);\n\n return this;\n }\n\n /**\n * 画像を追加\n */\n image(options: ImageOptions): this {\n // バリデーション\n const result = imageOptionsSchema.safeParse(options);\n if (!result.success) {\n throw new Error(`Invalid image options: ${result.error.message}`);\n }\n\n // ブロックを追加\n const block: Block = { type: \"image\", options };\n this.sheetState.blocks.push(block);\n\n return this;\n }\n\n /**\n * 空行を追加\n */\n space(lines = 1): this {\n // バリデーション\n if (lines <= 0) {\n throw new Error(\"space() の引数は正の整数である必要があります\");\n }\n\n // ブロックを追加\n const block: Block = { type: \"space\", lines };\n this.sheetState.blocks.push(block);\n\n return this;\n }\n\n /**\n * 新しいシートを追加(WorkbookBuilderに委譲)\n */\n sheet(name?: string): SheetBuilder {\n return this.workbook.sheet(name);\n }\n\n /**\n * ブラウザ向け出力オブジェクトを取得(WorkbookBuilderに委譲)\n */\n getBrowser() {\n return this.workbook.getBrowser();\n }\n\n /**\n * Node.js向け出力オブジェクトを取得(WorkbookBuilderに委譲)\n */\n getNode() {\n return this.workbook.getNode();\n }\n}\n","import { writeWorkbook } from \"../engine/writer\";\nimport { BrowserOutput } from \"../output/browser\";\nimport { NodeOutput } from \"../output/node\";\nimport type { WorkbookState } from \"../types/workbook\";\nimport { validateSheetName } from \"../validators/excel-constraints\";\nimport { SheetBuilder } from \"./sheet-builder\";\n\nexport class WorkbookBuilder {\n private state: WorkbookState;\n\n constructor() {\n this.state = {\n sheets: [],\n };\n }\n\n /**\n * シートを追加する\n * @param name シート名(省略時は \"Sheet1\", \"Sheet2\", ...)\n */\n sheet(name?: string): SheetBuilder {\n // シート名が省略された場合、自動生成\n const sheetName = name ?? `Sheet${this.state.sheets.length + 1}`;\n\n // シート名のExcel制約チェック\n validateSheetName(sheetName);\n\n // 既存のシート名と重複チェック\n if (this.state.sheets.some((s) => s.name === sheetName)) {\n throw new Error(`シート名 \"${sheetName}\" は既に存在します`);\n }\n\n // 新しいシートを追加\n const sheetState = { name: sheetName, blocks: [] };\n this.state.sheets.push(sheetState);\n\n // SheetBuilder を返す(このワークブックの状態を共有)\n return new SheetBuilder(this, sheetState);\n }\n\n /**\n * ワークブックの状態を取得(内部用)\n */\n getState(): WorkbookState {\n return this.state;\n }\n\n /**\n * ブラウザ向け出力オブジェクトを取得\n */\n async getBrowser(): Promise<BrowserOutput> {\n const workbook = await writeWorkbook(this.state);\n return new BrowserOutput(workbook);\n }\n\n /**\n * Node.js向け出力オブジェクトを取得\n */\n async getNode(): Promise<NodeOutput> {\n const workbook = await writeWorkbook(this.state);\n return new NodeOutput(workbook);\n }\n}\n\n/**\n * xlkit ファクトリ関数\n */\nexport function xlkit(): WorkbookBuilder {\n return new WorkbookBuilder();\n}\n","import ExcelJS from \"exceljs\";\nimport { SheetReader } from \"./sheet-reader\";\n\n/**\n * ワークブックの読み取り\n */\nexport class WorkbookReader {\n constructor(private workbook: ExcelJS.Workbook) {}\n\n /**\n * シート名の配列を取得\n */\n get sheetNames(): string[] {\n return this.workbook.worksheets.map((ws) => ws.name);\n }\n\n /**\n * シートを取得(名前指定)\n */\n sheet(name: string): SheetReader {\n const worksheet = this.workbook.getWorksheet(name);\n if (!worksheet) {\n throw new Error(`シート \"${name}\" が見つかりません`);\n }\n return new SheetReader(worksheet);\n }\n\n /**\n * シートを取得(インデックス指定、0-indexed)\n */\n sheetAt(index: number): SheetReader {\n const worksheet = this.workbook.worksheets[index];\n if (!worksheet) {\n throw new Error(`インデックス ${index} のシートが見つかりません`);\n }\n return new SheetReader(worksheet);\n }\n\n /**\n * シート数を取得\n */\n get sheetCount(): number {\n return this.workbook.worksheets.length;\n }\n}\n\n/**\n * Excelファイルを読み取る\n */\nexport async function read(source: Buffer | string): Promise<WorkbookReader> {\n const workbook = new ExcelJS.Workbook();\n\n if (Buffer.isBuffer(source)) {\n // Bufferから読み取り\n // @ts-expect-error Node.js Buffer<ArrayBufferLike>とExcelJSのBuffer型に互換性問題\n await workbook.xlsx.load(source);\n } else {\n // ファイルパスから読み取り\n await workbook.xlsx.readFile(source);\n }\n\n return new WorkbookReader(workbook);\n}\n","import type { Cell } from \"exceljs\";\nimport { argbToHex } from \"../styles/converter\";\nimport type { CellStyle, LineStyle } from \"../types/style\";\n\n/**\n * セルの値とスタイルを保持\n */\nexport class CellReader {\n constructor(private cell: Cell) {}\n\n /**\n * セルの値を取得\n */\n get value(): string | number | boolean | null {\n const val = this.cell.value;\n\n // リッチテキストの場合\n if (val && typeof val === \"object\" && \"richText\" in val) {\n return val.richText.map((rt: { text: string }) => rt.text).join(\"\");\n }\n\n // 数式の場合(結果を返す)\n if (val && typeof val === \"object\" && \"result\" in val) {\n const result = val.result;\n if (typeof result === \"string\" || typeof result === \"number\" || typeof result === \"boolean\") {\n return result;\n }\n return null;\n }\n\n // プリミティブ値\n if (typeof val === \"string\" || typeof val === \"number\" || typeof val === \"boolean\") {\n return val;\n }\n\n return null;\n }\n\n /**\n * セルのスタイルを取得\n */\n get style(): CellStyle | undefined {\n const cellStyle = this.cell.style;\n if (!cellStyle) return undefined;\n\n const xlkitStyle: CellStyle = {};\n\n // フォント\n if (cellStyle.font) {\n if (cellStyle.font.name) xlkitStyle.fontFamily = cellStyle.font.name;\n if (cellStyle.font.size) xlkitStyle.fontSize = cellStyle.font.size;\n if (cellStyle.font.bold) xlkitStyle.bold = true;\n if (cellStyle.font.italic) xlkitStyle.italic = true;\n if (cellStyle.font.underline) xlkitStyle.underline = true;\n if (cellStyle.font.strike) xlkitStyle.strike = true;\n\n // 色\n if (cellStyle.font.color?.argb) {\n xlkitStyle.color = argbToHex(cellStyle.font.color.argb);\n }\n }\n\n // 塗りつぶし\n if (cellStyle.fill?.type === \"pattern\" && cellStyle.fill.fgColor?.argb) {\n xlkitStyle.fill = argbToHex(cellStyle.fill.fgColor.argb);\n }\n\n // 配置\n if (cellStyle.alignment?.horizontal) {\n const align = cellStyle.alignment.horizontal;\n if (align === \"left\" || align === \"center\" || align === \"right\") {\n xlkitStyle.align = align;\n }\n }\n\n // 数値フォーマット\n if (cellStyle.numFmt) {\n xlkitStyle.format = this.detectFormat(cellStyle.numFmt);\n\n // 小数点以下の桁数を検出\n if (xlkitStyle.format === \"number\") {\n const match = cellStyle.numFmt.match(/\\.(\\d+)/);\n if (match) {\n xlkitStyle.decimalPlaces = match[1].length;\n }\n\n // 桁区切りカンマ\n if (cellStyle.numFmt.includes(\",\")) {\n xlkitStyle.thousandsSeparator = true;\n }\n }\n }\n\n return Object.keys(xlkitStyle).length > 0 ? xlkitStyle : undefined;\n }\n\n /**\n * 数値フォーマットから format を検出\n */\n private detectFormat(numFmt: string): \"string\" | \"number\" | \"date\" | undefined {\n if (numFmt === \"@\") return \"string\";\n if (numFmt.includes(\"yyyy\") || numFmt.includes(\"mm\") || numFmt.includes(\"dd\")) {\n return \"date\";\n }\n if (numFmt.includes(\"#\") || numFmt.includes(\"0\")) {\n return \"number\";\n }\n return undefined;\n }\n\n /**\n * セルの罫線情報を取得\n */\n get border(): CellBorder | undefined {\n const cellBorder = this.cell.border;\n if (!cellBorder) return undefined;\n\n const result: CellBorder = {};\n\n if (cellBorder.top?.style) {\n result.top = {\n style: cellBorder.top.style as LineStyle,\n color: cellBorder.top.color?.argb ? argbToHex(cellBorder.top.color.argb) : undefined,\n };\n }\n if (cellBorder.bottom?.style) {\n result.bottom = {\n style: cellBorder.bottom.style as LineStyle,\n color: cellBorder.bottom.color?.argb ? argbToHex(cellBorder.bottom.color.argb) : undefined,\n };\n }\n if (cellBorder.left?.style) {\n result.left = {\n style: cellBorder.left.style as LineStyle,\n color: cellBorder.left.color?.argb ? argbToHex(cellBorder.left.color.argb) : undefined,\n };\n }\n if (cellBorder.right?.style) {\n result.right = {\n style: cellBorder.right.style as LineStyle,\n color: cellBorder.right.color?.argb ? argbToHex(cellBorder.right.color.argb) : undefined,\n };\n }\n\n return Object.keys(result).length > 0 ? result : undefined;\n }\n}\n\n/**\n * セルの罫線情報\n */\nexport type CellBorder = {\n top?: { style: LineStyle; color?: string };\n bottom?: { style: LineStyle; color?: string };\n left?: { style: LineStyle; color?: string };\n right?: { style: LineStyle; color?: string };\n};\n","import type { Worksheet } from \"exceljs\";\nimport { CellReader } from \"./cell-reader\";\n\n/**\n * シートの読み取り\n */\nexport class SheetReader {\n constructor(private worksheet: Worksheet) {}\n\n /**\n * シート名を取得\n */\n get name(): string {\n return this.worksheet.name;\n }\n\n /**\n * セルを取得(A1形式)\n */\n cell(address: string): CellReader {\n const cell = this.worksheet.getCell(address);\n return new CellReader(cell);\n }\n\n /**\n * セルを取得(行・列番号)\n */\n cellAt(row: number, col: number): CellReader {\n const cell = this.worksheet.getCell(row, col);\n return new CellReader(cell);\n }\n\n /**\n * マージされたセル範囲を取得\n */\n get mergedCells(): string[] {\n // ExcelJSは \"A1:B2\" 形式の配列を返す\n // Note: modelは内部プロパティのため型定義にない\n const model = (this.worksheet as unknown as { model?: { merges?: string[] } }).model;\n return model?.merges || [];\n }\n\n /**\n * 行数を取得\n */\n get rowCount(): number {\n return this.worksheet.rowCount;\n }\n\n /**\n * 列数を取得\n */\n get columnCount(): number {\n return this.worksheet.columnCount;\n }\n}\n"],"mappings":"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","names":["ExcelJS","import_zod","import_zod","import_zod","import_zod","import_exceljs","ExcelJS"]}
@@ -0,0 +1,283 @@
1
+ import ExcelJS, { Cell, Worksheet } from 'exceljs';
2
+
3
+ declare class BrowserOutput {
4
+ private workbook;
5
+ constructor(workbook: ExcelJS.Workbook);
6
+ /**
7
+ * ブラウザでダウンロード
8
+ */
9
+ download(fileName: string): Promise<void>;
10
+ }
11
+
12
+ declare class NodeOutput {
13
+ private workbook;
14
+ constructor(workbook: ExcelJS.Workbook);
15
+ /**
16
+ * ファイルに保存
17
+ */
18
+ saveToFile(filePath: string): Promise<void>;
19
+ /**
20
+ * Bufferとして取得
21
+ */
22
+ toBuffer(): Promise<Buffer>;
23
+ }
24
+
25
+ type ImageSource = Buffer | string;
26
+ type ImageOptions = {
27
+ source: ImageSource;
28
+ width?: number;
29
+ height?: number;
30
+ row?: number;
31
+ col?: number;
32
+ };
33
+
34
+ type AlignType = "left" | "center" | "right";
35
+ type FormatType = "string" | "number" | "date";
36
+ type CellStyle = {
37
+ fontFamily?: string;
38
+ fontSize?: number;
39
+ bold?: boolean;
40
+ italic?: boolean;
41
+ underline?: boolean;
42
+ strike?: boolean;
43
+ color?: string;
44
+ fill?: string;
45
+ align?: AlignType;
46
+ format?: FormatType;
47
+ decimalPlaces?: number;
48
+ thousandsSeparator?: boolean;
49
+ };
50
+ type LineStyle = "thin" | "medium" | "thick" | "dotted" | "dashed" | "double";
51
+ type BorderStyle = {
52
+ outline?: LineStyle;
53
+ headerBody?: LineStyle;
54
+ headerInner?: LineStyle;
55
+ bodyInner?: LineStyle;
56
+ borderColor?: string;
57
+ };
58
+ type TableStyle = {
59
+ header?: CellStyle;
60
+ body?: CellStyle;
61
+ };
62
+
63
+ type LeafColumn<T> = {
64
+ key: keyof T & string;
65
+ label: string;
66
+ style?: CellStyle;
67
+ mergeSameValues?: boolean;
68
+ };
69
+ type ParentColumn<T> = {
70
+ label: string;
71
+ children: Column<T>[];
72
+ };
73
+ type Column<T> = LeafColumn<T> | ParentColumn<T>;
74
+
75
+ type TablePreset = "basic" | "minimal" | "striped";
76
+ type AutoWidthOption = "all" | "body" | false;
77
+ type TableOptions<T> = {
78
+ preset?: TablePreset;
79
+ columns: Column<T>[];
80
+ data: (T & {
81
+ _style?: Partial<Record<keyof T, CellStyle>>;
82
+ })[];
83
+ autoWidth?: AutoWidthOption;
84
+ mergeSameValues?: boolean;
85
+ style?: TableStyle;
86
+ border?: BorderStyle;
87
+ conditionalStyle?: (row: T, col: keyof T) => CellStyle | Record<string, never>;
88
+ };
89
+
90
+ type StyledCell = {
91
+ value: string | number | boolean;
92
+ style?: CellStyle;
93
+ };
94
+ type TextInput = string | StyledCell;
95
+
96
+ type BlockType = "table" | "text" | "image" | "space";
97
+ type Block = {
98
+ type: "table";
99
+ options: TableOptions<Record<string, unknown>>;
100
+ } | {
101
+ type: "text";
102
+ input: TextInput;
103
+ } | {
104
+ type: "image";
105
+ options: ImageOptions;
106
+ } | {
107
+ type: "space";
108
+ lines: number;
109
+ };
110
+ type SheetState = {
111
+ name: string;
112
+ blocks: Block[];
113
+ };
114
+ type WorkbookState = {
115
+ sheets: SheetState[];
116
+ };
117
+
118
+ declare class SheetBuilder {
119
+ private workbook;
120
+ private sheetState;
121
+ constructor(workbook: WorkbookBuilder, sheetState: SheetState);
122
+ /**
123
+ * テーブルを追加
124
+ */
125
+ table<T>(options: TableOptions<T>): this;
126
+ /**
127
+ * テキストを追加
128
+ */
129
+ text(input: TextInput): this;
130
+ /**
131
+ * 画像を追加
132
+ */
133
+ image(options: ImageOptions): this;
134
+ /**
135
+ * 空行を追加
136
+ */
137
+ space(lines?: number): this;
138
+ /**
139
+ * 新しいシートを追加(WorkbookBuilderに委譲)
140
+ */
141
+ sheet(name?: string): SheetBuilder;
142
+ /**
143
+ * ブラウザ向け出力オブジェクトを取得(WorkbookBuilderに委譲)
144
+ */
145
+ getBrowser(): Promise<BrowserOutput>;
146
+ /**
147
+ * Node.js向け出力オブジェクトを取得(WorkbookBuilderに委譲)
148
+ */
149
+ getNode(): Promise<NodeOutput>;
150
+ }
151
+
152
+ declare class WorkbookBuilder {
153
+ private state;
154
+ constructor();
155
+ /**
156
+ * シートを追加する
157
+ * @param name シート名(省略時は "Sheet1", "Sheet2", ...)
158
+ */
159
+ sheet(name?: string): SheetBuilder;
160
+ /**
161
+ * ワークブックの状態を取得(内部用)
162
+ */
163
+ getState(): WorkbookState;
164
+ /**
165
+ * ブラウザ向け出力オブジェクトを取得
166
+ */
167
+ getBrowser(): Promise<BrowserOutput>;
168
+ /**
169
+ * Node.js向け出力オブジェクトを取得
170
+ */
171
+ getNode(): Promise<NodeOutput>;
172
+ }
173
+ /**
174
+ * xlkit ファクトリ関数
175
+ */
176
+ declare function xlkit(): WorkbookBuilder;
177
+
178
+ /**
179
+ * セルの値とスタイルを保持
180
+ */
181
+ declare class CellReader {
182
+ private cell;
183
+ constructor(cell: Cell);
184
+ /**
185
+ * セルの値を取得
186
+ */
187
+ get value(): string | number | boolean | null;
188
+ /**
189
+ * セルのスタイルを取得
190
+ */
191
+ get style(): CellStyle | undefined;
192
+ /**
193
+ * 数値フォーマットから format を検出
194
+ */
195
+ private detectFormat;
196
+ /**
197
+ * セルの罫線情報を取得
198
+ */
199
+ get border(): CellBorder | undefined;
200
+ }
201
+ /**
202
+ * セルの罫線情報
203
+ */
204
+ type CellBorder = {
205
+ top?: {
206
+ style: LineStyle;
207
+ color?: string;
208
+ };
209
+ bottom?: {
210
+ style: LineStyle;
211
+ color?: string;
212
+ };
213
+ left?: {
214
+ style: LineStyle;
215
+ color?: string;
216
+ };
217
+ right?: {
218
+ style: LineStyle;
219
+ color?: string;
220
+ };
221
+ };
222
+
223
+ /**
224
+ * シートの読み取り
225
+ */
226
+ declare class SheetReader {
227
+ private worksheet;
228
+ constructor(worksheet: Worksheet);
229
+ /**
230
+ * シート名を取得
231
+ */
232
+ get name(): string;
233
+ /**
234
+ * セルを取得(A1形式)
235
+ */
236
+ cell(address: string): CellReader;
237
+ /**
238
+ * セルを取得(行・列番号)
239
+ */
240
+ cellAt(row: number, col: number): CellReader;
241
+ /**
242
+ * マージされたセル範囲を取得
243
+ */
244
+ get mergedCells(): string[];
245
+ /**
246
+ * 行数を取得
247
+ */
248
+ get rowCount(): number;
249
+ /**
250
+ * 列数を取得
251
+ */
252
+ get columnCount(): number;
253
+ }
254
+
255
+ /**
256
+ * ワークブックの読み取り
257
+ */
258
+ declare class WorkbookReader {
259
+ private workbook;
260
+ constructor(workbook: ExcelJS.Workbook);
261
+ /**
262
+ * シート名の配列を取得
263
+ */
264
+ get sheetNames(): string[];
265
+ /**
266
+ * シートを取得(名前指定)
267
+ */
268
+ sheet(name: string): SheetReader;
269
+ /**
270
+ * シートを取得(インデックス指定、0-indexed)
271
+ */
272
+ sheetAt(index: number): SheetReader;
273
+ /**
274
+ * シート数を取得
275
+ */
276
+ get sheetCount(): number;
277
+ }
278
+ /**
279
+ * Excelファイルを読み取る
280
+ */
281
+ declare function read(source: Buffer | string): Promise<WorkbookReader>;
282
+
283
+ export { type AlignType, type AutoWidthOption, type Block, type BlockType, type BorderStyle, type CellBorder, CellReader, type CellStyle, type Column, type FormatType, type ImageOptions, type ImageSource, type LeafColumn, type LineStyle, type ParentColumn, SheetReader, type SheetState, type StyledCell, type TableOptions, type TablePreset, type TableStyle, type TextInput, WorkbookReader, type WorkbookState, read, xlkit };