Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Check

on:
pull_request:
push:
branches: [main]
workflow_dispatch:

permissions:
contents: read

jobs:
render:
name: Render (Quarto ${{ matrix.quarto }})
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
# The extensions declare quarto-required >=1.7.0; test that floor and
# the current stable release.
quarto: ["1.7.34", "1.10.19"]
steps:
- uses: actions/checkout@v7

- name: Install XeLaTeX and image tools
run: |
sudo apt-get update
sudo apt-get install --yes --no-install-recommends \
texlive-xetex texlive-latex-recommended texlive-latex-extra \
texlive-fonts-recommended lmodern \
libxml2-utils librsvg2-bin poppler-utils imagemagick

- uses: quarto-dev/quarto-actions/setup@v2
with:
version: ${{ matrix.quarto }}

- run: scripts/check.sh
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
/example/paper.html
/example/paper.pdf
/example/fonts/
/example/policyengine-wordmark.pdf
/example/policyengine-wordmark.svg
/output/
/tmp/

Expand Down
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ Use `policyengine-paper-pdf` and `policyengine-paper-html` in the document

Metadata:

- `wordmark`: the PolicyEngine wordmark heads the PDF and HTML title blocks;
defaults to `true`. Set `wordmark: false` to omit it from a document, or set
it under one format to omit it there only. When no author lists an
affiliation, the title block falls back to a "PolicyEngine" byline; the
wordmark replaces that fallback. Author affiliations always print.
- `kicker`: short register line above the title; defaults to `WORKING PAPER`.
- `revision`: revision number shown with the ISO document date.
- `status`: Markdown body for the status banner; the format supplies its label.
Expand All @@ -21,6 +26,23 @@ Metadata:

See `example/paper.qmd` for a minimal two-format paper.

Rendering copies the format's resources beside the document: `fonts/` and
`policyengine-wordmark.pdf` for PDF, `policyengine-wordmark.svg` for HTML.
Projects with an output directory also copy the SVG beside each page. Add these
copies to `.gitignore`.

## Development

`scripts/check.sh` validates the SVG assets, confirms the committed PDF
wordmark still matches the SVG, and renders test documents in every paper
format with and without the wordmark. It needs Quarto, XeLaTeX, xmllint,
rsvg-convert, pdftoppm and ImageMagick; CI runs it on every pull request.

The PDF wordmark is a vector conversion of
`_extensions/policyengine/assets/policyengine-wordmark.svg`, committed so
rendering needs no conversion step. After editing the SVG, run
`scripts/build-wordmark-pdf.sh` and commit both files.

## License

Code in this repository is released under the [MIT License](LICENSE). Original text and figures are released under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) with attribution to PolicyEngine. Third-party data and materials keep their own terms.
5 changes: 5 additions & 0 deletions _extensions/policyengine-paper/_extension.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ contributes:
formats:
common:
number-sections: true
# The title block shows the theme wordmark; `wordmark: false` omits it.
wordmark: true
metadata-files:
- ../policyengine/theme-policyengine.yml
pdf:
Expand All @@ -15,6 +17,7 @@ contributes:
- margin=1.1in
format-resources:
- ../policyengine/fonts
- ../policyengine/assets/policyengine-wordmark.pdf
colorlinks: true
# Source: policyengine-ui-kit/src/theme/tokens.css:51 (--border).
code-block-border-left: "#E2E8F0"
Expand All @@ -32,5 +35,7 @@ contributes:
- default
- ../policyengine/policyengine.scss
css: ../policyengine/fonts.css
format-resources:
- ../policyengine/assets/policyengine-wordmark.svg
template-partials:
- ../policyengine/partials/title-block.html
5 changes: 5 additions & 0 deletions _extensions/policyengine/_extension.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ contributes:
formats:
common:
number-sections: true
# The title block shows the theme wordmark; `wordmark: false` omits it.
wordmark: true
metadata-files:
- theme-policyengine.yml
pdf:
Expand All @@ -15,6 +17,7 @@ contributes:
- margin=1.1in
format-resources:
- fonts
- assets/policyengine-wordmark.pdf
colorlinks: true
# Source: policyengine-ui-kit/src/theme/tokens.css:51 (--border).
code-block-border-left: "#E2E8F0"
Expand All @@ -32,5 +35,7 @@ contributes:
- default
- policyengine.scss
css: fonts.css
format-resources:
- assets/policyengine-wordmark.svg
template-partials:
- partials/title-block.html
Binary file not shown.
2 changes: 1 addition & 1 deletion _extensions/policyengine/assets/policyengine-wordmark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions _extensions/policyengine/partials/before-title.tex
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
\usepackage{titlesec}
\usepackage{etoolbox}
\usepackage{xurl}
% Quarto's template loads graphicx only under its `graphics` variable; the
% title block's wordmark needs it regardless.
\usepackage{graphicx}

\setmainfont[
Path={$policyengine-font-dir$/inter/},
Expand Down
12 changes: 10 additions & 2 deletions _extensions/policyengine/partials/title-block.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
</style>

<header id="title-block-header" class="quarto-title-block policyengine-title-block">
$if(wordmark)$
<img class="policyengine-wordmark" src="$policyengine-theme.wordmark-svg$" alt="$policyengine-theme.wordmark-alt$">
$endif$

<div class="policyengine-kicker">
<span class="policyengine-kicker-mark" aria-hidden="true">Σ</span>
<span>$if(kicker)$$kicker$$else$WORKING PAPER$endif$</span>
Expand All @@ -24,13 +28,17 @@ <h1 class="title">$title$</h1>
</div>
$endif$

<div class="policyengine-affiliations">
$if(by-affiliation)$
<div class="policyengine-affiliations">
$for(by-affiliation)$<span class="affiliation">$it.name$</span>$sep$<span aria-hidden="true"> · </span>$endfor$
</div>
$elseif(wordmark)$
$-- The wordmark already names the theme affiliation.
$elseif(policyengine-theme.affiliation)$
<div class="policyengine-affiliations">
<span class="affiliation">$policyengine-theme.affiliation$</span>
$endif$
</div>
$endif$

$if(revision)$
<div class="policyengine-revision">Revision $revision$$if(date-meta)$ <span aria-hidden="true">·</span> $date-meta$$endif$</div>
Expand Down
6 changes: 6 additions & 0 deletions _extensions/policyengine/partials/title.tex
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
\begingroup
\setlength{\parindent}{0pt}%
\begin{flushleft}
$if(wordmark)$
\includegraphics[height=0.3in,alt={$policyengine-theme.wordmark-alt$}]{$policyengine-theme.wordmark-pdf$}\par
\vspace{1.6em}
$endif$
{\policyenginemono\fontsize{7}{9}\selectfont
{\color{policyengineaccent}Σ}\hspace{0.7em}%
\MakeUppercase{$if(kicker)$$kicker$$else$WORKING PAPER$endif$}\par}
Expand All @@ -18,6 +22,8 @@
$if(by-affiliation)$
{\sffamily\small\color{policyenginemuted}
$for(by-affiliation)$$it.name$$sep$\enspace\textperiodcentered\enspace{}$endfor$\par}
$elseif(wordmark)$
$-- The wordmark already names the theme affiliation.
$elseif(policyengine-theme.affiliation)$
{\sffamily\small\color{policyenginemuted} $policyengine-theme.affiliation$\par}
$endif$
Expand Down
7 changes: 7 additions & 0 deletions _extensions/policyengine/policyengine.scss
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@ a:focus {
margin-block: 0 2.2rem;
}

.policyengine-wordmark {
display: block;
width: auto;
height: 2.25rem;
margin-bottom: 1.6rem;
}

.policyengine-kicker,
.policyengine-revision,
.policyengine-status-label {
Expand Down
8 changes: 7 additions & 1 deletion _extensions/policyengine/theme-policyengine.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,10 @@ policyengine-theme:
# Source: policyengine-ui-kit/src/theme/tokens.css:66 (--chart-3).
accent-hover-tex: "285E61"
affiliation: PolicyEngine
wordmark: assets/policyengine-wordmark.svg
# Quarto copies format-resources beside the document by basename, so the
# partials name the copies, not the assets/ paths.
# Source: policyengine-ui-kit/src/assets/logos/policyengine/teal.svg.
wordmark-svg: policyengine-wordmark.svg
# Built from the SVG by scripts/build-wordmark-pdf.sh.
wordmark-pdf: policyengine-wordmark.pdf
wordmark-alt: PolicyEngine
6 changes: 4 additions & 2 deletions example/paper.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@ author:
- name: PolicyEngine
date: 2026-08-15
date-format: iso
# The wordmark heads the title block by default; false omits it.
wordmark: true
kicker: working paper
revision: "1"
status: |
This draft demonstrates a status body with `code` and a
[local-font link](https://policyengine.org/).
theme: policyengine
abstract: |
A minimal paper that exercises the title, abstract, status, headings,
links, footnotes, and code treatments.
A minimal paper that exercises the wordmark, title, abstract, status,
headings, links, footnotes, and code treatments.
format:
policyengine-paper-pdf: default
policyengine-paper-html: default
Expand Down
18 changes: 18 additions & 0 deletions scripts/build-wordmark-pdf.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/usr/bin/env bash
# Rebuild the vector PDF wordmark that xelatex includes in the PDF title block.
# The PDF is committed so rendering a paper needs no SVG conversion step; run
# this script whenever assets/policyengine-wordmark.svg changes, then commit
# both files. scripts/check.sh fails if the two drift apart.
set -euo pipefail

root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
assets="$root/_extensions/policyengine/assets"

# A fixed epoch keeps cairo's CreationDate stable, so a rebuild with the same
# librsvg and cairo versions is byte-identical.
SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:-0}" rsvg-convert \
--format=pdf \
--output="$assets/policyengine-wordmark.pdf" \
"$assets/policyengine-wordmark.svg"

echo "Wrote $assets/policyengine-wordmark.pdf"
Loading
Loading