diff --git a/.github/workflows/docs-deploy.yml b/.github/workflows/docs-deploy.yml index 7d98e6d..5da08aa 100644 --- a/.github/workflows/docs-deploy.yml +++ b/.github/workflows/docs-deploy.yml @@ -6,7 +6,6 @@ on: - main paths: - "docs/**" - - "mkdocs.yml" - "pyproject.toml" - "sst.config.ts" - "package.json" @@ -66,7 +65,7 @@ jobs: run: | set -euo pipefail python -m pip install --upgrade pip - python -m pip install mkdocs mkdocs-material mkdocs-jupyter + python -m pip install sphinx pydata-sphinx-theme myst-parser myst-nb sphinx-copybutton sphinx-design linkify-it-py - name: Install deploy dependencies run: | diff --git a/.github/workflows/docs-doctest.yml b/.github/workflows/docs-doctest.yml index cb5ec0c..c53b9c4 100644 --- a/.github/workflows/docs-doctest.yml +++ b/.github/workflows/docs-doctest.yml @@ -30,7 +30,7 @@ jobs: run: | set -euo pipefail python -m pip install --upgrade pip - python -m pip install mkdocs mkdocs-material mkdocs-jupyter pytest + python -m pip install sphinx pydata-sphinx-theme myst-parser myst-nb sphinx-copybutton sphinx-design linkify-it-py pytest - name: Run docs build doctest run: | diff --git a/.gitignore b/.gitignore index 7ff9750..efd4560 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,8 @@ MANIFEST # built docs site/ +jupyter_execute/ +.jupyter_cache/ # Installer logs pip-log.txt diff --git a/README.md b/README.md index 4d864f4..b8eca3c 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,7 @@ dipole antennas, horn antennas, and planar microwave circuits. ## Building the docs The documentation site is built with -[MkDocs Material](https://squidfunk.github.io/mkdocs-material/). +[PyData Sphinx Theme](https://pydata-sphinx-theme.readthedocs.io/en/stable/index.html). A [justfile](https://github.com/casey/just) automates the full pipeline. ```bash @@ -118,8 +118,8 @@ just doctest # Or run each step individually: just nbrun # execute docs example notebooks with papermill -just nbdocs # no-op (MkDocs renders .ipynb directly) -just docs # build the MkDocs static site +just nbdocs # no-op (Sphinx renders .ipynb directly) +just docs # build the Sphinx static site (strict mode) # Serve locally for development just serve # starts a dev server on http://localhost:8080 @@ -136,7 +136,7 @@ Router managed by the private website infrastructure. ```bash npm install -python -m pip install mkdocs mkdocs-material mkdocs-jupyter +python -m pip install sphinx pydata-sphinx-theme myst-parser myst-nb sphinx-copybutton sphinx-design linkify-it-py ``` 2. Set environment variables: diff --git a/docs/PalaceToolkit.png b/docs/PalaceToolkit.png index 85f3fc3..facc6a2 100644 Binary files a/docs/PalaceToolkit.png and b/docs/PalaceToolkit.png differ diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..b61beed --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,79 @@ +"""Sphinx configuration for PalaceToolkit documentation.""" + +from __future__ import annotations + +project = "PalaceToolkit" +author = "EpsilonForge" + +extensions = [ + "myst_nb", + "sphinx.ext.mathjax", + "sphinx_copybutton", + "sphinx_design", +] + +source_suffix = { + ".md": "myst-nb", + ".ipynb": "myst-nb", +} + +root_doc = "index" +exclude_patterns = [ + "_build", + "Thumbs.db", + ".DS_Store", + "**/.ipynb_checkpoints", +] + +# MyST and notebook behavior +myst_enable_extensions = [ + "colon_fence", + "deflist", + "dollarmath", + "html_admonition", + "html_image", + "linkify", + "replacements", + "substitution", + "tasklist", +] + +nb_execution_mode = "off" +nb_render_markdown_format = "myst" +suppress_warnings = ["myst.header"] + +html_theme = "pydata_sphinx_theme" +html_title = "PalaceToolkit" +html_logo = "PalaceToolkit.png" +html_favicon = "PalaceToolkit.png" + +html_theme_options = { + "show_nav_level": 2, + "navigation_with_keys": True, + "logo": { + "text": "PalaceToolkit", + }, +} + +html_static_path = [ + "stylesheets", + "javascripts", +] + +html_css_files = ["interactive.css"] +html_js_files = [ + "https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js", + "mathjax.js", +] + +mathjax3_config = { + "tex": { + "inlineMath": [["$", "$"], ["\\(", "\\)"]], + "displayMath": [["$$", "$$"], ["\\[", "\\]"]], + "processEscapes": True, + "processEnvironments": True, + }, + "options": { + "ignoreHtmlClass": "tex2jax_ignore|mathjax_ignore", + }, +} diff --git a/docs/examples/differential_microstrip_modes.ipynb b/docs/examples/differential_microstrip_modes.ipynb index d50659f..56a449a 100644 --- a/docs/examples/differential_microstrip_modes.ipynb +++ b/docs/examples/differential_microstrip_modes.ipynb @@ -14,7 +14,7 @@ "tags": [] }, "source": [ - "# Differential Microstrip Modes (2D Cross-Section)\n", + "# Differential Microstrip Modes\n", "\n", "This notebook builds a boxed differential microstrip cross-section (substrate + air + ground plane + two PEC strips), solves eigenmodes, and plots the first fields." ] @@ -491,4 +491,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} diff --git a/docs/examples/img/dipole_mesh.htm b/docs/examples/img/dipole_mesh.htm deleted file mode 100644 index 2780b12..0000000 --- a/docs/examples/img/dipole_mesh.htm +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - VTK.js | Example - OfflineLocalView - - - -
- - - - - diff --git a/docs/examples/index.md b/docs/examples/index.md index 2ac5c50..4b7e923 100644 --- a/docs/examples/index.md +++ b/docs/examples/index.md @@ -7,36 +7,176 @@ Palace configuration, simulation, and post-processing. ## Antennas -| Example | Description | -|:--------|:------------| -| [Horn Antenna](horn_antenna.ipynb) | WR-90 rectangular waveguide transition to a horn antenna with waveport boundaries. | -| [Dipole Antenna Mesh](dipole_antenna_mesh.ipynb) | Half-wave dipole geometry and mesh generation workflow. | -| [Monopole Antenna](monopole_antenna.ipynb) | Quarter-wave monopole example with meshing and Palace setup. | -| [L Antenna](l_antenna.ipynb) | Bent-wire L-shaped antenna workflow including geometry and driven simulation setup. | -| [Patch Antenna](patch_antenna.ipynb) | Rectangular patch antenna model with substrate, feed, and boundary setup. | -| [Vivaldi Antenna](vivaldi_antenna.ipynb) | Tapered-slot (Vivaldi) antenna geometry and simulation example. | + ## Planar Microwave Circuits -| Example | Description | -|:--------|:------------| -| [Coax](coax.ipynb) | Coaxial line baseline example for geometry, mesh, and configuration setup. | -| [Coax to Waveguide Transition](coax_to_waveguide.ipynb) | Driven coax-to-waveguide transition example including geometry, mesh, and setup. | -| [Open-ended Stub](open_ended_stub.ipynb) | Open-ended microstrip stub component with geometry and simulation setup. | -| [Step in Width](step_in_width.ipynb) | Microstrip step-discontinuity example for meshing and EM analysis. | + ## Waveguide Structures -| Example | Description | -|:--------|:------------| -| [Waveguide Box](waveguide_box.ipynb) | Closed waveguide cavity/box example including full 3D setup and analysis. | + ## Waveguide Mode Solver -| Example | Description | -|:--------|:------------| -| [Hollow Rectangular Waveguide Modes](hollow_waveguide_modes.ipynb) | PEC waveguide eigenmodes compared with analytic TE/TM propagation constants. | -| [Dielectric Waveguide Modes](dielectric_waveguide_modes.ipynb) | Rectangular dielectric core in cladding with guided-mode classification and field plots. | -| [Microstrip Modes](microstrip_modes.ipynb) | Boxed 2D microstrip cross-section with PEC strip and outer conductor boundaries for hybrid mode analysis. | -| [Slotline Modes](slotline_modes.ipynb) | Boxed 2D slotline cross-section with two PEC slot conductors and open outer boundaries. | -| [Differential Microstrip Modes](differential_microstrip_modes.ipynb) | Boxed 2D differential microstrip with ground plane and two PEC strips for coupled-mode analysis. | + + +```{toctree} +:caption: Antennas +:maxdepth: 1 +:hidden: + +horn_antenna +dipole_antenna_mesh +monopole_antenna +l_antenna +patch_antenna +vivaldi_antenna +``` + +```{toctree} +:caption: Planar Microwave Circuits +:maxdepth: 1 +:hidden: + +coax +coax_to_waveguide +open_ended_stub +step_in_width +``` + +```{toctree} +:caption: Waveguide Structures +:maxdepth: 1 +:hidden: + +waveguide_box +``` + +```{toctree} +:caption: Waveguide Mode Solver +:maxdepth: 1 +:hidden: + +hollow_waveguide_modes +dielectric_waveguide_modes +microstrip_modes +slotline_modes +differential_microstrip_modes +``` diff --git a/docs/examples/microstrip_modes.ipynb b/docs/examples/microstrip_modes.ipynb index 3db4015..bc4bf62 100644 --- a/docs/examples/microstrip_modes.ipynb +++ b/docs/examples/microstrip_modes.ipynb @@ -14,7 +14,7 @@ "tags": [] }, "source": [ - "# Microstrip Modes (2D Cross-Section)\n", + "# Microstrip Modes\n", "\n", "This notebook builds a simple boxed microstrip cross-section (substrate + air + PEC strip conductor), solves eigenmodes with `WaveguideModeSolver`, and plots the first fields." ] diff --git a/docs/examples/slotline_modes.ipynb b/docs/examples/slotline_modes.ipynb index 240f261..108158f 100644 --- a/docs/examples/slotline_modes.ipynb +++ b/docs/examples/slotline_modes.ipynb @@ -14,7 +14,7 @@ "tags": [] }, "source": [ - "# Slotline Modes (2D Cross-Section)\n", + "# Slotline Modes\n", "\n", "This notebook builds a boxed slotline cross-section (substrate + air + two PEC slot conductors), solves eigenmodes with `WaveguideModeSolver`, and plots mode fields." ] diff --git a/docs/full-course.md b/docs/full-course.md index 4278153..7a41248 100644 --- a/docs/full-course.md +++ b/docs/full-course.md @@ -37,7 +37,7 @@ design workflows. ---
- + Get the Full Course →
diff --git a/docs/getting-started/geometry-and-meshing.md b/docs/getting-started/geometry-and-meshing.md index 2001f77..b3d820e 100644 --- a/docs/getting-started/geometry-and-meshing.md +++ b/docs/getting-started/geometry-and-meshing.md @@ -45,9 +45,10 @@ The pipeline: 5. **Assigns physical groups** — volumes get their entity name; surfaces at material interfaces are auto-labelled (e.g. `"conductor__dielectric"`). -!!! tip - The `mesh_order` controls which material wins at overlapping regions. - Think of it as a z-index: small number = highest priority = never cut. +```{tip} +The `mesh_order` controls which material wins at overlapping regions. +Think of it as a z-index: small number = highest priority = never cut. +``` ## Mesh generation diff --git a/docs/getting-started/index.md b/docs/getting-started/index.md index 5c36630..6c866ee 100644 --- a/docs/getting-started/index.md +++ b/docs/getting-started/index.md @@ -73,3 +73,11 @@ python -c "from palacetoolkit.simulation import set_palace_path; set_palace_path See the dedicated Ubuntu build guide and compatibility policy for details. +```{toctree} +:maxdepth: 1 + +geometry-and-meshing +simulation-setup +post-processing +``` + diff --git a/docs/getting-started/simulation-setup.md b/docs/getting-started/simulation-setup.md index 60bc70d..d718c78 100644 --- a/docs/getting-started/simulation-setup.md +++ b/docs/getting-started/simulation-setup.md @@ -76,8 +76,8 @@ A typical Palace JSON config has these top-level keys: { "Problem": { "Type": "Driven" }, "Model": { "Mesh": "model.msh", "L0": 1e-3 }, - "Domains": { "Materials": [...] }, - "Boundaries": { "PEC": {...}, "LumpedPort": [...], "Absorbing": {...} }, + "Domains": { "Materials": [] }, + "Boundaries": { "PEC": {}, "LumpedPort": [], "Absorbing": {} }, "Solver": { "Driven": { "MinFreq": 1.0, "MaxFreq": 10.0, "FreqStep": 0.5 } } } ``` diff --git a/docs/index.md b/docs/index.md index 958a940..be197d5 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,12 +1,12 @@
- PalaceToolkit + PalaceToolkit
# PalaceToolkit -A lightweight Python package that integrates +PalaceToolkit is a lightweight Python package that integrates [Palace](https://awslabs.github.io/palace/) and -[Gmsh](https://gmsh.info/) into a unified simulation workflow. +[Gmsh](https://gmsh.info/) into a unified open-source electromagnetic FEM simulation workflow. --- @@ -33,3 +33,12 @@ electromagnetic solving. In a single Python script you can: | [Full Course](full-course.md) | Structured video lectures | | [Palace docs](https://awslabs.github.io/palace/) | Upstream Palace reference | | [Gmsh docs](https://gmsh.info/doc/texinfo/gmsh.html) | Upstream Gmsh reference | + +```{toctree} +:maxdepth: 2 +:hidden: + +getting-started/index +examples/index +full-course +``` diff --git a/docs/javascripts/mathjax.js b/docs/javascripts/mathjax.js index 68dbff0..dc16d4e 100644 --- a/docs/javascripts/mathjax.js +++ b/docs/javascripts/mathjax.js @@ -1,16 +1,3 @@ -window.MathJax = { - tex: { - inlineMath: [["$", "$"], ["\\(", "\\)"]], - displayMath: [["$$", "$$"], ["\\[", "\\]"]], - processEscapes: true, - processEnvironments: true, - }, - options: { - ignoreHtmlClass: "tex2jax_ignore|mathjax_ignore", - processHtmlClass: "arithmatex|jp-RenderedHTMLCommon|jp-RenderedMarkdown", - }, -}; - (() => { const mathTargetSelector = [ ".arithmatex", @@ -31,21 +18,16 @@ window.MathJax = { }); }; - // Run once after all scripts are loaded. - window.addEventListener("load", typesetMath); - - // Re-typeset after Material for MkDocs instant navigation updates the DOM. - const subscribeToInstantNavigation = () => { - if (typeof document$ !== "undefined" && document$.subscribe) { - document$.subscribe(() => { - window.requestAnimationFrame(typesetMath); - }); - } - }; - - if (document.readyState === "complete") { - subscribeToInstantNavigation(); + if (document.readyState === "complete" || document.readyState === "interactive") { + window.requestAnimationFrame(typesetMath); } else { - window.addEventListener("load", subscribeToInstantNavigation); + window.addEventListener("DOMContentLoaded", () => { + window.requestAnimationFrame(typesetMath); + }); } + + // Some browsers restore page state from bfcache on history navigation. + window.addEventListener("pageshow", () => { + window.requestAnimationFrame(typesetMath); + }); })(); diff --git a/docs/stylesheets/interactive.css b/docs/stylesheets/interactive.css index 34e412d..1291701 100644 --- a/docs/stylesheets/interactive.css +++ b/docs/stylesheets/interactive.css @@ -1,3 +1,11 @@ +/* Theme variable bridge: Material (old) + PyData (new). */ +:root { + --ptk-border-color: var(--pst-color-border, var(--md-default-fg-color--lightest, #d1d5db)); + --ptk-muted-text-color: var(--pst-color-text-muted, var(--md-default-fg-color--light, #6b7280)); + --ptk-text-color: var(--pst-color-text-base, var(--md-default-fg-color, #1f2937)); + --ptk-code-bg: var(--pst-color-surface, var(--md-code-bg-color, #fafafa)); +} + /* Side-by-side interactive 3D viewer iframes */ .mesh-viewer-row { display: flex; @@ -10,7 +18,7 @@ flex: 1 1 48%; min-width: 300px; height: 450px; - border: 1px solid var(--md-default-fg-color--lightest); + border: 1px solid var(--ptk-border-color); border-radius: 8px; } @@ -18,7 +26,7 @@ width: 100%; text-align: center; font-style: italic; - color: var(--md-default-fg-color--light); + color: var(--ptk-muted-text-color); margin-top: 0.25rem; } @@ -37,25 +45,35 @@ max-height: calc(var(--ptk-output-visible-lines, 10) * var(--ptk-output-line-height, 1.35) * 1em); overflow: auto; padding: 0.75rem; - border: 1px solid var(--md-default-fg-color--lightest); + border: 1px solid var(--ptk-border-color); border-radius: 8px; - background: var(--md-code-bg-color, #fafafa); + background: var(--ptk-code-bg); line-height: var(--ptk-output-line-height, 1.35); white-space: pre; } -/* mkdocs-jupyter text outputs: clamp to ~10 lines and scroll vertically. */ -.jupyter-wrapper .jp-OutputArea .jp-RenderedText.jp-OutputArea-output > pre { +/* Notebook text outputs: clamp to ~10 lines and scroll vertically. */ +.jupyter-wrapper .jp-OutputArea .jp-RenderedText.jp-OutputArea-output > pre, +.nboutput .output_area .output pre, +.nboutput .output_area pre, +.cell_output .output.stream pre, +.cell_output .output.stderr pre, +.cell_output .output.text_plain pre, +.cell-output .output.stream pre, +.cell-output .output.stderr pre, +.cell-output .output.text_plain pre, +.cell_output pre[id^="codecell"], +.cell-output pre[id^="codecell"] { max-height: calc(var(--ptk-notebook-output-lines, 10) * 1.35em) !important; overflow-y: auto !important; overflow-x: auto; display: block; line-height: 1.35; box-sizing: border-box; - border: 1px solid var(--md-default-fg-color--lightest); + border: 1px solid var(--ptk-border-color); border-radius: 6px; background: #ffffff !important; - color: var(--md-default-fg-color, #1f2937) !important; + color: var(--ptk-text-color) !important; padding: 0.75rem; margin: 0; white-space: pre; @@ -63,10 +81,111 @@ /* Keep HTML/interactive outputs full-size with no clipping by default. */ .jupyter-wrapper .jp-OutputArea .jp-RenderedHTMLCommon.jp-OutputArea-output, -.jupyter-wrapper .jp-OutputArea .jp-RenderedHTMLCommon.jp-OutputArea-output * { +.jupyter-wrapper .jp-OutputArea .jp-RenderedHTMLCommon.jp-OutputArea-output *, +.nboutput .output_area .output_html, +.nboutput .output_area .output_html *, +.cell_output .output.text_html, +.cell_output .output.text_html *, +.cell-output .output.text_html, +.cell-output .output.text_html * { max-height: none !important; } -.jupyter-wrapper .jp-OutputArea .jp-RenderedHTMLCommon.jp-OutputArea-output { +.jupyter-wrapper .jp-OutputArea .jp-RenderedHTMLCommon.jp-OutputArea-output, +.nboutput .output_area .output_html, +.cell_output .output.text_html, +.cell-output .output.text_html { overflow: visible !important; } + +.ptk-cta-button { + display: inline-block; + border-radius: 999px; + border: 1px solid var(--ptk-text-color); + color: var(--ptk-text-color); + text-decoration: none; + font-weight: 600; +} + +.ptk-cta-button:hover { + text-decoration: none; + opacity: 0.9; +} + +.ptk-gallery-card { + height: 100%; + border: 1px solid var(--ptk-border-color); + border-radius: 10px; + background: #ffffff; + overflow: hidden; + transition: transform 0.16s ease, box-shadow 0.16s ease; +} + +.ptk-gallery-link { + text-decoration: none; + color: inherit; +} + +.ptk-gallery-link:hover { + text-decoration: none; +} + +.ptk-gallery-link:hover .ptk-gallery-card { + transform: translateY(-2px); + box-shadow: 0 8px 20px rgba(0, 0, 0, 0.08); +} + +.ptk-gallery-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 1rem; + margin: 0.5rem 0 1.5rem; +} + +@media (max-width: 1100px) { + .ptk-gallery-grid { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } +} + +@media (max-width: 700px) { + .ptk-gallery-grid { + grid-template-columns: 1fr; + } +} + +.ptk-gallery-card .sd-card-img-top { + height: 140px; + object-fit: contain; + padding: 0.75rem; + background: var(--ptk-code-bg); + border-bottom: 1px solid var(--ptk-border-color); +} + +.ptk-gallery-card .sd-card-title { + min-height: 2.6em; +} + +.ptk-gallery-card img { + display: block; + width: 100%; + height: 96px; + object-fit: contain; + padding: 0.5rem; + background: var(--ptk-code-bg); + border-bottom: 1px solid var(--ptk-border-color); +} + +.ptk-gallery-card h3 { + margin: 0; + padding: 0.6rem 0.7rem 0.25rem; + font-size: 0.95rem; +} + +.ptk-gallery-card p { + margin: 0; + padding: 0 0.7rem 0.7rem; + color: var(--ptk-muted-text-color); + font-size: 0.88rem; + line-height: 1.4; +} diff --git a/docs/stylesheets/patch.png b/docs/stylesheets/patch.png new file mode 100644 index 0000000..1800160 Binary files /dev/null and b/docs/stylesheets/patch.png differ diff --git a/justfile b/justfile index 5d8d817..b2f4379 100644 --- a/justfile +++ b/justfile @@ -14,13 +14,20 @@ nbrun: ipykernel {{python}} -m papermill "$nb" "$nb" -k palacetoolkit --cwd {{examples}}; \ done -# Step 2: Build MkDocs site (renders notebooks directly via mkdocs-jupyter) +# Step 2: Build Sphinx site (renders notebooks via myst-nb) nbdocs: - @echo "Notebook conversion is not required; MkDocs renders .ipynb directly." + @echo "Notebook conversion is not required; Sphinx renders .ipynb directly." -# Step 3: Build MkDocs site +# Step 3: Build Sphinx site docs: - {{python}} -m mkdocs build + rm -rf site + {{python}} -m sphinx -W --keep-going -b html docs site + +# Alias used by contributors coming from MkDocs-style workflows +build: docs + +# Explicit docs build alias for CI/local parity +docs-build: docs # All three steps in sequence docs-full: nbrun nbdocs docs @@ -36,7 +43,15 @@ install-local: # Dev server serve: - {{python}} -m mkdocs serve -a localhost:8080 + {{python}} -m sphinx_autobuild docs site --host localhost --port 8080 \ + --ignore "site/*" \ + --ignore "jupyter_execute/*" \ + --ignore ".jupyter_cache/*" \ + --re-ignore "docs/examples/postpro/.*" \ + --re-ignore "docs/examples/.*\\.(msh|json|config|conf)$" + +# Explicit docs serve alias +docs-serve: serve # Strip outputs from notebooks before committing nbclean: diff --git a/mkdocs.yml b/mkdocs.yml deleted file mode 100644 index df87776..0000000 --- a/mkdocs.yml +++ /dev/null @@ -1,79 +0,0 @@ -site_name: PalaceToolkit -site_description: Electromagnetic simulation with Palace and Gmsh. -site_url: https://www.epsilonforge.com/palace-toolkit/ - -theme: - name: material - logo: PalaceToolkit.png - favicon: PalaceToolkit.png - features: - - content.code.copy - - navigation.instant - - navigation.tabs - - navigation.top - palette: - - scheme: default - primary: indigo - accent: deep orange - -markdown_extensions: - - admonition - - pymdownx.superfences - - pymdownx.highlight: - anchor_linenums: true - - pymdownx.arithmatex: - generic: true - - attr_list - - md_in_html - - tables - - toc: - permalink: true - -plugins: - - search - - mkdocs-jupyter: - execute: false - include_source: true - ignore_h1_titles: true - -# Prevent MkDocs from warning about .htm viewer files not in nav -not_in_nav: | - examples/img/** - -extra_javascript: - - https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js - - javascripts/mathjax.js - - https://unpkg.com/mathjax@3/es5/tex-mml-chtml.js - -extra_css: - - stylesheets/interactive.css - -nav: - - Home: index.md - - Getting Started: - - getting-started/index.md - - Geometry & Meshing: getting-started/geometry-and-meshing.md - - Simulation Setup: getting-started/simulation-setup.md - - Post-processing: getting-started/post-processing.md - - Examples: - - Overview: examples/index.md - - Antennas: - - Horn Antenna: examples/horn_antenna.ipynb - - Dipole Antenna Mesh: examples/dipole_antenna_mesh.ipynb - - Monopole Antenna: examples/monopole_antenna.ipynb - - L Antenna: examples/l_antenna.ipynb - - Patch Antenna: examples/patch_antenna.ipynb - - Vivaldi Antenna: examples/vivaldi_antenna.ipynb - - Structures and Components: - - Coax: examples/coax.ipynb - - Coax to Waveguide Transition: examples/coax_to_waveguide.ipynb - - Open-ended Stub: examples/open_ended_stub.ipynb - - Step in Width: examples/step_in_width.ipynb - - Waveguide Box: examples/waveguide_box.ipynb - - 2D Mode solver: - - Hollow Rectangular Waveguide Modes: examples/hollow_waveguide_modes.ipynb - - Dielectric Waveguide Modes: examples/dielectric_waveguide_modes.ipynb - - Microstrip Modes: examples/microstrip_modes.ipynb - - Slotline Modes: examples/slotline_modes.ipynb - - Differential Microstrip Modes: examples/differential_microstrip_modes.ipynb - - Full Course: full-course.md diff --git a/pyproject.toml b/pyproject.toml index 4abcec5..2562404 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,9 +18,14 @@ dependencies = [ plot = ["pandas", "matplotlib"] palace-cpu = [] docs = [ - "mkdocs", - "mkdocs-material", - "mkdocs-jupyter", + "sphinx", + "pydata-sphinx-theme", + "myst-parser", + "myst-nb", + "sphinx-copybutton", + "sphinx-design", + "sphinx-autobuild", + "linkify-it-py", "pyvista[jupyter]", "nbconvert", "ipykernel", diff --git a/sst.config.ts b/sst.config.ts index 2763fca..0e36084 100644 --- a/sst.config.ts +++ b/sst.config.ts @@ -35,7 +35,7 @@ export default $config({ const docs = new sst.aws.StaticSite("PalaceToolkitDocs", { path: ".", build: { - command: "mkdocs build", + command: "python -m sphinx -W --keep-going -b html docs site", output: "site", }, router: { diff --git a/tests/test_docs_build.py b/tests/test_docs_build.py index 450feed..ceb2492 100644 --- a/tests/test_docs_build.py +++ b/tests/test_docs_build.py @@ -19,7 +19,17 @@ def test_docs_build_has_no_errors() -> None: env["DOCS_BUILD"] = "1" result = subprocess.run( - [sys.executable, "-m", "mkdocs", "build", "--strict"], + [ + sys.executable, + "-m", + "sphinx", + "-W", + "--keep-going", + "-b", + "html", + "docs", + "site", + ], cwd=ROOT, env=env, capture_output=True, @@ -30,7 +40,7 @@ def test_docs_build_has_no_errors() -> None: if result.returncode != 0: output = "\n".join([result.stdout.strip(), result.stderr.strip()]).strip() pytest.fail( - "mkdocs build failed in strict mode.\n" + "sphinx-build failed in strict mode.\n" f"exit_code={result.returncode}\n" f"{output}" ) \ No newline at end of file