<details class="site-nav" style="width: 100%; margin-bottom: 1.5em;"><summary style="display: flex; align-items: center; justify-content: space-between; width: 100%; list-style: none; padding: 8px 0; border-bottom: 1px solid #E6E4D9; pointer-events: none;"><a href="Index" class="internal-link nav-home" style="text-decoration: none; font-size: 1.5em; pointer-events: auto;"><span style="color: #B8B6AA; font-weight: 600;">Anthony Lopopolo</span></a><span style="font-size: 24px; color: #6F6E69; pointer-events: auto; cursor: pointer;">☰</span></summary><div style="text-align: right;"><a href="Index" class="internal-link" style="display: block; text-align: right; padding: 10px 0; text-decoration: none; font-size: 18px; font-weight: 500; text-transform: uppercase; letter-spacing: 1.5px; color: #6F6E69; border-bottom: 1px solid #E6E4D9;">Home</a><a href="About" class="internal-link" style="display: block; text-align: right; padding: 10px 0; text-decoration: none; font-size: 18px; font-weight: 500; text-transform: uppercase; letter-spacing: 1.5px; color: #6F6E69; border-bottom: 1px solid #E6E4D9;">About</a><a href="Commentary" class="internal-link" style="display: block; text-align: right; padding: 10px 0; text-decoration: none; font-size: 18px; font-weight: 500; text-transform: uppercase; letter-spacing: 1.5px; color: #6F6E69; border-bottom: 1px solid #E6E4D9;">Commentary</a><a href="Featured Work" class="internal-link" style="display: block; text-align: right; padding: 10px 0; text-decoration: none; font-size: 18px; font-weight: 500; text-transform: uppercase; letter-spacing: 1.5px; color: #6F6E69; border-bottom: none;">Featured Work</a></div></details> # My digital book collection *Everything on my desk, bookshelf, and wish list.* ## 📖 Currently Reading ```dataviewjs const IMG_STYLE = "position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; display: block; image-rendering: smooth; cursor: default;"; function getCoverUrl(title) { if (!title) return null; var name = String(title).trim(); var path = "Books/Covers/" + name + ".jpg"; var file = app.vault.getAbstractFileByPath(path); if (!file) { // Try short name for Italy if (name.toLowerCase().includes("italy")) { file = app.vault.getAbstractFileByPath("Books/Covers/Italy.jpg"); } } if (!file) return null; return app.vault.adapter.getResourcePath(file.path); } function loadCover(container, title, url) { if (!url) { var fb = container.createEl("div", { attr: { style: "position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; padding: 12px; text-align: center;" } }); fb.createEl("span", { text: title, attr: { style: "font-size: 12px; font-weight: 500; color: #6F6E69; line-height: 1.3;" } }); return; } var img = container.createEl("img", { attr: { src: url, alt: title, style: IMG_STYLE } }); img.onerror = function() { this.remove(); loadCover(container, title, null); }; img.onload = function() { if (this.naturalWidth <= 1 || this.naturalHeight <= 1) { this.remove(); loadCover(container, title, null); } }; } const books = dv.pages('#books') .where(p => p.status === "🔵 Currently Reading" && !p.file.path.includes("Template")) .sort(p => { const author = p.author ? (Array.isArray(p.author) ? p.author[0] : p.author) : "zzz"; const parts = String(author).trim().split(/\s+/); return parts[parts.length - 1].toLowerCase(); }, 'asc'); if (books.length === 0) { dv.paragraph("No books currently reading."); } else { const grid = dv.el("div", "", { attr: { style: "display: grid; grid-template-columns: repeat(4, 1fr); gap: 24px; margin: 12px 0; max-width: 720px; justify-items: start;" } }); while (grid.firstChild) grid.firstChild.remove(); books.forEach(book => { const coverUrl = getCoverUrl(book.file.name); const author = book.author ? book.author.join(", ") : "Unknown"; const rawCurrentPage = book["current-page"]; const hasCurrentPage = rawCurrentPage !== null && rawCurrentPage !== undefined && String(rawCurrentPage).trim() !== ""; const currentPage = parseInt(rawCurrentPage) || 0; const totalPages = parseInt(book.pages) || 0; const progress = totalPages > 0 && currentPage > 0 ? Math.round((currentPage / totalPages) * 100) : 0; const card = grid.createEl("div", { attr: { style: "display: flex; flex-direction: column; gap: 6px; min-width: 0; width: 100%;" } }); const coverDiv = card.createEl("div", { attr: { style: "width: 100%; padding-bottom: 150%; position: relative; border-radius: 4px; overflow: hidden; background: #E6E4D9; cursor: default;" } }); loadCover(coverDiv, book.file.name, coverUrl); const info = card.createEl("div", { attr: { style: "display: flex; flex-direction: column; gap: 2px;" } }); info.createEl("a", { text: book.file.name, cls: "internal-link", attr: { "data-href": book.file.path, href: book.file.path, style: "font-size: 13px; font-weight: 600; text-decoration: none; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;" } }); info.createEl("div", { text: author, attr: { style: "font-size: 12px; color: #6F6E69; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;" } }); if (hasCurrentPage && totalPages > 0) { const barContainer = info.createEl("div", { attr: { style: "width: 100%; height: 6px; background: #E6E4D9; border-radius: 3px; overflow: hidden; margin-top: 4px;" } }); barContainer.createEl("div", { attr: { style: "height: 100%; width: " + progress + "%; background: linear-gradient(90deg, #4a9eff 0%, #3d8ceb 100%); border-radius: 3px;" } }); } }); } ``` ## ✅ Finished ```dataviewjs const IMG_STYLE = "position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; display: block; image-rendering: smooth; cursor: default;"; function getCoverUrl(title) { if (!title) return null; var name = String(title).trim(); var path = "Books/Covers/" + name + ".jpg"; var file = app.vault.getAbstractFileByPath(path); if (!file) { // Try short name for Italy if (name.toLowerCase().includes("italy")) { file = app.vault.getAbstractFileByPath("Books/Covers/Italy.jpg"); } } if (!file) return null; return app.vault.adapter.getResourcePath(file.path); } function loadCover(container, title, url) { if (!url) { var fb = container.createEl("div", { attr: { style: "position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; padding: 12px; text-align: center;" } }); fb.createEl("span", { text: title, attr: { style: "font-size: 12px; font-weight: 500; color: #6F6E69; line-height: 1.3;" } }); return; } var img = container.createEl("img", { attr: { src: url, alt: title, style: IMG_STYLE } }); img.onerror = function() { this.remove(); loadCover(container, title, null); }; img.onload = function() { if (this.naturalWidth <= 1 || this.naturalHeight <= 1) { this.remove(); loadCover(container, title, null); } }; } const books = dv.pages('#books') .where(p => p.status === "✅ Finished" && !p.file.path.includes("Template")) .sort(p => { const author = p.author ? (Array.isArray(p.author) ? p.author[0] : p.author) : "zzz"; const parts = String(author).trim().split(/\s+/); return parts[parts.length - 1].toLowerCase(); }, 'asc'); if (books.length === 0) { dv.paragraph("No finished books yet."); } else { const grid = dv.el("div", "", { attr: { style: "display: grid; grid-template-columns: repeat(4, 1fr); gap: 24px; margin: 12px 0; max-width: 720px; justify-items: start;" } }); while (grid.firstChild) grid.firstChild.remove(); books.forEach(book => { const coverUrl = getCoverUrl(book.file.name); const author = book.author ? book.author.join(", ") : "Unknown"; let stars = ""; if (book.rating) { let rating; if (typeof book.rating === 'string' && book.rating.includes('/')) { const rParts = book.rating.split('/'); rating = parseFloat(rParts[0]); } else { rating = typeof book.rating === 'number' ? book.rating : parseFloat(book.rating); } if (!isNaN(rating)) { const fullStars = Math.floor(rating); const hasHalfStar = rating % 1 >= 0.5; stars = "⭐".repeat(fullStars); if (hasHalfStar) stars += "✨"; } else { stars = String(book.rating); } } const card = grid.createEl("div", { attr: { style: "display: flex; flex-direction: column; gap: 6px; min-width: 0; width: 100%;" } }); const coverDiv = card.createEl("div", { attr: { style: "width: 100%; padding-bottom: 150%; position: relative; border-radius: 4px; overflow: hidden; background: #E6E4D9; cursor: default;" } }); loadCover(coverDiv, book.file.name, coverUrl); const info = card.createEl("div", { attr: { style: "display: flex; flex-direction: column; gap: 2px;" } }); info.createEl("a", { text: book.file.name, cls: "internal-link", attr: { "data-href": book.file.path, href: book.file.path, style: "font-size: 13px; font-weight: 600; text-decoration: none; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;" } }); info.createEl("div", { text: author, attr: { style: "font-size: 12px; color: #6F6E69; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;" } }); if (stars) { info.createEl("div", { text: stars, attr: { style: "font-size: 13px; letter-spacing: 1px; margin-top: 2px;" } }); } }); } ``` ## 📚 Want to Read ```dataviewjs const IMG_STYLE = "position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; display: block; image-rendering: smooth; cursor: default;"; function getCoverUrl(title) { if (!title) return null; var name = String(title).trim(); var path = "Books/Covers/" + name + ".jpg"; var file = app.vault.getAbstractFileByPath(path); if (!file) { // Try short name for Italy if (name.toLowerCase().includes("italy")) { file = app.vault.getAbstractFileByPath("Books/Covers/Italy.jpg"); } } if (!file) return null; return app.vault.adapter.getResourcePath(file.path); } function loadCover(container, title, url) { if (!url) { var fb = container.createEl("div", { attr: { style: "position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; padding: 12px; text-align: center;" } }); fb.createEl("span", { text: title, attr: { style: "font-size: 12px; font-weight: 500; color: #6F6E69; line-height: 1.3;" } }); return; } var img = container.createEl("img", { attr: { src: url, alt: title, style: IMG_STYLE } }); img.onerror = function() { this.remove(); loadCover(container, title, null); }; img.onload = function() { if (this.naturalWidth <= 1 || this.naturalHeight <= 1) { this.remove(); loadCover(container, title, null); } }; } const books = dv.pages('#books') .where(p => p.status === "📚 Want to Read" && !p.file.path.includes("Template")) .sort(p => { const author = p.author ? (Array.isArray(p.author) ? p.author[0] : p.author) : "zzz"; const parts = String(author).trim().split(/\s+/); return parts[parts.length - 1].toLowerCase(); }, 'asc'); if (books.length === 0) { dv.paragraph("No books in Want to Read list."); } else { const grid = dv.el("div", "", { attr: { style: "display: grid; grid-template-columns: repeat(4, 1fr); gap: 24px; margin: 12px 0; max-width: 720px; justify-items: start;" } }); while (grid.firstChild) grid.firstChild.remove(); books.forEach(book => { const coverUrl = getCoverUrl(book.file.name); const author = book.author ? book.author.join(", ") : "Unknown"; const card = grid.createEl("div", { attr: { style: "display: flex; flex-direction: column; gap: 6px; min-width: 0; width: 100%;" } }); const coverDiv = card.createEl("div", { attr: { style: "width: 100%; padding-bottom: 150%; position: relative; border-radius: 4px; overflow: hidden; background: #E6E4D9; cursor: default;" } }); loadCover(coverDiv, book.file.name, coverUrl); const info = card.createEl("div", { attr: { style: "display: flex; flex-direction: column; gap: 2px;" } }); info.createEl("a", { text: book.file.name, cls: "internal-link", attr: { "data-href": book.file.path, href: book.file.path, style: "font-size: 13px; font-weight: 600; text-decoration: none; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;" } }); info.createEl("div", { text: author, attr: { style: "font-size: 12px; color: #6F6E69; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;" } }); if (book["buy-link"]) { const shopText = book["buy-from"] ? String(book["buy-from"]) : "Shop"; info.createEl("a", { text: shopText, attr: { href: String(book["buy-link"]), target: "_blank", rel: "noopener", style: "display: inline-block; font-size: 11px; padding: 3px 8px; background: #F2F0E5; color: #6F6E69; text-decoration: none; border-radius: 3px; border: 1px solid #E6E4D9; margin-top: 4px; width: fit-content;" } }); } }); } ``` ## 📊 Books by Genre ```dataviewjs const finishedBooks = dv.pages('#books') .where(p => p.status === "✅ Finished" && !p.file.path.includes("Template")); // Group books by genre const genreMap = new Map(); finishedBooks.forEach(book => { if (book.genre) { const genres = Array.isArray(book.genre) ? book.genre : [book.genre]; genres.forEach(genre => { if (genre) { if (!genreMap.has(genre)) { genreMap.set(genre, []); } genreMap.get(genre).push(book); } }); } }); if (genreMap.size === 0) { dv.paragraph("*No finished books with genres yet.*"); } else { // Sort genres alphabetically const sortedGenres = Array.from(genreMap.keys()).sort(); const headers = ["Genre", "Books Finished"]; const rows = sortedGenres.map(genre => { const books = genreMap.get(genre); return [ genre, "✓".repeat(books.length) + " (" + books.length + ")" ]; }); dv.table(headers, rows); } /* LIBRARY_DATA_START Test Book;;;;;;✅ Finished;;3/5;;;;;;;;;; Francesco;;Aldo Cazzullo;;9791259854902;;📚 Want to Read;;;;https://www.amazon.ca/dp/B0F5YL1LLB/?coliid=I47O6NFQUX0A7&colid=308YVPNDP3CSR&psc=1&ref_=list_c_wl_lv_ov_lig_dp_it;;Amazon;;;;272;;Biography The Price of Time;;Edward Chancellor;;0802160069;;📚 Want to Read;;;;https://www.amazon.ca/dp/0802160069/?coliid=I26741DDT2WCG2&colid=308YVPNDP3CSR&psc=1&ref_=list_c_wl_lv_ov_lig_dp_it;;Amazon;;;;416;;Finance Shogun;;James Clavell;;1982537523;;🔵 Currently Reading;;;;;;;;50;;1312;;Historical Fiction Fall of Civilizations;;Paul Cooper;;1335013415;;📚 Want to Read;;;;https://www.amazon.ca/dp/1335013415/?coliid=I23AYXCN5S26N6&colid=308YVPNDP3CSR&psc=1&ref_=list_c_wl_lv_ov_lig_dp_it;;Amazon;;;;576;;History Women of War;;Suzanne Cope;;059347600X;;📚 Want to Read;;;;https://www.amazon.ca/dp/059347600X/?coliid=I11N9AU93AUFR3&colid=308YVPNDP3CSR&psc=1&ref_=list_c_wl_lv_ov_lig_dp_it;;Amazon;;;;480;;History Raising Hare;;Chloe Dalton;;180530271X;;📚 Want to Read;;;;https://www.amazon.ca/dp/180530271X/?coliid=I1WHLL49VSQMBS&colid=308YVPNDP3CSR&psc=1&ref_=list_c_wl_lv_ov_lig_dp_it;;Amazon;;;;304;;Nature Enshittification;;Cory Doctorow;;0374619328;;📚 Want to Read;;;;https://www.amazon.ca/dp/0374619328/?coliid=I373LMGNVKW6UF&colid=308YVPNDP3CSR&psc=1&ref_=list_c_wl_lv_ov_lig_dp_it;;Amazon;;;;352;;Technology Everybody Loses;;Danny Funt;;166806202X;;📚 Want to Read;;;;https://www.amazon.ca/dp/166806202X/?coliid=I2SEE03PUFLZSQ&colid=308YVPNDP3CSR&psc=1&ref_=list_c_wl_lv_ov_lig_dp_it;;Amazon;;;;320;;Sports Challenger;;Adam Higginbotham;;198217661X;;📚 Want to Read;;;;https://www.amazon.ca/dp/198217661X/?coliid=I3MPPOW8QQ1CHU&colid=308YVPNDP3CSR&psc=1&ref_=list_c_wl_lv_ov_lig_dp_it;;Amazon;;;;576;;History Ask Iwata;;Satoru Iwata;;197472154X;;📚 Want to Read;;;;https://www.amazon.ca/dp/197472154X/?coliid=I18C2L2B9B9CRE&colid=308YVPNDP3CSR&psc=1&ref_=list_c_wl_lv_ov_lig_dp_it#detailBullets_feature_div;;Amazon;;;;176;;Business Wabi Sabi;;Beth Kempton;;0062905155;;📚 Want to Read;;;;https://www.amazon.ca/dp/0062905155/?coliid=IQIQLZ5M2YGIJ&colid=308YVPNDP3CSR&psc=1&ref_=list_c_wl_lv_ov_lig_dp_it;;Amazon;;;;256;;Philosophy The Reading Life;;C. S. Lewis;;0062849972;;📚 Want to Read;;;;https://www.amazon.ca/dp/0062849972/?coliid=I2TYA5IMWIE1PA&colid=308YVPNDP3CSR&psc=1&ref_=list_c_wl_lv_ov_lig_dp_it;;Amazon;;;;192;;Essays On Writing (and Writers);;C. S. Lewis;;0063276445;;📚 Want to Read;;;;https://www.amazon.ca/dp/0063276445/?coliid=I2C0MJMIZCE5P7&colid=308YVPNDP3CSR&psc=1&ref_=list_c_wl_lv_ov_lig_dp_it;;Amazon;;;;208;;Essays Super Nintendo;;Keza MacDonald;;0593802683;;🔵 Currently Reading;;;;;;;;1;;304;;Business The Art of Simple Living;;Shunmyo Masuno;;0143134043;;📚 Want to Read;;;;https://www.amazon.ca/dp/0143134043/?coliid=IXYGZ08AEPFP7&colid=308YVPNDP3CSR&psc=1&ref_=list_c_wl_lv_ov_lig_dp_it;;Amazon;;;;224;;Philosophy The Idea Machine;;Joel J. Miller;;1493088939;;📚 Want to Read;;;;https://www.amazon.ca/dp/1493088939/?coliid=I1VUCP8WREW9F4&colid=308YVPNDP3CSR&psc=1&ref_=list_c_wl_lv_ov_lig_dp_it;;Amazon;;;;344;;History John Candy;;Paul Myers;;1487009526;;📚 Want to Read;;;;https://www.amazon.ca/dp/1487009526/?coliid=I25T6TDYMX7157&colid=308YVPNDP3CSR&psc=1&ref_=list_c_wl_lv_ov_lig_dp_it;;Amazon;;;;352;;Biography Miracles and Wonder;;Elaine Pagels;;0385547463;;📚 Want to Read;;;;https://www.amazon.ca/dp/0385547463/?coliid=I1O6NRUZGFDI72&colid=308YVPNDP3CSR&psc=1&ref_=list_c_wl_lv_ov_lig_dp_it;;Amazon;;;;336;;Religion 1929;;Andrew Ross Sorkin;;0593296966;;📚 Want to Read;;;;https://www.amazon.ca/dp/0593296966/?coliid=I1643G41U3I247&colid=308YVPNDP3CSR&psc=1&ref_=list_c_wl_lv_ov_lig_dp_it;;Amazon;;;;592;;History Italy - In the Footsteps of the Great Artists;;Nick Trend, Cassandre Montoriol;;0500027536;;📚 Want to Read;;;;https://www.amazon.ca/dp/0500027536/?coliid=IU1GEGW3003EL&colid=308YVPNDP3CSR&psc=1&ref_=list_c_wl_lv_ov_lig_dp_it;;Amazon;;;;352;;Travel A Dictionary of Color Combinations;;Sanzo Wada;;4861522471;;📚 Want to Read;;;;https://www.amazon.ca/dp/4861522471/?coliid=IBNFLOZ1EMDPB&colid=308YVPNDP3CSR&psc=1&ref_=list_c_wl_lv_ov_lig_dp_it;;Amazon;;;;256;;Design Breakneck;;Dan Wang;;1324106034;;📚 Want to Read;;;;https://www.amazon.ca/dp/1324106034/?coliid=I3N723QER78X7Z&colid=308YVPNDP3CSR&psc=1&ref_=list_c_wl_lv_ov_lig_dp_it;;Amazon;;;;288;;Technology Lone Wolf;;Adam Weymouth;;1039057527;;📚 Want to Read;;;;https://www.amazon.ca/dp/1039057527/?coliid=I37IZKV4IS7QH1&colid=308YVPNDP3CSR&psc=1&ref_=list_c_wl_lv_ov_lig_dp_it;;Amazon;;;;288;;Nature LIBRARY_DATA_END */ ``` --- [[index|← Back to Home]]