From 6e578f8a605d06b9722566b3e71f9bd0ecbea170 Mon Sep 17 00:00:00 2001 From: Tommy Keswick Date: Wed, 2 Sep 2026 12:00:22 -0700 Subject: [PATCH] Ship the theme's assets with the site instead of fetching them The shared template fetched site.css, code-blocks.css and copyToClipboard.js by absolute URL, so every site built with this action depended on CL-web-components publishing to S3 and on caltechlibrary.github.io acting as an asset host. Nobody agreed to either arrangement and nothing tested them. The S3 copies were thirteen months stale, reporting 0.0.12 against a project at 0.0.16. None of the three belonged where it was. code-blocks.css styles pre and the copy button on documentation pages; copyToClipboard.js creates that button and is not a web component at all; site.css styles :root, body, header, nav, section and aside, which is exactly the structure this template emits. They are this theme's files, and the projects holding them were consumers. They now live in pandoc/css and pandoc/js, and build-pandoc copies them into every site it builds. footer-global.js and the Caltech Library logo keep their CDN URLs, because sites outside this build system embed them. Projects customize by adding, not replacing: --extra-css and --extra-js ship a project's own files and load them after the theme's, and for CSS that is enough to override anything, because later rules win. No project needs a copy of a theme file, so no project can hold a stale one. --site-base prefixes the asset URLs, defaulting to // where Pages puts a project site. The default is set by the action, not the script, so the script keeps knowing nothing about CI -- run by hand with no --site-base it emits relative URLs and the output opens from disk. ADR-0008 records the decision and the three rejected alternatives. --- .github/actions/build-pandoc/action.yml | 30 ++ .github/workflows/docs-pandoc.yml | 22 + CHANGELOG.md | 20 + README.md | 38 ++ bin/build-pandoc.sh | 44 +- ...08-ship-the-themes-assets-with-the-site.md | 120 +++++ pandoc/css/code-blocks.css | 69 +++ pandoc/css/site.css | 481 ++++++++++++++++++ pandoc/js/copyToClipboard.js | 30 ++ pandoc/page.tmpl | 12 +- 10 files changed, 862 insertions(+), 4 deletions(-) create mode 100644 docs/decisions/0008-ship-the-themes-assets-with-the-site.md create mode 100644 pandoc/css/code-blocks.css create mode 100644 pandoc/css/site.css create mode 100644 pandoc/js/copyToClipboard.js diff --git a/.github/actions/build-pandoc/action.yml b/.github/actions/build-pandoc/action.yml index 009e38d..119808f 100644 --- a/.github/actions/build-pandoc/action.yml +++ b/.github/actions/build-pandoc/action.yml @@ -37,6 +37,26 @@ inputs: rather than adding to them. required: false default: "" + site-base: + description: >- + URL prefix the site is served under, used for the theme's own CSS and JS. + Defaults to //, which is where GitHub Pages puts a project site. Set + it to / for a site served at a domain root. + required: false + default: /${{ github.event.repository.name }}/ + extra-css: + description: >- + Stylesheets to ship with the site and load after the theme's, one path per + line. Later rules win, so this is enough to restyle anything the theme + does without forking it. + required: false + default: "" + extra-js: + description: >- + Scripts to ship with the site and load after the theme's, one path per + line. + required: false + default: "" search: description: >- Add a Search item to the theme's nav. Set this when you also run the @@ -84,6 +104,9 @@ runs: PROJECT: ${{ inputs.project }} REPO_URL: ${{ inputs.repo-url }} SEARCH: ${{ inputs.search }} + SITE_BASE: ${{ inputs.site-base }} + EXTRA_CSS: ${{ inputs.extra-css }} + EXTRA_JS: ${{ inputs.extra-js }} run: | ARGS=(--docs-dir "$DOCS_DIR" --output "$OUTPUT" --index-from "$INDEX_FROM") [ -n "$PROJECT" ] && ARGS+=(--project "$PROJECT") @@ -99,4 +122,11 @@ runs: while IFS= read -r line; do [ -n "$line" ] && ARGS+=(--include "$line") done <<< "$INCLUDE" + [ -n "$SITE_BASE" ] && ARGS+=(--site-base "$SITE_BASE") + while IFS= read -r line; do + [ -n "$line" ] && ARGS+=(--extra-css "$line") + done <<< "$EXTRA_CSS" + while IFS= read -r line; do + [ -n "$line" ] && ARGS+=(--extra-js "$line") + done <<< "$EXTRA_JS" "${{ github.action_path }}/../../../bin/build-pandoc.sh" "${ARGS[@]}" diff --git a/.github/workflows/docs-pandoc.yml b/.github/workflows/docs-pandoc.yml index 25cf4de..cb3c067 100644 --- a/.github/workflows/docs-pandoc.yml +++ b/.github/workflows/docs-pandoc.yml @@ -56,6 +56,25 @@ on: type: string required: false default: "" + site-base: + description: >- + URL prefix the site is served under. Defaults to //. Set it to / + for a site served at a domain root. + type: string + required: false + default: "" + extra-css: + description: >- + Stylesheets to ship and load after the theme's, one path per line. + type: string + required: false + default: "" + extra-js: + description: >- + Scripts to ship and load after the theme's, one path per line. + type: string + required: false + default: "" index-from: description: Basename whose page becomes index.html. type: string @@ -103,6 +122,9 @@ jobs: include: ${{ inputs.include }} template: ${{ inputs.template }} lua-filters: ${{ inputs.lua-filters }} + site-base: ${{ inputs.site-base || format('/{0}/', github.event.repository.name) }} + extra-css: ${{ inputs.extra-css }} + extra-js: ${{ inputs.extra-js }} index-from: ${{ inputs.index-from }} search: ${{ inputs.pagefind }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 672f938..525fcd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,8 +12,28 @@ what moved. See ## [Unreleased] +### Added + +- The Pandoc theme's own CSS and JS now live here, in `pandoc/css` and + `pandoc/js`, and are copied into every site `build-pandoc` builds. A + published site serves them itself instead of fetching them from another + project's CDN. See + [ADR-0008](docs/decisions/0008-ship-the-themes-assets-with-the-site.md). +- `build-pandoc` inputs `extra-css` and `extra-js`: files a project ships with + its site and loads *after* the theme's. For CSS that is enough to restyle + anything the theme does, because later rules win, so no project needs a copy + of a theme file. +- `build-pandoc` input `site-base`, the URL prefix those assets are served + under. Defaults to `//`; set it to `/` for a site at a domain root. + ### Changed +- The shared template no longer fetches `site.css`, `code-blocks.css` or + `copyToClipboard.js` by absolute URL. Those had made every documentation site + depend on `CL-web-components` publishing to S3 and on + `caltechlibrary.github.io` acting as an asset host; the S3 copies were + thirteen months stale. `footer-global.js` and the Caltech Library logo keep + their CDN URLs, because sites outside this build system embed them. - Documented which repeated values in examples must match and which are coincidental: a build action's `output` and `deploy-site`'s `path` must be the same directory, while `prefix` and the path in `public-base-url` need diff --git a/README.md b/README.md index b41a75e..4136b60 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,9 @@ but do not deploy it. | `include` | — | Files or directories to copy into the site verbatim, one per line | | `template` | shared theme | Pandoc template; point at a file in your repo to override | | `lua-filters` | shared filters | One path per line. **Replaces** the defaults rather than adding to them | +| `site-base` | `//` | URL prefix the site is served under. Set it to `/` for a domain root | +| `extra-css` | — | Stylesheets shipped and loaded **after** the theme's, one per line | +| `extra-js` | — | Scripts shipped and loaded after the theme's, one per line | | `index-from` | `README` | Basename whose page becomes `index.html` | | `pre-build` | — | Shell command to run before rendering, e.g. `deno task build` | | `pagefind` | `true` | Build a Pagefind search index | @@ -154,12 +157,47 @@ coincidence. | `include` | — | Files or directories copied in verbatim, one per line | | `template` | shared theme | Pandoc template; point at your own file to override | | `lua-filters` | shared filters | One per line. **Replaces** the defaults | +| `site-base` | `//` | URL prefix the site is served under. Set it to `/` for a domain root | +| `extra-css` | — | Stylesheets shipped and loaded **after** the theme's, one per line | +| `extra-js` | — | Scripts shipped and loaded after the theme's, one per line | | `index-from` | `README` | Basename that becomes `index.html` | | `search` | `false` | Add a Search item to the nav — set it when you also run `index-site` | | `project` | repository name | Shown in the page title | | `repo-url` | this repository | Link in the theme's nav | | `pandoc-version` | `3.8.2.1` | Pinned so a Pandoc release cannot change published output | +#### Customizing the theme + +The theme's stylesheets and scripts live in `pandoc/css` and `pandoc/js` here, +and are copied into every site this action builds. A published site serves them +itself; it does not fetch them from anywhere else. Updating them for everyone is +a change here plus a move of `v1`. + +To change how a site looks, **add** rather than replace: + +```yaml +- uses: caltechlibrary/workflows/.github/actions/build-pandoc@v1 + with: + extra-css: pandoc/css/my-project.css +``` + +Your file ships alongside the theme's and loads after them, so a rule in it +beats the theme's rule for the same selector. That is enough to restyle +anything the theme does without copying a theme file into your repository — +and a copy you do not have is a copy that cannot fall behind. + +Naming your file the same as a theme file replaces it instead. That works, +but it is a fork; prefer a new name. + +`site-base` prefixes the URLs of both. It defaults to `//`, where GitHub +Pages puts a project site. A site served at a domain root sets `site-base: /`. +Running `bin/build-pandoc.sh` by hand with no `--site-base` emits relative URLs, +so the output opens correctly straight from disk. + +For a page structure the theme does not offer, `template` still points Pandoc at +your own file. That opts you out of future changes to the shared template, which +is the trade you are making. + ### `build-zensical` | Input | Default | | diff --git a/bin/build-pandoc.sh b/bin/build-pandoc.sh index 388e4ec..fa43276 100755 --- a/bin/build-pandoc.sh +++ b/bin/build-pandoc.sh @@ -14,6 +14,15 @@ # Defaults for the template and Lua filters resolve to this repository's # pandoc/ directory, so a project gets the shared Caltech theme without # copying it. Pass --template or --lua-filter to override. +# +# The theme's own CSS and JS are copied into the site from pandoc/css and +# pandoc/js, so a published site serves them itself rather than fetching them +# from somewhere else. Projects add their own with --extra-css/--extra-js, +# which load after the theme's; for CSS that is enough to override any of it, +# because later rules win. Nothing needs to be forked to be customized. +# +# --site-base prefixes those URLs. It has no default here because this script +# knows nothing about where a site is published; the action supplies one. set -euo pipefail @@ -26,6 +35,9 @@ INDEX_FROM="README" PROJECT="" REPO_URL="" SEARCH_PAGE="" +SITE_BASE="" +declare -a EXTRA_CSS=() +declare -a EXTRA_JS=() declare -a LUA_FILTERS=() declare -a EXTRA_SOURCES=() declare -a INCLUDE=() @@ -40,6 +52,9 @@ Options: --lua-filter FILE repeatable (default: shared filters) --extra-source PATH Markdown outside --docs-dir, repeatable --include PATH file or directory to copy into the site, repeatable + --site-base PREFIX URL prefix for theme assets, e.g. /my-repo/ + --extra-css FILE stylesheet to ship and load after the theme, repeatable + --extra-js FILE script to ship and load after the theme, repeatable --index-from BASE basename that becomes index.html (default: README) --project NAME site name for the theme --repo-url URL repository link for the theme @@ -56,6 +71,9 @@ while [ $# -gt 0 ]; do --lua-filter) LUA_FILTERS+=("$2"); shift 2 ;; --extra-source) EXTRA_SOURCES+=("$2"); shift 2 ;; --include) INCLUDE+=("$2"); shift 2 ;; + --site-base) SITE_BASE="$2"; shift 2 ;; + --extra-css) EXTRA_CSS+=("$2"); shift 2 ;; + --extra-js) EXTRA_JS+=("$2"); shift 2 ;; --index-from) INDEX_FROM="$2"; shift 2 ;; --project) PROJECT="$2"; shift 2 ;; --repo-url) REPO_URL="$2"; shift 2 ;; @@ -71,7 +89,8 @@ if [ ${#LUA_FILTERS[@]} -eq 0 ]; then LUA_FILTERS=("$HERE/pandoc/links-to-html.lua" "$HERE/pandoc/add-col-scope.lua") fi -for f in "$TEMPLATE" "${LUA_FILTERS[@]}"; do +for f in "$TEMPLATE" "${LUA_FILTERS[@]}" \ + ${EXTRA_CSS[@]+"${EXTRA_CSS[@]}"} ${EXTRA_JS[@]+"${EXTRA_JS[@]}"}; do [ -f "$f" ] || { echo "build-pandoc: no such file: $f" >&2; exit 1; } done [ -d "$DOCS_DIR" ] || { echo "build-pandoc: no such directory: $DOCS_DIR" >&2; exit 1; } @@ -85,6 +104,14 @@ for f in "${LUA_FILTERS[@]}"; do PANDOC_ARGS+=("--lua-filter=$f"); done [ -n "$PROJECT" ] && PANDOC_ARGS+=("--variable=project:$PROJECT") [ -n "$REPO_URL" ] && PANDOC_ARGS+=("--variable=repo-url:$REPO_URL") [ -n "$SEARCH_PAGE" ] && PANDOC_ARGS+=("--variable=search:true") +[ -n "$SITE_BASE" ] && PANDOC_ARGS+=("--variable=site-base:$SITE_BASE") +# The template composes the path, so it only needs the filename. +for f in ${EXTRA_CSS[@]+"${EXTRA_CSS[@]}"}; do + PANDOC_ARGS+=("--variable=extra-css:$(basename "$f")") +done +for f in ${EXTRA_JS[@]+"${EXTRA_JS[@]}"}; do + PANDOC_ARGS+=("--variable=extra-js:$(basename "$f")") +done rendered=0 render_one() { @@ -124,6 +151,21 @@ shopt -s nullglob for html in "$DOCS_DIR"/*.html; do cp -p "$html" "$OUTPUT/"; done shopt -u nullglob +# The theme's assets, then the project's on top. A project file with the same +# name as a theme file replaces it, which works but forks it -- prefer a new +# file and let the cascade do the work. +for dir in css js; do + [ -d "$HERE/pandoc/$dir" ] || continue + mkdir -p "$OUTPUT/$dir" + cp -p "$HERE/pandoc/$dir"/* "$OUTPUT/$dir/" +done +for f in ${EXTRA_CSS[@]+"${EXTRA_CSS[@]}"}; do + mkdir -p "$OUTPUT/css"; cp -p "$f" "$OUTPUT/css/" +done +for f in ${EXTRA_JS[@]+"${EXTRA_JS[@]}"}; do + mkdir -p "$OUTPUT/js"; cp -p "$f" "$OUTPUT/js/" +done + for path in ${INCLUDE[@]+"${INCLUDE[@]}"}; do # shellcheck disable=SC2086 # likewise for item in $path; do diff --git a/docs/decisions/0008-ship-the-themes-assets-with-the-site.md b/docs/decisions/0008-ship-the-themes-assets-with-the-site.md new file mode 100644 index 0000000..421f798 --- /dev/null +++ b/docs/decisions/0008-ship-the-themes-assets-with-the-site.md @@ -0,0 +1,120 @@ +# 8. Ship the theme's assets with the site; projects add rather than replace + +- Status: accepted +- Date: 2026-09-02 + +## Context and Problem Statement + +The shared Pandoc template fetched its own assets by absolute URL from another +project's CDN: + +```html + + + +``` + +So every site built with this action depended on `CL-web-components` publishing +to S3 and on `caltechlibrary.github.io` acting as an asset host. Neither +arrangement was agreed to by anyone, and nothing tested either. The S3 copies +were thirteen months out of date when this was found: they reported version +`0.0.12` while the project itself was at `0.0.16`. + +The files are not what their location suggested. `code-blocks.css` styles +`pre` and the copy button on documentation pages; `copyToClipboard.js` creates +that button and is not a web component at all — no `customElements.define`, +and not exported from its project's `mod.js`. `site.css` styles `:root`, `body`, +`header`, `nav`, `section` and `aside`: exactly the structure this template +emits. All three are this theme's, and the projects holding them were consumers +rather than owners. + +That leaves a second question. Once the theme owns its assets, how does a +project change how its own site looks? + +## Decision + +**The theme's assets live here, in `pandoc/css` and `pandoc/js`, and +`build-pandoc` copies them into every site it builds.** A published site serves +them itself and fetches nothing. + +**Projects add; they do not replace.** `--extra-css` and `--extra-js` ship a +project's own files and load them *after* the theme's. For CSS that is +sufficient to override anything, because later rules win. + +`--site-base` prefixes both, defaulting to `//` where GitHub Pages puts a +project site. The default is set by the action, not the script, so the script +keeps knowing nothing about CI. + +## Considered Options + +1. Keep fetching assets from another project's CDN +2. Publish the theme's assets to S3 from this repository +3. Ship them with each site, and let projects overlay files by name +4. Ship them with each site, and let projects add files that load afterwards + +## Decision Outcome + +**Chosen: option 4.** + +### Option 1: keep the CDN references — rejected + +It makes every documentation site in the organization depend on one project's +bucket and on a content repository nobody designated as an asset host. The +staleness that prompted this was the predictable result. + +### Option 2: publish the assets to S3 from here — rejected for now + +Coherent, and right for assets that sites outside this build system embed — +`footer-global.js` is exactly that, and keeps its CDN URL. But for files only +this theme's own pages use, it buys a publishing pipeline, a role and a +versioning convention to solve a problem that copying already solves. + +### Option 3: overlay by filename — rejected + +To change one rule, a project copies the whole theme file into its repository +and edits it. That copy is committed, edited by a human, and silently falls +behind when the theme improves. It is the failure this repository exists to +avoid, reproduced one directory down. + +### Option 4: additive — chosen + +A project's file contains only what is genuinely the project's. Nothing +duplicates the baseline, so nothing can drift from it. The cascade does the +overriding, which is what a cascade is for. + +## Consequences + +Good: + +- A site serves its own styling and depends on nothing at render time. +- Fixing the theme is one change here plus a move of `v1`, and reaches every + adopting repository. +- No project needs a copy of a theme file, so no project can hold a stale one. + +Bad, and accepted: + +- Each built site carries its own copy of the assets. These are build output, + not committed files — regenerated every run, editable by nobody — so they + are duplication in the same sense `dist/` is, which is to say not the kind + that rots. +- Assets are copied even when a project overrides the template and references + none of them. The result is an unused file on that site. Detecting this would + mean parsing the template for references, which is worse than the waste. +- Overriding by filename still works, because the copy is unconditional. It is + documented as a fork rather than prevented. +- The `--template` escape hatch remains, and a project taking it opts out of + future changes to the shared template. That is the cost of total control, and + it is confined to one file. + +## More Information + +- The assets came from `CL-web-components` and `caltechlibrary.github.io`. Both + keep their copies until they adopt this build; those copies are leftovers, and + this repository is canonical. +- caltechlibrary/caltechlibrary.github.io#6 — the organization site consuming + the theme it currently hosts. It is served at a domain root, so it will be the + first user of `site-base: /`. +- caltechlibrary/CL-web-components#51 — retiring that project's forked + template. +- [ADR-0002](0002-reference-shared-logic-rather-than-copying-it.md) — the same + argument applied to logic rather than assets. diff --git a/pandoc/css/code-blocks.css b/pandoc/css/code-blocks.css new file mode 100644 index 0000000..6116945 --- /dev/null +++ b/pandoc/css/code-blocks.css @@ -0,0 +1,69 @@ +/* code-block.css */ + +/* CSS variables for code block */ +:root { + /* Font family for the code block */ + --code-font-family: monospace; + + /* Border color for the code block */ + --code-border-color: #ccc; + + /* Background color for the entire code block */ + --code-background-color: #f5f5f5; + + /* Copy button variables */ + --copy-button-bg-color: #fff; + --copy-button-border-color: #ccc; + --copy-button-text-color: #000; + --copy-button-hover-bg-color: #f0f0f0; +} + +pre { + border: 2px solid var(--code-border-color); + border-radius: 5px; + background-color: var(--code-background-color); + padding: 1em; + margin: 0.5em 0; + overflow-x: auto; + max-width: 100%; + position: relative; +} + +pre > code { + display: block; + font-family: var(--code-font-family); + line-height: 1.5; + white-space: pre; +} + +.copy-button { + background-color: var(--copy-button-bg-color); + border: 1px solid var(--copy-button-border-color); + color: var(--copy-button-text-color); + border-radius: 3px; + padding: 5px 10px; + cursor: pointer; + font-size: 14px; + position: absolute; + right: 10px; + top: 10px; /* Position the button at the top */ +} + +.copy-button:hover { + background-color: var(--copy-button-hover-bg-color); +} + +.copy-button:hover::after { + content: 'Copy to Clipboard'; + position: absolute; + right: 100%; + top: 50%; + background-color: var(--copy-button-hover-bg-color); + color: var(--copy-button-text-color); + border: 1px solid var(--copy-button-border-color); + border-radius: 3px; + padding: 5px 10px; + margin-right: 5px; + white-space: nowrap; + transform: translateY(-50%); +} diff --git a/pandoc/css/site.css b/pandoc/css/site.css new file mode 100644 index 0000000..ce83d7e --- /dev/null +++ b/pandoc/css/site.css @@ -0,0 +1,481 @@ + +/** + * site.css - stylesheet for the Caltech Library's Digital Library Development Group's sandbox. + * + * orange: #FF6E1E; + * + * Secondary pallet: + * + * lightgrey: #C8C8C8 + * grey: #76777B + * darkgrey: #616265 + * slategrey: #AAA99F + * + * Impact Pallete see: http://identity.caltech.edu/web/colors + * + * TODO: Need to make a small screen friendly version + * + * + * ============================================ + * Customization & Theming Notes + * ============================================ + * + * This stylesheet uses CSS custom properties (variables) + * to allow optional theming and customization. + * + * Default values are defined in the :root selector below. + * These defaults will be used automatically if no overrides + * are provided. + * + * To customize styles, create a separate CSS file and define + * your own :root variables there. Then include that file + * AFTER this stylesheet in your HTML. + * + * Example: + * + * + * + * + * In custom.css: + * + * :root { + * --color-primary: #0055cc; + * --color-nav-bg: black; + * } + * + * Only override the variables you need—everything else will + * fall back to the defaults defined here. + * + * This approach allows: + * - Zero configuration for most users + * - Simple overrides for advanced users + * - Safe fallback values if variables are missing + * + * Note: CSS applies the "cascade" rule, meaning later files + * override earlier ones when selectors have equal specificity. + */ + +/* Base values */ +:root { + /* Primary */ + --color-primary: #FF6E1E; + + /* Secondary palette */ + --color-lightgrey: #C8C8C8; + --color-grey: #76777B; + --color-darkgrey: #616265; + --color-slategrey: #AAA99F; + + /* Base */ + --color-text: black; + --color-bg: white; + --color-link: #747267; + --color-nav-bg: #333333; + --color-footer-bg: #303030; + --color-border: red; + + --font-family-base: Open Sans, Helvetica, Sans-Serif; + --font-size-base: 14px; + + /* special cases */ + --color-announcement: white; + --color-bg-announcement: orange; +} + +body { + margin: 0; + border: 0; + padding: 0; + width: 100%; + height: 100%; + color: var(--color-text, black); + background-color: var(--color-bg, white); + font-family: var(--font-family-base, Open Sans, Helvetica, Sans-Serif); + font-size: var(--font-size-base, 14px); +} + +header { + position: relative; + display: block; + color: var(--color-bg, white); + background-color: var(--color-bg, white); + z-index: 2; + height: 105px; + vertical-align: middle; +} + +header img { + position: relative; + display: inline; + padding-left: 20px; + margin: 0; + height: 42px; + padding-top: 32px; +} + +header h1 { + position: relative; + display: inline-block; + margin: 0; + border: 0; + padding: 0; + font-size: 3em; + font-weight: normal; + vertical-align: 0.78em; + color: var(--color-primary, #FF6E1E); +} + +header a, header a:link, header a:visited, header a:active, header a:hover, header a:focus { + color: var(--color-primary, #FF6E1E); + background-color: inherit; +} + +a, a:link, a:visited { + color: var(--color-link, #747267); + background-color: inherit; +} + +a:active, a:hover, a:focus { + color: var(--color-primary, #FF6E1E); + font-weight: bolder; +} + +nav { + position: relative; + display: block; + width: 100%; + margin: 0; + padding: 0; + font-size: 0.78em; + vertical-align: middle; + color: var(--color-text, black); + background-color: var(--color-nav-bg, #333333); + text-align: left; +} + +nav div { + display: inline-block; + /* padding-left: 10em; */ + margin-left: 10em; + margin-right: 0; +} + +nav a, nav a:link, nav a:visited, nav a:active { + color: var(--color-bg, white); + background-color: inherit; + text-decoration: none; +} + +nav a:hover, nav a:focus { + color: var(--color-primary, #FF6E1E); + background-color: inherit; + text-decoration: none; +} + +nav div h2 { + position: relative; + display: block; + min-width: 20%; + margin: 0; + font-size: 1.24em; + font-style: normal; +} + +nav div > ul { + display: none; + padding-left: 0.24em; + text-align: left; +} + +nav ul { + display: inline-block; + padding-left: 0.24em; + list-style-type: none; + text-align: left; + text-decoration: none; +} + +nav ul li { + display: inline; + padding: 1em; +} + +section { + position: relative; + display: inline-block; + width: auto; + max-width: 98%; + height: 100%; + color: var(--color-text, black); + background-color: var(--color-bg, white); + margin: 0; + padding-top: 2em; + padding-bottom: 2em; + padding-left: 1em; + padding-right: 2em; +} + +section > menu { + display: flex; + list-style: none; + padding: 0; + margin: 0; +} + +section > menu > li { + flex-grow: 1; +} + +section h1 { + font-size: 1.32em; +} + +section h2 { + font-size: 1.12em; + font-style: italic; +} + +section h3 { + font-size: 1em; + /* text-transform: uppercase; */ +} + +section ul { + list-style-type: disc; +} + + +section a, section a:link, section a:visited, section a:active { + font-style: italic; + font-weight: normal; + text-decoration: underline; +} + +section a:hover, section a:focus { + color: var(--color-primary, #FF6E1E); + text-decoration: none; +} + +/* + * We want the links in the output of the Builder widget to pop out + * as links. + */ +section.widget a, section.widget a:link, section.widget a:visited, section.widget a:active { + color: var(--color-widget-link, blue); +} + +aside { + margin: 0; + border: 0; + padding-left: 1em; + position: relative; + display: inline-block; + text-align: right; +} + +aside h2 { + font-size: 1em; + text-transform: uppercase; +} + +aside h2 > a { + font-style: normal; +} + +aside ul { + margin: 0; + padding: 0; + display: block; + list-style-type: none; +} + +aside ul li { + font-size: 0.82em; +} + +aside ul > ul { + padding-left: 1em; + font-size: 0.72em; +} + +footer { + position: fixed; + bottom: 0; + display: block; + width: 100%; + height: 2em; + color: var(--color-bg, white); + background-color: var(--color-footer-bg, #303030); + font-size: 80%; + text-align: left; + vertical-align: middle; + z-index: 2; +} + +footer h1, footer span, footer address { + position: relative; + display: inline-block; + margin: 0; + padding-left: 0.24em; + font-family: var(--font-family-base, Open Sans, Helvetica, Sans-Serif); + font-size: 1m; +} + +footer h1 { + font-weight: normal; +} + +footer a, footer a:link, footer a:visited, footer a:active, footer a:focus, footer a:hover { + padding: 0; + display: inline; + margin: 0; + color: var(--color-primary, #FF6E1E); + text-decoration: none; +} + +/* Form styling */ +/* +form { + display: block; + padding: 1em; + border-style: solid; + border-radius: 0.82em; + border-width: 0.18em; + border-color: red; +} +*/ + +form div label { + display: inline; + margin: 0.72em; + text-align: right; + min-width: 5em; +} + +form div input[type=button] { + margin: 1em; + border-radius: 82em; +} + +/* Widget is the outer container for either a + * BuilderWidget or SearchWidger */ +.widget { + display: block; + flex-flow: row wrap; + padding: 1em; + border-style: solid; + border-radius: 0.82em; + border-width: 0.18em; + border-color: var(--border-color, red); +} + +.announcement { + color: var(--color-announcement, white); + background-color: var(--color-bg-announcement, orange); + padding: 1em; + margin-top: 2em; + margin-bottom: 2em; + margin-left: 0em; + margin-right: 0em; + text-overflow: ellipsis; + border: 1px solid black; +} + +/* +.article-result, .publication-result, .book_section-result { + margin-bottom: 1.24em; +} +*/ + + +/* + * Search box and results layout + */ +.search-box { + display: block; +} + +.search-box div { + display: block; +} + +.search-box div label { + vertical-align: top; +} + +.search-go-button { + display: block; +} + +.search-go-button input { + text-align: center; + margin: 0.24em; +} + +.search-result-pager { + padding-top: 1.24em; + padding-bottom: 1.24em; +} + +.search-results { + margin-top:0; + margin-bottom:0; + margin-left: 0; + margin-right: 1.24em; + padding: 0; +} +.search-result { + padding-top: 0.24em; + padding-bottom: 1.24em; +} + +.search-result:nth-child(odd) { + background-color: var(--color-lightgrey, lightgrey); +} + +.field-name, .matched-name, .index-name { + display: inline-block; + width: 6%; + margin-right: 1.24em; + text-transform: lowercase; + text-align: right; + vertical-align: top; +} + +.field-value, .matched-value, .index-value { + display: inline-block; + text-align: left; + vertical-align: top; +} + +.index-name, .index-value { + font-style: italic; + font-size: smaller; +} + +a.visually-hidden:focus { + position: static; + display: block; + width: 9rem; + height: 1rem; + margin: 5px; + overflow: visible; + clip: auto; + white-space: normal; + padding: 0.5rem 1rem; + border: 2px solid var(--color-text, while); + border-radius: 4px; + background-color: var(--color-bg, while); +} + +a.visually-hidden { + position: absolute; + width: 1px; + height: 1px; + padding: 0px; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} diff --git a/pandoc/js/copyToClipboard.js b/pandoc/js/copyToClipboard.js new file mode 100644 index 0000000..becbceb --- /dev/null +++ b/pandoc/js/copyToClipboard.js @@ -0,0 +1,30 @@ +document.addEventListener('DOMContentLoaded', function() { + const preElements = document.querySelectorAll('pre'); + + preElements.forEach(pre => { + const codeElement = pre.querySelector('code'); + if (codeElement) { + const copyButton = document.createElement('button'); + copyButton.className = 'copy-button'; + copyButton.innerHTML = '📋'; // Clipboard emoji + copyButton.setAttribute('title', 'Copy to Clipboard'); // Tooltip text + + copyButton.addEventListener('click', () => { + const textToCopy = codeElement.textContent; + navigator.clipboard.writeText(textToCopy).then(() => { + copyButton.textContent = 'Copied!'; + setTimeout(() => { + copyButton.innerHTML = '📋'; + }, 2000); + }).catch(err => { + console.error('Failed to copy text: ', err); + }); + }); + + pre.style.position = 'relative'; + pre.appendChild(copyButton); + } + }); +}); + +export {}; // This makes the file a module diff --git a/pandoc/page.tmpl b/pandoc/page.tmpl index 81de7c8..22af848 100644 --- a/pandoc/page.tmpl +++ b/pandoc/page.tmpl @@ -4,9 +4,15 @@ $title$$if(project)$ — $project$$endif$ - - - + + +$for(extra-css)$ + +$endfor$ + +$for(extra-js)$ + +$endfor$