Skip to content

Instantly share code, notes, and snippets.

@mekarpeles
Created January 6, 2026 12:49
Show Gist options
  • Select an option

  • Save mekarpeles/5bd8a773e5900a55683fea7e326dd763 to your computer and use it in GitHub Desktop.

Select an option

Save mekarpeles/5bd8a773e5900a55683fea7e326dd763 to your computer and use it in GitHub Desktop.
Extract openlibrary bulk search as TSV
// Function to safely escape and quote a string for CSV/TSV
const escapeAndQuoteTSV = str => {
const value = (str?.toString() || '').trim();
const escapedValue = value.replace(/"/g, '""');
return `"${escapedValue}"`;
};
// Script to extract Original Columns + All Match Details from Shadow DOM, with QUOTING
const shadowRoot = document.querySelector('ol-bulk-search')?.shadowRoot;
if (!shadowRoot) {
console.error('ERROR: Could not find <ol-bulk-search> or its shadowRoot.');
'';
} else {
// --- Data Extraction (Same as before) ---
const headerRow = shadowRoot.querySelector('.tableWrapper thead tr:nth-child(2)');
if (!headerRow) {
console.error('ERROR: Could not find header row.');
'';
}
const headers = Array.from(headerRow.querySelectorAll('th'))
.map(th => th.textContent.trim()); // Headers unquoted for object keys
const outputKeys = [...headers, 'MatchTitle', 'MatchByline', 'MatchURL'];
const tsvDataArray = []; // Array to hold objects for console.table()
const matchRows = shadowRoot.querySelectorAll('tr.matchRow');
if (matchRows.length === 0) {
console.warn('WARNING: Found 0 data rows inside the Shadow Root.');
}
// --- Row Processing ---
matchRows.forEach(row => {
const cells = Array.from(row.querySelectorAll('td'));
// Extract data for original columns (skip 1st (order#), skip last (book card))
const rowDataValues = cells.slice(1, cells.length - 1).map(td => td.textContent.trim());
// Extract match details
const bookCardCell = cells[cells.length - 1];
const matchTitle = bookCardCell.querySelector('.book-card--primary .info .title')?.textContent.trim() || '';
const matchByline = bookCardCell.querySelector('.book-card--primary .info .byline')?.textContent.trim() || '';
const matchURL = bookCardCell.querySelector('.book-card--primary .info .title')?.href || '';
const finalRowValues = [...rowDataValues, matchTitle, matchByline, matchURL];
// Create an object for console.table
const rowObject = {};
outputKeys.forEach((key, index) => {
rowObject[key] = finalRowValues[index];
});
tsvDataArray.push(rowObject);
});
// --- Output Generation (The New Part) ---
console.log('--- BEAUTIFUL CONSOLE TABLE (Easier to read) ---');
console.table(tsvDataArray); // Prints a clean table in the console!
// Fallback: Generate the raw TSV string (quoted) for easy copying to a spreadsheet
const tsvOutput = [outputKeys.map(escapeAndQuoteTSV).join('\t')].concat(
tsvDataArray.map(obj => outputKeys.map(key => escapeAndQuoteTSV(obj[key])).join('\t'))
).join('\n');
console.log('\n--- RAW QUOTED TSV STRING (Copy for Spreadsheet) ---');
console.log('NOTE: The raw string may still show \\t and \\n, but it is ready to paste.');
console.log(tsvOutput);
// Return the final TSV
tsvOutput;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment