Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: export as markdown #245

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 42 additions & 2 deletions src/components/molecules/RunContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ export const RunContent = ({ row, currentLog, interpretationInProgress, logEndRe
}
}, [row.serializableOutput]);


// Function to convert table data to CSV format
const convertToCSV = (data: any[], columns: string[]): string => {
const header = columns.join(',');
Expand All @@ -58,6 +57,29 @@ export const RunContent = ({ row, currentLog, interpretationInProgress, logEndRe
return [header, ...rows].join('\n');
};


const convertToMarkdown = (data: any[], columns: string[]): string => {

const headerRow = `| ${columns.join(' | ')} |`;

// Create separator row for Markdown tables
const separatorRow = `| ${columns.map(() => '---').join(' | ')} |`;


const dataRows = data.map(row =>
`| ${columns.map(col => {

const value = row[col];
return value === undefined || value === "" ? "-" :

String(value).replace(/\|/g, '\\|').replace(/\n/g, ' ');
}).join(' | ')} |`
);


return [headerRow, separatorRow, ...dataRows].join('\n');
};
Comment on lines +61 to +81
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance the robustness of Markdown conversion

The implementation needs improvements in type safety and data handling:

-const convertToMarkdown = (data: any[], columns: string[]): string => {
+interface TableData {
+  [key: string]: string | number | boolean | null | undefined;
+}
+
+const convertToMarkdown = (data: TableData[], columns: string[]): string => {
   const headerRow = `| ${columns.join(' | ')} |`;
   const separatorRow = `| ${columns.map(() => '---').join(' | ')} |`;
   
   const dataRows = data.map(row => 
     `| ${columns.map(col => {
       const value = row[col];
-      return value === undefined || value === "" ? "-" : 
-             String(value).replace(/\|/g, '\\|').replace(/\n/g, ' ');
+      if (value === null || value === undefined || value === "") {
+        return "-";
+      }
+      return String(value)
+        .replace(/\|/g, '\\|')
+        .replace(/\n/g, ' ')
+        .replace(/\[/g, '\\[')
+        .replace(/\]/g, '\\]')
+        .replace(/\*/g, '\\*')
+        .replace(/_/g, '\\_');
     }).join(' | ')} |`
   );

   return [headerRow, separatorRow, ...dataRows].join('\n');
 };

The changes:

  1. Add proper TypeScript interface for table data
  2. Handle null values explicitly
  3. Escape additional Markdown special characters
  4. Remove unnecessary empty lines
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const convertToMarkdown = (data: any[], columns: string[]): string => {
const headerRow = `| ${columns.join(' | ')} |`;
// Create separator row for Markdown tables
const separatorRow = `| ${columns.map(() => '---').join(' | ')} |`;
const dataRows = data.map(row =>
`| ${columns.map(col => {
const value = row[col];
return value === undefined || value === "" ? "-" :
String(value).replace(/\|/g, '\\|').replace(/\n/g, ' ');
}).join(' | ')} |`
);
return [headerRow, separatorRow, ...dataRows].join('\n');
};
interface TableData {
[key: string]: string | number | boolean | null | undefined;
}
const convertToMarkdown = (data: TableData[], columns: string[]): string => {
const headerRow = `| ${columns.join(' | ')} |`;
const separatorRow = `| ${columns.map(() => '---').join(' | ')} |`;
const dataRows = data.map(row =>
`| ${columns.map(col => {
const value = row[col];
if (value === null || value === undefined || value === "") {
return "-";
}
return String(value)
.replace(/\|/g, '\\|')
.replace(/\n/g, ' ')
.replace(/\[/g, '\\[')
.replace(/\]/g, '\\]')
.replace(/\*/g, '\\*')
.replace(/_/g, '\\_');
}).join(' | ')} |`
);
return [headerRow, separatorRow, ...dataRows].join('\n');
};


const downloadCSV = () => {
const csvContent = convertToCSV(tableData, columns);
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
Expand All @@ -71,6 +93,19 @@ export const RunContent = ({ row, currentLog, interpretationInProgress, logEndRe
document.body.removeChild(link);
};

const downloadMarkdown = () => {
const markdownContent = convertToMarkdown(tableData, columns);
const blob = new Blob([markdownContent], { type: 'text/markdown;charset=utf-8;' });
const url = URL.createObjectURL(blob);

const link = document.createElement("a");
link.href = url;
link.setAttribute("download", "data.md");
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};
Comment on lines +96 to +107
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add cleanup and error handling to downloadMarkdown function

The current implementation might cause memory leaks and doesn't handle potential errors.

 const downloadMarkdown = () => {
-  const markdownContent = convertToMarkdown(tableData, columns);
-  const blob = new Blob([markdownContent], { type: 'text/markdown;charset=utf-8;' });
-  const url = URL.createObjectURL(blob);
+  try {
+    const markdownContent = convertToMarkdown(tableData, columns);
+    const blob = new Blob([markdownContent], { type: 'text/markdown;charset=utf-8;' });
+    const url = URL.createObjectURL(blob);
 
-  const link = document.createElement("a");
-  link.href = url;
-  link.setAttribute("download", "data.md");
-  document.body.appendChild(link);
-  link.click();
-  document.body.removeChild(link);
+    const link = document.createElement("a");
+    link.href = url;
+    link.setAttribute("download", "data.md");
+    document.body.appendChild(link);
+    link.click();
+    document.body.removeChild(link);
+    URL.revokeObjectURL(url);
+  } catch (error) {
+    console.error('Failed to download markdown:', error);
+    // Consider adding user feedback here
+  }
 };

The changes:

  1. Add error handling with try-catch
  2. Clean up the URL object to prevent memory leaks
  3. Consider adding user feedback for errors
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const downloadMarkdown = () => {
const markdownContent = convertToMarkdown(tableData, columns);
const blob = new Blob([markdownContent], { type: 'text/markdown;charset=utf-8;' });
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.setAttribute("download", "data.md");
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};
const downloadMarkdown = () => {
try {
const markdownContent = convertToMarkdown(tableData, columns);
const blob = new Blob([markdownContent], { type: 'text/markdown;charset=utf-8;' });
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.setAttribute("download", "data.md");
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);
} catch (error) {
console.error('Failed to download markdown:', error);
// Consider adding user feedback here
}
};


return (
<Box sx={{ width: '100%' }}>
<TabContext value={tab}>
Expand Down Expand Up @@ -129,6 +164,11 @@ export const RunContent = ({ row, currentLog, interpretationInProgress, logEndRe
>
<a style={{ textDecoration: 'none', cursor: 'pointer' }}>Download as CSV</a>
</Typography>
<Typography
onClick={downloadMarkdown}
>
<a style={{ textDecoration: 'none', cursor: 'pointer' }}>Download as Markdown</a>
</Typography>
</Box>
{tableData.length > 0 ? (
<TableContainer component={Paper} sx={{ maxHeight: 440, marginTop: 2 }}>
Expand Down Expand Up @@ -199,4 +239,4 @@ export const RunContent = ({ row, currentLog, interpretationInProgress, logEndRe
</TabContext>
</Box>
);
};
};