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$