Skip to content

opendsm/opendsm-website

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

63 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

The website was made using the following:

Automatic code documentations assumes google-style docstrings. For examples on how to format google-style docstrings, see here: https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html

To install

Note for Mac Users: On a Mac with Apple Silicon it may be necessary to first install some relevant libraries that are needed for OpenDSM:

brew install openblas
brew install lapack

Each of the above will also prompt you to set some environment variables with commands like export LDFLAGS="/some/appropriate/location/", so run these commands one at a time and look at the tail end of the output for instruction.

To install the necessary packages, run the following from the opendsm-website directory

python3 -m venv .venv
. .venv/bin/activate
python3 -m pip install --upgrade pip
python3 -m pip install .
python3 -m mkdocs serve

To run

From opendsm-website directory run:

. .venv/bin/activate
python3 -m mkdocs serve

When editing opendsm docstrings (which feed the API reference), also watch the package source so the API pages live-reload: mkdocs serve -a localhost:8001 -w ..

Versioning

The published site is versioned with mike. Each documentation version is published at /vX.Y/ (shown as X.Y in the version selector) and mirrors an opendsm release; patch releases (vX.Y.Z) refresh the existing vX.Y version rather than creating a new one. main builds the dev version; the newest stable release carries the stable alias (shown as a badge in the version selector), and the site root redirects to stable. mike orders the version selector itself (dev first, then releases newest→oldest).

Deployment runs from .github/workflows/website_deployment.yaml:

  • push to main → builds/refreshes the dev version (opendsm @master)
  • push a vX.Y.Z tag → builds version vX.Y, moves stable, sets it as default
  • Actions → Run workflow (workflow_dispatch) → builds an arbitrary version (for backfilling)

Each stable version pins opendsm to its release

The API reference is generated from the installed opendsm, so a version must be built with pyproject.toml pinning opendsm to that release — otherwise it silently documents master (which can differ substantially). To make this reliable, every published stable version lives on a long-lived version/X.Y branch: it is main's content with the opendsm dependency re-pinned to the release commit/tag. dev (built from main) keeps @master.

main, gh-pages, and version/** are protected from deletion by a repository ruleset. Force-pushes are still allowed, so the refresh below works.

Publishing or refreshing a stable version (e.g. 1.2):

  1. Rebuild the branch from current main and re-pin opendsm:
    git checkout main && git pull
    git checkout -B version/1.2
    # in pyproject.toml: opendsm @ git+https://github.com/opendsm/opendsm@<release-commit-or-tag>
    git commit -am "Pin opendsm to the 1.2 release"
    git push -f origin version/1.2
  2. Actions → Run workflow on version/1.2 with version=v1.2, alias=stable, set_default=true.

Backfilling an older version is the same flow on its own version/X.Y branch, dispatched with version=vX.Y (leave alias/set_default unset unless it should become the newest stable).

Deprecating a superseded version

The install page and the version/Python badges pin themselves at build time. The hooks/version_pins.py hook reads the installed opendsm version and its supported Python versions, then checks PyPI: if a newer release line exists, the version is treated as superseded and its install page renders the pinned command (uv pip install "opendsm==X.Y.Z" --exclude-newer <date>), links the release tag, switches the badges to static values, and adds a deprecation note. The freeze date is the successor line's release date, read from PyPI.

So deprecating a version needs no page edits — only the pyproject.toml opendsm pin you already set on its version/X.Y branch. Two overrides exist:

  • When an intermediate line was skipped, add it to SUPERSEDED_BY in hooks/version_pins.py (e.g. "1.0": "1.2" freezes 1.0 to 1.2's release date rather than the abandoned 1.1).
  • To force a date for a one-off build, set the OPENDSM_FREEZE_DATE env var (the freeze_date workflow_dispatch input wires it through).

Local preview

Content and code render with plain mkdocs serve. The version-selector dropdown only appears when a versions.json is reachable, so to preview it either run mike serve (after a local mike deploy), or drop a throwaway gitignored src/versions.json:

[{"version": "dev", "title": "dev", "aliases": []}, {"version": "v1.2", "title": "v1.2", "aliases": ["stable"]}]

Gotchas

  • Internal links and assets must use site:-prefixed paths (e.g. site:assets/..., site:documentation/...), never root-absolute /assets/.... Only site: links are rewritten to the active version's base; absolute links break once served under a version path.
  • CNAME and robots.txt live at the gh-pages root, not under src/ (which would land in a version directory). A manual gh-pages cleanup must preserve both.

Do not enable navigation.instant — it conflicts with Osano (investigated, settled)

navigation.instant is deliberately off and should stay off as long as the Osano cookie-consent script (src/overrides/main.html) is loaded. This was investigated end-to-end; the conflict is architectural and cannot be cleanly fixed. Don't repeat the investigation.

Instant loading turns the site into an SPA — on every internal navigation it removes the old [data-md-component=container] subtree and inserts the new page's, rather than doing a full reload. Osano's bundle runs a MutationObserver on document.documentElement (the whole tree), and on every childList change it (a) re-scans all added nodes to enforce script/cookie/iframe blocking, and (b) re-renders its consent widget when one of its required nodes is removed. Instant nav fires both on every navigation: the widget re-render is a visible consent-banner flash, and the full re-scan of the incoming page is a multi-second cursor stall on large pages (e.g. the CalTRACK technical appendix). Confirmed by reading both Material's instant-nav code and the Osano bundle; Osano injects no <style>/<link>, so this is not a CSS-preservation problem — the trigger is the DOM mutation itself.

Why it can't be fixed: Osano's observer scope and behavior are hardcoded in its bundle and are its consent-enforcement — suppressing or narrowing the observer defeats the compliance function it exists for. Self-hosting a patched osano.js would freeze a compliance-critical, frequently-updated, obfuscated third-party script and require perpetual re-patching, with real compliance-drift and security risk. Neither is an acceptable trade for snappier navigation on a docs site.

Conclusion: instant nav is incompatible with any document-wide consent/observer script like Osano. If the goal was avoiding the version selector's first-load late-paint, solve that without instant nav (see the version-box-static approach), or accept it.

About

Official OpenDSM website

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors