diff --git a/.github/workflows/docker-build-push.yml b/.github/workflows/docker-build-push.yml new file mode 100644 index 0000000..0d5801f --- /dev/null +++ b/.github/workflows/docker-build-push.yml @@ -0,0 +1,51 @@ +name: Create and publish a Docker image + +on: + workflow_call: + +jobs: + build-and-push-image: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Log in to the Container registry + uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Figure out branch name + shell: bash + run: echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT + id: extract_branch + - name: Determine docker image tag + shell: bash + id: determine_tag + run: | + if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then + echo "tag=latest" >> $GITHUB_OUTPUT + else + echo "tag=${{ steps.extract_branch.outputs.branch }}" >> $GITHUB_OUTPUT + fi + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + # Buildx for caching + - uses: docker/setup-buildx-action@v3 + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: . + push: true + tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.determine_tag.outputs.tag }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.github/workflows/release-book.yml b/.github/workflows/release-book.yml new file mode 100644 index 0000000..118dca5 --- /dev/null +++ b/.github/workflows/release-book.yml @@ -0,0 +1,71 @@ +name: Release the book + +on: + push: + branches: + - main +env: + IMAGE: ghcr.io/${{ github.repository }}:latest + +jobs: + build-and-push-image: + uses: ./.github/workflows/docker-build-push.yml + + release-book-website: + needs: build-and-push-image + runs-on: ubuntu-latest + steps: + - name: Set up git repository + uses: actions/checkout@v3 + - name: Print dependency versions + uses: addnab/docker-run-action@v3 + with: + image: ${{ env.IMAGE }} + options: -v ${{ github.workspace }}:/app + run: | + cd /app/book + make show_tools_version + - name: Print build variables + uses: addnab/docker-run-action@v3 + with: + image: ${{ env.IMAGE }} + options: -v ${{ github.workspace }}:/app + run: | + cd /app/book + make printvars + - name: Bake the book + uses: addnab/docker-run-action@v3 + with: + image: ${{ env.IMAGE }} + options: -v ${{ github.workspace }}:/app + run: | + cd /app/book + make -j bake + - name: Release baked book to S3 + uses: shallwefootball/s3-upload-action@master + with: + aws_key_id: ${{ secrets.AWS_KEY_ID }} + aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY}} + aws_bucket: ${{ secrets.AWS_BUCKET_BOOK }} + source_dir: book/release + destination_dir: release-recipes + - name: Upload book Artifacts + uses: actions/upload-artifact@v3 + with: + name: books + path: | + book/book_serif/book.log + book/book_serif/book.pdf + book/book-epub/book.epub + invalidate-book-cache: + needs: release-book-website + runs-on: ubuntu-latest + steps: + - name: Invalidate Cloudfront book cache + uses: chetan/invalidate-cloudfront-action@v2 + env: + DISTRIBUTION: ${{ secrets.CLOUDFRONT_DISTRIBUTION_BOOK }} + PATHS: "/*" + AWS_REGION: "us-east-1" + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} \ No newline at end of file diff --git a/.github/workflows/test-book-pull-request.yml b/.github/workflows/test-book-pull-request.yml new file mode 100644 index 0000000..9243cca --- /dev/null +++ b/.github/workflows/test-book-pull-request.yml @@ -0,0 +1,11 @@ +name: Test building book + +on: + pull_request: + +jobs: + + test-building-book: + uses: ./.github/workflows/test-book.yml + with: + docker-image: ghcr.io/${{ github.repository }}:latest diff --git a/.github/workflows/test-book-push.yml b/.github/workflows/test-book-push.yml new file mode 100644 index 0000000..7fe35a6 --- /dev/null +++ b/.github/workflows/test-book-push.yml @@ -0,0 +1,10 @@ +name: Test building book + +on: + push: + +jobs: + test-building-book: + uses: ./.github/workflows/test-book.yml + with: + docker-image: ghcr.io/${{ github.repository }}:latest diff --git a/.github/workflows/test-book.yml b/.github/workflows/test-book.yml new file mode 100644 index 0000000..af02be1 --- /dev/null +++ b/.github/workflows/test-book.yml @@ -0,0 +1,55 @@ +name: Test book for given image + +on: + workflow_call: + inputs: + docker-image: + required: true + type: string + +jobs: + test-book: + runs-on: ubuntu-latest + steps: + - name: Set up git repository + uses: actions/checkout@v3 + - name: Print dependency versions + uses: addnab/docker-run-action@v3 + with: + image: ${{ inputs.docker-image }} + options: -v ${{ github.workspace }}:/app + run: | + cd /app/book + make show_tools_version + - name: Print build variables + uses: addnab/docker-run-action@v3 + with: + image: ${{ inputs.docker-image }} + options: -v ${{ github.workspace }}:/app + run: | + cd /app/book + make printvars + - name: Test baking the book pdf + uses: addnab/docker-run-action@v3 + with: + image: ${{ inputs.docker-image }} + options: -v ${{ github.workspace }}:/app + run: | + cd /app/book + make build_serif_pdf build_ebook + - name: Test baking the book epub + uses: addnab/docker-run-action@v3 + with: + image: ${{ inputs.docker-image }} + options: -v ${{ github.workspace }}:/app + run: | + cd /app/book + make build_ebook + - name: Upload book Artifacts + uses: actions/upload-artifact@v3 + with: + name: books + path: | + book/book_serif/book.log + book/book_serif/book.pdf + book/book-epub/book.epub \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f1a04f0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,43 @@ +.DS_Store +*.xbb +*.aux +*.fdb_latexmk +*.fls +*.log +*.synctex.gz +*.toc +*.pdf +*.bbl +*.bcf +*.blg +*.run.xml +*.html +*.dlog +*.bak +*.opf +book/book.out +.vscode/ +book/bookch* +book/figures/*.png +book/figures/*.pdf +book/figures/*.in +book/book*.4ct +book/book*.4tc +book/book*.css +book/book*.dvi +book/book*.idv +book/book*.lg +book/book*.ncx +book/book*.out +book/book*.tmp +book/book*.xref +book/book*.svg +# Directories created during build +book/book_sans_serif/* +book/book_serif/* +book/static_website_html/* +website/static_website_html/* +book/epub/ +book/book-epub/ +book/bw-book-epub/* +book/release/* diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b20f278 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,62 @@ +FROM debian:trixie + +LABEL "maintainer"="Hendrik Kleinwächter " +LABEL "repository"="https://github.com/hendricius/the-sourdough-framework-recipes" +LABEL "homepage"="https://github.com/hendricius/the-sourdough-framework-recipes" +LABEL org.opencontainers.image.source="https://github.com/hendricius/the-sourdough-framework-recipes" + +# Print release information if needed +RUN cat /etc/*release* + +# Install base depdendencies +RUN apt-get update && \ + apt-get install --yes -y --no-install-recommends \ + sudo \ + make \ + tidy \ + pandoc \ + zip \ + git \ + wget \ + imagemagick \ + rsync \ + wget \ + perl \ + xzdec \ + # dvisvgm dependencies + build-essential \ + fonts-texgyre \ + fontconfig \ + libfontconfig1 \ + libkpathsea-dev \ + libptexenc-dev \ + libsynctex-dev \ + libx11-dev \ + libxmu-dev \ + libxaw7-dev \ + libxt-dev \ + libxft-dev \ + libwoff-dev + +# Install TeX +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + texlive-full \ + texlive-luatex + +# Compile latest dvisvgm +RUN wget https://github.com/mgieseki/dvisvgm/releases/download/3.1.2/dvisvgm-3.1.2.tar.gz && \ + mv dvisvgm-3.1.2.tar.gz dvisvgm.tar.gz && \ + tar -xzf dvisvgm.tar.gz && \ + cd dvisvgm-* && \ + ./configure && \ + make && \ + make install + +# Make sure everything is UTF-8 +RUN echo "export LC_ALL=en_US.UTF-8" >> /root/.bashrc && \ + echo "export LANG=en_US.UTF-8" >> /root/.bashrc + +WORKDIR /root + +CMD ["/bin/bash"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3b7b82d --- /dev/null +++ b/LICENSE @@ -0,0 +1,427 @@ +Attribution-ShareAlike 4.0 International + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More_considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution-ShareAlike 4.0 International Public +License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution-ShareAlike 4.0 International Public License ("Public +License"). To the extent this Public License may be interpreted as a +contract, You are granted the Licensed Rights in consideration of Your +acceptance of these terms and conditions, and the Licensor grants You +such rights in consideration of benefits the Licensor receives from +making the Licensed Material available under these terms and +conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. BY-SA Compatible License means a license listed at + creativecommons.org/compatiblelicenses, approved by Creative + Commons as essentially the equivalent of this Public License. + + d. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + e. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + f. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + g. License Elements means the license attributes listed in the name + of a Creative Commons Public License. The License Elements of this + Public License are Attribution and ShareAlike. + + h. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + i. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + j. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + k. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + l. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + m. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part; and + + b. produce, reproduce, and Share Adapted Material. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. Additional offer from the Licensor -- Adapted Material. + Every recipient of Adapted Material from You + automatically receives an offer from the Licensor to + exercise the Licensed Rights in the Adapted Material + under the conditions of the Adapter's License You apply. + + c. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + b. ShareAlike. + + In addition to the conditions in Section 3(a), if You Share + Adapted Material You produce, the following conditions also apply. + + 1. The Adapter's License You apply must be a Creative Commons + license with the same License Elements, this version or + later, or a BY-SA Compatible License. + + 2. You must include the text of, or the URI or hyperlink to, the + Adapter's License You apply. You may satisfy this condition + in any reasonable manner based on the medium, means, and + context in which You Share Adapted Material. + + 3. You may not offer or impose any additional or different terms + or conditions on, or apply any Effective Technological + Measures to, Adapted Material that restrict exercise of the + rights granted under the Adapter's License You apply. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material, + + including for purposes of Section 3(b); and + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the “Licensor.” The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + +Creative Commons may be contacted at creativecommons.org. diff --git a/README.md b/README.md new file mode 100644 index 0000000..92f21d2 --- /dev/null +++ b/README.md @@ -0,0 +1,71 @@ +# The Sourdough Framework Recipes + +The Sourdough Framework Recipes is an open-source recipe book dedicated to +enabling you make the best possible bread at home. + +![The book cover](book/cover/cover-page.jpg) + +## Background + +4 years after launching the repositories [the-bread-code](https://github.com/hendricius/the-bread-code) +, [pizza-dough](https://github.com/hendricius/pizza-dough) +and [the-sourdough-framework](https://github.com/hendricius/the-sourdough-framework) I +created this project to provide you with easy recipes to bake sourdough bread and yeast-based bread at home. +It is recommended to read The Sourdough +Framework first as it is the basis for the recipes in this book. + + +## 🍞 Baking the book (Docker) + +```console +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 and size optimized Black&White), run: + +```console +make bake +``` + +You can check the files in the folder `book/release/` + +You can get some help on building various versions with: + +```console +cd book/ +make help +``` +## Support + +Did you find a typo, or feel the wording could be improved? +Feel free to open up a pull request at any time. + +I believe that the knowledge this book provides is essential to everyone. +That's why I decided to open source my knowledge hoping +that it will reach more people all over the world without +budget constraints. + +If you would like to contribute with a small donation you can do so +via my [ko-fi page.](https://breadco.de/book) Your donation will tremendously +help me to cover costs related to running the-bread-code. It furthermore allows +me to dedicate time to continuously update and improve this book. + +## Links + +* [The Sourdough Framework](https://github.com/hendricius/the-sourdough-framework) +* [My YouTube channel](https://youtube.com/c/thebreadcode) +* [Ask a question on Discord](https://breadco.de/discord) + +## License + +This work is licensed under a [Creative Commons Attribution-ShareAlike 4.0 +International License][cc-by-sa]. + +[![CC BY-SA 4.0][cc-by-sa-image]][cc-by-sa] + +[cc-by-sa]: http://creativecommons.org/licenses/by-sa/4.0/ +[cc-by-sa-image]: https://licensebuttons.net/l/by-sa/4.0/88x31.png +[cc-by-sa-shield]: https://img.shields.io/badge/License-CC%20BY--SA%204.0-lightgrey.svg diff --git a/book/book.mk4 b/book/book.mk4 new file mode 100644 index 0000000..83932a0 --- /dev/null +++ b/book/book.mk4 @@ -0,0 +1,18 @@ +local filter = require "make4ht-filter" +local removeHeight = function(s) return s:gsub('height="%d+"', '') end +local removeWidth = function(s) return s:gsub('width="%d+"', '') end +local removeMaxWidth = function(s) return s:gsub(' max-width: %d+px;', '') end +local removeFixedSettings = function(s) return removeMaxWidth(removeWidth(removeHeight(s))) end +local process = filter{removeFixedSettings} +local domfilter = require "make4ht-domfilter" + + +filter_settings "collapsetoc" { + toc_query = "nav.TOC" +} + +local domprocess = domfilter{"collapsetoc"} +Make:latexmk {} +-- Make:htlatex {} +Make:match("html$",process) +Make:match("html$",domprocess) diff --git a/book/book.tex b/book/book.tex new file mode 100644 index 0000000..9b64842 --- /dev/null +++ b/book/book.tex @@ -0,0 +1,41 @@ +\documentclass[paper=a4, twoside=false, fontsize=12pt, parskip=half, + bibliography=totoc, listof=totoc]{scrbook} + +% General packages +\usepackage{sourdough} + +% Basic attributes +\author{Hendrik Kleinwächter} +\title{The Sourdough Framework Recipes} + +\begin{document} +\input{cover/cover.tex} +\titlepage + +\frontmatter +{% +\hypersetup{hidelinks} +\ifdefined\HCode\else\tableofcontents\fi +} + +\input{preface/preface} + +\mainmatter + +\chapter{Introduction}% +\input{introduction/introduction} + +\chapter{Whole-grain sandwich loaf}% +\input{whole-grain-sandwich/whole-grain-sandwich} + +\chapter{Brioche buns}% +\input{brioche-buns/brioche-buns} + +\chapter{Naan}% +\input{naan/naan} + +\chapter{Chocolate chip cookies}% +\input{chocolate-chip-cookies/chocolate-chip-cookies} + + +\end{document} diff --git a/book/book_sans_serif.tex b/book/book_sans_serif.tex new file mode 100644 index 0000000..4174a9f --- /dev/null +++ b/book/book_sans_serif.tex @@ -0,0 +1,2 @@ +\def\isaccessible{1} +\input{book.tex} diff --git a/book/brioche-buns/brioche-buns-baking.jpg b/book/brioche-buns/brioche-buns-baking.jpg new file mode 100644 index 0000000..6b058b5 Binary files /dev/null and b/book/brioche-buns/brioche-buns-baking.jpg differ diff --git a/book/brioche-buns/brioche-buns-before-baking.jpg b/book/brioche-buns/brioche-buns-before-baking.jpg new file mode 100644 index 0000000..20234b7 Binary files /dev/null and b/book/brioche-buns/brioche-buns-before-baking.jpg differ diff --git a/book/brioche-buns/brioche-buns.jpg b/book/brioche-buns/brioche-buns.jpg new file mode 100644 index 0000000..3c707b5 Binary files /dev/null and b/book/brioche-buns/brioche-buns.jpg differ diff --git a/book/brioche-buns/brioche-buns.tex b/book/brioche-buns/brioche-buns.tex new file mode 100644 index 0000000..1059b98 --- /dev/null +++ b/book/brioche-buns/brioche-buns.tex @@ -0,0 +1,107 @@ +\noindent\textbf{About this recipe:}\\ +This recipe will make you delicious, buttery fluffy brioche buns. They +can be eaten on its own or used as a basis for burgers. This is my goto recipe +that I have perfected over the years. They can be made both with sourdough and +yeast. The yeasted buns are typically ready within 1 to 2 hours whereas the +sourdough buns will take around 10~hours to complete. + +They can also be frozen and stored for an extended period of time. This +way you will always have fresh buns at hand. + +To really make them shine it is essential to include a high buttery content. +This makes them softer and improves the taste. Furthermore no water is used, +the milk will improve the softness even further. + +\begin{figure}[h] + \centering + \includegraphics[width=\textwidth]{brioche-buns} + \caption{Fluffy buttery brioche buns. The perfect burger companion.} +\end{figure} + +\noindent\textbf{Ingredients:} + +\begin{center} +\begin{tabular}{|c|l|r|r|} + \hline + \textbf{No.} & \textbf{Ingredient} & \textbf{Quantity} & \textbf{Baker's math} \\ + \hline + 1 & All purpose flour & 500 g = 8 buns & 100\% \\ + \hline + 2 & Milk, warm & 200 g & 40\% \\ + \hline + 4 & Butter, warm & 200 g & 40\% \\ + \hline + 3 & Eggs & 2pc & 1 per 250 g flour \\ + \hline + 4 & Sugar & 50 g & 10\% \\ + \hline + 5 & Salt & 10 g & 2\% \\ + \hline + 6 & Sourdough starter & 50 g & 10\% \\ + \hline +\end{tabular} +\end{center} + +\begin{figure}[h] + \centering + \includegraphics[width=\textwidth]{brioche-buns-before-baking} + \caption{Brioche buns ready to be made. This time they have been made with + an addition of 20\% whole-wheat.} +\end{figure} + +\noindent\textbf{Instructions:} +\begin{center} +\begin{tabular}{|c|p{12cm}|} + \hline + \textbf{Step} & \textbf{Instruction} \\ + \hline + 1 & Mix everything together. Wait for 20~minutes and knead for 5~minutes. + The dough should not be overly wet and sticky. If it is too sticky, proceed + and add more flour. Knead a bit more and wait 20~minutes. Make a smooth + dough ball so that the surface you are touching is not too sticky. \\ + \hline + 2 & Stretch and fold once after around 30 minutes. \\ + \hline + 3 & Wait until dough doubled in size, for sourdough aim for a 50\% size + increase. Stretch and fold for sourdough whenever you see the dough + flattens out a lot. \\ + \hline + 4 & Preshape into equally portioned dough balls. Make sure they are nice + and smooth. Do not shape buns, the pre-shaping is sufficient. \\ + \hline + 5 & Place dough balls on a rack with parchment paper. Cover with a wetted + kitchen towel so that they do not dry out. \\ + \hline +\end{tabular} +\end{center} + +\noindent\textbf{Baking:} +To make the buns as soft as possible, make sure to bake them with as much steam +as possible. They are steamed all the way from the start to the end. If you +bake with too little steam they will turn dark too quickly and will be less +soft. Furthermore it is essential to bake at a lower temperature compared to +regular bread. This further improves softness. If you prefer a harder crust, +you can remove the source of steam once the buns no longer expand in size. + +\begin{center} +\begin{tabular}{|c|p{12cm}|} + \hline + \textbf{Step} & \textbf{Instruction} \\ + 1 & Once you see that they have increased by around 25\% in size preheat + the oven to around 180°C (350°F). \\ + \hline + 2 & Cover buns with egg wash. To make the wash mix 1 egg with 100 ml of + water. Place buns in the oven. Bake with as much steam as possible, this + ensures that they become nice and soft. \\ + \hline + 3 & Bake until golden brown. This typically takes around 30 to 40 minutes. \\ + \hline +\end{tabular} +\end{center} + +\begin{figure}[h] + \centering + \includegraphics[width=\textwidth]{brioche-buns-baking} + \caption{When baking more buns on 2~trays make sure to rotate the trays + once while baking. This will ensure even browning and cooking times.} +\end{figure} diff --git a/book/chocolate-chip-cookies/chocolate-chip-cookies-author.jpg b/book/chocolate-chip-cookies/chocolate-chip-cookies-author.jpg new file mode 100644 index 0000000..403a92d Binary files /dev/null and b/book/chocolate-chip-cookies/chocolate-chip-cookies-author.jpg differ diff --git a/book/chocolate-chip-cookies/chocolate-chip-cookies.jpg b/book/chocolate-chip-cookies/chocolate-chip-cookies.jpg new file mode 100644 index 0000000..2344955 Binary files /dev/null and b/book/chocolate-chip-cookies/chocolate-chip-cookies.jpg differ diff --git a/book/chocolate-chip-cookies/chocolate-chip-cookies.tex b/book/chocolate-chip-cookies/chocolate-chip-cookies.tex new file mode 100644 index 0000000..edbceb5 --- /dev/null +++ b/book/chocolate-chip-cookies/chocolate-chip-cookies.tex @@ -0,0 +1,99 @@ +\begin{figure}[h] + \centering + \includegraphics[width=0.3\textwidth]{chocolate-chip-cookies-author} + \caption{Luciano van der Toorn, Athens, Greece} +\end{figure} + +\noindent\textbf{Bio:}\\ +Luciano has been a passionate hobby baker for years +and then decided to focus his efforts on launching +a micro bakery in Greece. He is passionate about +fermenting and making people happy with great bread. + +\noindent\textbf{About this recipe:}\\ +Dive into a world of decadence with these chocolate chip cookies, +where every bite boasts the perfect balance of crisp edges and a soft, +chewy center. Studded generously with melt-in-your-mouth chocolate chunks, +each cookie promises a burst of rich flavor that'll leave you craving just one more. +Handcrafted with love and baked to golden perfection, +these cookies are the ultimate treat for both casual snackers and discerning dessert aficionados. + +\begin{figure}[h] + \centering + \includegraphics[width=0.6\textwidth]{chocolate-chip-cookies.jpg} + \caption{The chocolate chip cookies this recipe makes} +\end{figure} + +\noindent\textbf{Ingredients:} + +\begin{center} +\begin{tabular}{|c|l|r|} + \hline + \textbf{No.} & \textbf{Ingredient} & \textbf{Quantity} \\ + \hline + 1 & Butter, cubed & 115 g \\ + \hline + 2 & Butter, cubed & 55 g \\ + \hline + 3 & Dark brown sugar & 210 g \\ + \hline + 4 & White sugar & 50 g\\ + \hline + 5 & Egg & 1 pc \\ + \hline + 6 & Egg yolk & 2 pcs \\ + \hline + 7 & Vanilla extract & 2 tsp \\ + \hline + 8 & Bread flour & 210 g \\ + \hline + 9 & Salt & 4 g \\ + \hline + 10 & Baking soda & 4 g \\ + \hline + 11 & Choc. chips, 60-70\% cocoa & 170 g\\ + \hline +\end{tabular} +\end{center} + +\noindent\textbf{Instructions:} +\begin{center} +\begin{tabular}{|c|p{12cm}|} + \hline + \textbf{Step} & \textbf{Instruction} \\ + \hline + 1 & On medium heat, brown the \#1 until dark brown. Add to mixing bowl and let cool for 1 minute. \\ + \hline + 2 & Add \#2 to the mixing bowl (should not sizzle/foam), wait until everything is melted. \\ + \hline + 3 & Add \#3 and whisk until no clumps remain, ±30s. Add \#5, mix until incorporated. \\ + \hline + 4 & In a separate bowl, add all ingredients from \#6 and mix briefly. \\ + \hline + 5 & Add mix from step 3 to the mix of step 4, fold using rubber spatula until no dry spots remain. \\ + \hline + 6 & Fold \#7 into mixture. Do not over-mix to prevent gluten formation. \\ + \hline + 7 & Refrigerate (2-5°C) for at least 6 hours, max 5 days, or freeze max 6 months. \\ + \hline + 8 & Using ice cream scoops (size 24/20/16), make round balls and place on parchment lined sheets. \\ + \hline +\end{tabular} +\end{center} + +\noindent\textbf{Baking:} +\begin{center} +\begin{tabular}{|c|p{12cm}|} + \hline + \textbf{Step} & \textbf{Instruction} \\ + \hline + 1 & Baking in pre-heated oven set to 200C. Just before baking, using ice cream scoop (size 24, 20, or 16): Make round balls and place on parchment lined baking sheets. 60x40cm baking sheet holds 6 or 8 cookies. \\ + \hline + 2 & Bake for 10-14 min. at 200°C, no steam. \\ + \hline + 3 & For size 20 scoop: Bake for 14 minutes in deck oven. \\ + \hline + 4 & For size 24 scoop: Bake for 13 minutes in deck oven. \\ + \hline +\end{tabular} +\end{center} diff --git a/book/colors.tex b/book/colors.tex new file mode 100644 index 0000000..a02e515 --- /dev/null +++ b/book/colors.tex @@ -0,0 +1,12 @@ +\definecolor{codeblue}{RGB}{69, 161, 248} +\definecolor{codeblack}{RGB}{40, 40, 40} + +\definecolor{maingray}{HTML}{F8F8F8} + +\definecolor{hlocre}{HTML}{E5B874} +\definecolor{hlorange}{HTML}{EC7850} +\definecolor{hlyellow}{HTML}{FAE69E} + +\definecolor{pinkpic}{RGB}{246, 183, 194} +\definecolor{redpic}{RGB}{232, 72, 71} +\definecolor{yellowpic}{RGB}{246, 235, 51} diff --git a/book/cover/CC-BY-SA.png b/book/cover/CC-BY-SA.png new file mode 100644 index 0000000..0aa2662 Binary files /dev/null and b/book/cover/CC-BY-SA.png differ diff --git a/book/cover/cover-page.jpg b/book/cover/cover-page.jpg new file mode 100644 index 0000000..6bb735d Binary files /dev/null and b/book/cover/cover-page.jpg differ diff --git a/book/cover/cover.tex b/book/cover/cover.tex new file mode 100644 index 0000000..b1526ee --- /dev/null +++ b/book/cover/cover.tex @@ -0,0 +1,44 @@ +\thispagestyle{empty} +\setlength{\unitlength}{1mm} +\makeatletter +\if@twoside% + \noindent\begin{picture}(0,0)(1,-1) + \put(-16.3,-265){\includegraphics[width=1.33\linewidth]{cover/cover-page.jpg}} + \end{picture} +\else% + \noindent\begin{picture}(0,0)(1,-1) + \put(-23.3,-265){\includegraphics[width=1.33\linewidth]{cover/cover-page.jpg}} + \end{picture} +\fi% +\makeatother + +\newpage +\thispagestyle{empty} + +\rule{1pt}{\textheight} % Vertical line + % Whitespace between the vertical line and title page text +\hspace{0.05\textwidth} + % Paragraph box for holding the title page text, adjust the width to move the +% title page left or right on the page +%\raggedleft% +\parbox[b]{0.75\textwidth}{% +{\Huge\bfseries The Sourdough Framework Recipes}\\[2\baselineskip] % Title +{\large\textit{Version: \today}}\\[4\baselineskip] +{\Large\textsc{Hendrik Kleinwächter}} % Author name, lower case for consistent small caps + +% Whitespace between the title block and the copyright text +\vspace{0.5\textheight} + + +{\noindent +\begin{flushleft} + \includegraphics[width=3cm]{cover/CC-BY-SA}\par +The full source code for the book is available at +\url{https://github.com/hendricius/the-sourdough-framework-recipes/} under CC-BY-SA +license. +See \url{https://creativecommons.org/licenses/by-sa/4.0/} for more details. +Do not hesitate to report mistakes or sug\-gestions for +improvements. +\end{flushleft} +} +} diff --git a/book/figures/flowcharts_tikz.tex b/book/figures/flowcharts_tikz.tex new file mode 100644 index 0000000..592e7d9 --- /dev/null +++ b/book/figures/flowcharts_tikz.tex @@ -0,0 +1,32 @@ +\tikzstyle{every picture}+=[font=\footnotesize\sffamily] +\usetikzlibrary{calc, shapes, arrows, decorations.pathreplacing, calligraphy, + positioning} +\tikzstyle{decision} = [diamond, draw=codeblack, fill=codeblack, text=white, + text width=4.5em, text badly centered, node distance=3cm, inner sep=0pt, + line width=2mm] +\tikzstyle{block} = [rectangle, draw=codeblack, fill=white, text=black, + text width=5em, text centered, rounded corners, minimum height=4em, + line width=0.4mm] +\tikzstyle{decision_start} = [diamond, draw=codeblack, fill=pinkpic, text=black, + text width=4.5em, text badly centered, node distance=3cm, inner sep=0pt, + line width=0.4mm] +\tikzstyle{start} = [rectangle, draw=codeblack, fill=pinkpic, text=black, + text width=5em, text centered, rounded corners, minimum height=4em, + line width=0.4mm] +\tikzstyle{success} = [rectangle, draw=codeblack, fill=yellowpic, text=black, + text width=5em, text centered, rounded corners, minimum height=4em, + line width=0.4mm] +\tikzstyle{fail} = [rectangle, draw=codeblack, fill=redpic, text=black, + text width=5em, text centered, rounded corners, minimum height=4em, + line width=0.4mm] +\tikzstyle{line} = [draw, -latex', thick, ->,>=to] + +\tikzstyle{BC} = [decorate, % Brace Calligraphic + 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/figures/vars.tex b/book/figures/vars.tex new file mode 100644 index 0000000..b4bc120 --- /dev/null +++ b/book/figures/vars.tex @@ -0,0 +1,6 @@ +\documentclass[tikz]{standalone} +\usepackage{tikz} +\usepackage[mode=match, reset-text-family=false]{siunitx} +\DeclareSIUnit\degF{\text{°}F} +\input{flowcharts_tikz.tex} +\input{../colors.tex} diff --git a/book/introduction/introduction.tex b/book/introduction/introduction.tex new file mode 100644 index 0000000..6fdc2b6 --- /dev/null +++ b/book/introduction/introduction.tex @@ -0,0 +1,21 @@ +The recipes in this book are provided with the sourdough option by default. + +For every recipe fresh or dry yeast can be used interchangeably. If the recipe +calls for around 10\% of sourdough starter you can replace this with roughly +0.1\% of dry yeast or 0.3\% of fresh yeast. + +If you are in a rush some of the recipes can also be made with more yeast. +This can sometimes make sense if you want to opt for a fast leavened dough +such as burger buns or naans for instance. You can increase the dry yeast +percentage to around 1\% of the flour. If you want to opt for fresh yeast +multiply that with 3. That would be an equivalent of 3\% of fresh yeast in +terms of baker's math. When opting for a faster leavened dough it is +recommended to add some active malt. Opt for around 5\% based on the flour. +The malt will improve the enzymatic activity of your dough and provide better +results when making a faster dough. + +Please note though that while you can speed up the process, this also +reduces the quality of the final bread. A slow fermentation is the key +to making great bread at home. However - sometimes you might be in a rush +and you can increase the fermentation times with the aforementioned tips. +Every homemade bread is better than store-bought bread. \ No newline at end of file diff --git a/book/makefile b/book/makefile new file mode 100644 index 0000000..ecca617 --- /dev/null +++ b/book/makefile @@ -0,0 +1,320 @@ +# Macros for commands +LATEX := latexmk -cd -pdflua -lualatex="lualatex -interaction=nonstopmode" -synctex=1 -use-make +EBOOK := tex4ebook --lua -d epub -f epub -c tex4ebook.cfg +WEBSITE := make4ht --lua -c website.cfg -a debug -uf html5+tidy+common_domfilters +CLEAN := latexmk -cd -lualatex -c -use-make +CHECK_1 := lacheck +CHECK_2 := chktex +CONVERT_PIC := convert +REDUCE_PIC := -resize '800x800>' \ + -strip -interlace Plane -gaussian-blur 0.05 -quality 85\% \ + -set colorspace Gray -separate -evaluate-sequence Mean +RSYNC := rsync -au --exclude 'book.epub' --exclude '*.jpg' --exclude '*.png' + +# We want bash as shell +SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ + else if [ -x /bin/bash ]; then echo /bin/bash; \ + else echo sh; fi; fi) + +ifdef DEBUG +LATEX += -diagnostics +EBOOK += -a debug +WEBSITE += -a debug +endif + +website_dir := static_website_html + +# List all files that are dependencies +chapters = intro + +src_tables := $(wildcard tables/table-*.tex) +src_figures := $(wildcard figures/fig-*.tex) figures/flowcharts_tikz.tex + +src_tex := $(foreach directory, $(chapters), $(wildcard $(directory)/*.tex)) +src_tex += book.tex book_sans_serif.tex references.bib figures/vars.tex +src_tex += sourdough.sty colors.tex + +images := $(wildcard images/*/*.jpg) +images += $(wildcard images/*.jpg) +images += $(wildcard images/*.png) +images += $(wildcard images/*/*.png) +images += $(foreach directory, $(chapters), $(wildcard $(directory)/*.jpg)) +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 +# images to lower resolution and greyscale +bw_images := $(addprefix bw-book-epub/OEBPS/, $(images)) + +src_all := $(src_tex) $(src_figures) $(src_tables) tex4ebook.cfg book.mk4 $(images) + +website_src := $(src_all) website.cfg + +website_assets := $(wildcard ../website/assets/*) +ruby_src := ../website/modify_build.rb $(website_assets) +ruby_pkg := ../website/Gemfile ../website/Gemfile.lock + +tgt_figures := $(patsubst %.tex, %.png,$(src_figures)) + +# Default target is not all because most of the time we just want a pdf... +# and ebook take a long time to build. +.DEFAULT_GOAL := build_serif_pdf + +# Default rules for pdf and ebooks, getting overwritten when built in a +# sub-directory +%.pdf: %.tex + $(LATEX) $< + +# TODO: check if it works on github CI +%.png: %.tex + @echo "\input{./vars.tex}" > $@.in + # \b is backspace.. + @echo "\\\begin{document}" >> $@.in + @cat $< >> $@.in + @echo "\\\end{document}" >> $@.in + $(LATEX) $@.in + figures/export_figures.sh $@.pdf + +%.xbb: %.jpg + ebb -x $< + +book_serif/book.pdf: $(src_all) + $(LATEX) -output-directory=book_serif book.tex + +book_sans_serif/book_sans_serif.pdf: $(src_all) + $(LATEX) -output-directory=book_sans_serif book_sans_serif.tex + +.PHONY: copy_ebook_files + +epub/%.epub: %.tex $(src_all) cover/cover-page.xbb + $(EBOOK) $< + +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) $@ + +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 ./ + +# Now with the rules +# Expected usual rules first +.PHONY: all +all: bake + +.PHONY: help +help: + @echo "" + @echo "default: builds the book in pdf format (serif)" + @echo "" + @echo "all: pdf serif and sans-serif accessible version, as well as ebooks" + @echo " in colour and black&white versions" + @echo "" + @echo "bake: same as build all" + @echo "" + @echo "check: runs static analysis checker on LaTeX source to spot" + @echo " programming or typographic mistakes" + @echo "" + @echo "clean: delete all intermediate files keep targets (pdf/ebooks/website)" + @echo "" + @echo "mrproper: delete all generated files intermediate and pdf/ebooks/website" + @echo " clean_figures: delete intermediate TikZ files" + @echo " clean_website_build: delete intermediate website files" + @echo " clean_ebook_build: delete intermediate ebook files" + @echo "" + @echo "build_pdf: builds both serif and accessible pdf" + @echo "" + @echo "build_ebook: builds only the colour ebook" + @echo "" + @echo "build_bw_ebook: builds the low res black & white ebook" + @echo "" + @echo "build_sans_serif_pdf: build accessible pdf only" + @echo "" + @echo "build_serif_pdf: build serif pdf only" + @echo "" + @echo "figures: build TikZ figures" + @echo "" + @echo "release_serif: build serif only version of pdf and ebooks" + @echo "release_sans_serif: build sans-serif/accessible version of pdf" + @echo "" + @echo "website: build the static website from LaTeX sources and post-process it" + @echo "html: build the static website from LaTeX sources _without_ post-processing" + @echo "" + @echo "Debug targets:" + @echo "" + @echo "quick: compiles serif_pdf but runs lulatex only once" + @echo "" + @echo "quick_ebook: compiles ebook but runs lulatex only once" + @echo "" + @echo "show_tools_version: Show version of tools used on the build machine" + @echo "" + @echo "print-X: print makefile variable X" + @echo "" + @echo "printvars: print all variables in the makefile" + @echo "" + @echo "set DEBUG i.e make DEBUG=1 build_ebook to add debug flags to commands" + + +# Finally actual project targets (i.e. build pdf and ebooks) +.PHONY: build_pdf build_serif_pdf build_sans_serif_pdf build_ebook + +build_pdf: build_serif_pdf build_sans_serif_pdf + +build_serif_pdf: book_serif/book.pdf + +build_sans_serif_pdf: book_sans_serif/book_sans_serif.pdf + +build_ebook: epub/book.epub + +build_bw_ebook: epub/bw_book.epub + +# Goal is not really to have 0 warning reported but we should check we don't +# add many and if we do, we know they are false positive +check: $(SRC_TEX) + @echo "Running: " $(CHECK_1) + $(CHECK_1) book.tex + @echo "" + @echo "Running: " $(CHECK_2) + $(CHECK_2) book.tex + + +# Clean up and delete generated files +.PHONY: clean_figures clean_ebook_build clean_website_build clean mrproper +clean_figures: + - $(CLEAN) $(patsubst %.tex, %.png.in, $(src_figures)) + - rm $(patsubst %.tex, %.png.pdf, $(src_figures)) + - rm $(patsubst %.tex, %.png.in, $(src_figures)) + - rm $(wildcard figures/*.png.*) + - rm cover/cover-page.xbb + +clean_ebook_build: + -rm book*.{4ct,4tc,aux,bbl,bcf,blg,dvi,fdb_latexmk,fls,html} + -rm book*.{idv,lg,loc,log,ncx,run.xml,tmp,xref} + -rm book*x.svg + -rm book.css + -rm content.opf + +clean_website_build: clean_ebook_build + -rm book-*.svg + -rm book.{loc,dlog} + -rm $(subst $(website_dir)/,, $(wildcard $(website_dir)/*.html)) + +clean: clean_ebook_build clean_figures clean_website_build + $(CLEAN) -output-directory=book_serif book.tex + $(CLEAN) -output-directory=book_sans_serif book_sans_serif.tex + -rm book*/*.{bbl,loc,.run.xml} + -rm -rf book*-epub/META-INF + -rm -rf book*-epub/OEBPS + -rm book*-epub/mimetype + +mrproper: clean + $(CLEAN) -C $(src_figures) + $(CLEAN) -C -output-directory=book_serif book.tex + $(CLEAN) -C -output-directory=book_sans_serif book_sans_serif.tex + -rm -rf figures/*.png + -rm -rf *.html + -rm -rf *.svg + -rm -rf epub/ + -rm -rf release/ + -rm -rf book_serif/ + -rm -rf book_sans_serif/ + -rm -rf book-epub/ + -rm -rf $(website_dir) + +# top level releases rules +.PHONY: bake release_serif release_sans_serif + +bake: release_serif release_sans_serif + +release: + mkdir -p release + +release_serif: build_serif_pdf build_ebook build_bw_ebook | release + cp book_serif/book.pdf release/TheBreadCode-The-Sourdough-Framework-Recipes.pdf + cp epub/book.epub release/TheBreadCode-The-Sourdough-Framework-Recipes.epub + cp epub/bw_book.epub release/TheBreadCode-The-Sourdough-Framework-Recipes-black-and-white.epub + +release_sans_serif: build_sans_serif_pdf | release + cp book_sans_serif/book_sans_serif.pdf release/TheBreadCode-The-Sourdough-Framework-recipes-sans-serif.pdf + +# Website stuff +.PHONY: html website +$(website_dir)/book.html: $(website_src) cover/cover-page.xbb + $(WEBSITE) -d $(website_dir) book.tex + +html: $(website_dir)/book.html + cp $< $(website_dir)/index.html + +# Because packages will be installed in hard to predict places use a file as +# marker.. +../website/_bundle_install_done: $(ruby_pkg) + - rm ../website/$@ + cd ../website && bundle install + touch ../website/$@ + +# TODO: this will run every single time, but is so fast we don't really care +website: html ../website/_bundle_install_done $(ruby_src) + cd ../website && ruby modify_build.rb + +# Debug Stuff from now on +.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' -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 book.tex + +show_tools_version: # Show version of tools used on the build machine + - git log -n 1 + @echo "" + - uname -a + @echo "" + - $(SHELL) --version + @echo "" + - latexmk --version + @echo "" + - lualatex --version + @echo "" + - tex4ebook --version + @echo "" + - make4ht --version + @echo "" + - tidy -version + @echo "" + - dvisvgm --version + @echo "" + - lacheck --version + @echo "" + - chktex --version + @echo "" + - make --version + @echo "" + - biber -version + @echo "" + - ruby --version + @echo "" + - $(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 + +printvars: # Print all variables in the makefile + @$(foreach V,$(sort $(.VARIABLES)), \ + $(if $(filter-out environ% default automatic, \ + $(origin $V)),$(info $V=$($V) ($(value $V))))) diff --git a/book/naan/naan-traditional.jpg b/book/naan/naan-traditional.jpg new file mode 100644 index 0000000..8e46843 Binary files /dev/null and b/book/naan/naan-traditional.jpg differ diff --git a/book/naan/naan.jpg b/book/naan/naan.jpg new file mode 100644 index 0000000..3be6cde Binary files /dev/null and b/book/naan/naan.jpg differ diff --git a/book/naan/naan.tex b/book/naan/naan.tex new file mode 100644 index 0000000..c45396b --- /dev/null +++ b/book/naan/naan.tex @@ -0,0 +1,112 @@ +\noindent\textbf{About this recipe:}\\ +This recipe will provide you with delicious and fluffy naan bread. +While traditional naan bread is not leavened and made with the help of +a hot Tandoor oven, this recipe is tailored to be made with your +home oven setup. + +This recipe takes around 2 hours to complete when opting for the yeast based +dough. When using the sourdough option replace the yeast with around 10 +percent sourdough starter based on the flour. The sourdough option will take +longer to bulkferment but will present superb slightly tangy tasting naans. + +\begin{figure}[h] + \centering + \includegraphics[width=0.6\textwidth]{naan} + \caption{Fluffy naans topped with garlic butter} +\end{figure} + +\noindent\textbf{Ingredients:} + +\begin{center} +\begin{tabular}{|c|l|r|r|} + \hline + \textbf{No.} & \textbf{Ingredient} & \textbf{Quantity} & \textbf{Baker's math} \\ + \hline + 1 & All purpose flour & 400 g = 4 pieces & 100\% \\ + \hline + 2 & Water, warm & 160 g & 40\% \\ + \hline + 3 & Yogurt & 160 g & 40\% \\ + \hline + 4 & Butter & 40 g & 10\% \\ + \hline + 5 & Sugar & 12 g & 3\% \\ + \hline + 6 & Salt & 8 g & 2\% \\ + \hline + 7 & Sourdough starter & 40 g & 10\% \\ + \hline +\end{tabular} +\end{center} + +\noindent\textbf{Instructions:} +\begin{center} +\begin{tabular}{|c|p{12cm}|} + \hline + \textbf{Step} & \textbf{Instruction} \\ + \hline + 1 & Mix everything together. No need to heavily knead. Just stir it with + your hands. Let it rest for 20 minutes. This will help the gluten to + develop. Add the butter directly. The dough should not be too wet, + if you feel it is too sticky, proceed and add more flour. Make sure + to create a smooth dough ball before proceeding. \\ + \hline + 2 & Stretch and fold if you see the dough flattened out a lot \\ + \hline + 3 & Wait 30~minutes (different for sourdough) \\ + \hline + 4 & Stretch and fold if you see the dough flattened out a lot \\ + \hline + 5 & Wait until the dough is doubled in size, preshape into equally portioned + dough balls For the sourdough option aim for a 50\% size increase \\ + \hline + 6 & Preheat oven to max temperature for around 30~minutes \\ + \hline +\end{tabular} +\end{center} + +\noindent\textbf{Baking:} +\begin{center} +\begin{tabular}{|c|p{12cm}|} + \hline + \textbf{Step} & \textbf{Instruction} \\ + \hline + 1 & Stretch dough balls with hands. Use flour to make it non stick. Try to + degas the dough balls as little as possible while stretching. Similar to + making a pizza. \\ + \hline + 2 & Place naans on rack, stone or steel. Optional: Cover naans with melted + butter and garlic mixture. \\ + \hline + 3 & Bake until golden brown. Eat while still hot, or wrap in towel to + preserve moisture if eating later. When eating next day, rinse with water + and heat again in oven. \\ + \hline +\end{tabular} +\end{center} + +It is essential to have as high heat as possible during baking. This will give +the naan it's typical texture. For this reason if you have a broiler activate +it and bake the breads as close to it as possible. + +You can also bake the naans in a hot pan. In this case make sure to use a lid +on the pan to ensure even cooking from the evaporating steam. Flip the Naans +once and bake until golden brown. Try to push the naans down a bit after +flipping. This ensures that they bake evenly and do not have too charred +parts. + +Another option is to bake the naans on your bbq. Place the Naans on the hot +rack. Flip the Naans once after they can be removed from the rack with a +spatula. Bake until golden brown. + +The last option could be to purchase a Tandoor oven and bake it inside of it. +Place the Naans on the hot side of the Tandoor. Wait until they can be removed +from the side. Your naan is done. + +\begin{figure}[h] + \centering + \includegraphics[width=\textwidth]{naan-traditional} + \caption{Traditional naans are not leavened. The dough only consists of + flour, water and salt. The dough becomes fluffy due to the hot heat of the + tandoor oven. In this case, I used a pizza oven to reach 500°C (900°F)} +\end{figure} diff --git a/book/preface/gluten-tag.jpg b/book/preface/gluten-tag.jpg new file mode 100644 index 0000000..ff60b46 Binary files /dev/null and b/book/preface/gluten-tag.jpg differ diff --git a/book/preface/preface.tex b/book/preface/preface.tex new file mode 100644 index 0000000..0130914 --- /dev/null +++ b/book/preface/preface.tex @@ -0,0 +1,29 @@ +\chapter{Preface}% + +\begin{figure}[h] + \centering + \includegraphics[width=\textwidth]{gluten-tag} +\end{figure} + +Gluten Tag! + +Welcome to \textit{The Sourdough Framework Recipes}, a culinary compendium for +home bakers. This book is a sequel to \textit{The Sourdough Framework (TSF)} and builds upon +its knowledge. For this reason, it is recommended to read \textit{TSF} before following the recipes +shown in this book. + +Herein, you will find a blend of my baking insights and recipes from me and our global +community. This collection showcases the rich diversity of bread making, +featuring recipes from various cultures. It's more than a recipe book; it's a +celebration of global flavors and techniques. The goal of this book is to provide +you with inspiration for your daily bread-making. + +\textit{The Sourdough Framework Recipes} is a living testament to the communal +spirit of baking. I warmly invite you to contribute your recipes. This book +is an ongoing work and I hope that it becomes a great source of reference in the future. + +\bigskip + +Happy baking! + +\textbf{Hendrik} diff --git a/book/references.bib b/book/references.bib new file mode 100644 index 0000000..e69de29 diff --git a/book/sourdough.sty b/book/sourdough.sty new file mode 100644 index 0000000..c8973ec --- /dev/null +++ b/book/sourdough.sty @@ -0,0 +1,284 @@ +\ProvidesPackage{sourdough} +\usepackage{blindtext} +\usepackage{graphicx} +\usepackage{booktabs} +\usepackage{longtable} +\usepackage{chemformula} +\usepackage{chemfig} +\usepackage{booktabs} +\usepackage{makecell} +\usepackage[mode=match, reset-text-family=false]{siunitx} +\usepackage{fontspec} +\usepackage{calc} +\usepackage[font={sffamily, sbseries}]{quoting} +\usepackage{microtype} + +% style=nextline breaks on make4ht +\ifdefined\HCode\else +\usepackage{enumitem} +\setlist[description]{style=nextline, leftmargin=0cm} +\fi + +\DeclareNewTOC[ + type=flowchart,% + types=flowcharts,% , + float, + floattype=4,% + name=Flowchart,% + listname = {List of Flowcharts} +]{loc} +\setuptoc{loc}{chapteratlist} +\DeclareTOCStyleEntry[numwidth=3em]{tocline}{figure} + +% Common abbreviations +\newcommand{\ie}{\emph{i.e.}\@ifnextchar.{\!\@gobble}{}} +\newcommand{\eg}{\emph{e.g.}\@ifnextchar.{\!\@gobble}{}} + +% Consistent pH values +\newcommand{\pHvalue}[1]{pH~\SI{#1}{}} + +% For tables +\renewcommand\theadfont{\bfseries} + +\input{colors.tex} +% Define flowcharts macros independently so we can build them as png files +% for the website or something. This is supported in the makefile +\input{figures/flowcharts_tikz.tex} +% Fonts +\defaultfontfeatures{Scale=MatchLowercase, Ligatures=TeX} +% Define Semi-bold +\DeclareRobustCommand\sbseries{\fontseries{sb}\selectfont} +% Fonts for accessibility +\ifdefined\isaccessible + \setmainfont{Open Sans}[ + Scale=MatchLowercase] +\else + \setmainfont{TeX Gyre Pagella}[Scale=1.0] % Or Palatino Linotype, etc. + % TODO not available on github CI + % \setmonofont{Andale Mono}[Scale=MatchLowercase] +\fi +% Opens Sans in both case.. +\setsansfont{Open Sans}[ + Scale=MatchLowercase, + FontFace = {sb}{it}{* Semibold Italic}, + FontFace = {sb}{n}{*-semibold}] + +% Kerning in footnotes +\usepackage{fnpct} + +% References +\usepackage[backend=biber]{biblatex} +\addbibresource{references.bib} + +% Clickable links in the table of contents +\usepackage[ocgcolorlinks]{hyperref} +\usepackage{bookmark} +\hypersetup{% + linktoc=all, + linkcolor = hlorange, + urlcolor = codeblue, + citecolor = hlocre, + breaklinks = true, + pdfinfo={% + Title={The Sourdough Framework Recipes}, + Author={Hendrik Kleinw\"achter}, + Subject={The sourdough framework recipes}, + Keywords={Sourdough, dough, bread, wheat, baking, bake, home-baking, + yeast, rye, crumb, debug, gluten, dough strength, crust, DIY, + framework, https://the-sourdough-framework.com, + https://www.the-bread-code.io/, + https://github.com/hendricius/the-sourdough-framework-recipes, + open-source, CC-BY-SA} + } +} + + +% Folders where to search for images +\graphicspath{ + {images/} + {naan/} + {brioche-buns/} + {chocolate-chip-cookies/} + {whole-grain-sandwich/} + {preface/} +} + +% Caption and figure size below images +\usepackage{caption} +\captionsetup[figure]{font=footnotesize} + +\DeclareSIUnit\degF{\text{°}F} + +%----------------------------------------------------------------------------- +% KAO CHAPTER HEADING STYLES +%----------------------------------------------------------------------------- + +\newlength{\hscale} +\newlength{\vscale} +\newlength{\mtocshift} + +% By default, the scales are set to work for a4paper +\setlength{\hscale}{1mm} +\setlength{\vscale}{1mm} + +\newif\ifwidelayout% +\def\IfWideLayout{% + \ifwidelayout% + \expandafter\@firstoftwo% + \else% + \expandafter\@secondoftwo% + \fi% +} + +% Command to easily switch between chapter styles +\DeclareDocumentCommand{\setchapterstyle}{m}{% + \ifthenelse{\equal{plain}{#1}}{\chapterstyleplain}{} + \ifthenelse{\equal{bar}{#1}}{\chapterstylebar}{} + \ifthenelse{\equal{lines}{#1}}{\chapterstylelines}{} + \ifthenelse{\equal{kao}{#1}}{\chapterstylekao}{} +} + +% The default definition in KOMA script +\DeclareDocumentCommand{\chapterstyleplain}{}{% + \renewcommand{\chapterlinesformat}[3]{% + \@hangfrom{##2}{##3}} + \renewcommand*{\chapterformat}{% + \mbox{\chapappifchapterprefix{\nobreakspace}\thechapter% + \autodot\IfUsePrefixLine{}{\enskip}}} + \RedeclareSectionCommand[beforeskip=0cm,afterskip=10\vscale]{chapter} + \setlength{\mtocshift}{-1\vscale} +} + +% Gray bar +\DeclareDocumentCommand{\chapterstylebar}{}{% + \renewcommand*{\chapterformat}{% + \mbox{\chapappifchapterprefix{\nobreakspace}\thechapter% + \autodot\IfUsePrefixLine{}{\enskip}}% + } + \renewcommand{\chapterlinesformat}[3]{% + \begin{tikzpicture}[remember picture, overlay] + \node[ + anchor=south west, + xshift=\dimexpr - \hoffset - \oddsidemargin - 1in -1mm,%-30\hscale, + yshift=4.3mm, + rectangle, + fill=gray!20!white, + fill opacity=0.8, + inner ysep=5\vscale, + inner xsep=\dimexpr \hoffset + \oddsidemargin + 1in,%30\hscale, + text opacity=1, + text width=\paperwidth-40\hscale, + ]{\@hangfrom{##2}{##3}}; + \end{tikzpicture} + } + \RedeclareSectionCommand[beforeskip=-55\vscale,afterskip=6\vscale]{chapter} + \setlength{\mtocshift}{-1\vscale} +} + +% Lines +\renewcommand{\hrulefill}[1][0.4pt]{% + \leavevmode\leaders\hrule height #1\hfill\kern\z@% +} + +\DeclareDocumentCommand{\chapterstylelines}{}{% + \renewcommand*{\chapterformat}{% + \chapappifchapterprefix{\nobreakspace}\scalebox{3.5}{\thechapter\autodot}% + }% + \renewcommand\chapterlinesformat[3]{% + %\vspace*{-1cm}% + \leavevmode% + \makebox[0pt][l]{% + \makebox[\textwidth][l]{\hrulefill[1pt]##2}%\hfill%\par%\bigskip + \makebox[\marginparsep][l]{}% + \makebox[\marginparwidth][l]{}% + }\\ + %\vspace{.5cm} + \makebox[0pt][l]{% + \makebox[\textwidth][l]{##3}% + \makebox[\marginparsep][l]{}% + \makebox[\marginparwidth][l]{}% + }\\ + \makebox[0pt][l]{% + \makebox[\textwidth+\marginparsep+\marginparwidth][l]{\hrulefill[1.1pt]}% + }% + \RedeclareSectionCommand[beforeskip=0cm,afterskip=10\vscale]{chapter} + \setlength{\mtocshift}{-1\vscale}% +} +} +% The Kao style +\DeclareDocumentCommand{\chapterstylekao}{}{% + \IfWideLayout{% + \renewcommand*{\chapterformat}{% + \mbox{\chapappifchapterprefix{\nobreakspace}\scalebox{2.85}{\thechapter\autodot}}% + }% + \renewcommand\chapterlinesformat[3]{% + \vspace{3.5\vscale}% + \if@twoside% + \Ifthispageodd{% + \smash{\makebox[0pt][l]{% + \parbox[b]{\textwidth - 6.2\hscale}{\flushright{##3}}% + \makebox[6.2\hscale][c]{\rule[-2\vscale]{1pt}{27.4\vscale+\f@size mm}}% + \parbox[b]{\marginparwidth}{##2}% + }}% + }{ + \smash{\makebox[\textwidth + 6.2\hscale][r]{% + \parbox[b]{47.7\hscale + 6.2\hscale}{\flushright{##2}}% + \makebox[6.2\hscale][c]{\rule[-2\vscale]{1pt}{27.4\vscale+\f@size mm}}% + \parbox[b]{\textwidth}{\flushleft{##3}}% + }}% + } + \else% + \smash{\makebox[0pt][l]{% + \parbox[b]{\textwidth - 6.2\hscale}{\flushright{##3}}% + \makebox[6.2\hscale][c]{\rule[-2\vscale]{1pt}{27.4\vscale+\f@size mm}}% + \parbox[b]{\marginparwidth}{##2}% + }}% + \fi% + }% + }{% + \renewcommand*{\chapterformat}{% + \mbox{\chapappifchapterprefix{\nobreakspace}\scalebox{2.85}{\thechapter\autodot}}% + }% + \renewcommand\chapterlinesformat[3]{% + \vspace{3.5\vscale}% + \if@twoside% + \Ifthispageodd{% + \smash{\makebox[0pt][l]{% + \parbox[b]{\textwidth}{\flushright{##3}}% + \makebox[\marginparsep][c]{\rule[-2\vscale]{1pt}{27.4\vscale+\f@size mm}}% + \parbox[b]{\marginparwidth}{##2}% + }}% + }{ + \smash{\makebox[\textwidth][r]{% + \parbox[b]{\marginparwidth}{\flushright{##2}}% + \makebox[\marginparsep][c]{\rule[-2\vscale]{1pt}{27.4\vscale+\f@size mm}}% + \parbox[b]{\textwidth}{\flushleft{##3}}% + }}% + } + \else% + \smash{\makebox[0pt][l]{% + \parbox[b]{\textwidth}{\flushright{##3}}% + \makebox[\marginparsep][c]{\rule[-2\vscale]{1pt}{27.4\vscale+\f@size mm}}% + \parbox[b]{\marginparwidth}{##2}% + }}% + \fi% + }% + }% + \RedeclareSectionCommand[beforeskip=0cm,afterskip=10\vscale]{chapter}% + \setlength{\mtocshift}{-3.5\vscale}% +} + +% Takes as input the image path and optionally the "beforeskip" +\DeclareDocumentCommand{\setchapterimage}{O{55\vscale} m}{% + \setchapterpreamble[o]{% + \vspace*{-27\vscale}\hspace*{\dimexpr - \hoffset - \oddsidemargin - 1in}% + \includegraphics[width=\paperwidth,height=#1+27\vscale,keepaspectratio=false]{#2}% + }% + \chapterstylebar% + % beforeskip=-(figure_height-top_margin) + \RedeclareSectionCommand[beforeskip=-#1, afterskip=6\vscale]{chapter}% + \setlength{\mtocshift}{0cm}% +} + +% By default start with the lines style +\setchapterstyle{lines} diff --git a/book/style.css b/book/style.css new file mode 100644 index 0000000..02bcbc5 --- /dev/null +++ b/book/style.css @@ -0,0 +1,381 @@ +@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;800&display=swap'); + +:root{ + --ff-sans: 'Open Sans', sans-serif; + --fw-regular: 400; + --fw-bold: 800; + --f-lh: 28px; + --c-black: #282828; + --fs-xxxl: 32px; + --fs-xxl: 26px; + --fs-xl: 24px; + --fs-l: 22px; + --fs-m: 16px; + --padding-hamburger: 5px; +} + +@media (min-width: 1200px){ + :root { + font-size: 1.5vw; + } +} + +/* Maximal font size should be 24px, so stop font scalling at some point (24 / (1.5/100)) */ + +@media (min-width: 1500px){ + :root { + font-size: 20px; + } +} + +/* ************** */ +/* *** Layout *** */ +/* ************** */ + +body{ + margin:0; + padding:0; + font-family: var(--ff-sans); + font-weight: var(--fw-regular); + font-size: var(--fs-m); +} + +@media screen and (min-width: 57rem) { + body{ + display:grid; + grid-template-columns: 15rem 1fr; + } + main.main-content, main.titlepage, div.footnotes{max-width:40rem;grid-column: 2} + main.titlepage {grid-row: 1;} + nav.TOC{ + grid-row:1; + grid-column: 1; + min-height:100vh; + } +} + + +/* ****************** */ +/* *** Formatting *** */ +/* ****************** */ + +main.main-content,main.titlepage,div.footnotes{ + padding:1rem; +} + +.permalink { + opacity: 0.5; + text-decoration: none; + font-size: 0.75rem; + line-height: 0.8rem; + margin-left: 0.25rem; + color: black; + display: inline-block; +} + +.sectionHead, .subsectionHead { + display: flex; + align-items: center; + align-content: center; +} + +p.indent, p.noindent{ + text-indent: 0; + text-align: justify; +} +/* code{font-size:1.4rem;} */ +/* figure pre.listings{font-size: 1.4rem;} */ +figure.texsource, figure.shellcommand, figure.htmlsource, figure.luasource, figure.textsource{ + margin:0.5rem 0; + padding-left:0.5rem; + overflow:auto; +} +figure pre.listings{font-size: 1em;} + +.chapterToc, .sectionToc, .subsectionToc{margin:0;padding:0;} +nav.TOC{ + font-size:0; /* trick to remove vertical space above TOC entries */ +} + + .chapterToc ~ .likesectionToc, .chapterToc ~ .sectionToc, .likechapterToc ~ .likesectionToc, .likechapterToc ~ .sectionToc {padding-left:2em;margin-left:0} + .chapterToc ~ .likesectionToc ~ .likesubsectionToc, .chapterToc ~ .likesectionToc ~ .subsectionToc, .chapterToc ~ .sectionToc ~ .likesubsectionToc, .chapterToc ~ .sectionToc ~ .subsectionToc, .likechapterToc ~ .likesectionToc ~ .likesubsectionToc, .likechapterToc ~ .likesectionToc ~ .subsectionToc, .likechapterToc ~ .sectionToc ~ .likesubsectionToc, .likechapterToc ~ .sectionToc ~ .subsectionToc {padding-left:4em;margin-left:0;} + +nav.TOC span{ + margin-top:0; + font-size: 16px; +} + +nav.TOC a, nav.TOC a:visited{ + text-decoration:none; +} + +.chapterToc, +.sectionToc, +.subsectionToc, +.likechapterToc { + display: block; +} + +.chapterToc a, +.sectionToc a, +.subsectionToc a, +.likechapterToc a { + display: flex; + flex-grow: 1; + padding: 7px 10px 7px 15px; + justify-content: flex-start; + align-items: center; +} + +.chapterToc span, +.sectionToc span, +.subsectionToc span { + display: block; +} + +.chapterToc .chapter_number, .sectionToc .chapter_number, .subsectionToc .chapter_number { + margin-right: 7px; + white-space: nowrap; +} + +/* ************** */ +/* *** Colors *** */ +/* ************** */ + + +body{ + background-color: var(--c-black); +} + +a { + color: #5D9FF0; +} + +main.main-content, div.footnotes, main.titlepage{ + background-color:white; +} + +nav.TOC,nav.TOC a, nav.TOC a:visited{ + background-color: var(--c-black); + color:#fff; +} + +nav.TOC span:hover, +nav.TOC span:hover *, +nav.TOC span.chapterToc.selected, +nav.TOC span.chapterToc.selected a { + background-color:#5b5a58; +} + +figure.texsource, figure.shellcommand, figure.htmlsource, figure.luasource, figure.textsource{ + border:1px solid #cec1aa; + background-color:#d5e3c6; +} + +.main-content { + line-height: var(--f-lh); +} + +div.footnotes { + border: none; + margin-right: 0; +} + +.footnote-mark { + margin-right: 3px; +} + +table.tabular { + width: 100%; +} + +figure.figure { + margin: 30px 0px 30px 0px;; + text-align: center; + padding: 0; +} + +figcaption.caption { + text-indent: 0; + margin: 0; +} + +.table div.center, .table div.center div.center { + margin: 0; +} + +.table, div.tabular { + overflow-x: auto; +} + +.table table { + width: 100%; +} + +.menu { + position: relative; +} + +.toggle-menu-label { + display: none; +} + +.menu input { + display: none; +} + +.menu-items { + display: block; + list-style: none; + margin: 0; + padding: 0; +} + +.menu-items .chapterToc, .menu-items .likechapterToc { + display: block; +} + +.menu-items a { + text-decoration: none; +} + +.home-link { + display: block; +} + +.home-title { + display: block; +} + +@media (max-width: 768px) { + .toggle-menu-label { + display: block; + padding: 10px; + cursor: pointer; + } + + .hamb{ + cursor: pointer; + padding: var(--padding-hamburger); + margin-right: calc(var(--padding-hamburger) * -1); + display: flex; + align-items: center; + align-content: center; + justify-content: center; + } + + .hamb-line { + display: block; + filter: brightness(0) invert(1); + background: url("menu.svg") no-repeat center center; + background-size: contain; + width: 30px; + height: 30px; + font-size: 0px; + } + + span.hamb-line:hover { + background-color: transparent !important; + font-size: 0px; + } + + .menu-items { + display: none; + position: absolute; + top: 100%; + left: 0; + width: 100%; + background-color: var(--c-black); + z-index: 1; + } + + .menu { + background: var(--c-black); + display: flex; + padding: 10px 1rem; + position: relative; + align-items: center; + justify-content: space-between; + } + + #toggle-menu:checked ~ .menu-items { + display: block; + } + #toggle-menu:checked ~ .toggle-menu-label span { + background-image: url("close.svg"); + background-color: transparent !important; + } + + .logo { + display: block; + color: #000; + font-size: 20px; + font-weight: bold; + } + + .chapterToc a, .sectionToc a, .subsectionToc a, .likechapterToc a { + padding-left: 17px; + } + + .menu-items .chapterToc.home-link { + display: none; + } + + .home-title { + display: none; + } +} + +div.center { + margin-left: 0 !important; + margin-right: 0 !important; +} + +main.titlepage h2.chapterHead { + margin-top: 0px; +} + +h1 { + font-weight: var(--fw-bold); + text-transform: uppercase; + font-size: var(--fs-xxxl); +} + +h2 { + font-weight: var(--fw-bold); + text-transform: uppercase; + font-size: var(--fs-xxl); +} + +h3 { + font-weight: var(--fw-bold); + text-transform: uppercase; + font-size: var(--fs-xl); +} + +h4 { + font-weight: var(--fw-bold); + text-transform: uppercase; + font-size: var(--fs-l); +} + +.videoWrapper { + position: relative; + padding-bottom: 56.25%; + /* 16:9 */ + padding-top: 25px; + height: 0; +} + +.videoWrapper iframe { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.home-bread { + max-width: 100%; + margin-top: 1em; +} diff --git a/book/tex4ebook.cfg b/book/tex4ebook.cfg new file mode 100644 index 0000000..ca6cf6c --- /dev/null +++ b/book/tex4ebook.cfg @@ -0,0 +1,13 @@ +\Preamble{xhtml} +\renewcommand\listofflowcharts{% +\chapter*{\listoflocname}% +\TableOfContents[loc]% +} +\ConfigureToc{loc}{\HCode{}}{\ }{}{\HCode{
}} +\begin{document} +\Configure{DocumentLanguage}{en} +\Configure{OpfScheme}{URI} +\Configure{UniqueIdentifier}{https://the-bread-code.io} +\Configure{CoverMimeType}{image/jpeg} +\CoverMetadata{cover/cover-page.jpg} +\EndPreamble diff --git a/book/website.cfg b/book/website.cfg new file mode 100644 index 0000000..aa15921 --- /dev/null +++ b/book/website.cfg @@ -0,0 +1,43 @@ +\Preamble{xhtml,2,sec-filename,fn-in,fonts,svg,mathml,mathjax,nostyle} +\DeclareGraphicsExtensions{.png,.svg,.jpg,.jpeg,.JPG,.eps,.pdf,.mps} +% fix rendering of degree celsius +\DeclareSIUnit\degreeCelsius{\text{°C}} +\Configure{Gin-dim}{} +\Css{img { + max-width: 100\%; + height: auto; +}} + +\Configure{AddCss}{style.css} +\ConfigureEnv{titlepage}{\ifvmode\IgnorePar\fi\EndP\HCode{
}}{\ifvmode\IgnorePar\fi\EndP\HCode{
}}{}{} + +% Mini TOC +\Configure{crosslinks+}{% + \bgroup + % container for the page toc + \Configure{tableofcontents}{\IgnorePar\EndP\HCode{\Hnewline}\ShowPar}{}{}% + \TableOfContents[chapter,section,subsection]% Print table of contents before crosslinks + \egroup + \ifvmode\IgnorePar\fi\EndP% + \HCode{
\Hnewline\Hnewline}} +{\ifvmode\IgnorePar\fi\EndP% + \HCode{}}{}{} + +% configuration for TOC on the main page +\Configure{tableofcontents}{\IgnorePar\EndP\HCode{\Hnewline
\Hnewline}\ShowPar}{}{}% + +% close the
element started in \Configure{crosslinks+} +\Configure{@/BODY}{\ifvmode\IgnorePar\fi\EndP\HCode{
}} +% Goatcounter counting + +\renewcommand\listofflowcharts{% +\chapter*{\listoflocname}% +\TableOfContents[loc]% +} +\ConfigureToc{loc}{\HCode{}}{\ }{}{\HCode{
}} + +\begin{document} +\EndPreamble diff --git a/book/whole-grain-sandwich/whole-grain-sandwich-crumb.jpg b/book/whole-grain-sandwich/whole-grain-sandwich-crumb.jpg new file mode 100644 index 0000000..226431d Binary files /dev/null and b/book/whole-grain-sandwich/whole-grain-sandwich-crumb.jpg differ diff --git a/book/whole-grain-sandwich/whole-grain-sandwich-outside.jpg b/book/whole-grain-sandwich/whole-grain-sandwich-outside.jpg new file mode 100644 index 0000000..d0b3642 Binary files /dev/null and b/book/whole-grain-sandwich/whole-grain-sandwich-outside.jpg differ diff --git a/book/whole-grain-sandwich/whole-grain-sandwich.tex b/book/whole-grain-sandwich/whole-grain-sandwich.tex new file mode 100644 index 0000000..542648d --- /dev/null +++ b/book/whole-grain-sandwich/whole-grain-sandwich.tex @@ -0,0 +1,114 @@ +\noindent\textbf{About this recipe:}\\ +This recipe will make you a delicious whole-grain sandwich loaf. +The bread features a moist soft crumb and has a nice tang. +It's the perfect hearty whole-grain sandwich bread and can +be paired with savory toppings or sweet toppings. + +This is my go-to weekly bread which can be made with less +than 5~minutes of actual working time. Furthermore, this recipe can be +made with whole-grain flour. My go-to option is a blend of 50~percent +whole-rye flour and 50~percent whole-wheat flour. The recipe +features a high amount of water making kneading the dough impossible, +just requiring you to mix it initially. For this reason, there +is no need to do any gluten development that you would normally do +with a wheat or spelt-based dough. This recipe can also be made +with gluten-free flour like rice or corn. In that case, just substitute +the flour with your gluten-free flour. + +Since this bread is made in a loaf pan there's no need to care about +the readiness of the starter. You can use both an older and younger starter. +Depending on the starter activity level the fermentation will take longer +or be shorter. For a very inactive starter, the recipe can take up to 24 hours, +for a more active around 8-12 hours. + +\begin{figure}[h] + \centering + \includegraphics[width=\textwidth]{whole-grain-sandwich-outside} + \caption{An easy-to-make bread that can be paired with a variety of toppings.} +\end{figure} + +\noindent\textbf{Ingredients:} + +\begin{center} +\begin{tabular}{|c|l|r|r|} + \hline + \textbf{No.} & \textbf{Ingredient} & \textbf{Quantity} & \textbf{Baker's math} \\ + \hline + 1 & Whole-wheat flour, whole-rye flour & 400 g, 400g & 100\% \\ + \hline + 2 & Water, warm & 640 g & 80\% \\ + \hline + 3 & Sourdough starter & 80 g & 10\% \\ + \hline + 4 & Salt & 16 g & 2\% \\ + \hline +\end{tabular} +\end{center} + +\noindent\textbf{Instructions:} +\begin{center} +\begin{tabular}{|c|p{12cm}|} + \hline + \textbf{Step} & \textbf{Instruction} \\ + \hline + 1 & Mix all the ingredients until there are no chunks of + flour left. A spatula will make the whole process easier. \\ + \hline + 2 & Wait until the dough has increased by roughly 50~\% in size. \\ + \hline + 3 & Prepare a loaf pan. Use non-stick spray or a good amount of oil. \\ + \hline + 4 & Cover the loaf pan in oats. Shake the oats thoroughly in the loaf + pan so that they cover the walls. Let the rest of the oats fall out of the + pan. \\ + \hline + 5 & With a spatula remove the dough from your bulk ferment container and + cover the whole loaf pan. Gently pat down the dough in your loaf pan so + that the dough fully covers the pan. \\ + \hline + 4 & Spray some water on the top of your dough, or use a spatula to spread + water lightly on your dough's surface. Use the remaining oats to cover + the top of your dough. \\ + \hline + 4 & If you want to bake the bread now, wait 60~minutes letting the dough + sit on your counter. Alternatively place the dough in your fridge overnight, + up to a whole week until you are ready to bake. If you let the dough sit + in the fridge for more than 24~hours I recommend wrapping it in a plastic + bag so that the surface does not dry out too much. \\ + \hline +\end{tabular} +\end{center} + +\noindent\textbf{Baking:} +\begin{center} +\begin{tabular}{|c|p{12cm}|} + \hline + \textbf{Step} & \textbf{Instruction} \\ + \hline + 1 & Place the dough into a not preheated oven at 200°C (400°F) \\ + \hline + 2 & Place an inverted oven tray on top of your dough. Not directly + on the loaf pan, make sure to keep at least 2~cm distance. This + helps steaming. \\ + \hline + 3 & Wait for at least 45~minutes and let the bread bake. Ideally, take + a thermometer and measure the core temperature. Especially when fridge + proofing the dough baking can take longer. Once the dough has + reached 92°C (197°F) it is ready in theory. However, the top part of the loaf + might not be properly baked yet. It should have a nice dark color to it + similar to the the photos. \\ + \hline + 4 & Wait for at least 60~minutes before removing the dough from the loaf pan. \\ + \hline +\end{tabular} +\end{center} + +If you feel the final bread is a bit too sour you can toast the slices before +eating them. You can also consider baking your next bread for a longer period. +The heat will evaporate additional acids from the bread and make it taste milder. + +\begin{figure}[h] + \centering + \includegraphics[width=\textwidth]{whole-grain-sandwich-crumb} + \caption{The bread features a nice soft crumb texture.} +\end{figure} diff --git a/makefile b/makefile new file mode 100644 index 0000000..113f326 --- /dev/null +++ b/makefile @@ -0,0 +1,46 @@ +.DEFAULT_GOAL := build_pdf + +DOCKER_IMAGE := ghcr.io/hendricius/the-sourdough-framework +DOCKER_CMD := docker run --rm -it -v $(PWD):/opt/repo --platform linux/x86_64 $(DOCKER_IMAGE) /bin/bash -c + +.PHONY: bake build_pdf build_docker_image push_docker_image validate website +.PHONY: print_os_version start_shell printvars show_tools_version mrproper + +# Dockers targets +build_docker_image: + docker build -t $(DOCKER_IMAGE) -f Dockerfile --progress=plain . + +push_docker_image: build_docker_image + docker push $(DOCKER_IMAGE):latest + +# Books/website +build_serif_pdf: + $(DOCKER_CMD) "cd /opt/repo/book && make build_serif_pdf" + +build_ebook: + $(DOCKER_CMD) "cd /opt/repo/book && make 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" + +mrproper: + $(DOCKER_CMD) "cd /opt/repo/book && make mrproper" + +# Debug helpers +show_tools_version: + $(DOCKER_CMD) "cd /opt/repo/book && make show_tools_version" + +printvars: + $(DOCKER_CMD) "cd /opt/repo/book && make printvars" + +print_os_version: + $(DOCKER_CMD) "cat /etc/*release" + +start_shell: + docker run -it -v $(PWD):/opt/repo $(DOCKER_IMAGE) /bin/bash