Fixed PDF and EPUB generation to use toc.metadata.
This commit is contained in:
parent
e8df980d4b
commit
b4ae07e13c
9 changed files with 239 additions and 194 deletions
28
Makefile
28
Makefile
|
@ -12,6 +12,25 @@ AGDA := stack exec agda -- --no-libraries --include-path=standard-library/s
|
||||||
PANDOC := stack exec pandoc --
|
PANDOC := stack exec pandoc --
|
||||||
|
|
||||||
|
|
||||||
|
#################################################################################
|
||||||
|
# Build PLFA site, EPUB, and PDF
|
||||||
|
#################################################################################
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
all:
|
||||||
|
@echo "Building site..."
|
||||||
|
make build
|
||||||
|
@echo "Testing site..."
|
||||||
|
make test
|
||||||
|
@echo "Building epub..."
|
||||||
|
make epub-build
|
||||||
|
@echo "Testing epub..."
|
||||||
|
make epub-test
|
||||||
|
@echo "Building pdf..."
|
||||||
|
make pdf-build
|
||||||
|
@echo "Testing pdf..."
|
||||||
|
|
||||||
|
|
||||||
#################################################################################
|
#################################################################################
|
||||||
# Setup Git Hooks
|
# Setup Git Hooks
|
||||||
#################################################################################
|
#################################################################################
|
||||||
|
@ -165,7 +184,7 @@ include book/pdf.mk
|
||||||
|
|
||||||
|
|
||||||
#################################################################################
|
#################################################################################
|
||||||
# Setup dependencies
|
# Setup or check dependencies
|
||||||
#################################################################################
|
#################################################################################
|
||||||
|
|
||||||
.PHONY: setup-check-stack
|
.PHONY: setup-check-stack
|
||||||
|
@ -209,13 +228,6 @@ ifeq (,$(wildcard $(shell which latexmk)))
|
||||||
@echo "See: https://mg.readthedocs.io/latexmk.html"
|
@echo "See: https://mg.readthedocs.io/latexmk.html"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: setup-check-epubcheck
|
|
||||||
setup-check-epubcheck:
|
|
||||||
ifeq (,$(wildcard $(shell which epubcheck)))
|
|
||||||
@echo "The command you called requires EPUBCheck"
|
|
||||||
@echo "See: https://github.com/w3c/epubcheck"
|
|
||||||
endif
|
|
||||||
|
|
||||||
.PHONY: setup-check-rsync
|
.PHONY: setup-check-rsync
|
||||||
setup-check-rsync:
|
setup-check-rsync:
|
||||||
ifeq (,$(wildcard $(shell which rsync)))
|
ifeq (,$(wildcard $(shell which rsync)))
|
||||||
|
|
78
book/epub.md
78
book/epub.md
|
@ -1,71 +1,7 @@
|
||||||
---
|
$for(parts)$
|
||||||
title: Programming Language Foundations in Agda
|
# $title$
|
||||||
author:
|
$for(sections)$
|
||||||
- Philip Wadler
|
## $title$ {#$anchor$}
|
||||||
- Wen Kokke
|
$body$
|
||||||
- Jeremy G. Siek
|
$endfor$
|
||||||
description: This book is an introduction to programming language theory using the proof assistant Agda.
|
$endfor$
|
||||||
rights: Creative Commons Attribution 4.0 International License
|
|
||||||
language: en-US
|
|
||||||
---
|
|
||||||
|
|
||||||
# Front matter
|
|
||||||
|
|
||||||
``` {.include shift-heading-level-by=1}
|
|
||||||
src/plfa/frontmatter/dedication.md
|
|
||||||
src/plfa/frontmatter/preface.md
|
|
||||||
```
|
|
||||||
|
|
||||||
# Part 1: Logical Foundations
|
|
||||||
|
|
||||||
``` {.include shift-heading-level-by=1}
|
|
||||||
src/plfa/part1/Naturals.lagda.md
|
|
||||||
src/plfa/part1/Induction.lagda.md
|
|
||||||
src/plfa/part1/Relations.lagda.md
|
|
||||||
src/plfa/part1/Equality.lagda.md
|
|
||||||
src/plfa/part1/Isomorphism.lagda.md
|
|
||||||
src/plfa/part1/Connectives.lagda.md
|
|
||||||
src/plfa/part1/Negation.lagda.md
|
|
||||||
src/plfa/part1/Quantifiers.lagda.md
|
|
||||||
src/plfa/part1/Decidable.lagda.md
|
|
||||||
src/plfa/part1/Lists.lagda.md
|
|
||||||
```
|
|
||||||
|
|
||||||
# Part 2: Operational Semantics
|
|
||||||
|
|
||||||
``` {.include shift-heading-level-by=1}
|
|
||||||
src/plfa/part2/Lambda.lagda.md
|
|
||||||
src/plfa/part2/Properties.lagda.md
|
|
||||||
src/plfa/part2/DeBruijn.lagda.md
|
|
||||||
src/plfa/part2/More.lagda.md
|
|
||||||
src/plfa/part2/Bisimulation.lagda.md
|
|
||||||
src/plfa/part2/Inference.lagda.md
|
|
||||||
src/plfa/part2/Untyped.lagda.md
|
|
||||||
src/plfa/part2/Confluence.lagda.md
|
|
||||||
src/plfa/part2/BigStep.lagda.md
|
|
||||||
```
|
|
||||||
|
|
||||||
# Part 3: Denotational Semantics
|
|
||||||
|
|
||||||
``` {.include shift-heading-level-by=1}
|
|
||||||
src/plfa/part3/Denotational.lagda.md
|
|
||||||
src/plfa/part3/Compositional.lagda.md
|
|
||||||
src/plfa/part3/Soundness.lagda.md
|
|
||||||
src/plfa/part3/Adequacy.lagda.md
|
|
||||||
src/plfa/part3/ContextualEquivalence.lagda.md
|
|
||||||
```
|
|
||||||
|
|
||||||
# Appendix
|
|
||||||
|
|
||||||
``` {.include shift-heading-level-by=1}
|
|
||||||
src/plfa/part2/Substitution.lagda.md
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
# Backmatter
|
|
||||||
|
|
||||||
## Acknowledgements
|
|
||||||
``` {.include shift-heading-level-by=1}
|
|
||||||
_site/raw/plfa/backmatter/acknowledgements.md
|
|
||||||
src/plfa/backmatter/Fonts.lagda.md
|
|
||||||
```
|
|
||||||
|
|
56
book/epub.mk
56
book/epub.mk
|
@ -1,24 +1,36 @@
|
||||||
|
#################################################################################
|
||||||
|
# Configuration
|
||||||
|
#################################################################################
|
||||||
|
|
||||||
EPUB_DIR := book
|
EPUB_DIR := book
|
||||||
EPUB_TEMPLATE_DIR := $(EPUB_DIR)/templates
|
EPUB_TEMPLATE_DIR := $(EPUB_DIR)/templates
|
||||||
EPUB_LUA_DIR := $(EPUB_DIR)/lua
|
EPUB_LUA_DIR := $(EPUB_DIR)/lua
|
||||||
EPUB_LUA_SCRIPTS := $(wildcard $(EPUB_LUA_DIR)/*.lua)
|
EPUB_LUA_SCRIPTS := $(wildcard $(EPUB_LUA_DIR)/*.lua)
|
||||||
MD_DIR := src
|
MD_DIR := src
|
||||||
MD_FILES := README.md $(wildcard $(MD_DIR)/plfa/**/*.md)
|
MD_FILES := README.md $(wildcard $(MD_DIR)/plfa/**/*.md)
|
||||||
|
FRANKENFONT := public/webfonts/DejaVu-mononoki-Symbola-Droid.woff
|
||||||
|
|
||||||
|
|
||||||
# Compile PLFA to an EPUB
|
#################################################################################
|
||||||
|
# Compile PLFA to an EPUB using Pandoc
|
||||||
|
#################################################################################
|
||||||
|
|
||||||
.PHONY: epub-build
|
.PHONY: epub-build
|
||||||
epub-build: $(SITE_DIR)/plfa.epub
|
epub-build: $(SITE_DIR)/plfa.epub
|
||||||
|
|
||||||
$(SITE_DIR)/plfa.epub: book/epub.md book/epub.css $(MD_FILES) $(EPUB_LUA_SCRIPTS) | setup-install-pandoc
|
$(SITE_DIR)/plfa.epub: \
|
||||||
|
$(EPUB_DIR)/epub.md $(EPUB_DIR)/epub.css $(RAW_DIR)/epub.xml $(FRANKENFONT) \
|
||||||
|
$(MD_FILES) $(EPUB_LUA_SCRIPTS) | setup-install-pandoc
|
||||||
@$(PANDOC) \
|
@$(PANDOC) \
|
||||||
--strip-comments \
|
--strip-comments \
|
||||||
--css=epub/epub.css \
|
--css=$(EPUB_DIR)/epub.css \
|
||||||
--epub-embed-font='public/webfonts/DejaVu-mononoki-Symbola-Droid.woff' \
|
--epub-embed-font=$(FRANKENFONT) \
|
||||||
--lua-filter=$(EPUB_LUA_DIR)/include-files.lua \
|
--epub-metadata=$(RAW_DIR)/epub.xml
|
||||||
--lua-filter=$(EPUB_LUA_DIR)/single-file-links.lua \
|
--indented-code-class=default \
|
||||||
--lua-filter=$(EPUB_LUA_DIR)/epub-clean-html.lua \
|
|
||||||
--lua-filter=$(EPUB_LUA_DIR)/set-default-code-class.lua -M default-code-class=agda \
|
--lua-filter=$(EPUB_LUA_DIR)/set-default-code-class.lua -M default-code-class=agda \
|
||||||
|
--lua-filter=$(EPUB_LUA_DIR)/remove-badges.lua -M badge-url=https://img.shields.io/badge/ \
|
||||||
|
--lua-filter=$(EPUB_LUA_DIR)/epub-clean-html.lua \
|
||||||
|
--lua-filter=$(EPUB_LUA_DIR)/single-file-links.lua \
|
||||||
--standalone \
|
--standalone \
|
||||||
--fail-if-warnings \
|
--fail-if-warnings \
|
||||||
--toc --toc-depth=2 \
|
--toc --toc-depth=2 \
|
||||||
|
@ -26,13 +38,39 @@ $(SITE_DIR)/plfa.epub: book/epub.md book/epub.css $(MD_FILES) $(EPUB_LUA_SCRIPTS
|
||||||
$< -o $@
|
$< -o $@
|
||||||
|
|
||||||
|
|
||||||
|
#################################################################################
|
||||||
# Test EPUB with EPUBCheck
|
# Test EPUB with EPUBCheck
|
||||||
|
#################################################################################
|
||||||
|
|
||||||
.PHONY: epub-test
|
.PHONY: epub-test
|
||||||
epub-test: $(SITE_DIR)/plfa.epub | setup-check-epubcheck
|
epub-test: $(SITE_DIR)/plfa.epub | setup-check-epubcheck
|
||||||
epubcheck $(SITE_DIR)/plfa.epub
|
epubcheck $(SITE_DIR)/plfa.epub
|
||||||
|
|
||||||
|
|
||||||
# Clean generated files
|
#################################################################################
|
||||||
|
# Tasks for files that are generated by Hakyll
|
||||||
|
#################################################################################
|
||||||
|
|
||||||
|
$(RAW_DIR)/epub.xml: $(EPUB_DIR)/epub.xml
|
||||||
|
make build
|
||||||
|
|
||||||
|
|
||||||
|
#################################################################################
|
||||||
|
# Clean up and remove generated EPUB
|
||||||
|
#################################################################################
|
||||||
|
|
||||||
.PHONY: epub-clean
|
.PHONY: epub-clean
|
||||||
epub-clean:
|
epub-clean:
|
||||||
rm $(SITE_DIR)/plfa.epub
|
rm -f $(SITE_DIR)/plfa.epub
|
||||||
|
|
||||||
|
|
||||||
|
#################################################################################
|
||||||
|
# Setup or check dependencies
|
||||||
|
#################################################################################
|
||||||
|
|
||||||
|
.PHONY: setup-check-epubcheck
|
||||||
|
setup-check-epubcheck:
|
||||||
|
ifeq (,$(wildcard $(shell which epubcheck)))
|
||||||
|
@echo "The command you called requires EPUBCheck"
|
||||||
|
@echo "See: https://github.com/w3c/epubcheck"
|
||||||
|
endif
|
||||||
|
|
|
@ -12,22 +12,6 @@
|
||||||
-- pandoc's List type
|
-- pandoc's List type
|
||||||
local List = require 'pandoc.List'
|
local List = require 'pandoc.List'
|
||||||
|
|
||||||
--- Shift headings in block list by given number
|
|
||||||
local function shift_headings(blocks, shift_by)
|
|
||||||
if not shift_by then
|
|
||||||
return blocks
|
|
||||||
end
|
|
||||||
|
|
||||||
local shift_headings_filter = {
|
|
||||||
Header = function (header)
|
|
||||||
header.level = header.level + shift_by
|
|
||||||
return header
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
return pandoc.walk_block(pandoc.Div(blocks), shift_headings_filter).content
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Filter function for code blocks
|
--- Filter function for code blocks
|
||||||
function CodeBlock(cb)
|
function CodeBlock(cb)
|
||||||
|
|
||||||
|
@ -46,20 +30,22 @@ function CodeBlock(cb)
|
||||||
if line:sub(1,2) ~= '//' then
|
if line:sub(1,2) ~= '//' then
|
||||||
-- Read in the document at the file path specified by `line`.
|
-- Read in the document at the file path specified by `line`.
|
||||||
local fh = io.open(line)
|
local fh = io.open(line)
|
||||||
local document = pandoc.read(fh:read '*a', format)
|
local doc = pandoc.read(fh:read '*a', format)
|
||||||
|
blocks:extend(document.blocks)
|
||||||
fh:close()
|
fh:close()
|
||||||
|
|
||||||
-- Before shifting headings, add a title heading at the beginning of the chapter.
|
|
||||||
if document.meta.title then
|
|
||||||
local heading = pandoc.Header(1, pandoc.Str(pandoc.utils.stringify(document.meta.title)))
|
|
||||||
document.blocks:insert(1, heading)
|
|
||||||
end
|
|
||||||
-- Shift all headings by the user-specified amount, which is 0 by default.
|
|
||||||
local chapter = shift_headings(document.blocks, shift_heading_level_by)
|
|
||||||
|
|
||||||
-- Concatenate the chapter blocks (discarding the metadata) to the current document.
|
|
||||||
blocks:extend(chapter)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return blocks
|
return blocks
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Apply a filter to a document.
|
||||||
|
function apply_filter(doc, filters)
|
||||||
|
div = pandoc.Div(doc.blocks)
|
||||||
|
for _, filter in pairs(filters) do
|
||||||
|
if filter.Meta then
|
||||||
|
filter.Meta(doc.meta)
|
||||||
|
end
|
||||||
|
div = pandoc.walk_block(div, filter)
|
||||||
|
end
|
||||||
|
return pandoc.Pandoc(div.content, doc.meta)
|
||||||
|
end
|
||||||
|
|
83
book/pdf.mk
83
book/pdf.mk
|
@ -1,3 +1,7 @@
|
||||||
|
#################################################################################
|
||||||
|
# Configuration
|
||||||
|
#################################################################################
|
||||||
|
|
||||||
PDF_DIR := book
|
PDF_DIR := book
|
||||||
PDF_TEMPLATE_DIR := $(PDF_DIR)/templates
|
PDF_TEMPLATE_DIR := $(PDF_DIR)/templates
|
||||||
PDF_LUA_DIR := $(PDF_DIR)/lua
|
PDF_LUA_DIR := $(PDF_DIR)/lua
|
||||||
|
@ -5,6 +9,11 @@ MD_DIR := src
|
||||||
LAGDA_TEX_DIR := $(TMP_DIR)/lagda_tex
|
LAGDA_TEX_DIR := $(TMP_DIR)/lagda_tex
|
||||||
TEX_DIR := $(TMP_DIR)/tex
|
TEX_DIR := $(TMP_DIR)/tex
|
||||||
|
|
||||||
|
|
||||||
|
#################################################################################
|
||||||
|
# Helper functions for translating paths
|
||||||
|
#################################################################################
|
||||||
|
|
||||||
# Convert MD_DIR/%.md to its modified source path
|
# Convert MD_DIR/%.md to its modified source path
|
||||||
define MD_PATH
|
define MD_PATH
|
||||||
$(patsubst $(MD_DIR)/%/acknowledgements.md,$(RAW_DIR)/%/acknowledgements.md,\
|
$(patsubst $(MD_DIR)/%/acknowledgements.md,$(RAW_DIR)/%/acknowledgements.md,\
|
||||||
|
@ -28,7 +37,11 @@ $(patsubst $(RAW_DIR)/%,$(TEX_DIR)/%,\
|
||||||
$(patsubst $(MD_DIR)/%.lagda.md,$(TEX_DIR)/%.tex,$(1))))))
|
$(patsubst $(MD_DIR)/%.lagda.md,$(TEX_DIR)/%.tex,$(1))))))
|
||||||
endef
|
endef
|
||||||
|
|
||||||
# List source and intermediate files
|
|
||||||
|
#################################################################################
|
||||||
|
# Lists of source and intermediate files
|
||||||
|
#################################################################################
|
||||||
|
|
||||||
PDF_LUA_SCRIPTS := $(wildcard $(PDF_LUA_DIR)/*.lua)
|
PDF_LUA_SCRIPTS := $(wildcard $(PDF_LUA_DIR)/*.lua)
|
||||||
PDF_STATIC_FILES := $(PDF_DIR)/pdf.tex $(PDF_DIR)/DejaVu-mononoki-Symbola-Droid.ttf
|
PDF_STATIC_FILES := $(PDF_DIR)/pdf.tex $(PDF_DIR)/DejaVu-mononoki-Symbola-Droid.ttf
|
||||||
MD_FILES := README.md $(wildcard $(MD_DIR)/plfa/**/*.md)
|
MD_FILES := README.md $(wildcard $(MD_DIR)/plfa/**/*.md)
|
||||||
|
@ -37,16 +50,10 @@ LAGDA_TEX_FILES := $(call LAGDA_TEX_PATH,$(LAGDA_MD_FILES))
|
||||||
TEX_FILES := $(call TEX_PATH,$(MD_FILES) $(RAW_DIR)/pdf.tex $(PDF_STATIC_FILES))
|
TEX_FILES := $(call TEX_PATH,$(MD_FILES) $(RAW_DIR)/pdf.tex $(PDF_STATIC_FILES))
|
||||||
|
|
||||||
|
|
||||||
# Generated by Hakyll
|
#################################################################################
|
||||||
$(RAW_DIR)/pdf.tex: $(PDF_DIR)/pdf.tex $(MD_DIR)/plfa/toc.metadata
|
# Compile PLFA to a PDF via Pandoc and Latexmk
|
||||||
make build
|
#################################################################################
|
||||||
|
|
||||||
# Generated by Hakyll
|
|
||||||
$(RAW_DIR)/plfa/backmatter/acknowledgements.md: $(MD_DIR)/plfa/backmatter/acknowledgements.md
|
|
||||||
make build
|
|
||||||
|
|
||||||
|
|
||||||
# Compile PLFA to a PDF
|
|
||||||
.PHONY: pdf-build
|
.PHONY: pdf-build
|
||||||
pdf-build: $(SITE_DIR)/plfa.pdf
|
pdf-build: $(SITE_DIR)/plfa.pdf
|
||||||
|
|
||||||
|
@ -55,6 +62,10 @@ $(SITE_DIR)/plfa.pdf: $(TEX_FILES)
|
||||||
@cp $(TEX_DIR)/pdf.pdf $(SITE_DIR)/plfa.pdf
|
@cp $(TEX_DIR)/pdf.pdf $(SITE_DIR)/plfa.pdf
|
||||||
|
|
||||||
|
|
||||||
|
#################################################################################
|
||||||
|
# Definitions of various compilation tasks
|
||||||
|
#################################################################################
|
||||||
|
|
||||||
# Copy static files needed by PDF compilation
|
# Copy static files needed by PDF compilation
|
||||||
define MK_COPYSTATIC_RULE
|
define MK_COPYSTATIC_RULE
|
||||||
src := $(1)
|
src := $(1)
|
||||||
|
@ -65,6 +76,14 @@ $$(dst): $$(src)
|
||||||
@cp $$< $$@
|
@cp $$< $$@
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
# Copy static files from PDF_DIR/% to TEX_DIR/%
|
||||||
|
$(foreach static_file,\
|
||||||
|
$(PDF_STATIC_FILES),\
|
||||||
|
$(eval $(call MK_COPYSTATIC_RULE,\
|
||||||
|
$(call MD_PATH,$(static_file)),\
|
||||||
|
$(call TEX_PATH,$(static_file)))))
|
||||||
|
|
||||||
|
|
||||||
# Compile Markdown files to LaTeX
|
# Compile Markdown files to LaTeX
|
||||||
#
|
#
|
||||||
# NOTE: Passing --indented-code-classes=default sets the class for /indented/ code blocks
|
# NOTE: Passing --indented-code-classes=default sets the class for /indented/ code blocks
|
||||||
|
@ -85,26 +104,9 @@ $$(dst): $$(src) $(PDF_LUA_SCRIPTS) | setup-install-pandoc
|
||||||
--lua-filter=$(PDF_LUA_DIR)/remove-badges.lua -M badge-url=https://img.shields.io/badge/ \
|
--lua-filter=$(PDF_LUA_DIR)/remove-badges.lua -M badge-url=https://img.shields.io/badge/ \
|
||||||
--lua-filter=$(PDF_LUA_DIR)/latex-render-codeblocks.lua -M unchecked-files=README.md \
|
--lua-filter=$(PDF_LUA_DIR)/latex-render-codeblocks.lua -M unchecked-files=README.md \
|
||||||
--lua-filter=$(PDF_LUA_DIR)/single-file-links.lua \
|
--lua-filter=$(PDF_LUA_DIR)/single-file-links.lua \
|
||||||
--lua-filter=$(PDF_LUA_DIR)/single-file-headers.lua \
|
|
||||||
$$< -o $$@
|
$$< -o $$@
|
||||||
endef
|
endef
|
||||||
|
|
||||||
# Compile Literate Agda files to LaTeX
|
|
||||||
define MK_LAGDA_MD2TEX_RULE
|
|
||||||
src := $(1)
|
|
||||||
dst := $(2)
|
|
||||||
$$(dst): $$(src) $(LAGDA_TEX_FILES) | setup-install-agda setup-check-latexmk
|
|
||||||
@$(AGDA) --include-path=$(LAGDA_TEX_DIR) --latex --latex-dir=$(TEX_DIR) $$<
|
|
||||||
endef
|
|
||||||
|
|
||||||
|
|
||||||
# Copy static files (from PDF_DIR/% to TEX_DIR/%)
|
|
||||||
$(foreach static_file,\
|
|
||||||
$(PDF_STATIC_FILES),\
|
|
||||||
$(eval $(call MK_COPYSTATIC_RULE,\
|
|
||||||
$(call MD_PATH,$(static_file)),\
|
|
||||||
$(call TEX_PATH,$(static_file)))))
|
|
||||||
|
|
||||||
# Compile .md files (from MD_DIR/%.md to TEX_DIR/%.tex)
|
# Compile .md files (from MD_DIR/%.md to TEX_DIR/%.tex)
|
||||||
$(foreach md_file,\
|
$(foreach md_file,\
|
||||||
$(filter-out %.lagda.md,$(MD_FILES)),\
|
$(filter-out %.lagda.md,$(MD_FILES)),\
|
||||||
|
@ -119,6 +121,15 @@ $(foreach lagda_md_file,\
|
||||||
$(lagda_md_file),\
|
$(lagda_md_file),\
|
||||||
$(call LAGDA_TEX_PATH,$(lagda_md_file)))))
|
$(call LAGDA_TEX_PATH,$(lagda_md_file)))))
|
||||||
|
|
||||||
|
|
||||||
|
# Compile Literate Agda files to LaTeX
|
||||||
|
define MK_LAGDA_MD2TEX_RULE
|
||||||
|
src := $(1)
|
||||||
|
dst := $(2)
|
||||||
|
$$(dst): $$(src) $(LAGDA_TEX_FILES) | setup-install-agda setup-check-latexmk
|
||||||
|
@$(AGDA) --include-path=$(LAGDA_TEX_DIR) --latex --latex-dir=$(TEX_DIR) $$<
|
||||||
|
endef
|
||||||
|
|
||||||
# Compile .lagda.tex files (from LAGDA_TEX_DIR/%.lagda.tex to TEX_DIR/%.tex)
|
# Compile .lagda.tex files (from LAGDA_TEX_DIR/%.lagda.tex to TEX_DIR/%.tex)
|
||||||
$(foreach lagda_md_file,\
|
$(foreach lagda_md_file,\
|
||||||
$(LAGDA_MD_FILES),\
|
$(LAGDA_MD_FILES),\
|
||||||
|
@ -127,7 +138,23 @@ $(foreach lagda_md_file,\
|
||||||
$(call TEX_PATH,$(lagda_md_file)))))
|
$(call TEX_PATH,$(lagda_md_file)))))
|
||||||
|
|
||||||
|
|
||||||
# Clean generated files
|
|
||||||
|
#################################################################################
|
||||||
|
# Tasks for files that are generated by Hakyll
|
||||||
|
#################################################################################
|
||||||
|
|
||||||
|
$(RAW_DIR)/pdf.tex: $(PDF_DIR)/pdf.tex $(MD_DIR)/plfa/toc.metadata
|
||||||
|
make build
|
||||||
|
|
||||||
|
# Generated by Hakyll
|
||||||
|
$(RAW_DIR)/plfa/backmatter/acknowledgements.md: $(MD_DIR)/plfa/backmatter/acknowledgements.md
|
||||||
|
make build
|
||||||
|
|
||||||
|
|
||||||
|
#################################################################################
|
||||||
|
# Clean up and remove generated PDF
|
||||||
|
#################################################################################
|
||||||
|
|
||||||
.PHONY: pdf-clean
|
.PHONY: pdf-clean
|
||||||
pdf-clean:
|
pdf-clean:
|
||||||
@rm -rf $(SITE_DIR)/plfa.pdf $(LAGDA_TEX_DIR) $(TEX_DIR)
|
@rm -rf $(SITE_DIR)/plfa.pdf $(LAGDA_TEX_DIR) $(TEX_DIR)
|
||||||
|
|
69
book/pdf.tex
69
book/pdf.tex
|
@ -7,12 +7,20 @@
|
||||||
\setsansfont{DejaVu Sans}
|
\setsansfont{DejaVu Sans}
|
||||||
\setmonofont{[DejaVu-mononoki-Symbola-Droid.ttf]}
|
\setmonofont{[DejaVu-mononoki-Symbola-Droid.ttf]}
|
||||||
\usepackage{soul}
|
\usepackage{soul}
|
||||||
\usepackage[most]{tcolorbox}
|
\usepackage{tcolorbox}
|
||||||
\tcbuselibrary{skins,breakable}
|
\tcbuselibrary{skins,breakable}
|
||||||
\usepackage{listings}
|
\usepackage{fancyvrb}
|
||||||
\usepackage{xcolor}
|
\usepackage{xcolor}
|
||||||
\usepackage{tikz}
|
\usepackage{tikz}
|
||||||
\usepackage{setspace}
|
\usepackage{setspace}
|
||||||
|
\usepackage{geometry}
|
||||||
|
\geometry{
|
||||||
|
a4paper,
|
||||||
|
total={170mm,257mm},
|
||||||
|
left=20mm,
|
||||||
|
top=20mm,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
% Wrap texttt lines
|
% Wrap texttt lines
|
||||||
\sloppy
|
\sloppy
|
||||||
|
@ -20,48 +28,37 @@
|
||||||
% Disable section numbering
|
% Disable section numbering
|
||||||
\setcounter{secnumdepth}{0}
|
\setcounter{secnumdepth}{0}
|
||||||
|
|
||||||
|
% Set the global text color:
|
||||||
|
\definecolor{textcolor}{111111}
|
||||||
|
\color{textcolor}
|
||||||
|
|
||||||
% Change background color for inline code in markdown files.
|
% Change background color for inline code in markdown files.
|
||||||
% The following code does not work well for long text as the
|
% The following code does not work well for long text as the
|
||||||
% text will exceed the page boundary.
|
% text will exceed the page boundary.
|
||||||
\definecolor{bgcolor}{HTML}{EEEEFF}
|
\definecolor{background-color}{HTML}{EEEEFF}
|
||||||
\let\oldtexttt\texttt%
|
\let\oldtexttt\texttt%
|
||||||
\renewcommand{\texttt}[1]{\colorbox{bgcolor}{\oldtexttt{#1}}}
|
\renewcommand{\texttt}[1]{\colorbox{bgcolor}{\oldtexttt{#1}}}
|
||||||
|
|
||||||
% Indent verbatim to be the same as agda code blocks.
|
% Box with background colour similar to web version:
|
||||||
\lstdefinestyle{codeBlockStyle}{
|
|
||||||
basicstyle=\ttfamily,
|
|
||||||
numbers=none
|
|
||||||
}
|
|
||||||
\newtcolorbox{agda}[1][]{
|
\newtcolorbox{agda}[1][]{
|
||||||
frame hidden,
|
frame hidden,
|
||||||
colback=bgcolor,
|
colback=background-color,
|
||||||
spartan,
|
spartan,
|
||||||
left=5pt,
|
left=5pt,
|
||||||
boxrule=0pt,
|
boxrule=0pt,
|
||||||
breakable,
|
breakable,
|
||||||
}
|
}
|
||||||
\newtcblisting{pre}{
|
|
||||||
frame hidden,
|
|
||||||
colback=bgcolor,
|
|
||||||
spartan,
|
|
||||||
width=\textwidth,
|
|
||||||
listing only,
|
|
||||||
listing options={style=codeBlockStyle},
|
|
||||||
arc=0mm,
|
|
||||||
top=0mm,
|
|
||||||
bottom=0mm,
|
|
||||||
left=0mm,
|
|
||||||
right=0mm,
|
|
||||||
boxrule=0pt,
|
|
||||||
breakable,
|
|
||||||
}
|
|
||||||
|
|
||||||
\usepackage{geometry}
|
% Verbatim environment similarly indented to Agda code blocks.
|
||||||
\geometry{
|
\DefineVerbatimEnvironment{verbatim}{Verbatim}{xleftmargin=0pt}%
|
||||||
a4paper,
|
|
||||||
total={170mm,257mm},
|
% Adding backgrounds to verbatim environments.
|
||||||
left=20mm,
|
\newenvironment{pre}{
|
||||||
top=20mm,
|
\VerbatimEnvironment
|
||||||
|
\begin{agda}
|
||||||
|
\begin{verbatim}
|
||||||
|
}{\end{verbatim}
|
||||||
|
\end{agda}
|
||||||
}
|
}
|
||||||
|
|
||||||
% Use special font families without TeX ligatures for Agda code.
|
% Use special font families without TeX ligatures for Agda code.
|
||||||
|
@ -78,7 +75,6 @@
|
||||||
|
|
||||||
\AgdaNoSpaceAroundCode{}
|
\AgdaNoSpaceAroundCode{}
|
||||||
|
|
||||||
|
|
||||||
% Adjust spacing after toc numbering
|
% Adjust spacing after toc numbering
|
||||||
\usepackage{tocloft}
|
\usepackage{tocloft}
|
||||||
\setlength\cftchapnumwidth{3em}
|
\setlength\cftchapnumwidth{3em}
|
||||||
|
@ -86,11 +82,12 @@
|
||||||
|
|
||||||
% Style links with colors instead of boxes:
|
% Style links with colors instead of boxes:
|
||||||
% https://tex.stackexchange.com/q/823
|
% https://tex.stackexchange.com/q/823
|
||||||
|
\definecolor{linkcolor}{HTML}{2A7AE2}
|
||||||
\hypersetup{
|
\hypersetup{
|
||||||
colorlinks,
|
colorlinks,
|
||||||
linkcolor={red!50!black},
|
linkcolor={linkcolor},
|
||||||
citecolor={blue!50!black},
|
citecolor={linkcolor},
|
||||||
urlcolor={blue!80!black}
|
urlcolor={linkcolor}
|
||||||
}
|
}
|
||||||
|
|
||||||
\begin{document}
|
\begin{document}
|
||||||
|
@ -150,6 +147,8 @@ $endif$
|
||||||
|
|
||||||
% Include each section.
|
% Include each section.
|
||||||
$for(sections)$
|
$for(sections)$
|
||||||
|
\hypertarget{$anchor$}{%
|
||||||
|
\chapter{$title$}\label{$anchor$}}
|
||||||
\input{$tex_path$}
|
\input{$tex_path$}
|
||||||
$endfor$
|
$endfor$
|
||||||
|
|
||||||
|
|
69
hs/Main.hs
69
hs/Main.hs
|
@ -2,9 +2,12 @@
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
|
||||||
import Control.Monad ((<=<), forM_)
|
import Control.Monad ((<=<), forM_)
|
||||||
|
import qualified Data.ByteString.Char8 as BS
|
||||||
|
import Data.Char (toLower)
|
||||||
import Data.Functor ((<&>))
|
import Data.Functor ((<&>))
|
||||||
import Data.List (isPrefixOf)
|
import Data.List (isPrefixOf, stripPrefix)
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
|
import qualified Data.Yaml as Y
|
||||||
import Hakyll
|
import Hakyll
|
||||||
import Hakyll.Web.Agda
|
import Hakyll.Web.Agda
|
||||||
import Hakyll.Web.Routes.Permalink
|
import Hakyll.Web.Routes.Permalink
|
||||||
|
@ -18,6 +21,9 @@ import qualified Text.CSL as CSL
|
||||||
import qualified Text.CSL.Pandoc as CSL (processCites)
|
import qualified Text.CSL.Pandoc as CSL (processCites)
|
||||||
import Text.Pandoc (Pandoc(..), ReaderOptions(..), WriterOptions(..), Extension(..))
|
import Text.Pandoc (Pandoc(..), ReaderOptions(..), WriterOptions(..), Extension(..))
|
||||||
import qualified Text.Pandoc as Pandoc
|
import qualified Text.Pandoc as Pandoc
|
||||||
|
import Text.Pandoc.Definition (Block(..))
|
||||||
|
import Text.Pandoc.Walk (walk)
|
||||||
|
import Text.Printf
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- Configuration
|
-- Configuration
|
||||||
|
@ -66,7 +72,7 @@ siteContext = mconcat
|
||||||
, "authors/jsiek.metadata"
|
, "authors/jsiek.metadata"
|
||||||
]
|
]
|
||||||
, constField "google_analytics" "UA-125055580-1"
|
, constField "google_analytics" "UA-125055580-1"
|
||||||
, defaultContext
|
, addAnchor defaultContext
|
||||||
]
|
]
|
||||||
|
|
||||||
siteSectionContext :: Context String
|
siteSectionContext :: Context String
|
||||||
|
@ -77,10 +83,10 @@ siteSectionContext = mconcat
|
||||||
]
|
]
|
||||||
|
|
||||||
tableOfContentsContext :: Context String -> Context String
|
tableOfContentsContext :: Context String -> Context String
|
||||||
tableOfContentsContext ctx = Context $ \k a _ -> do
|
tableOfContentsContext ctx = Context $ \k a _ ->
|
||||||
metadata <- getMetadata "src/plfa/toc.metadata"
|
unContext (objectContext ctx) k a
|
||||||
m <- makeItem metadata
|
=<< makeItem
|
||||||
unContext (objectContext ctx) k a m
|
=<< getMetadata "src/plfa/toc.metadata"
|
||||||
|
|
||||||
acknowledgementsContext :: Context String
|
acknowledgementsContext :: Context String
|
||||||
acknowledgementsContext = mconcat
|
acknowledgementsContext = mconcat
|
||||||
|
@ -145,13 +151,48 @@ addTexPath = addDerivedField "tex_path" deriveTexPath
|
||||||
|
|
||||||
texPath :: FilePath -> FilePath
|
texPath :: FilePath -> FilePath
|
||||||
texPath fnDotMd
|
texPath fnDotMd
|
||||||
| fnDotMd == "README.md" = "plfa/frontmatter/README.tex"
|
| fnDotMd == "README.md" = "plfa/frontmatter/README.tex"
|
||||||
| any (`isPrefixOf` fnDotMd) ["src/", "book/"] = dropTopDirectory (replaceExtensions fnDotMd ".tex")
|
| any (`isPrefixOf` fnDotMd) ["src/", "book/"] = dropTopDirectory (replaceExtensions fnDotMd ".tex")
|
||||||
| otherwise = error ("textPath: cannot map " <> fnDotMd)
|
| otherwise = error ("textPath: cannot map " <> fnDotMd)
|
||||||
|
|
||||||
dropTopDirectory :: FilePath -> FilePath
|
dropTopDirectory :: FilePath -> FilePath
|
||||||
dropTopDirectory = joinPath . tail . splitPath
|
dropTopDirectory = joinPath . tail . splitPath
|
||||||
|
|
||||||
|
-- Add an anchor based on the permalink, to be used as the header id.
|
||||||
|
addAnchor :: Context a -> Context a
|
||||||
|
addAnchor = addDerivedField "anchor" deriveAnchor
|
||||||
|
where
|
||||||
|
deriveAnchor :: Context a -> [String] -> Item a -> Compiler ContextField
|
||||||
|
deriveAnchor ctx a i = do
|
||||||
|
fld <- unContext ctx "permalink" a i
|
||||||
|
case fld of
|
||||||
|
StringField permalink -> StringField <$> anchor permalink
|
||||||
|
_ -> fail "Key 'permalink' does not return a String"
|
||||||
|
|
||||||
|
anchor :: String -> Compiler String
|
||||||
|
anchor permalink =
|
||||||
|
let maybeAnchor = map toLower <$> (stripSuffix "/" <=< stripPrefix "/") permalink
|
||||||
|
in maybe (fail $ printf "Key 'permalink' malformed '%s'" permalink) return maybeAnchor
|
||||||
|
|
||||||
|
stripSuffix :: String -> String -> Maybe String
|
||||||
|
stripSuffix suf str = reverse <$> stripPrefix (reverse suf) (reverse str)
|
||||||
|
|
||||||
|
-- Add the metadata back to the file as a Yaml header.
|
||||||
|
addMetadata :: Item String -> Compiler (Item String)
|
||||||
|
addMetadata item = do
|
||||||
|
metadata <- getMetadata (itemIdentifier item)
|
||||||
|
let yaml = "---\n" <> BS.unpack (Y.encode metadata) <> "---\n\n"
|
||||||
|
withItemBody (\body -> return (yaml <> body)) item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- Shift all headers by a given value.
|
||||||
|
shiftHeadersBy :: Int -> Pandoc -> Pandoc
|
||||||
|
shiftHeadersBy n = walk shiftHeader
|
||||||
|
where
|
||||||
|
shiftHeader :: Block -> Block
|
||||||
|
shiftHeader (Header level attr inlines) = Header (level + n) attr inlines
|
||||||
|
shiftHeader block = block
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- Build site
|
-- Build site
|
||||||
|
@ -179,7 +220,7 @@ main = do
|
||||||
>>= processCites csl bib
|
>>= processCites csl bib
|
||||||
<&> writeHTML5With siteWriterOptions
|
<&> writeHTML5With siteWriterOptions
|
||||||
>>= saveSnapshot "content"
|
>>= saveSnapshot "content"
|
||||||
>>= loadAndApplyTemplate "templates/page.html" siteSectionContext
|
>>= loadAndApplyTemplate "templates/page.html" siteSectionContext
|
||||||
>>= loadAndApplyTemplate "templates/default.html" siteSectionContext
|
>>= loadAndApplyTemplate "templates/default.html" siteSectionContext
|
||||||
>>= prettifyUrls
|
>>= prettifyUrls
|
||||||
|
|
||||||
|
@ -195,7 +236,7 @@ main = do
|
||||||
>>= processCites csl bib
|
>>= processCites csl bib
|
||||||
<&> writeHTML5With siteWriterOptions
|
<&> writeHTML5With siteWriterOptions
|
||||||
>>= saveSnapshot "content"
|
>>= saveSnapshot "content"
|
||||||
>>= loadAndApplyTemplate "templates/page.html" siteSectionContext
|
>>= loadAndApplyTemplate "templates/page.html" siteSectionContext
|
||||||
>>= loadAndApplyTemplate "templates/default.html" siteSectionContext
|
>>= loadAndApplyTemplate "templates/default.html" siteSectionContext
|
||||||
>>= prettifyUrls
|
>>= prettifyUrls
|
||||||
|
|
||||||
|
@ -241,7 +282,7 @@ main = do
|
||||||
route $ gsubRoute "src/" (const "raw/")
|
route $ gsubRoute "src/" (const "raw/")
|
||||||
compile $ getResourceBody
|
compile $ getResourceBody
|
||||||
>>= applyAsTemplate acknowledgementsContext
|
>>= applyAsTemplate acknowledgementsContext
|
||||||
>>= loadAndApplyTemplate "templates/metadata.md" siteContext
|
>>= addMetadata
|
||||||
|
|
||||||
-- Compile raw version of index used in constructing the PDF
|
-- Compile raw version of index used in constructing the PDF
|
||||||
match "book/pdf.tex" $ do
|
match "book/pdf.tex" $ do
|
||||||
|
@ -249,6 +290,12 @@ main = do
|
||||||
compile $ getResourceBody
|
compile $ getResourceBody
|
||||||
>>= applyAsTemplate (addTexPath (tableOfContentsContext siteSectionContext))
|
>>= applyAsTemplate (addTexPath (tableOfContentsContext siteSectionContext))
|
||||||
|
|
||||||
|
-- Compile raw version of index used in constructing the EPUB
|
||||||
|
match "book/epub.md" $ do
|
||||||
|
route $ gsubRoute "book/" (const "raw/")
|
||||||
|
compile $ getResourceBody
|
||||||
|
>>= applyAsTemplate (tableOfContentsContext siteSectionContext)
|
||||||
|
|
||||||
-- Compile metadata XML used in constructing the EPUB
|
-- Compile metadata XML used in constructing the EPUB
|
||||||
match "book/epub.xml" $ version "raw" $ do
|
match "book/epub.xml" $ version "raw" $ do
|
||||||
route $ constRoute "raw/epub.xml"
|
route $ constRoute "raw/epub.xml"
|
||||||
|
|
|
@ -12,19 +12,19 @@ build-type: Simple
|
||||||
common shared-properties
|
common shared-properties
|
||||||
ghc-options: -Wall
|
ghc-options: -Wall
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
build-depends: aeson >=1.4 && <1.5
|
build-depends: aeson >=1.4 && <1.6
|
||||||
, base >=4.6 && <5
|
, base >=4.6 && <5
|
||||||
, bytestring >=0.10 && <0.11
|
, bytestring >=0.10 && <0.11
|
||||||
, containers >=0.6 && <0.7
|
, containers >=0.6 && <0.7
|
||||||
, directory >=1.2 && <1.4
|
, directory >=1.2 && <1.4
|
||||||
, doctemplates >=0.8 && <0.9
|
, doctemplates >=0.8 && <1.0
|
||||||
, extra >=1.7 && <1.8
|
, extra >=1.7 && <1.8
|
||||||
, filemanip >=0.3 && <0.4
|
, filemanip >=0.3 && <0.4
|
||||||
, filepath >=1.3 && <1.5
|
, filepath >=1.3 && <1.5
|
||||||
, frontmatter >=0.1 && <0.2
|
, frontmatter >=0.1 && <0.2
|
||||||
, hakyll >=4.10 && <4.15
|
, hakyll >=4.10 && <4.15
|
||||||
, pandoc >=2.1 && <2.11
|
, pandoc >=2.1 && <2.11
|
||||||
, pandoc-types >=1.20 && <1.21
|
, pandoc-types >=1.20 && <1.23
|
||||||
, pandoc-citeproc >=0.17 && <0.18
|
, pandoc-citeproc >=0.17 && <0.18
|
||||||
, text >=1.2 && <1.3
|
, text >=1.2 && <1.3
|
||||||
, unordered-containers >=0.2 && <0.3
|
, unordered-containers >=0.2 && <0.3
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<article class="post">
|
<article class="post">
|
||||||
$partial("templates/next.html")$
|
$partial("templates/next.html")$
|
||||||
<header class="post-header">
|
<header class="post-header">
|
||||||
<h1 class="post-title">$title$</h1>
|
<h1 class="post-title" $if(anchor)$id="$anchor$"$endif$>$title$</h1>
|
||||||
</header>
|
</header>
|
||||||
<div class="post-content">
|
<div class="post-content">
|
||||||
$body$
|
$body$
|
||||||
|
|
Loading…
Reference in a new issue