From 0e5e87841ad643a1acf28722f2e5feb9f4577fe4 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 17 Jun 2026 22:16:42 +0000 Subject: [PATCH 1/3] Add MkDocs Material documentation site for GitHub Pages Add a hosted documentation site (the Python equivalent of the R NNS pkgdown site) built with MkDocs + Material and deployed to GitHub Pages at https://ovvo-financial.github.io/NNS-python/. - mkdocs.yml: Material theme, search, light/dark toggle, and a nav that maps onto the existing Markdown docs: Home, Install, Quick start, API reference, API status, Conventions (+ plot parity policy), Parity with R NNS (+ sync contract/status), Benchmarks, Release notes (+ release process). Existing docs/*.md are reused; previously orphaned pages are folded in as sub-pages so nothing is unreachable. - docs/index.md, install.md, quick_start.md, release_notes.md: new pages derived from the README, kept consistent with current Stable, parity-focused messaging and the optional native-extension build. - .github/workflows/docs.yml: build with `mkdocs build --strict` and deploy via actions/deploy-pages on push to main (and manual dispatch). - pyproject.toml: add a `docs` dependency group (mkdocs-material, pymdown-extensions). - README.md: add a docs badge and link to the hosted site. - .gitignore: ignore the MkDocs `site/` build output. The site builds cleanly under `mkdocs build --strict`. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01BwFx145eq6LfzZFFMvp8BD --- .github/workflows/docs.yml | 60 ++++++++++++++++++++++++ .gitignore | 3 ++ README.md | 4 ++ docs/index.md | 95 ++++++++++++++++++++++++++++++++++++++ docs/install.md | 55 ++++++++++++++++++++++ docs/quick_start.md | 75 ++++++++++++++++++++++++++++++ docs/release_notes.md | 31 +++++++++++++ mkdocs.yml | 84 +++++++++++++++++++++++++++++++++ pyproject.toml | 4 ++ 9 files changed, 411 insertions(+) create mode 100644 .github/workflows/docs.yml create mode 100644 docs/index.md create mode 100644 docs/install.md create mode 100644 docs/quick_start.md create mode 100644 docs/release_notes.md create mode 100644 mkdocs.yml diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 00000000..9c2333ea --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,60 @@ +name: Docs + +on: + push: + branches: [main] + paths: + - "docs/**" + - "mkdocs.yml" + - ".github/workflows/docs.yml" + workflow_dispatch: + +# Allow only one concurrent deployment, and let in-progress runs finish. +concurrency: + group: pages + cancel-in-progress: false + +permissions: + contents: read + pages: write + id-token: write + +jobs: + build: + name: Build site + runs-on: ubuntu-latest + steps: + - name: Check out repo + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Install MkDocs + run: | + python -m pip install -U pip + python -m pip install \ + "mkdocs-material>=9.5" \ + "pymdown-extensions>=10" + + - name: Build (strict) + run: mkdocs build --strict + + - name: Upload Pages artifact + uses: actions/upload-pages-artifact@v3 + with: + path: site + + deploy: + name: Deploy to GitHub Pages + needs: build + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Deploy + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.gitignore b/.gitignore index 7c38440c..8cd4fa79 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,6 @@ tools/NNS/src/*.o # Stray R plotting artifact from headless regeneration Rplots.pdf + +# MkDocs build output +/site/ diff --git a/README.md b/README.md index 5a179925..8e18db15 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ [![PyPI package](https://img.shields.io/badge/package-ovvo--nns-blue)](https://pypi.org/project/ovvo-nns/) [![Python](https://img.shields.io/badge/python-3.11%2B-blue)](https://www.python.org/) +[![Docs](https://img.shields.io/badge/docs-ovvo--financial.github.io-blue)](https://ovvo-financial.github.io/NNS-python/) [![License](https://img.shields.io/badge/license-GPL--3.0--only-blue)](LICENSE) `ovvo-nns` brings Nonlinear Nonparametric Statistics to Python as the `nns` import package. It is a parity-focused port of the R `NNS` 13.0+ package, designed for real-world data that violate symmetry, linearity, or distributional assumptions. @@ -178,6 +179,9 @@ uv run python examples/run_all_vignettes.py ## Documentation +The full documentation site is hosted at +****. + - [API reference manual](docs/api_reference.md) - [API status and known gaps](docs/api_status.md) - [Behavior conventions and intentional divergences](docs/conventions.md) diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 00000000..28206d95 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,95 @@ +# NNS Python + +[![PyPI package](https://img.shields.io/pypi/v/ovvo-nns?label=ovvo-nns&color=blue)](https://pypi.org/project/ovvo-nns/) +[![Python](https://img.shields.io/badge/python-3.11%2B-blue)](https://www.python.org/) +[![License](https://img.shields.io/badge/license-GPL--3.0--only-blue)](https://github.com/OVVO-Financial/NNS-python/blob/main/LICENSE) + +`ovvo-nns` brings **Nonlinear Nonparametric Statistics** to Python as the `nns` +import package. It is a parity-focused port of the R `NNS` 13.0+ package, +designed for real-world data that violate symmetry, linearity, or distributional +assumptions. + +NNS is built around partial moments — the lower and upper components of variance — +and uses them across nonlinear dependence, correlation, causation, regression, +classification, forecasting, stochastic dominance, stochastic superiority, Monte +Carlo simulation, and numerical differentiation workflows. + +!!! note "Origin" + NNS was created by Fred Viole as the companion R package to Viole, F. and + Nawrocki, D. (2013), *Nonlinear Nonparametric Statistics: Using Partial + Moments*. **Book (2nd Edition):** . + For a direct quantitative finance implementation of NNS, see + [OVVO Labs](https://www.ovvolabs.com). + +## Package at a glance + +| Item | Value | +|---|---| +| Distribution package | `ovvo-nns` | +| Import package | `nns` | +| Python | `>=3.11` | +| Required runtime dependencies | NumPy, SciPy | +| R required at runtime | No | +| Native acceleration | Private, optional `nns._nnscore` kernels where available | +| Public API status | Stable, parity-focused | +| License | GPL-3.0-only | + +The public package is Python-native and does not call R at runtime. Some core +kernels can use the private `_nnscore` extension when it is present, while public +functions keep Python implementations and explicit fallback behavior. + +## Get started + +
+ +- :material-download: **[Install](install.md)** + + `pip install ovvo-nns`, then `import nns`. + +- :material-rocket-launch: **[Quick start](quick_start.md)** + + Partial moments, dependence, regression, and forecasting in a few lines. + +- :material-book-open-variant: **[API reference](api_reference.md)** + + Function-by-function index with R `NNS` name crosswalks. + +- :material-check-decagram: **[API status](api_status.md)** + + Implemented, partial, guarded, and known-gap paths. + +
+ +## Main API areas + +| Area | Representative functions | +|---|---| +| Partial moments | `lpm`, `upm`, `lpm_ratio`, `upm_ratio`, `pm_matrix` | +| Classical moment helpers | `mean_pm`, `var_pm`, `skew_pm`, `kurt_pm`, `nns_moments` | +| Dependence, correlation, copula | `nns_dep`, `nns_cor`, `nns_copula` | +| Causation | `nns_causation`, `causal_matrix` | +| Regression and classification | `nns_reg`, `nns_m_reg`, `nns_stack`, `nns_boost` | +| Forecasting | `nns_seas`, `nns_arma`, `nns_arma_optim`, `nns_var` | +| Distribution tools | `nns_cdf`, `nns_anova`, `nns_norm` | +| Stochastic dominance | `fsd`, `ssd`, `tsd`, `nns_sd_cluster`, `sd_efficient_set` | +| Stochastic superiority and simulation | `nns_ss`, `nns_mc`, `nns_meboot` | +| Differentiation | `nns_diff`, `dy_dx`, `dy_d` | +| Categorical helpers | `encode_factor_codes`, `factor_2_dummy`, `factor_2_dummy_fr`, `prepare_factor_predictors` | + +See [API status](api_status.md) for implemented, partial, guarded, and known-gap +paths. + +## Design boundaries + +NNS Python prioritizes stable public behavior from installed R NNS 13.0+, not +private helper parity. The package returns NumPy arrays and plain dictionaries +rather than R `data.table` objects, uses explicit Python errors for several +unsafe R coercions, and generally ignores plotting side effects. + +See [behavior conventions](conventions.md) for detailed compatibility notes and +[parity with R NNS](parity.md) for the parity target and automation. + +## Attribution + +Upstream R package and reference implementation: +[OVVO-Financial/NNS](https://github.com/OVVO-Financial/NNS). diff --git a/docs/install.md b/docs/install.md new file mode 100644 index 00000000..e3adc7aa --- /dev/null +++ b/docs/install.md @@ -0,0 +1,55 @@ +# Install + +## From PyPI + +```bash +pip install ovvo-nns +``` + +The distribution package is **`ovvo-nns`**; the import package is **`nns`**: + +```python +import nns + +print(nns.__version__) +``` + +Installing `ovvo-nns` includes the Matplotlib plotting API (`nns.plotting`). +Matplotlib is a regular dependency and is imported lazily, so `import nns` stays +light. See the [plot parity policy](plot_parity_policy.md) for details. + +## Requirements + +| Requirement | Value | +|---|---| +| Python | `>=3.11` (CPython 3.11, 3.12, 3.13, 3.14) | +| Runtime dependencies | NumPy, SciPy, Matplotlib | +| R at runtime | Not required | + +R is used only for parity tests and local cache regeneration, never at normal +runtime. + +## Wheels vs. source builds + +Published wheels should be preferred when available. They ship the optional +private native extension (`nns._nnscore`) prebuilt for supported platforms. + +Source builds compile the optional native extension with +[`scikit-build-core`](https://scikit-build-core.readthedocs.io/) and +[`nanobind`](https://nanobind.readthedocs.io/), which require a C++17 toolchain. +Public APIs keep Python implementations and explicit fallback behavior, so the +native extension remains a private, benchmark-backed implementation detail rather +than a public API. + +## Development install + +```bash +uv sync --group dev +uv run pytest +uv run ruff check . +uv run mypy +``` + +The default parity suite is cache-backed and does not require `Rscript`. +`Rscript` and the R `NNS` package are needed only when regenerating parity caches +or running live R comparison scripts. diff --git a/docs/quick_start.md b/docs/quick_start.md new file mode 100644 index 00000000..eb44605e --- /dev/null +++ b/docs/quick_start.md @@ -0,0 +1,75 @@ +# Quick start + +These snippets mirror the runnable +[example vignettes](https://github.com/OVVO-Financial/NNS-python/tree/main/examples/vignettes), +which are exercised in CI so they stay in sync with the package. + +## Partial moments + +```python +import numpy as np +from nns import lpm, upm + +x = np.array([-2.0, -1.0, 0.5, 3.0], dtype=np.float64) + +lower = lpm(degree=2, target=0.0, x=x) +upper = upm(degree=2, target=0.0, x=x) + +print("lower partial moment:", lower) +print("upper partial moment:", upper) +``` + +## Nonlinear dependence + +```python +import numpy as np +from nns import nns_cor, nns_dep + +grid = np.linspace(-2.0, 2.0, 80, dtype=np.float64) +y = grid**2 + +print("NNS dependence:", nns_dep(grid, y)) +print("NNS correlation:", nns_cor(grid, y)) +``` + +## Nonlinear regression + +Fit a nonlinear regression and estimate new points: + +```python +import numpy as np +from nns import nns_reg + +x = np.linspace(-3.0, 3.0, 80, dtype=np.float64) +y = np.sin(x) + 0.2 * x +points = np.array([-1.5, 0.0, 1.5], dtype=np.float64) + +fit = nns_reg(x, y, point_est=points, confidence_interval=None) + +print("R2:", fit["R2"]) +print(np.column_stack((points, fit["Point.est"]))) +``` + +## Forecasting + +Forecast a univariate series: + +```python +import numpy as np +from nns import nns_arma, nns_seas + +t = np.arange(1, 60, dtype=np.float64) +series = 10.0 + np.sin(t / 3.0) + 0.05 * t + +seasonality = nns_seas(series, modulo=[3, 4, 6], mod_only=True) +forecast = nns_arma(series, h=3, seasonal_factor=4, method="lin") + +print("best seasonal period:", seasonality["best.period"]) +print("forecast:", forecast) +``` + +## Next steps + +- Browse the full [API reference](api_reference.md). +- Check the [API status](api_status.md) for partial, guarded, and known-gap paths. +- Read the [behavior conventions](conventions.md) for intentional divergences from R. diff --git a/docs/release_notes.md b/docs/release_notes.md new file mode 100644 index 00000000..ec702f61 --- /dev/null +++ b/docs/release_notes.md @@ -0,0 +1,31 @@ +# Release notes + +The authoritative, per-version release history is published to: + +- **PyPI release history:** +- **GitHub Releases:** + +The currently published version is shown by the badge on the +[home page](index.md) and by: + +```python +import nns + +print(nns.__version__) +``` + +## Versioning + +`ovvo-nns` uses standard semantic-style version numbers (`MAJOR.MINOR.PATCH`). +The public API is **stable and parity-focused**: documented public behavior is +not expected to break across minor releases. Known partial, guarded, and +known-gap paths are tracked on the [API status](api_status.md) page, and +intentional divergences from R `NNS` are recorded in the +[conventions](conventions.md). + +Version numbers are kept consistent across `pyproject.toml`, the package +`__version__`, and the README. This is enforced in CI by +`scripts/check_version_consistency.py`. + +For how releases are built, signed, and published, see the +[release process](releasing.md). diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 00000000..5b233a07 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,84 @@ +site_name: NNS Python +site_description: Nonlinear Nonparametric Statistics for Python — a parity-focused port of R NNS. +site_url: https://ovvo-financial.github.io/NNS-python/ +site_author: Fred Viole + +repo_name: OVVO-Financial/NNS-python +repo_url: https://github.com/OVVO-Financial/NNS-python +edit_uri: edit/main/docs/ + +copyright: Copyright © Fred Viole — GPL-3.0-only + +theme: + name: material + features: + - navigation.instant + - navigation.tracking + - navigation.top + - navigation.sections + - toc.follow + - content.code.copy + - content.action.edit + - search.suggest + - search.highlight + palette: + - media: "(prefers-color-scheme: light)" + scheme: default + primary: indigo + accent: indigo + toggle: + icon: material/weather-night + name: Switch to dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + primary: indigo + accent: indigo + toggle: + icon: material/weather-sunny + name: Switch to light mode + icon: + repo: fontawesome/brands/github + +plugins: + - search + +markdown_extensions: + - admonition + - attr_list + - md_in_html + - tables + - toc: + permalink: true + - pymdownx.highlight: + anchor_linenums: true + - pymdownx.inlinehilite + - pymdownx.snippets + - pymdownx.superfences + - pymdownx.details + +extra: + social: + - icon: fontawesome/brands/github + link: https://github.com/OVVO-Financial/NNS-python + - icon: fontawesome/brands/python + link: https://pypi.org/project/ovvo-nns/ + +# Pages that exist in docs/ but are surfaced as sub-pages of the nav below. +# Keep this nav aligned with README "Documentation" links. +nav: + - Home: index.md + - Install: install.md + - Quick start: quick_start.md + - API reference: api_reference.md + - API status: api_status.md + - Conventions: + - Behavior conventions: conventions.md + - Plot parity policy: plot_parity_policy.md + - Parity with R NNS: + - Parity overview: parity.md + - Sync contract: sync_contract.md + - Sync status: sync_status.md + - Benchmarks: benchmarks.md + - Release notes: + - Release notes: release_notes.md + - Release process: releasing.md diff --git a/pyproject.toml b/pyproject.toml index f57dd863..518a3dbe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,6 +48,10 @@ dev = [ "pytest-xdist>=3.8.0", "ruff", ] +docs = [ + "mkdocs-material>=9.5", + "pymdown-extensions>=10", +] [build-system] requires = ["scikit-build-core", "nanobind"] From 76af8dcb65afe6586f662d23495ef1f1a76478f7 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 17 Jun 2026 22:24:02 +0000 Subject: [PATCH 2/3] Style docs site to match the R NNS pkgdown (Bootswatch Cosmo) look The R NNS site (https://ovvo-financial.github.io/NNS/) is a pkgdown site built with Bootstrap 5 + the Bootswatch "Cosmo" theme. Bring the Material for MkDocs site visually in line with it: - Cosmo palette: blue #2780e3 primary driving a solid-blue top navbar with white text, matching link/accent colors, for both light and dark schemes (docs/stylesheets/cosmo.css). - Flat design: squared corners on code blocks, admonitions, tables, buttons, and search, mirroring Cosmo's flat aesthetic. - Typography: Source Sans 3 body / Source Code Pro mono, the Source Sans family Cosmo uses, with slightly bolder headings. - Top navbar layout via navigation.tabs (+ sticky), replacing the plain sidebar so top-level sections read like pkgdown's navbar. - The NNS hex sticker as the site logo and favicon (docs/assets/nns_hex_sticker.png), as on the pkgdown site. Site still builds cleanly under `mkdocs build --strict`. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01BwFx145eq6LfzZFFMvp8BD --- docs/assets/nns_hex_sticker.png | Bin 0 -> 47227 bytes docs/stylesheets/cosmo.css | 77 ++++++++++++++++++++++++++++++++ mkdocs.yml | 17 ++++--- 3 files changed, 89 insertions(+), 5 deletions(-) create mode 100644 docs/assets/nns_hex_sticker.png create mode 100644 docs/stylesheets/cosmo.css diff --git a/docs/assets/nns_hex_sticker.png b/docs/assets/nns_hex_sticker.png new file mode 100644 index 0000000000000000000000000000000000000000..a0271fb32c0b7e414717d211d95ac9863ea749f8 GIT binary patch literal 47227 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 code, +.md-typeset code, +.md-typeset .highlight, +.md-typeset .admonition, +.md-typeset details, +.md-typeset table:not([class]), +.md-typeset .md-button, +.md-search__form, +.md-search__output { + border-radius: 0 !important; +} + +/* Cosmo navbar feel: tighter, uppercase-ish weight on the top tabs */ +.md-tabs { + font-weight: 600; +} + +/* Source Sans renders a touch light; nudge headings bolder like Cosmo */ +.md-typeset h1, +.md-typeset h2, +.md-typeset h3 { + font-weight: 700; + letter-spacing: -0.01em; +} + +/* Cosmo-style primary buttons (flat, solid blue) */ +.md-typeset .md-button--primary { + background-color: var(--md-primary-fg-color); + border-color: var(--md-primary-fg-color); + color: #fff; +} +.md-typeset .md-button--primary:hover { + background-color: var(--md-primary-fg-color--dark); + border-color: var(--md-primary-fg-color--dark); +} + +/* Keep the hex sticker logo crisp and reasonably sized in the header */ +.md-header__button.md-logo img { + height: 1.6rem; + width: auto; +} diff --git a/mkdocs.yml b/mkdocs.yml index 5b233a07..84f7657f 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -11,11 +11,19 @@ copyright: Copyright © Fred Viole — GPL-3.0-only theme: name: material + logo: assets/nns_hex_sticker.png + favicon: assets/nns_hex_sticker.png + # Match the R NNS pkgdown site (Bootstrap 5 + Bootswatch "Cosmo"): + # flat design, a solid blue top navbar, and the Source Sans typeface. + font: + text: Source Sans 3 + code: Source Code Pro features: - navigation.instant - navigation.tracking + - navigation.tabs + - navigation.tabs.sticky - navigation.top - - navigation.sections - toc.follow - content.code.copy - content.action.edit @@ -24,21 +32,20 @@ theme: palette: - media: "(prefers-color-scheme: light)" scheme: default - primary: indigo - accent: indigo toggle: icon: material/weather-night name: Switch to dark mode - media: "(prefers-color-scheme: dark)" scheme: slate - primary: indigo - accent: indigo toggle: icon: material/weather-sunny name: Switch to light mode icon: repo: fontawesome/brands/github +extra_css: + - stylesheets/cosmo.css + plugins: - search From 2a43294605f528c4dc270c2ed66ed7b1e484ddc9 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 17 Jun 2026 22:29:27 +0000 Subject: [PATCH 3/3] Match pkgdown home layout: text-brand navbar, body hex sticker, aside blocks Using the actual R NNS pkgdown homepage as reference, tighten the visual match beyond the Cosmo palette/fonts: - Navbar uses a text brand (site name) like pkgdown's "NNS" brand, so the hex sticker is no longer a header logo. It now sits at the top of the home page body at width 150 (left-aligned), followed by the badges and the H1, mirroring the pkgdown landing page order. - Add Links / License / Citation / Developers sections to the home page, mirroring pkgdown's right-hand aside. - Footer credit set to "Developed by Fred Viole." to match pkgdown. - Badges recolored to the Cosmo blue (#2780e3); bold navbar brand weight. - Keep favicon as the hex sticker. Site still builds cleanly under `mkdocs build --strict`. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01BwFx145eq6LfzZFFMvp8BD --- docs/index.md | 32 ++++++++++++++++++++++++++++---- docs/stylesheets/cosmo.css | 8 ++++---- mkdocs.yml | 6 ++++-- 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/docs/index.md b/docs/index.md index 28206d95..43cf29f2 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,8 +1,10 @@ -# NNS Python +NNS hex sticker + +[![PyPI package](https://img.shields.io/pypi/v/ovvo-nns?label=ovvo-nns&color=2780e3)](https://pypi.org/project/ovvo-nns/) +[![Python](https://img.shields.io/badge/python-3.11%2B-2780e3)](https://www.python.org/) +[![License](https://img.shields.io/badge/license-GPL--3.0--only-2780e3)](https://github.com/OVVO-Financial/NNS-python/blob/main/LICENSE) -[![PyPI package](https://img.shields.io/pypi/v/ovvo-nns?label=ovvo-nns&color=blue)](https://pypi.org/project/ovvo-nns/) -[![Python](https://img.shields.io/badge/python-3.11%2B-blue)](https://www.python.org/) -[![License](https://img.shields.io/badge/license-GPL--3.0--only-blue)](https://github.com/OVVO-Financial/NNS-python/blob/main/LICENSE) +# NNS Python `ovvo-nns` brings **Nonlinear Nonparametric Statistics** to Python as the `nns` import package. It is a parity-focused port of the R `NNS` 13.0+ package, @@ -89,6 +91,28 @@ unsafe R coercions, and generally ignores plotting side effects. See [behavior conventions](conventions.md) for detailed compatibility notes and [parity with R NNS](parity.md) for the parity target and automation. +## Links + +- [View on PyPI](https://pypi.org/project/ovvo-nns/) +- [Browse source code](https://github.com/OVVO-Financial/NNS-python) +- [Report a bug](https://github.com/OVVO-Financial/NNS-python/issues) + +## License + +[GPL-3.0-only](https://www.gnu.org/licenses/gpl-3.0.en.html) + +## Citation + +NNS is the companion to Viole, F. and Nawrocki, D. (2013), +*Nonlinear Nonparametric Statistics: Using Partial Moments* (ISBN: 1490523995). +2nd edition: . + +## Developers + +- **Fred Viole** — author and maintainer +- **Roberto Spadim** — contributor +- **Rasheed Khoshnaw** — contributor + ## Attribution Upstream R package and reference implementation: diff --git a/docs/stylesheets/cosmo.css b/docs/stylesheets/cosmo.css index 0dc30e5c..480c4ccd 100644 --- a/docs/stylesheets/cosmo.css +++ b/docs/stylesheets/cosmo.css @@ -70,8 +70,8 @@ border-color: var(--md-primary-fg-color--dark); } -/* Keep the hex sticker logo crisp and reasonably sized in the header */ -.md-header__button.md-logo img { - height: 1.6rem; - width: auto; +/* Cosmo navbar-brand: bold, slightly larger package name */ +.md-header__title { + font-weight: 700; + font-size: 1.05rem; } diff --git a/mkdocs.yml b/mkdocs.yml index 84f7657f..178392c8 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -7,11 +7,13 @@ repo_name: OVVO-Financial/NNS-python repo_url: https://github.com/OVVO-Financial/NNS-python edit_uri: edit/main/docs/ -copyright: Copyright © Fred Viole — GPL-3.0-only +copyright: Developed by Fred Viole. theme: name: material - logo: assets/nns_hex_sticker.png + # pkgdown's navbar uses a text brand ("NNS") with the hex sticker shown in + # the home page body, so we keep the header text-only and place the sticker + # on the home page instead of using it as a header logo. favicon: assets/nns_hex_sticker.png # Match the R NNS pkgdown site (Bootstrap 5 + Bootswatch "Cosmo"): # flat design, a solid blue top navbar, and the Source Sans typeface.