PLUGIN
Report4 Downloads
Converts Markdown table to Excel file.
Project Files
src / toolsProvider.ts
import { tool, Tool, ToolsProviderController } from "@lmstudio/sdk";
import { z } from "zod";
import fs from "fs";
import fsp from "fs/promises";
import { join } from "path";
import * as ExcelJS from "exceljs";
export async function toolsProvider(ctl: ToolsProviderController): Promise<Tool[]> {
const tools: Tool[] = [];
const excelTool = tool({
name: "GenerateExcel",
description:
"Convert Markdown table to Excel file.",
parameters: {
text: z.string().describe("Markdown table content to include in the Excel file"),
filename: z.string().optional().describe("Optional filename"),
},
implementation: async ({ text, filename }, { status, warn }) => {
try {
status("Generating Excel...");
const workingDir = ctl.getWorkingDirectory();
await fsp.mkdir(workingDir, { recursive: true });
const fileExists = (p: string) => {
try {
return fs.existsSync(p);
} catch {
return false;
}
};
const timestamp = Date.now();
let fileName = filename || `ai-output-${timestamp}.xlsx`;
// Ensure filename has .xlsx extension
if (filename && !filename.toLowerCase().endsWith('.xlsx')) {
fileName = `${filename}.xlsx`;
}
const filePath = join(workingDir, fileName);
// Parse markdown table and convert to Excel
const lines = text.split('\n').filter(line => line.trim() !== '');
const tableRows = lines.filter(line => line.includes('|'));
if (tableRows.length === 0) {
throw new Error("No table data found in the provided text");
}
// Parse table data and filter out separator rows (lines with dashes)
const data = tableRows
.filter(row => {
// Check if row is a separator (contains only dashes, spaces, and pipes)
const content = row.replace(/[\|\s]/g, ''); // Remove pipes and spaces
return !/^-+$/.test(content); // Filter out rows that are only dashes
})
.map(row =>
row.split('|').map(cell => cell.trim()).filter(cell => cell !== '')
);
if (data.length === 0) {
throw new Error("No valid table data found after filtering separators");
}
// Create workbook and worksheet
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet("Sheet1");
// Add data to worksheet
data.forEach((row, index) => {
worksheet.addRow(row);
// Style header row if it's the first row
if (index === 0) {
const headerRow = worksheet.getRow(1);
headerRow.eachCell((cell) => {
cell.font = { bold: true };
cell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FFE0E0E0' }
};
});
}
});
// Auto-fit columns
worksheet.columns.forEach(column => {
let maxLength = 0;
if (column.eachCell) {
column.eachCell({ includeEmpty: true }, (cell) => {
const cellValue = cell.value ? cell.value.toString() : '';
maxLength = Math.max(maxLength, cellValue.length);
});
}
column.width = Math.min(Math.max(maxLength + 2, 10), 50);
});
// Write file
await workbook.xlsx.writeFile(filePath);
status(`Excel saved as ${fileName}`);
return { filename: fileName, path: filePath };
} catch (err: any) {
console.error("Excel generation failed:", err);
warn(`Failed to generate Excel: ${err?.message ?? String(err)}`);
return { error: err?.message ?? String(err) };
}
},
});
tools.push(excelTool);
return tools;
}
src / toolsProvider.ts
import { tool, Tool, ToolsProviderController } from "@lmstudio/sdk";
import { z } from "zod";
import fs from "fs";
import fsp from "fs/promises";
import { join } from "path";
import * as ExcelJS from "exceljs";
export async function toolsProvider(ctl: ToolsProviderController): Promise<Tool[]> {
const tools: Tool[] = [];
const excelTool = tool({
name: "GenerateExcel",
description:
"Convert Markdown table to Excel file.",
parameters: {
text: z.string().describe("Markdown table content to include in the Excel file"),
filename: z.string().optional().describe("Optional filename"),
},
implementation: async ({ text, filename }, { status, warn }) => {
try {
status("Generating Excel...");
const workingDir = ctl.getWorkingDirectory();
await fsp.mkdir(workingDir, { recursive: true });
const fileExists = (p: string) => {
try {
return fs.existsSync(p);
} catch {
return false;
}
};
const timestamp = Date.now();
let fileName = filename || `ai-output-${timestamp}.xlsx`;
// Ensure filename has .xlsx extension
if (filename && !filename.toLowerCase().endsWith('.xlsx')) {
fileName = `${filename}.xlsx`;
}
const filePath = join(workingDir, fileName);
// Parse markdown table and convert to Excel
const lines = text.split('\n').filter(line => line.trim() !== '');
const tableRows = lines.filter(line => line.includes('|'));
if (tableRows.length === 0) {
throw new Error("No table data found in the provided text");
}
// Parse table data and filter out separator rows (lines with dashes)
const data = tableRows
.filter(row => {
// Check if row is a separator (contains only dashes, spaces, and pipes)
const content = row.replace(/[\|\s]/g, ''); // Remove pipes and spaces
return !/^-+$/.test(content); // Filter out rows that are only dashes
})
.map(row =>
row.split('|').map(cell => cell.trim()).filter(cell => cell !== '')
);
if (data.length === 0) {
throw new Error("No valid table data found after filtering separators");
}
// Create workbook and worksheet
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet("Sheet1");
// Add data to worksheet
data.forEach((row, index) => {
worksheet.addRow(row);
// Style header row if it's the first row
if (index === 0) {
const headerRow = worksheet.getRow(1);
headerRow.eachCell((cell) => {
cell.font = { bold: true };
cell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FFE0E0E0' }
};
});
}
});
// Auto-fit columns
worksheet.columns.forEach(column => {
let maxLength = 0;
if (column.eachCell) {
column.eachCell({ includeEmpty: true }, (cell) => {
const cellValue = cell.value ? cell.value.toString() : '';
maxLength = Math.max(maxLength, cellValue.length);
});
}
column.width = Math.min(Math.max(maxLength + 2, 10), 50);
});
// Write file
await workbook.xlsx.writeFile(filePath);
status(`Excel saved as ${fileName}`);
return { filename: fileName, path: filePath };
} catch (err: any) {
console.error("Excel generation failed:", err);
warn(`Failed to generate Excel: ${err?.message ?? String(err)}`);
return { error: err?.message ?? String(err) };
}
},
});
tools.push(excelTool);
return tools;
}