From 9610ebe5e30f6e0aa860ab24fb6b7eef4de25491 Mon Sep 17 00:00:00 2001 From: achekery <6503526+achekery@users.noreply.github.com> Date: Wed, 13 May 2026 14:45:34 -0700 Subject: [PATCH 1/2] docs: harden latex and mermaid rendering --- docs/javascripts/mathjax.js | 73 ++++++++++++++-- .../dynamic_interval_management/README.md | 2 +- .../static/pruning-mermaid.txt | 2 +- mkdocs.yml | 3 +- pyproject.toml | 2 +- uv.lock | 83 +------------------ 6 files changed, 72 insertions(+), 93 deletions(-) diff --git a/docs/javascripts/mathjax.js b/docs/javascripts/mathjax.js index b186af6..00ff089 100644 --- a/docs/javascripts/mathjax.js +++ b/docs/javascripts/mathjax.js @@ -1,16 +1,73 @@ window.MathJax = { tex: { - inlineMath: [["\\(", "\\)"]], - displayMath: [["\\[", "\\]"]], - processEscapes: true, - processEnvironments: true + inlineMath: [["\\(", "\\)"], ["$", "$"]], + displayMath: [["\\[", "\\]"], ["$$", "$$"]], + processEscapes: true }, options: { - ignoreHtmlClass: ".*|", processHtmlClass: "arithmatex" } }; -document.subscribe(() => { - MathJax.typesetPromise() -}) +let isRendering = false; + +/** + * Main render function to handle both LaTeX and Mermaid diagrams. + * Designed for MkDocs Material's Single Page App (SPA) navigation. + */ +const renderAll = () => { + if (isRendering) return; + isRendering = true; + + // 1. Mermaid: Surgical Unwrap and Render + if (typeof mermaid !== "undefined") { + const blocks = document.querySelectorAll('.mermaid code'); + let needsMermaidRun = false; + + blocks.forEach(code => { + const pre = code.parentElement; + // Only process if we haven't unwrapped this specific block yet + if (!pre.hasAttribute('data-processed')) { + pre.textContent = code.textContent; + pre.setAttribute('data-processed', 'true'); + needsMermaidRun = true; + } + }); + + if (needsMermaidRun) { + mermaid.initialize({ startOnLoad: false, theme: 'default' }); + mermaid.run({ + nodes: document.querySelectorAll('.mermaid') + }); + } + } + + // 2. MathJax: Render LaTeX notations like O(log N) + if (window.MathJax && window.MathJax.typesetPromise) { + window.MathJax.typesetPromise(); + } + + // Release the mutex after a short delay to allow DOM to settle + setTimeout(() => { + isRendering = false; + }, 100); +}; + +/** + * MutationObserver catches content changes during instant navigation + * without requiring the fragile document.subscribe hook. + */ +const observer = new MutationObserver((mutations) => { + if (!isRendering) { + renderAll(); + } +}); + +// Start observing the body for new module content +observer.observe(document.body, { + childList: true, + subtree: true +}); + +// Initial load execution +window.addEventListener('load', renderAll); \ No newline at end of file diff --git a/docs/modules/dynamic_interval_management/README.md b/docs/modules/dynamic_interval_management/README.md index 21111fc..b4f739f 100644 --- a/docs/modules/dynamic_interval_management/README.md +++ b/docs/modules/dynamic_interval_management/README.md @@ -22,7 +22,7 @@ The theoretical lower bound for merging $N$ static intervals is $\Omega(N \log N The advantage of an Augmented AVL Interval Tree is its ability to prune search branches that cannot contain an overlap, ensuring $O(\log N)$ search time. ```mermaid -{% include "modules/dynamic_interval_management/static/pruning-mermaid.txt" %} +--8<-- "modules/dynamic_interval_management/static/pruning-mermaid.txt" ``` ## 2. Design Approaches diff --git a/docs/modules/dynamic_interval_management/static/pruning-mermaid.txt b/docs/modules/dynamic_interval_management/static/pruning-mermaid.txt index 55d9c34..10b41e4 100644 --- a/docs/modules/dynamic_interval_management/static/pruning-mermaid.txt +++ b/docs/modules/dynamic_interval_management/static/pruning-mermaid.txt @@ -1,5 +1,5 @@ graph TD - Start([Search for Overlap with Query [7, 9]]) --> Root + Start(["Search for Overlap with Query [7, 9]"]) --> Root Root{"Node: [5, 8]
Subtree Max: 20"} -- "Overlap Check" --> Match Root -- "Check Left Subtree" --> LeftCheck{"Left Subtree Max >= 7?"} diff --git a/mkdocs.yml b/mkdocs.yml index 2d4243d..c258abf 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -19,7 +19,7 @@ markdown_extensions: class: mermaid format: !!python/name:pymdownx.superfences.fence_code_format - pymdownx.arithmatex: - generic: true # For your O(log N) LaTeX notations + generic: true - pymdownx.snippets: base_path: docs @@ -46,3 +46,4 @@ nav: extra_javascript: - javascripts/mathjax.js - https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js + - https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 50b4a16..847cdd3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,9 +19,9 @@ dev = [ docs = [ "mkdocs-macros-plugin>=1.5.0", "mkdocs-material>=9.7.6", - "mkdocs-mermaid2-plugin>=1.2.3", "mkdocstrings-python>=2.0.3", "mkdocstrings[python]>=1.0.4", + "pymdown-extensions>=10.21.2", ] lint = [ "ruff>=0.15.12", diff --git a/uv.lock b/uv.lock index e372fed..5e8f9ad 100644 --- a/uv.lock +++ b/uv.lock @@ -32,19 +32,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3e/5c/fb93d3092640a24dfb7bd7727a24016d7c01774ca013e60efd3f683c8002/backrefs-7.0-py314-none-any.whl", hash = "sha256:a6448b28180e3ca01134c9cf09dcebafad8531072e09903c5451748a05f24bc9", size = 412349, upload-time = "2026-04-28T16:28:02.412Z" }, ] -[[package]] -name = "beautifulsoup4" -version = "4.14.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "soupsieve" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/c3/b0/1c6a16426d389813b48d95e26898aff79abbde42ad353958ad95cc8c9b21/beautifulsoup4-4.14.3.tar.gz", hash = "sha256:6292b1c5186d356bba669ef9f7f051757099565ad9ada5dd630bd9de5fa7fb86", size = 627737, upload-time = "2025-11-30T15:08:26.084Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl", hash = "sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb", size = 107721, upload-time = "2025-11-30T15:08:24.087Z" }, -] - [[package]] name = "certifi" version = "2026.4.22" @@ -217,9 +204,9 @@ dev = [ docs = [ { name = "mkdocs-macros-plugin" }, { name = "mkdocs-material" }, - { name = "mkdocs-mermaid2-plugin" }, { name = "mkdocstrings", extra = ["python"] }, { name = "mkdocstrings-python" }, + { name = "pymdown-extensions" }, ] lint = [ { name = "ruff" }, @@ -238,21 +225,12 @@ dev = [{ name = "pytest", specifier = ">=9.0.3" }] docs = [ { name = "mkdocs-macros-plugin", specifier = ">=1.5.0" }, { name = "mkdocs-material", specifier = ">=9.7.6" }, - { name = "mkdocs-mermaid2-plugin", specifier = ">=1.2.3" }, { name = "mkdocstrings", extras = ["python"], specifier = ">=1.0.4" }, { name = "mkdocstrings-python", specifier = ">=2.0.3" }, + { name = "pymdown-extensions", specifier = ">=10.21.2" }, ] lint = [{ name = "ruff", specifier = ">=0.15.12" }] -[[package]] -name = "editorconfig" -version = "0.17.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/88/3a/a61d9a1f319a186b05d14df17daea42fcddea63c213bcd61a929fb3a6796/editorconfig-0.17.1.tar.gz", hash = "sha256:23c08b00e8e08cc3adcddb825251c497478df1dada6aefeb01e626ad37303745", size = 14695, upload-time = "2025-06-09T08:21:37.097Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/96/fd/a40c621ff207f3ce8e484aa0fc8ba4eb6e3ecf52e15b42ba764b457a9550/editorconfig-0.17.1-py3-none-any.whl", hash = "sha256:1eda9c2c0db8c16dbd50111b710572a5e6de934e39772de1959d41f64fc17c82", size = 16360, upload-time = "2025-06-09T08:21:35.654Z" }, -] - [[package]] name = "fonttools" version = "4.62.1" @@ -346,19 +324,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, ] -[[package]] -name = "jsbeautifier" -version = "1.15.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "editorconfig" }, - { name = "six" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/ea/98/d6cadf4d5a1c03b2136837a435682418c29fdeb66be137128544cecc5b7a/jsbeautifier-1.15.4.tar.gz", hash = "sha256:5bb18d9efb9331d825735fbc5360ee8f1aac5e52780042803943aa7f854f7592", size = 75257, upload-time = "2025-02-27T17:53:53.252Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2d/14/1c65fccf8413d5f5c6e8425f84675169654395098000d8bddc4e9d3390e1/jsbeautifier-1.15.4-py3-none-any.whl", hash = "sha256:72f65de312a3f10900d7685557f84cb61a9733c50dcc27271a39f5b0051bf528", size = 94707, upload-time = "2025-02-27T17:53:46.152Z" }, -] - [[package]] name = "kiwisolver" version = "1.5.0" @@ -647,23 +612,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31", size = 8728, upload-time = "2023-11-22T19:09:43.465Z" }, ] -[[package]] -name = "mkdocs-mermaid2-plugin" -version = "1.2.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "beautifulsoup4" }, - { name = "jsbeautifier" }, - { name = "mkdocs" }, - { name = "pymdown-extensions" }, - { name = "requests" }, - { name = "setuptools" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/2a/6d/308f443a558b6a97ce55782658174c0d07c414405cfc0a44d36ad37e36f9/mkdocs_mermaid2_plugin-1.2.3.tar.gz", hash = "sha256:fb6f901d53e5191e93db78f93f219cad926ccc4d51e176271ca5161b6cc5368c", size = 16220, upload-time = "2025-10-17T19:38:53.047Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1a/4b/6fd6dd632019b7f522f1b1f794ab6115cd79890330986614be56fd18f0eb/mkdocs_mermaid2_plugin-1.2.3-py3-none-any.whl", hash = "sha256:33f60c582be623ed53829a96e19284fc7f1b74a1dbae78d4d2e47fe00c3e190d", size = 17299, upload-time = "2025-10-17T19:38:51.874Z" }, -] - [[package]] name = "mkdocstrings" version = "1.0.4" @@ -1044,15 +992,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c0/98/6beb4b351e472e5f4c4613f7c35a5290b8be2497e183825310c4c3a3984b/ruff-0.15.12-py3-none-win_arm64.whl", hash = "sha256:a538f7a82d061cee7be55542aca1d86d1393d55d81d4fcc314370f4340930d4f", size = 11120821, upload-time = "2026-04-24T18:16:57.979Z" }, ] -[[package]] -name = "setuptools" -version = "82.0.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/4f/db/cfac1baf10650ab4d1c111714410d2fbb77ac5a616db26775db562c8fab2/setuptools-82.0.1.tar.gz", hash = "sha256:7d872682c5d01cfde07da7bccc7b65469d3dca203318515ada1de5eda35efbf9", size = 1152316, upload-time = "2026-03-09T12:47:17.221Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9d/76/f789f7a86709c6b087c5a2f52f911838cad707cc613162401badc665acfe/setuptools-82.0.1-py3-none-any.whl", hash = "sha256:a59e362652f08dcd477c78bb6e7bd9d80a7995bc73ce773050228a348ce2e5bb", size = 1006223, upload-time = "2026-03-09T12:47:15.026Z" }, -] - [[package]] name = "six" version = "1.17.0" @@ -1071,15 +1010,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575, upload-time = "2021-05-16T22:03:41.177Z" }, ] -[[package]] -name = "soupsieve" -version = "2.8.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7b/ae/2d9c981590ed9999a0d91755b47fc74f74de286b0f5cee14c9269041e6c4/soupsieve-2.8.3.tar.gz", hash = "sha256:3267f1eeea4251fb42728b6dfb746edc9acaffc4a45b27e19450b676586e8349", size = 118627, upload-time = "2026-01-20T04:27:02.457Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl", hash = "sha256:ed64f2ba4eebeab06cc4962affce381647455978ffc1e36bb79a545b91f45a95", size = 37016, upload-time = "2026-01-20T04:27:01.012Z" }, -] - [[package]] name = "super-collections" version = "0.6.2" @@ -1101,15 +1031,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/33/d1/8bb87d21e9aeb323cc03034f5eaf2c8f69841e40e4853c2627edf8111ed3/termcolor-3.3.0-py3-none-any.whl", hash = "sha256:cf642efadaf0a8ebbbf4bc7a31cec2f9b5f21a9f726f4ccbb08192c9c26f43a5", size = 7734, upload-time = "2025-12-29T12:55:20.718Z" }, ] -[[package]] -name = "typing-extensions" -version = "4.15.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, -] - [[package]] name = "tzdata" version = "2026.2" From 7b858c9d10e4f69346f60955e659d8f1b697f7c9 Mon Sep 17 00:00:00 2001 From: achekery <6503526+achekery@users.noreply.github.com> Date: Wed, 13 May 2026 14:46:51 -0700 Subject: [PATCH 2/2] docs: harden latex and mermaid rendering --- mkdocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index c258abf..6634348 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -46,4 +46,4 @@ nav: extra_javascript: - javascripts/mathjax.js - https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js - - https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js \ No newline at end of file + - https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js