Skip to content

Instantly share code, notes, and snippets.

@agucova
Last active December 19, 2023 04:42
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save agucova/ebafb6743225efaeb9acb1f888757468 to your computer and use it in GitHub Desktop.
Save agucova/ebafb6743225efaeb9acb1f888757468 to your computer and use it in GitHub Desktop.
// Clean and simplify HTML
function cleanHTML(html: string): string {
const div = document.createElement('div');
div.innerHTML = html;
// Remove all class attributes and data-* attributes
div.querySelectorAll('*').forEach(el => {
el.removeAttribute('class');
Array.from(el.attributes).forEach(attr => {
if (attr.name.startsWith('data-')) {
el.removeAttribute(attr.name);
}
});
});
// Remove contents of <header> tags
div.querySelectorAll('header').forEach(el => el.remove());
// Only keep specific tags supported by Anki
const allowedTags = ['p', 'strong', 'sup', 'sub', 'em', 'img', 'ul', 'ol', 'li'];
div.querySelectorAll('*').forEach(el => {
if (!allowedTags.includes(el.tagName.toLowerCase())) {
el.replaceWith(...el.childNodes);
}
});
return div.innerHTML;
}
// Function to escape CSV string
function escapeCSV(str: string): string {
const escapedStr = str.replace(/"/g, '""');
return `"${escapedStr}"`;
}
// Scrape cards and prepare CSV
function scrapeAndPrepareCSV(): string {
const rows: string[] = [];
rows.push("Question,Answer");
const cardRows = document.querySelectorAll('.smart-card-row');
for (const row of cardRows) {
const questionFace = row.querySelector('.question-face');
const answerFace = row.querySelector('.answer-face');
if (!questionFace || !answerFace) continue;
const question = cleanHTML(questionFace.innerHTML);
const answer = cleanHTML(answerFace.innerHTML);
rows.push(`${escapeCSV(question)},${escapeCSV(answer)}`);
}
return rows.join('\n');
}
// Function to get deck and pack names for the filename
function getFilename(): string {
const deckElement = document.querySelector('.deck-name');
const packElement = document.querySelector('.deck-detail-header .pack-name');
let filename = 'anki_flashcards';
if (deckElement) {
filename = deckElement.innerHTML.trim();
}
if (packElement) {
const packName = packElement.innerHTML.trim();
filename = `${packName}_${filename}`;
}
return `${filename}.csv`;
}
// Function to trigger file download
function downloadCSV(csvString: string, filename: string): void {
const blob = new Blob([csvString], { type: 'text/csv;charset=utf-8;' });
const link = document.createElement('a');
const url = URL.createObjectURL(blob);
link.setAttribute('href', url);
link.setAttribute('download', filename);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);
}
downloadCSV(scrapeAndPrepareCSV(), getFilename());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment