1import { archive } from './archive-data.js'; 2import { action, escape, passage, essayUrl } from './chapter-elements.js'; 3 4const editions = { 5 'war-of-art': ['The War of Art', 'Steven Pressfield', 'resistance'], 6 'mans-search-for-meaning': ['Manâs Search for Meaning', 'Viktor Frankl', 'meaning'], 7 'the-four-agreements': ['The Four Agreements', 'Don Miguel Ruiz', 'agreements'], 8 'how-to-live-on-24-hours-per-day': ['How to Live on 24 Hours a Day', 'Arnold Bennett', 'hours'], 9 'how-to-think-like-a-roman-emperor': ['How to Think Like a Roman Emperor', 'Donald Robertson', 'emperor'], 10 'the-art-of-world-wisdom': ['The Art of Worldly Wisdom', 'Baltasar Gracián', 'wisdom'], 11 'the-easy-life-is-not-always-the-good-life': ['The Choice of Hercules', 'A reading note by Scott Flear', 'hercules'], 12}; 13 14export const bookNotes = archive.filter((entry) => entry.category === 'Book notes'); 15 16/** Every published book-note entry becomes a book; private notebooks stay private. */ 17export function libraryPage() { 18 return `<section class="library-intro"><h1 id="chapter-title">Book notes</h1><h2>A few books.<br>A lot of underlining.</h2><p>History, philosophy and the ideas I keep arguing with. These are all ${bookNotes.length} book-note entries in my published archive. Pick one off the shelf.</p><label class="library-search">Find a book or an author<input type="search" id="book-search" placeholder="Try Stoicism, Frankl or meaningâ¦" autocomplete="off"></label><p class="library-count" id="book-count" role="status">${bookNotes.length} notes on the shelf</p></section> 19 <div class="book-shelf full-library">${bookNotes.map((entry) => { 20 const [title, author, style] = editions[entry.slug] || [entry.title, 'Scottâs reading notes', 'resistance']; 21 const isReadingNote = entry.slug === 'the-easy-life-is-not-always-the-good-life'; 22 return `<a class="book book-${style}" data-book="${escape([title, author, entry.title, entry.description].join(' ').toLowerCase())}" href="${essayUrl(entry.slug)}"><span>${escape(author)}</span><h3>${escape(title)}</h3><small>${isReadingNote ? 'An essay on useful difficulty' : 'My notes & takeaways'}<br><span>Open the notes â</span></small></a>`; 23 }).join('')}</div><p class="library-empty" id="library-empty" hidden>No notes match that search. Try a title, author or a different idea.</p> 24 ${passage('Reading is the start of the conversation.', 'These are my notes rather than a substitute for the books. Sometimes an idea becomes an essay of its own, like the Choice of Hercules. I first encountered that story through Donald Robertsonâs How to Think Like a Roman Emperor.')} 25 <div class="chapter-final-link">${action('Browse the full writing archive', 'https://scottflear.com/essays/')}</div>`; 26} 27 28/** Filter the existing shelf without rebuilding links or moving keyboard focus. */ 29export function filterBooks(value) { 30 const query = value.trim().toLowerCase(); 31 let count = 0; 32 document.querySelectorAll('[data-book]').forEach((book) => { 33 book.hidden = !book.dataset.book.includes(query); 34 if (!book.hidden) count++; 35 }); 36 document.getElementById('book-count').textContent = `${count} ${count === 1 ? 'note' : 'notes'} on the shelf`; 37 document.getElementById('library-empty').hidden = count !== 0; 38}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.