diff --git a/.github/workflows/release-book.yml b/.github/workflows/release-book.yml index f10092b..65738ea 100644 --- a/.github/workflows/release-book.yml +++ b/.github/workflows/release-book.yml @@ -32,7 +32,7 @@ jobs: options: -v ${{ github.workspace }}:/app run: | cd /app/book - make bake + make -j bake - name: Release baked book to S3 uses: shallwefootball/s3-upload-action@master with: diff --git a/.github/workflows/validate-book-build.yml b/.github/workflows/validate-book-build.yml index 35aafa5..adf48e2 100644 --- a/.github/workflows/validate-book-build.yml +++ b/.github/workflows/validate-book-build.yml @@ -29,4 +29,4 @@ jobs: options: -v ${{ github.workspace }}:/app run: | cd /app/book - make -j build_pdf build_ebook + make -j build_serif_pdf build_ebook diff --git a/.gitignore b/.gitignore index 12d6473..b92da4e 100644 --- a/.gitignore +++ b/.gitignore @@ -12,53 +12,31 @@ *.run.xml *.html *.dlog +*.bak +*.opf book/book.out .vscode/ -book/book.synctex* -book/tikz-cache/* book/bookch* -book/content.opf -book/output-epub book/figures/*.png book/figures/*.pdf book/figures/*.in -book/tables/*.png -book/tables/*.pdf -book/release/* book/book*.4ct book/book*.4tc -book/book*.aux -book/book*.bbl -book/book*.bcf -book/book*.blg book/book*.css book/book*.dvi -book/book*.html book/book*.idv book/book*.lg -book/book*.log -book/book*.mobi -book/book*.azw3 -book/book*.epub book/book*.ncx book/book*.out -book/book*.pdf -book/book*.run.xml book/book*.tmp -book/book*.toc book/book*.xref -book/book*.html book/book*.svg -book/book-epub/ -book/book-mobi/ -book/book-azw3/ -*.bak -book_sans_serif/ -book_serif/ -release_sans_serif/ -book/book_sans_serif-epub/ +# Directories created during build +book/book_sans_serif/* +book/book_serif/* book/static_website_html/* -book/bw-book-epub/* -epub/ -*.opf website/static_website_html/* +book/epub/ +book/book-epub/ +book/bw-book-epub/* +book/release/* diff --git a/README.md b/README.md index 3a4c0dd..e3b7963 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ make Then you can check out the file `book/book.pdf` If you want to 🍞 bake all the versions including ebook variants (.pdf, .epub -in colour or size optimized Black&White), run: +in colour and size optimized Black&White), run: ```console make bake @@ -43,8 +43,9 @@ You can check the files in the folder `book/release/` ## 🍞 Baking the book locally (LaTeX) -Make sure you have `biber` and `latexmk` installed. Refer to your system's -installation instructions for LaTeX. To create the serif .pdf format, run: +Make sure you have `biber`, `latexmk` and ``ImageMagick`` installed. Refer to +your system's installation instructions for LaTeX. To create the serif .pdf +format, run: ```console cd book/ @@ -52,11 +53,11 @@ make ``` If you want to 🍞 bake all the versions including ebook variants (.pdf, .epub -in colour or size optimized Black&White), run: +in colour and size optimized Black&White), run: ```console cd book/ -make bake +make -j bake ``` You can check the files in the folder `book/release/` @@ -74,16 +75,16 @@ The below versions are automatically built on every push to the `main` branch. * [Download compiled .pdf version](https://www.the-bread-code.io/book.pdf) * [Download compiled .epub version](https://www.the-bread-code.io/book.epub) -There's an additional enhanced accessibility version using a sans serif font: +There's an additional enhanced accessibility version using a sans-serif font: -* [Download compiled .pdf version](https://www.the-bread-code.io/book-sans-serif.pdf) +* [Download compiled sans-serif .pdf version](https://www.the-bread-code.io/book-sans-serif.pdf) -An additional black and white ebook is provided with a greatly reduced file size. This -shrinks the book from more than 50MB down to ~5MB: +An additional black and white ebook is provided with a greatly reduced file +size. This shrinks the book from more than 50MB down to ~5MB: -* [Download compiled .epub version](https://www.the-bread-code.io/bw-book.epub) +* [Download compiled B&W .epub version](https://www.the-bread-code.io/bw-book.epub) -## Online HTML version (WIP) +## Online HTML version Head over to [https://www.the-sourdough-framework.com](https://www.the-sourdough-framework.com) diff --git a/book/book_sans_serif.tex b/book/book_sans_serif.tex index 0377a38..4174a9f 100644 --- a/book/book_sans_serif.tex +++ b/book/book_sans_serif.tex @@ -1,4 +1,2 @@ \def\isaccessible{1} -% We have to use a symlink to book.tex to prevent tex4ebook to load book.ht4 -% before loading any other package and create conflicts -\input{sourdough_book.tex} +\input{book.tex} diff --git a/book/figures/fig-life-planet-sourdough-timeline.tex b/book/figures/fig-life-planet-sourdough-timeline.tex new file mode 100644 index 0000000..0db4ee7 --- /dev/null +++ b/book/figures/fig-life-planet-sourdough-timeline.tex @@ -0,0 +1,70 @@ +\begin{tikzpicture} + % Draw horizontal line + \draw[line width=1pt] (0,0) -- (\textwidth,0); + + % Define the width of each segment + \pgfmathsetlengthmacro{\segmentwidth}{\textwidth/12} + + % Draw lines for the events, higher up so that they don't overflow the text + % Placing the lines has been a bit manual work of trying different values + % Maritime bacteria. + + \draw[line width=1pt] (2.8*\segmentwidth,1) -- (2.8*\segmentwidth,0.2); + % Eukaryotes + \draw[line width=1pt] (5.8*\segmentwidth,1.5) -- (5.8*\segmentwidth,0.2); + % First bacteria on land + \draw[line width=1pt] (9.1*\segmentwidth,-1.25) -- (9.1*\segmentwidth,-0.2); + % Maritime fungi ancestors + \draw[line width=1pt] (9.5*\segmentwidth,-2) -- (9.5*\segmentwidth,-0.2); + % Fungi on land + \draw[line width=1pt] (10.8*\segmentwidth,-2.75) -- (10.8*\segmentwidth,-0.2); + % Yeasts on land + \draw[line width=1pt] (11.1*\segmentwidth,-3.0) -- (11.1*\segmentwidth,-0.2); + % First dinosaurs + \draw[line width=1pt] (11.4*\segmentwidth,0.5) -- (11.4*\segmentwidth,0.2); + % Pangea begins to rift apart + \draw[line width=1pt] (11.6*\segmentwidth,1) -- (11.6*\segmentwidth,0.2); + % Dinosaur extinction + \draw[line width=1pt] (11.9*\segmentwidth,1.5) -- (11.9*\segmentwidth,0.2); + + % Special lines for december events since they are so close togehter + \draw[line width=1pt] (12.0*\segmentwidth,3.0) -- (12.0*\segmentwidth,0.2); % Main branch + \draw[line width=1pt] (12.0*\segmentwidth,3.0) -- (11.75*\segmentwidth,2.5); % Branch to first humans + \draw[line width=1pt] (12.0*\segmentwidth,3.0) -- (11.75*\segmentwidth,3.0); % Branch to Jordan + \draw[line width=1pt] (12.0*\segmentwidth,3.0) -- (11.75*\segmentwidth,3.5); % Branch to Pasteur + + % Draw months and month separators + \foreach \i/\month in {0/Jan, 1/Feb, 2/Mar, 3/Apr, 4/May, 5/Jun, 6/Jul, 7/Aug, 8/Sep, 9/Oct, 10/Nov, 11/Dec} { + % Separators + \draw[line width=1pt] (\i*\segmentwidth,0.1) -- (\i*\segmentwidth,-0.1); + % Month names + \node[timeline_event, below] at ({(\i+0.5)*\segmentwidth},-0.1) {\month}; + } + \draw[line width=1pt] (\textwidth,0.1) -- (\textwidth,-0.1); + + % Full timeline width for billion years + \draw[line width=1pt] (0,-3.8) -- node[midway, timeline_timespan] {5.45 billion years} (\textwidth,-3.8); + \draw[line width=1pt] (0,-3.7) -- (0,-3.9); + \draw[line width=1pt] (\textwidth,-3.7) -- (\textwidth,-3.9); + + % Indicator for the period of 3 months = 1.1 billion years + \draw[line width=1pt] (0,-1.0) -- node[midway, timeline_timespan] {1.11 billion years} ({\segmentwidth * 3},-1.0); + \draw[line width=1pt] (0,-0.9) -- (0,-1.1); + \draw[line width=1pt] ({\segmentwidth * 3},-0.9) -- ({\segmentwidth * 3},-1.1); + + % Place events on the timeline with dates using the timeline_event style + % As a calculation I used (4.54 billion years / 12 months = 0.3785 billion years/month. + \node[timeline_event, above] at (2.0*\segmentwidth,1) {Mar 25 - First maritime bacteria and archae}; + \node[timeline_event, above] at (4.50*\segmentwidth,1.5) {June 25 - First organisms with nuklei (eukaryotes)}; + \node[timeline_event, above] at (7.8*\segmentwidth,-1.5) {Oct 4 - First bacteria on land}; + \node[timeline_event, above] at (8.0*\segmentwidth,-2.25) {Oct 15 - First maritime ancestors of fungi}; + \node[timeline_event, above] at (9.7*\segmentwidth,-2.75) {Nov 24 - Fungi on land}; + \node[timeline_event, above] at (10.5*\segmentwidth,-3.25) {Dec 3 - Yeasts on land}; + \node[timeline_event, above] at (10.2*\segmentwidth,0.5) {Dec 14 - First dinosaurs}; + \node[timeline_event, above] at (9.8*\segmentwidth,1) {Dec 17 - Pangea begins to rift apart}; + \node[timeline_event, above] at (10.33*\segmentwidth,1.5) {Dec 29 - Dinosaurs go extinct}; + \node[timeline_event, above, anchor=east, align=right] at (11.75*\segmentwidth,2.5) {Dec 31 - First humans}; + \node[timeline_event, above, anchor=east, align=right] at (11.75*\segmentwidth,3.0) {Dec 31 - Sourdough in Jordan (23:59:55)}; + \node[timeline_event, above, anchor=east, align=right] at (11.75*\segmentwidth,3.5) {Dec 31 - Louis Pasteur isolated yeast (23:59:59)}; + +\end{tikzpicture} diff --git a/book/figures/flowcharts_tikz.tex b/book/figures/flowcharts_tikz.tex index ece37e2..5a8bb6a 100644 --- a/book/figures/flowcharts_tikz.tex +++ b/book/figures/flowcharts_tikz.tex @@ -25,3 +25,8 @@ decoration={calligraphic brace, amplitude=3mm, raise=1mm}, very thick, pen colour={black} ] \tikzstyle{loop} = [arc, draw=codeblack, line width=0.4mm] + +\tikzstyle{timeline_event}=[align=center, fill=white, inner sep=2pt] + +\tikzstyle{timeline_timespan} = [rectangle, draw=codeblack, fill=pinkpic, text=black, + text centered, rounded corners, line width=0.4mm] diff --git a/book/history/sourdough-history.tex b/book/history/sourdough-history.tex index f767f98..a7fbf4f 100644 --- a/book/history/sourdough-history.tex +++ b/book/history/sourdough-history.tex @@ -9,11 +9,78 @@ lessons from the past. \end{quoting} -Sourdough has been made since ancient times. The exact origins of fermented +The story of sourdough bread begins in prehistoric oceans. These oceans were the +birthplace of all life on Earth. To better envision the vast history of +our planet, lets create a timeline in one~year/365~days. On this scale, +January~1 signifies Earth's +formation 4.54~billion years ago. Midnight on December~31 is the present. +Each day represents roughly 12~million years. This technique simplifies the +complexity of time but also renders the extraordinary expanse of our planet's +history into a more graspable timeframe. We humans, are in fact a recent +addition to our planet, so young that we made our first appearance on +the evening of December~31. It seems that humans managed to arrive just +in time to join the celebration at the end of the year. + +The story of sourdough bread begins in ancient oceans. These oceans were the +birthplace of all Earth's life. To better envision the vast history of +our planet lets create a timeline of 1~year. On this scale, January~1 signifies Earth's +formation 4.54~billion years ago. Midnight on December~31 is our present. +Each day represents roughly 12~million years. This technique simplifies the +complexity of time but also renders the extraordinary expanse of our planet's +history into a more graspable frame. We humans are in fact a recent addition +to our planet, so young that we made appearance on the evening of December~31. +It seems that humans managed to arrive just in time to join +the celebration at year's end. + +On March~25, the oceans birthed the first single-celled bacteria. In these +waters, another single-celled life form, \emph{archaea}, also thrived. These +organisms inhabit extreme environments, from boiling vents to icy waters. + +\begin{figure}[!htb] +\begin{center} + \input{figures/fig-life-planet-sourdough-timeline.tex} + \caption[Sourdough microbiology timeline]{Timeline of significant events + starting from the first day of Earth's existence, + divided into months, and extending to the present day, + marked at midnight. This visualization shows the pivotal steps + of life and sourdough on earth.}% +\end{center} +\end{figure} + +Whoever comes first first, bacteria or archaea, remains debated. For three +months (or approximately 1.1~billion years), these life forms dominated +the oceans. Then, on June~25 in an highly unlikely event, an archaeon consumed a bacterium. +Instead of digesting it, they formed a symbiotic relationship. This led to the +first nucleated organisms, marking an evolutionary milestone. This event lead +to the development of plants, fungi and also ultimately humans. + +Life stayed aquatic for another three months. +On October~4, bacteria first colonized land. By October~15, the +first aquatic fungi appeared. They adapted and, by November~24, had colonized +land. + +By December~3rd, yeasts emerged on land. This laid groundwork for bread-making. +Jump 140~million years to December~14, and dinosaurs arose. Just a couple +of days after their appearance on December~17 the super continent pangea +started to rift apart, reshaping the continents into their current form. +The dinosaurs reigned until December~29 when they faced extinction. +Another 25~million years later, or our timeline's 2~days after the dinosaur +extinction, humans appeared. + +A few hours later after the arrival of humans, a more subtle culinary +revolution was unfolding. By \num{12000}~BC, just 5 seconds before our metaphorical +midnight, the first sourdough breads were being baked in ancient Jordan. A blink of +an eye later, or 4~seconds in our time compression, Pasteur's groundbreaking work +with yeasts set the stage for modern bread-making. From the moment this book +began to take shape to your current reading, only milliseconds have ticked by~\cite{Yong_2017}. + +Now delving deeper into the realm of sourdough, it can likely be traced to aforementioned +Ancient Jordan~\cite{jordan+bread}. Looking at the earth's timeline sourdough +bread can be considered a very recent invention. + +The exact origins of fermented bread are, however, unknown. One of the most ancient preserved -sourdough breads has been excavated in Switzerland. -However, based on recent research, some scientists speculate that sourdough -bread had already been made in \num{12000}~BC in ancient Jordan~\cite{jordan+bread}. +sourdough breads has been excavated in Switzerland~\cite{switzerland+bread}. \begin{figure}[ht] \includegraphics[width=\textwidth]{einkorn-crumb} @@ -28,7 +95,7 @@ dough and at her return a few days later, she noticed that the dough had increased in size and smelled funky. She decided to bake the dough anyway and was rewarded with a much lighter, softer, better tasting bread dough. From that day -on she continued to make bread this way. +on she continued to make bread this way~\cite{egyptian+bread}. Little did the people back then know that tiny microorganisms were the reason the bread was better. It is not clear when diff --git a/book/makefile b/book/makefile index c1af2fe..a480ad2 100644 --- a/book/makefile +++ b/book/makefile @@ -1,6 +1,6 @@ # Macros for commands LATEX := latexmk -cd -pdflua -lualatex="lualatex -interaction=nonstopmode" -synctex=1 -use-make -EBOOK := tex4ebook --lua -d epub -c tex4ebook.cfg +EBOOK := tex4ebook --lua -d epub -f epub -c tex4ebook.cfg WEBSITE := make4ht --lua -c website.cfg -a debug -uf html5+tidy+common_domfilters+dvisvgm_hashes CLEAN := latexmk -cd -lualatex -c -use-make CHECK_1 := lacheck @@ -45,7 +45,7 @@ images += $(foreach directory, $(chapters), $(wildcard $(directory)/*/*.jpg)) images += $(foreach directory, $(chapters), $(wildcard $(directory)/*.png)) images += $(foreach directory, $(chapters), $(wildcard $(directory)/*/*.png)) -# Black and White ebook, we will just re-zip directory after converting the +# Black and White ebook, we will just re-zip directory after converting the # images to lower resolution and greyscale bw_images := $(addprefix bw-book-epub/OEBPS/, $(images)) @@ -87,33 +87,28 @@ book_serif/book.pdf: $(src_all) book_sans_serif/book_sans_serif.pdf: $(src_all) $(LATEX) -output-directory=book_sans_serif book_sans_serif.tex -.PHONY: bw_epub copy_ebook_files +.PHONY: copy_ebook_files epub/%.epub: %.tex $(src_all) cover/cover-page.xbb - $(EBOOK) -f epub $< + $(EBOOK) $< -bw-book-epub: - mkdir -p bw-book-epub - -copy_ebook_files: build_ebook | bw-book-epub +copy_ebook_files: build_ebook $(RSYNC) book-epub/ bw-book-epub/ # We not convert SVG to B&W or lower res for now as they are super small # anyway bw-book-epub/OEBPS/%.jpg: %.jpg + mkdir -p $(dir $@) $(CONVERT_PIC) $< $(REDUCE_PIC) $@ bw-book-epub/OEBPS/%.png: %.png + mkdir -p $(dir $@) $(CONVERT_PIC) $< $(REDUCE_PIC) $@ -bw_ebook.zip: copy_ebook_files $(bw_images) - zip -qXr9D bw_ebook.zip bw-book-epub +epub/bw_book.epub: copy_ebook_files $(bw_images) + cd bw-book-epub; zip -q0X ../epub/bw_book.epub mimetype + cd bw-book-epub; zip -q9XrD ../epub/bw_book.epub ./ -epub/bw_book.epub: bw_ebook.zip - mv bw_ebook.zip epub/bw_book.epub - -bw_epub: epub/bw_book.epub | bw-book-epub - # Now with the rules # Expected usual rules first @@ -280,19 +275,22 @@ website: html ../website/_bundle_install_done $(ruby_src) cd ../website && ruby modify_build.rb # Debug Stuff from now on -.PHONY: quick show_tools_version printvars +.PHONY: quick quick_ebook show_tools_version printvars # Those 2 targets allow fast debug cycles but not resolving references etc +# They also ignore dependencies and run each time you call them. quick: # run latex only once no biber, no references etc... - $(LATEX) -e '$$max_repeat=1' -output-directory=book_serif book.tex + $(LATEX) -e '$$max_repeat=1' -halt-on-error -output-directory=book_serif book.tex quick_ebook: cover/cover-page.xbb # run latex only once no biber, ref etc... - $(EBOOK) --mode draft -f epub book.tex + $(EBOOK) --mode draft book.tex show_tools_version: # Show version of tools used on the build machine - git log -n 1 @echo "" - - ${SHELL} --version + - uname -a + @echo "" + - $(SHELL) --version @echo "" - latexmk --version @echo "" @@ -314,11 +312,10 @@ show_tools_version: # Show version of tools used on the build machine @echo "" - ruby --version @echo "" - - convert --version + - $(CONVERT_PIC) --version @echo "" - rsync --version - # You can find the value of variable X with the following command: # make print-X print-%: ; @echo $* = $($*) # Print a makefile variable diff --git a/book/references.bib b/book/references.bib index 39e1c6d..6184dc4 100644 --- a/book/references.bib +++ b/book/references.bib @@ -98,6 +98,33 @@ howpublished = {\url{https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6077754/}} } +@article{switzerland+bread, + author = {Pasquale Catzeddu}, + title = {Flour and Breads and their Fortification in Health and Disease Prevention}, + pages = {37--46}, + year = {2011} +} + +@book{Yong_2017, + place = {London}, + title = {I contain multitudes: The microbes within US and a grander view of life}, + publisher = {Vintage}, + author = {Yong, Ed}, + year = {2017}, + pages = {5--9} +} + +@article{egyptian+bread, + title = {Investigation of ancient Egyptian baking and brewing methods by correlative microscopy}, + volume = {273}, + DOI = {10.1126/science.273.5274.488}, + number = {5274}, + journal = {Science}, + author = {Samuel, Delwen}, + year = {1996}, + pages = {488–490} +} + @article{vienna+breadrolls, author = {Eben Norton Horsford}, title = {Report on Vienna bread}, diff --git a/book/sourdough_book.tex b/book/sourdough_book.tex deleted file mode 120000 index c0a4f0d..0000000 --- a/book/sourdough_book.tex +++ /dev/null @@ -1 +0,0 @@ -book.tex \ No newline at end of file diff --git a/book/style.css b/book/style.css index 7a1c2a2..7d919df 100644 --- a/book/style.css +++ b/book/style.css @@ -62,6 +62,18 @@ main.main-content,main.titlepage,div.footnotes{ padding:1rem; } +.sectionHead a.permalink { + opacity: 0.5; + text-decoration: none; + font-size: 0.75rem; + vertical-align: top; + line-height: 0.8rem; + margin-left: 0.25rem; + padding-top: 0.2rem; + color: black; + display: inline-block; +} + p.indent, p.noindent{ text-indent: 0; text-align: justify; diff --git a/makefile b/makefile index a52e6e3..2756c5b 100644 --- a/makefile +++ b/makefile @@ -1,45 +1,45 @@ +.DEFAULT_GOAL := build_pdf + DOCKER_IMAGE := ghcr.io/hendricius/the-sourdough-framework +DOCKER_CMD := docker run -it -v $(PWD):/opt/repo $(DOCKER_IMAGE) /bin/bash -c -.PHONY: build_pdf -build_pdf: mrproper - docker run -it -v $(PWD):/opt/repo $(DOCKER_IMAGE) /bin/bash -c "cd /opt/repo/book && make" +.PHONY: bake build_pdf build_docker_image push_docker_image validate website +.PHONY: print_os_version start_shell printvars show_tools_version mrproper -.PHONY: bake -bake: mrproper - docker run -it -v $(PWD):/opt/repo $(DOCKER_IMAGE) /bin/bash -c "cd /opt/repo/book && make bake" - -.PHONY: build_docker_image +# Dockers targets build_docker_image: docker build -t $(DOCKER_IMAGE) -f Dockerfile --progress=plain . -.PHONY: push_docker_image -push_docker_image: +push_docker_image: build_docker_image docker push $(DOCKER_IMAGE):latest -.PHONY: website -website: mrproper - docker run -it -v $(PWD):/opt/repo $(DOCKER_IMAGE) /bin/bash -c "cd /opt/repo/book && make website" +# Books/website -.PHONY: validate -validate: mrproper - docker run -it -v $(PWD):/opt/repo $(DOCKER_IMAGE) /bin/bash -c "cd /opt/repo/book && make -j build_pdf build_ebook" +# Quicker run for each commit, shall catch most problems +validate: + $(DOCKER_CMD) "cd /opt/repo/book && make -j build_serif_pdf build_ebook" + +build_pdf: + $(DOCKER_CMD) "cd /opt/repo/book && make" + +bake: + $(DOCKER_CMD) "cd /opt/repo/book && make -j bake" + +website: + $(DOCKER_CMD) "cd /opt/repo/book && make website" -.PHONY: mrproper mrproper: - docker run -it -v $(PWD):/opt/repo $(DOCKER_IMAGE) /bin/bash -c "cd /opt/repo/book && make mrproper" + $(DOCKER_CMD) "cd /opt/repo/book && make mrproper" -.PHONY: show_tools_version +# Debug helpers show_tools_version: - docker run -it -v $(PWD):/opt/repo $(DOCKER_IMAGE) /bin/bash -c "cd /opt/repo/book && make show_tools_version" + $(DOCKER_CMD) "cd /opt/repo/book && make show_tools_version" -.PHONY: printvars printvars: - docker run -it -v $(PWD):/opt/repo $(DOCKER_IMAGE) /bin/bash -c "cd /opt/repo/book && make printvars" + $(DOCKER_CMD) "cd /opt/repo/book && make printvars" -.PHONY: print_os_version print_os_version: - docker run -it -v $(PWD):/opt/repo $(DOCKER_IMAGE) /bin/bash -c "cat /etc/*release" + $(DOCKER_CMD) "cat /etc/*release" -.PHONY: start_shell start_shell: docker run -it -v $(PWD):/opt/repo $(DOCKER_IMAGE) /bin/bash diff --git a/website/assets/script.js b/website/assets/script.js index 69c4906..e7127e5 100644 --- a/website/assets/script.js +++ b/website/assets/script.js @@ -8,4 +8,14 @@ document.addEventListener('DOMContentLoaded', function() { }); } }); + + // Add permalinks to headers + var heads = document.querySelectorAll('.sectionHead'); + heads.forEach(function (head) { + let permalink = document.createElement("a"); + permalink.href = '#' + head.id; + permalink.classList.add('permalink'); + permalink.append('🔗'); + head.append(permalink); + }); });