diff --git a/.gitignore b/.gitignore index 0d6bd13..477c66c 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,8 @@ builds package-lock.json public resources -.codegpt \ No newline at end of file +.codegpt + +# Debugging expanded epub files +ebooks/contents/ +ebooks/pandoc.log diff --git a/ebooks/README.md b/ebooks/README.md index 6f18df0..caa0ecb 100644 --- a/ebooks/README.md +++ b/ebooks/README.md @@ -1,6 +1,23 @@ +# wisdom.epub +This is the latest version of the document exported from .md via Pandoc. +To compile this ebook, run the following command in the terminal: +```bash +./ebooks/compile.sh +``` +The script assumes you have Pandoc installed. On macOS, you can install it using Homebrew: -This is the latest version of the document exported from .md via Pandoc. \ No newline at end of file +```bash +brew install pandoc +``` + +## Markdown Pre-Processing + +We use Pandoc's lua filters to process the Markdown files before converting them to EPUB. + +You can add as many filters as you like in the `ebooks/filters` directory. The filters will be applied in the order they are listed in the `compile.sh` script. + +ChatGPT and Claude are pretty good at drafting lua filters. diff --git a/ebooks/compile.sh b/ebooks/compile.sh new file mode 100755 index 0000000..2083122 --- /dev/null +++ b/ebooks/compile.sh @@ -0,0 +1,64 @@ +#! /usr/bin/env bash + +# Ensure we are at the root of the project repository, +# regardless of where this script is run from. +cd "$(dirname "$0")/.." + +# NOTES: +# Assumes we want exactly one wisdom per page in the EPUB. +# This assumes the md file is grouped into sections by h2 (##) +# and that within each section, each wisdom is a separate list item. + +# Export EBOOK_VIEWER environment variable to specify the application +# Reasonable options: `calibre`, `Books` +EBOOK_VIEWER=${EBOOK_VIEWER:-"Books"} +# Append the current date to the EPUB filename +# DESTINATION="ebooks/Wisdom-$(date +%Y-%m-%d).epub" +DESTINATION="ebooks/wisdom.epub" + +## Pass --debug to Pandoc for verbose output if needed. +if [[ "$1" == "--debug" ]]; then + PANDOC_DEBUG="--verbose --log=ebooks/pandoc.log" +else + PANDOC_DEBUG="" +fi + +echo "Compiling wisdom.md to $DESTINATION..." +pandoc wisdom.md -o $DESTINATION \ + --metadata title="Merlin's Wisdom Project" \ + --metadata author="Merlin Mann" \ + --metadata date="$(date +%Y-%m-%d)" \ + --metadata description="Or: “Everybody likes being given a glass of water.”" \ + --metadata language="en" \ + --css=ebooks/style.css \ + --shift-heading-level-by=-1 \ + --toc --toc-depth=2 \ + --split-level=2 \ + --epub-cover-image=ebooks/cover.jpg \ + --lua-filter=ebooks/filters/strip-comments.lua \ + --lua-filter=ebooks/filters/process-md.lua \ + $PANDOC_DEBUG; + +if [[ $? -ne 0 ]]; then + echo "Error: pandoc failed to compile wisdom.md." + exit 1 +fi + +## If debugging, expand the zip file to inspect its contents. +if [[ "$1" == "--debug" ]]; then + echo "Debugging enabled. Compiled EPUB will be expanded for inspection." + unzip -l $DESTINATION + unzip -d ebooks/contents $DESTINATION + echo "EPUB contents extracted to ebooks/contents/" + exit 0 +fi + +## If the `open` command is available, open the EPUB after compiling. +if command -v open &> /dev/null; then + echo "Opening $DESTINATION..." + open $DESTINATION -a $EBOOK_VIEWER +else + echo "Compiled successfully. You can find the EPUB at ebooks/wisdom.epub" +fi + +exit 0 diff --git a/ebooks/filters/process-md.lua b/ebooks/filters/process-md.lua new file mode 100644 index 0000000..e5785c2 --- /dev/null +++ b/ebooks/filters/process-md.lua @@ -0,0 +1,22 @@ +-- Enable this to _replace_ horizontal rules with a page break +-- Currently, style.css applies this class to all
elements +-- function HorizontalRule(el) +-- return pandoc.RawBlock('html', '
') +-- end + +function center_and_page_separate(el) + -- Convert to raw HTML to add classes to
  • elements + local items = {} + for i, item in ipairs(el.content) do + local item_html = pandoc.write(pandoc.Pandoc(item), 'html') + -- Remove any existing

    tags if they wrap the content + item_html = item_html:gsub('

    (.-)

    ', '%1') + table.insert(items, '
  • ' .. item_html .. '
  • ') + end + + return pandoc.RawBlock('html', '') +end + +-- Apply the same transformation to BulletList and OrderedList +BulletList = center_and_page_separate +OrderedList = center_and_page_separate diff --git a/ebooks/filters/strip-comments.lua b/ebooks/filters/strip-comments.lua new file mode 100644 index 0000000..f33487b --- /dev/null +++ b/ebooks/filters/strip-comments.lua @@ -0,0 +1,23 @@ +function RawBlock(el) + if el.format == 'html' then + -- Remove HTML comments + el.text = el.text:gsub("" , "") + -- Clean up extra whitespace + el.text = el.text:gsub("^%s*$", "") + end + -- Return nil to remove empty blocks + if el.text == "" then + return {} + end + return el +end + +function RawInline(el) + if el.format == 'html' then + el.text = el.text:gsub("" , "") + if el.text == "" then + return {} + end + end + return el +end diff --git a/ebooks/style.css b/ebooks/style.css new file mode 100644 index 0000000..cad71b7 --- /dev/null +++ b/ebooks/style.css @@ -0,0 +1,40 @@ +body { + font-family: 'Garamond', serif; + font-size: 18px; + line-height: 1.5; + /* increase the kerning a bit */ + letter-spacing: 1px; +} + +hr, .page-break { + page-break-after: always; +} + +li { + list-style-type: none; +} + +/* Content Centering on the page. + Only one of these should be used at a time. +*/ +/* body { + display: flex; + align-items: center; + min-height: 100vh; + text-align: center; +} */ + +/* This is not currently applied to blockquotes and more complex pages. */ +.center-page { + display: flex; + align-items: center; + min-height: 100vh; + max-height: 70ch; + text-align: center; + justify-content: center; +} + +.center-page em, +.center-page strong { + align-self: center; +} diff --git a/ebooks/wisdom.epub b/ebooks/wisdom.epub new file mode 100644 index 0000000..99813c1 Binary files /dev/null and b/ebooks/wisdom.epub differ diff --git a/wisdom.md b/wisdom.md index 9fc83d2..7f6e2f8 100644 --- a/wisdom.md +++ b/wisdom.md @@ -1,13 +1,15 @@ --- -Author: Merlin Mann +title: Merlin's Wisdom Project +author: Merlin Mann --- + # Merlin's Wisdom Project -![Your Author](/i/cover.jpg) +![Your Author](i/cover.jpg) Or: “*Everybody likes being given a glass of water*.” @@ -22,15 +24,15 @@ It's only advice for you because it **had** to be advice for me. ## Epigraphs -> Yet here, Laertes! aboard, aboard, for shame! -> The wind sits in the shoulder of your sail, +> Yet here, Laertes! aboard, aboard, for shame! +> The wind sits in the shoulder of your sail, > And you are stay'd for. — *Hamlet*, Act 1, Scene 3. ---- -