PageSourceSearch

https://scottflear.com/room-home-20260919/library.js?v=330aaeed1fb6

js scottflear.com collected 2026-09-25 03:18:33 UTC 3,287 bytes, 38 lines download raw bytes

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.