From a240947b6694f90963e4a1cb8abadf52a2c76090 Mon Sep 17 00:00:00 2001 From: MICRORACK Date: Thu, 25 Dec 2025 01:52:43 +0400 Subject: [PATCH 1/2] Initial commit --- .github/workflows/deploy.yml | 79 ++++ .gitignore | 24 + README.md | 74 ++++ docs/CNAME | 1 + docs/LICENSE.md | 427 ++++++++++++++++++ docs/assets/extra.css | 782 +++++++++++++++++++++++++++++++++ docs/assets/extra.js | 215 +++++++++ docs/assets/icon.png | Bin 0 -> 25309 bytes docs/assets/logo.png | Bin 0 -> 10208 bytes docs/assets/logo_compact.png | Bin 0 -> 1824 bytes docs/assets/martian-mono.woff2 | Bin 0 -> 21640 bytes mkdocs.yml | 80 ++++ requirements.txt | 2 + scripts/convert_admonitions.py | 111 +++++ scripts/update_nav.py | 109 +++++ 15 files changed, 1904 insertions(+) create mode 100644 .github/workflows/deploy.yml create mode 100644 .gitignore create mode 100644 README.md create mode 100644 docs/CNAME create mode 100644 docs/LICENSE.md create mode 100644 docs/assets/extra.css create mode 100644 docs/assets/extra.js create mode 100644 docs/assets/icon.png create mode 100644 docs/assets/logo.png create mode 100644 docs/assets/logo_compact.png create mode 100644 docs/assets/martian-mono.woff2 create mode 100644 mkdocs.yml create mode 100644 requirements.txt create mode 100644 scripts/convert_admonitions.py create mode 100644 scripts/update_nav.py diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..958d044 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,79 @@ +name: Deploy MkDocs to GitHub Pages + +on: + push: + branches: + - site + repository_dispatch: + types: [modules-updated] + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout site branch + uses: actions/checkout@v4 + + - name: Checkout master branch content + uses: actions/checkout@v4 + with: + ref: master + path: master-content + + - name: Copy module content from master + run: | + # Copy README.md as index page + cp master-content/README.md docs/index.md + echo "Copied README.md -> docs/index.md" + + # Copy each module directory from master to docs/ + for dir in master-content/mod-*/; do + module=$(basename "$dir") + rm -rf "docs/${module}" + cp -r "$dir" "docs/" + echo "Copied ${module}/" + done + # Clean up + rm -rf master-content + echo "=== Module files in docs/ ===" + ls -la docs/mod-* | head -30 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - name: Install dependencies + run: pip install -r requirements.txt + + - name: Update navigation from H1 titles + run: python scripts/update_nav.py + + - name: Build site + run: mkdocs build + + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: ./site + + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c8fdbff --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# Build artifacts +site/ + +# Content fetched from master during build +docs/mod-*/ +docs/index.md + +# Python virtual environment +.venv/ +venv/ +env/ + +# Python cache +__pycache__/ +*.py[cod] +*$py.class + +# IDE +.vscode/ +.idea/ + +# OS +.DS_Store +Thumbs.db diff --git a/README.md b/README.md new file mode 100644 index 0000000..afc7406 --- /dev/null +++ b/README.md @@ -0,0 +1,74 @@ +# Modules - Site Branch + +This branch contains the MkDocs build configuration for the MICRORACK Modules documentation. + +**⚠️ Do not edit content here directly!** Edit the source markdown files in the `master` branch instead. + +## How it works + +1. Content is edited in the `master` branch (bare markdown files) +2. GitHub Actions automatically syncs content to this branch +3. MkDocs builds and deploys to GitHub Pages + +## Branch Structure + +### Master Branch (source - bare markdown) +``` +repo/ +├── README.md # Index page content +├── LICENSE.md # License file +├── .github/ +│ └── workflows/ +│ └── sync-to-site.yml # Sync workflow +├── mod-vco/ +│ ├── README.md +│ └── mod-vco.png +├── mod-vcf/ +│ ├── README.md +│ └── mod-vcf.png +└── ... (other modules) +``` + +### Site Branch (this branch) +``` +repo/ +├── README.md # This file +├── mkdocs.yml # MkDocs configuration +├── requirements.txt # Python dependencies +├── scripts/ +│ └── convert_admonitions.py +├── .github/ +│ └── workflows/ +│ └── deploy.yml # Deploy workflow +└── docs/ + ├── index.md # ← synced from master/README.md + ├── LICENSE.md # ← synced from master/LICENSE.md + ├── CNAME + ├── assets/ # CSS, JS, logos, fonts + └── mod-*/ # ← synced from master/mod-*/ +``` + +## Local Development + +```bash +pip install -r requirements.txt +mkdocs serve +``` + +Visit http://127.0.0.1:8000 + +## GitHub Configuration + +After creating the site branch: + +1. **GitHub Pages Settings** (Settings → Pages): + - Source: `GitHub Actions` + +2. **Add site branch to allowed deployment branches**: + ```bash + gh api repos/OWNER/REPO/environments/github-pages/deployment-branch-policies \ + --method POST -f name=site + ``` + +3. **Actions Permissions** (Settings → Actions → General): + - Workflow permissions: Read and write permissions diff --git a/docs/CNAME b/docs/CNAME new file mode 100644 index 0000000..1476a2d --- /dev/null +++ b/docs/CNAME @@ -0,0 +1 @@ +modules.microrack.org diff --git a/docs/LICENSE.md b/docs/LICENSE.md new file mode 100644 index 0000000..7d4f96c --- /dev/null +++ b/docs/LICENSE.md @@ -0,0 +1,427 @@ +Attribution-ShareAlike 4.0 International + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution-ShareAlike 4.0 International Public +License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution-ShareAlike 4.0 International Public License ("Public +License"). To the extent this Public License may be interpreted as a +contract, You are granted the Licensed Rights in consideration of Your +acceptance of these terms and conditions, and the Licensor grants You +such rights in consideration of benefits the Licensor receives from +making the Licensed Material available under these terms and +conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. BY-SA Compatible License means a license listed at + creativecommons.org/compatiblelicenses, approved by Creative + Commons as essentially the equivalent of this Public License. + + d. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + e. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + f. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + g. License Elements means the license attributes listed in the name + of a Creative Commons Public License. The License Elements of this + Public License are Attribution and ShareAlike. + + h. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + i. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + j. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + k. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + l. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + m. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part; and + + b. produce, reproduce, and Share Adapted Material. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. Additional offer from the Licensor -- Adapted Material. + Every recipient of Adapted Material from You + automatically receives an offer from the Licensor to + exercise the Licensed Rights in the Adapted Material + under the conditions of the Adapter's License You apply. + + c. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + b. ShareAlike. + + In addition to the conditions in Section 3(a), if You Share + Adapted Material You produce, the following conditions also apply. + + 1. The Adapter's License You apply must be a Creative Commons + license with the same License Elements, this version or + later, or a BY-SA Compatible License. + + 2. You must include the text of, or the URI or hyperlink to, the + Adapter's License You apply. You may satisfy this condition + in any reasonable manner based on the medium, means, and + context in which You Share Adapted Material. + + 3. You may not offer or impose any additional or different terms + or conditions on, or apply any Effective Technological + Measures to, Adapted Material that restrict exercise of the + rights granted under the Adapter's License You apply. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material, + including for purposes of Section 3(b); and + + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the “Licensor.” The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + +Creative Commons may be contacted at creativecommons.org. diff --git a/docs/assets/extra.css b/docs/assets/extra.css new file mode 100644 index 0000000..79b9852 --- /dev/null +++ b/docs/assets/extra.css @@ -0,0 +1,782 @@ +/* Martian Mono font for entire site */ +@font-face { + font-family: 'Martian Mono'; + src: url('martian-mono.woff2') format('woff2'); + font-weight: 100 900; + font-style: normal; + font-display: block; +} + +/* Apply Martian Mono globally */ +:root { + --md-text-font: 'Martian Mono', monospace; + --md-code-font: 'Martian Mono', monospace; +} + +body, .md-typeset { + font-family: 'Martian Mono', monospace !important; + font-weight: 400 !important; +} + +/* Header - light/dark theme support, sticky at top */ +.md-header { + background-color: #ffffff !important; + border-bottom: none !important; + color: #000000 !important; + box-shadow: none !important; + position: sticky !important; + top: 0 !important; + z-index: 4 !important; +} + +.md-source { + display: flex !important; + flex-direction: row; + align-items: center; + justify-content: end; + gap: 0.5rem; +} + +@media screen and (max-width: 76.1875em) { + .md-source { + margin-right: 1.8rem; + } +} + +[data-md-color-scheme="slate"] .md-header { + background-color: #1e1e1e !important; + color: #ffffff !important; +} + +/* Show header shadow when scrolled */ +.md-header--shadow { + box-shadow: 0 2px 0 0 #eee !important; +} + +[data-md-color-scheme="slate"] .md-header--shadow { + box-shadow: 0 2px 0 0 #333 !important; +} + +/* Header branding */ +.md-header__title { + font-family: 'Martian Mono', monospace !important; + font-size: 1.2rem; + font-weight: 400 !important; + color: #000000 !important; + cursor: pointer; + text-transform: uppercase; + margin-left: 0 !important; +} + +[data-md-color-scheme="slate"] .md-header__title { + color: #ffffff !important; +} + +.md-header__topic { + font-family: 'Martian Mono', monospace !important; + font-weight: 400 !important; + color: #000000 !important; +} + +[data-md-color-scheme="slate"] .md-header__topic { + color: #ffffff !important; +} + +.md-header__topic:first-child { + font-weight: 400 !important; +} + +/* Logo sizing */ +.md-header__button.md-logo { + padding: 0.1rem; + margin-right: 0.2rem; +} + +.md-header__button.md-logo img { + height: 1rem; + width: auto; + filter: none; +} + +[data-md-color-scheme="slate"] .md-header__button.md-logo img { + filter: brightness(0) invert(1); +} + +/* Mobile: show compact logo between burger and title */ +@media screen and (max-width: 76.1875em) { + .md-header__button.md-logo { + display: none !important; + visibility: hidden !important; + width: 0 !important; + height: 0 !important; + overflow: hidden !important; + } + + .md-header__title { + display: flex !important; + align-items: center; + } + + .md-header__title::before { + content: ''; + display: inline-block; + width: 1.4rem; + height: 1.4rem; + margin-right: 0.4rem; + background-image: url('logo_compact.png'); + background-size: contain; + background-repeat: no-repeat; + background-position: center; + flex-shrink: 0; + filter: brightness(0); + } + + [data-md-color-scheme="slate"] .md-header__title::before { + filter: brightness(0) invert(1); + } +} + +/* Header icons */ +.md-header__button { + color: #000000 !important; +} + +[data-md-color-scheme="slate"] .md-header__button { + color: #ffffff !important; +} + +.md-header__button svg { + fill: #000000 !important; +} + +[data-md-color-scheme="slate"] .md-header__button svg { + fill: #ffffff !important; +} + +/* Header inner padding for tabs layout */ +.md-header__inner { + padding: 17px 0 0 !important; +} + +.md-grid { + max-width: 1252px !important; +} + +/* Home, specs, docs, and forum links in tabs row (desktop) */ +.md-tabs__item--home { + margin-left: auto !important; +} + +.md-tabs__item--home .md-tabs__link, +.md-tabs__item--specs .md-tabs__link, +.md-tabs__item--docs .md-tabs__link, +.md-tabs__item--forum .md-tabs__link { + display: flex; + align-items: center; + opacity: 0.7; + transition: opacity 0.2s; +} + +.md-tabs__item--home .md-tabs__link:hover, +.md-tabs__item--specs .md-tabs__link:hover, +.md-tabs__item--docs .md-tabs__link:hover, +.md-tabs__item--forum .md-tabs__link:hover { + opacity: 1; +} + +.md-tabs__item--home svg, +.md-tabs__item--specs svg, +.md-tabs__item--docs svg, +.md-tabs__item--forum svg { + fill: currentColor; +} + +/* Hide home/specs/docs/forum in tabs on mobile (shown in drawer instead) */ +@media screen and (max-width: 76.1875em) { + .md-tabs__item--home, + .md-tabs__item--specs, + .md-tabs__item--docs, + .md-tabs__item--forum, + .md-tabs__item--home-link { + display: none !important; + } +} + +/* Navigation tabs - white background with sawtooth separator */ +.md-tabs { + background-color: #ffffff !important; + border-bottom: none !important; + box-shadow: none !important; + position: relative; + padding-bottom: 20px; + overflow: hidden; +} + +[data-md-color-scheme="slate"] .md-tabs { + background-color: #1e1e1e !important; +} + +.md-tabs::after { + content: ''; + position: absolute; + bottom: -10px; + left: 0; + width: 100%; + height: 20px; + background-image: url('data:image/svg+xml;charset=utf8,'); + background-repeat: repeat-x; + background-size: 100% 20px; + pointer-events: none; + background-color: var(--md-default-bg-color); +} + +[data-md-color-scheme="slate"] .md-tabs::after { + background-image: url('data:image/svg+xml;charset=utf8,'); +} + +.md-tabs__link { + font-family: 'Martian Mono', monospace !important; + font-size: 0.75rem; + font-weight: 400 !important; + color: #000000 !important; +} + +[data-md-color-scheme="slate"] .md-tabs__link { + color: #ffffff !important; +} + +.md-tabs__item { + text-transform: uppercase; +} + +/* Sidebar */ +.md-nav__link { + font-family: 'Martian Mono', monospace !important; + font-weight: 400 !important; +} + +/* Sidebar navigation items padding */ +.md-nav--primary > .md-nav__list > .md-nav__item:first-child .md-nav__link { + padding-left: 0.8rem; +} + +.md-nav--primary > .md-nav__list > .md-nav__item:not(:first-child) .md-nav__link { + padding-left: 1.6rem; +} + +/* Hide section titles in sidebar on desktop (redundant with tabs) */ +@media screen and (min-width: 76.25em) { + .md-nav--primary > .md-nav__list > .md-nav__item--nested > .md-nav__link { + display: none; + } +} + +/* Indent nested navigation items (except first item which is the index) */ +.md-nav--primary > .md-nav__list > .md-nav__item--nested > .md-nav > .md-nav__list > .md-nav__item:not(:first-child) { + padding-left: 1rem; +} + +/* Mobile drawer nested items */ +@media screen and (max-width: 76.1875em) { + .md-nav__item--nested { + text-transform: uppercase; + } +} + +.md-nav__docs-link { + display: none; +} + +/* Mobile drawer styling */ +.md-nav__title[for="__drawer"], +.md-nav__header, +.md-nav__title { + background-color: #ffffff !important; + color: #000000 !important; +} + +[data-md-color-scheme="slate"] .md-nav__title[for="__drawer"], +[data-md-color-scheme="slate"] .md-nav__header, +[data-md-color-scheme="slate"] .md-nav__title { + background-color: #1e1e1e !important; + color: #ffffff !important; +} + +/* Hide text in mobile drawer title */ +@media screen and (max-width: 76.1875em) { + label.md-nav__title[for="__drawer"] { + font-size: 0 !important; + height: auto !important; + min-height: 2.4rem !important; + padding: 0.4rem 0.6rem !important; + margin-bottom: 10px !important; + } + + label.md-nav__title[for="__drawer"] .md-logo, + label.md-nav__title[for="__drawer"] .md-logo img { + font-size: 1rem !important; + } + + label.md-nav__title[for^="__nav_"] { + font-size: 0 !important; + height: auto !important; + min-height: 2.4rem !important; + padding: 0.4rem 0.6rem !important; + } + + label.md-nav__title[for^="__nav_"] .md-nav__icon { + font-size: 1rem !important; + } +} + +/* Desktop: transparent sidebar backgrounds */ +@media screen and (min-width: 76.25em) { + .md-sidebar--primary, + .md-nav--primary { + background-color: transparent !important; + } + + [data-md-color-scheme="slate"] .md-sidebar--primary, + [data-md-color-scheme="slate"] .md-nav--primary { + background-color: transparent !important; + } +} + +/* Mobile: solid drawer background */ +@media screen and (max-width: 76.1875em) { + .md-nav--primary { + background-color: #ffffff !important; + } + + [data-md-color-scheme="slate"] .md-nav--primary { + background-color: #1e1e1e !important; + } +} + +/* Make nav titles transparent */ +.md-nav__title { + background-color: transparent !important; +} + +.md-nav[data-md-level="1"] > .md-nav__title, +.md-nav--secondary > .md-nav__title { + background-color: transparent !important; +} + +/* Logo in drawer */ +.md-nav__title .md-logo img, +.md-nav__header .md-logo img { + filter: none !important; +} + +[data-md-color-scheme="slate"] .md-nav__title .md-logo img, +[data-md-color-scheme="slate"] .md-nav__header .md-logo img { + filter: brightness(0) invert(1) !important; +} + +/* Active link in drawer */ +.md-nav__link--active { + color: #000000 !important; +} + +[data-md-color-scheme="slate"] .md-nav__link--active { + color: #ffffff !important; +} + +/* Drawer icons */ +.md-nav__title svg, +.md-nav__header svg, +.md-nav__link svg, +.md-nav__icon { + fill: #000000 !important; + color: #000000 !important; +} + +[data-md-color-scheme="slate"] .md-nav__title svg, +[data-md-color-scheme="slate"] .md-nav__header svg, +[data-md-color-scheme="slate"] .md-nav__link svg, +[data-md-color-scheme="slate"] .md-nav__icon { + fill: #ffffff !important; + color: #ffffff !important; +} + +/* External links in mobile drawer - fixed at bottom */ +.md-nav__external-links { + display: none; +} + +@media screen and (max-width: 76.1875em) { + .md-nav__external-links { + display: flex; + justify-content: space-between; + flex-direction: row; + gap: 0.75rem; + position: absolute; + bottom: 0; + left: 0; + right: 0; + padding: 1rem; + background: var(--md-default-bg-color); + border-top: 1px solid var(--md-default-fg-color--lightest); + } + + .md-nav__external-link { + display: flex; + align-items: center; + gap: 0.2rem; + color: var(--md-typeset-color) !important; + text-decoration: none; + text-transform: uppercase; + font-family: 'Martian Mono', monospace; + font-size: 0.85rem; + } + + .md-nav__external-link .md-nav__icon-text { + width: 18px; + text-align: center; + font-size: 1.1rem; + line-height: 0.8; + } + + .md-nav__external-link svg { + width: 1.2rem; + height: 1.2rem; + } + + .md-nav--primary > .md-nav__list { + padding-bottom: 6rem; + } +} + +/* Search */ +.md-search__input { + font-family: 'Martian Mono', monospace !important; + color: #000000 !important; + background-color: #f5f5f5 !important; + border: 1px solid #ddd !important; +} + +.md-search__input:hover { + background-color: #eeeeee !important; + border-color: #ccc !important; +} + +.md-search__input:focus { + background-color: #ffffff !important; + border-color: #673ab7 !important; +} + +[data-md-color-scheme="slate"] .md-search__input { + color: #ffffff !important; + background-color: #2d2d2d !important; + border-color: #444 !important; +} + +[data-md-color-scheme="slate"] .md-search__input:hover { + background-color: #333333 !important; + border-color: #555 !important; +} + +[data-md-color-scheme="slate"] .md-search__input:focus { + background-color: #1e1e1e !important; + border-color: #673ab7 !important; +} + +.md-search__input::placeholder { + color: #666666 !important; +} + +[data-md-color-scheme="slate"] .md-search__input::placeholder { + color: #999999 !important; +} + +.md-search__input+.md-search__icon { + color: var(--md-default-fg-color--light); +} + +/* Headings */ +.md-typeset h1, .md-typeset h2, .md-typeset h3, +.md-typeset h4, .md-typeset h5, .md-typeset h6 { + font-family: 'Martian Mono', monospace !important; + font-weight: 500 !important; + position: relative; + opacity: 1; + transition: opacity 0.2s ease; +} + +.md-typeset h2:hover, .md-typeset h3:hover, +.md-typeset h4:hover, .md-typeset h5:hover, .md-typeset h6:hover { + opacity: 0.7; +} + +/* Permalink */ +.md-typeset h2 .headerlink, +.md-typeset h3 .headerlink, +.md-typeset h4 .headerlink, +.md-typeset h5 .headerlink, +.md-typeset h6 .headerlink { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + opacity: 0; + text-indent: -9999px; + overflow: hidden; + cursor: pointer; + z-index: 1; +} + +.md-typeset h1 .headerlink { + display: none; +} + +.md-typeset h1 > a:not(.headerlink), +.md-typeset h2 > a:not(.headerlink), +.md-typeset h3 > a:not(.headerlink), +.md-typeset h4 > a:not(.headerlink), +.md-typeset h5 > a:not(.headerlink), +.md-typeset h6 > a:not(.headerlink) { + position: relative; + z-index: 2; +} + +/* Code blocks */ +.md-typeset code, .md-typeset pre { + font-family: 'Martian Mono', monospace !important; +} + +/* Center all images in content */ +.md-typeset img { + display: block; + margin-left: auto; + margin-right: auto; +} + +/* Page navigation buttons */ +.page-nav { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 1rem; + margin-top: 3rem; + padding-top: 1.5rem; + border-top: 1px solid var(--md-default-fg-color--lightest); +} + +.page-nav__btn { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 1rem 1.25rem; + border: 1px solid var(--md-default-fg-color--lightest); + border-radius: 0.5rem; + text-decoration: none; + color: var(--md-typeset-color); + background: transparent; + transition: border-color 0.2s, background-color 0.2s; +} + +.page-nav__btn:hover { + border-color: var(--md-primary-fg-color); + background: var(--md-default-fg-color--lightest); +} + +.page-nav__btn--prev { + justify-content: flex-start; +} + +.page-nav__btn--next { + justify-content: flex-end; + text-align: right; +} + +.page-nav__arrow { + font-size: 1.5rem; + font-weight: 300; + opacity: 0.6; + line-height: 1; +} + +.page-nav__text { + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +.page-nav__label { + font-size: 0.7rem; + text-transform: uppercase; + letter-spacing: 0.05em; + opacity: 0.6; +} + +.page-nav__name { + font-size: 0.95rem; + font-weight: 500; +} + +.page-nav__spacer { + /* Empty space when no prev/next */ +} + +@media (max-width: 600px) { + .page-nav { + grid-template-columns: 1fr; + } + + .page-nav__btn--prev, + .page-nav__btn--next { + justify-content: flex-start; + text-align: left; + } + + .page-nav__btn--next .page-nav__arrow { + order: -1; + } +} + +/* Table of contents */ +.md-nav--secondary > .md-nav__title { + font-family: 'Martian Mono', monospace !important; + font-weight: 600 !important; + background-color: transparent !important; +} + +.md-nav--secondary .md-nav__link { + font-family: 'Martian Mono', monospace !important; +} + +/* Footer */ +.md-footer { + background-color: #ffffff !important; + color: #000 !important; + border-top: 2px solid #eee; +} + +[data-md-color-scheme="slate"] .md-footer { + background-color: #1e1e1e !important; + color: #ffffff !important; + border-top: 2px solid #333; +} + +.md-footer-meta { + background-color: #ffffff !important; + padding: 0.5rem 0 !important; + color: #000000 !important; +} + +[data-md-color-scheme="slate"] .md-footer-meta { + background-color: #1e1e1e !important; + color: #ffffff !important; +} + +.md-footer-meta__inner { + display: flex; + flex-wrap: wrap; + justify-content: center; + align-items: center; +} + +.md-copyright { + display: block !important; + text-align: center; + width: 100%; + font-family: 'Martian Mono', monospace !important; + font-size: 0.7rem; + padding: 0.5rem 0; + color: #000000 !important; +} + +[data-md-color-scheme="slate"] .md-copyright { + color: #ffffff !important; +} + +.md-copyright__highlight { + color: #000000 !important; +} + +[data-md-color-scheme="slate"] .md-copyright__highlight { + color: #ffffff !important; +} + +.md-copyright a { + color: #000000 !important; + text-decoration: underline; +} + +[data-md-color-scheme="slate"] .md-copyright a { + color: #ffffff !important; +} + +.md-social { + display: none !important; +} + +.md-footer__inner { + background-color: #f8f8f8 !important; +} + +[data-md-color-scheme="slate"] .md-footer__inner { + background-color: #252525 !important; +} + +.md-footer__link { + color: #000 !important; +} + +[data-md-color-scheme="slate"] .md-footer__link { + color: #ffffff !important; +} + +.md-footer__link:hover { + color: #000 !important; +} + +[data-md-color-scheme="slate"] .md-footer__link:hover { + color: #ffffff !important; +} + +.md-footer__title { + color: #000 !important; + font-family: 'Martian Mono', monospace !important; +} + +[data-md-color-scheme="slate"] .md-footer__title { + color: #ffffff !important; +} + +.md-footer__direction { + color: #000 !important; + font-family: 'Martian Mono', monospace !important; + font-size: 0.7rem; +} + +[data-md-color-scheme="slate"] .md-footer__direction { + color: #ffffff !important; +} + +.md-footer__button { + color: #000 !important; +} + +[data-md-color-scheme="slate"] .md-footer__button { + color: #ffffff !important; +} + +/* Hide old header nav (now using tabs) */ +.md-header__nav { + display: none !important; +} + +/* ======================================== + TEMPORARILY HIDE DOCS LINK + ======================================== */ +/* Hide DOCS tab on desktop */ +.md-tabs__item--docs { + display: none !important; +} + +/* Hide DOCS link in mobile drawer */ +.md-nav__external-link[href*="docs-test"] { + display: none !important; +} diff --git a/docs/assets/extra.js b/docs/assets/extra.js new file mode 100644 index 0000000..7a1470c --- /dev/null +++ b/docs/assets/extra.js @@ -0,0 +1,215 @@ +// Make header title clickable to root +document.addEventListener('DOMContentLoaded', function() { + const headerTitle = document.querySelector('.md-header__title'); + if (headerTitle) { + headerTitle.addEventListener('click', function(e) { + if (e.target.tagName === 'A') return; + + const target = e.target.closest('.md-header__topic'); + if (target && !target.matches(':first-child')) { + e.preventDefault(); + window.scrollTo({ top: 0, behavior: 'smooth' }); + if (window.location.hash) { + history.replaceState(null, '', window.location.pathname); + } + } else { + window.location.href = '/'; + } + }); + } + + // Add specs, docs, forum, and home links to tabs row (aligned right on desktop) + const tabsList = document.querySelector('.md-tabs__list'); + if (tabsList) { + // Add icon to Modules tab + const modulesTab = Array.from(tabsList.querySelectorAll('.md-tabs__link')).find(link => + link.textContent.trim() === 'Modules' + ); + if (modulesTab) { + const icon = ''; + modulesTab.innerHTML = icon + 'Modules'; + } + + // Specs link + const specsItem = document.createElement('li'); + specsItem.className = 'md-tabs__item md-tabs__item--home md-tabs__item--specs'; + specsItem.innerHTML = 'Specs'; + tabsList.appendChild(specsItem); + + // Docs link + const docsItem = document.createElement('li'); + docsItem.className = 'md-tabs__item md-tabs__item--docs'; + docsItem.innerHTML = 'Docs'; + tabsList.appendChild(docsItem); + + // Forum link + const forumItem = document.createElement('li'); + forumItem.className = 'md-tabs__item md-tabs__item--forum'; + forumItem.innerHTML = 'Forum'; + tabsList.appendChild(forumItem); + + // Home link + const homeItem = document.createElement('li'); + homeItem.className = 'md-tabs__item md-tabs__item--home-link'; + homeItem.innerHTML = 'Home'; + tabsList.appendChild(homeItem); + } + + // Add specs, docs and forum links to mobile drawer (fixed at bottom) + const drawerNav = document.querySelector('.md-nav--primary'); + if (drawerNav) { + const linksContainer = document.createElement('div'); + linksContainer.className = 'md-nav__external-links'; + linksContainer.innerHTML = 'SpecsDocsForum'; + drawerNav.appendChild(linksContainer); + } + + // Reset mobile drawer to root level when opened + const drawerToggle = document.getElementById('__drawer'); + if (drawerToggle) { + drawerToggle.addEventListener('change', function() { + if (this.checked) { + document.querySelectorAll('.md-nav__toggle').forEach(function(toggle) { + if (toggle.id && toggle.id.startsWith('__nav_')) { + toggle.checked = false; + } + }); + } + }); + } + + // For module pages: move h1 title after the first image + const isModulePage = window.location.pathname.match(/\/mod-/); + + if (isModulePage) { + const content = document.querySelector('.md-content__inner'); + if (content) { + const h1 = content.querySelector('h1'); + const firstImg = content.querySelector('img'); + if (h1 && firstImg) { + const imgParent = firstImg.closest('p') || firstImg; + imgParent.after(h1); + } + } + } + + // Add prev/next navigation buttons + addPageNavigation(); + + function addPageNavigation() { + const content = document.querySelector('.md-content__inner'); + if (!content) return; + + const currentPath = window.location.pathname.replace(/\/$/, '') || '/'; + const isIndexPage = currentPath === '' || currentPath === '/'; + const isModulePage = currentPath.includes('/mod-'); + + // Only show navigation on index and module pages + if (!isIndexPage && !isModulePage) return; + + // Collect all module page links from the sidebar + const moduleLinks = []; + const seen = new Set(); + + // If on a module page, add current page (it won't be in sidebar as a link) + if (isModulePage) { + const currentName = document.querySelector('h1')?.textContent?.trim() || currentPath.split('/').pop(); + moduleLinks.push({ + href: currentPath + '/', + name: currentName, + fullPath: currentPath + }); + seen.add(currentPath); + } + + document.querySelectorAll('.md-nav--primary .md-nav__link').forEach(function(link) { + const href = link.getAttribute('href'); + if (!href || href.startsWith('#') || href.startsWith('javascript:')) return; + + // Only include module pages (containing mod-) + if (!href.includes('mod-')) return; + + const fullHref = new URL(href, window.location.href).pathname.replace(/\/$/, ''); + + if (!seen.has(fullHref)) { + seen.add(fullHref); + moduleLinks.push({ + href: href, + name: link.textContent.trim(), + fullPath: fullHref + }); + } + }); + + // Sort by fullPath to ensure consistent order + moduleLinks.sort((a, b) => a.fullPath.localeCompare(b.fullPath)); + + let prevItem = null; + let nextItem = null; + + if (isIndexPage) { + // Index page: prev = main site, next = first module + prevItem = { label: 'Main Site', href: 'https://microrack.org', name: 'microrack.org' }; + if (moduleLinks.length > 0) { + nextItem = { label: 'Next', ...moduleLinks[0] }; + } + } else if (isModulePage) { + // Module page: find position in list + let currentIndex = -1; + for (let i = 0; i < moduleLinks.length; i++) { + if (moduleLinks[i].fullPath === currentPath) { + currentIndex = i; + break; + } + } + + if (currentIndex === -1) return; + + // Previous: link to previous module, or main site for first module + if (currentIndex > 0) { + prevItem = { label: 'Previous', ...moduleLinks[currentIndex - 1] }; + } else { + prevItem = { label: 'Main Site', href: 'https://microrack.org', name: 'microrack.org' }; + } + + // Next: link to next module, or specs site for last module + if (currentIndex < moduleLinks.length - 1) { + nextItem = { label: 'Next', ...moduleLinks[currentIndex + 1] }; + } else { + nextItem = { label: 'Specs', href: 'https://specs.microrack.org', name: 'specs.microrack.org' }; + } + } + + if (!prevItem && !nextItem) return; + + const navContainer = document.createElement('div'); + navContainer.className = 'page-nav'; + + if (prevItem) { + const prevBtn = document.createElement('a'); + prevBtn.href = prevItem.href; + prevBtn.className = 'page-nav__btn page-nav__btn--prev'; + prevBtn.innerHTML = ''; + navContainer.appendChild(prevBtn); + } else { + const spacer = document.createElement('div'); + spacer.className = 'page-nav__spacer'; + navContainer.appendChild(spacer); + } + + if (nextItem) { + const nextBtn = document.createElement('a'); + nextBtn.href = nextItem.href; + nextBtn.className = 'page-nav__btn page-nav__btn--next'; + nextBtn.innerHTML = ''; + navContainer.appendChild(nextBtn); + } else { + const spacer = document.createElement('div'); + spacer.className = 'page-nav__spacer'; + navContainer.appendChild(spacer); + } + + const article = content.querySelector('article') || content; + article.appendChild(navContainer); + } +}); diff --git a/docs/assets/icon.png b/docs/assets/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..c3d05b51d8aa97e9d33d8f6b71f2f22f8dbb2a79 GIT binary patch literal 25309 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%0D@vzwYM>Ox--r@psFIDmN@lmB6 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 Y%gvH%Q_0?+AcNatFb| z<6Akgi^&8JO$q_z2Sp4H$WaVYw&+zcDSjtCYm5{owwrW5{?lP-A^zfi;0iygapXs| zBs6y1GpP7@Laf`DT`rQ)O^{-owJCB5s>1AXc@V?;Auh@@+O4MLjPN{|JqJ8k#^1D? zb3{F_hKGjsdIX=_^@T!Q9_^z1Pe5hkoj4rsZ8}c%X@iHPbwmI5Ln!*-8DR?AbJ<#w zP2-0pV&0EbqIZRVp_s82;&4-Z9BzgPf>{=Fi5!(1L2pX{Ly@)$$9Gri0(reivu^qP zjAH=cS>za~DOq4C0ATG2@v#R>&p(@-Eb!-%t1QtwaBbuLEM+dw3|g z5soj$jmk$^`Iu*}l0=A)u5G%|`mp>a?`+S)w$ESO~l@jDV!-(=-AEPF1TA(%&=U9dLEK1McnPjI=#ND~IvoFBi4Kx+tr9ui zr@f)Yw=^B!aA)-<_dj{Q+BcP%@c|+57TNm5^8DH1B{hLF z(2y!C{>!xZztjdvqh-(4h67p=J&bCo8?|Twv|ehcSB`+$2IHz(ZYF`v_#vR(<}8J*LMXsSymX&<=-?2c&7Q0ubTFqJ2C$e z(|p5P(l0Yp;K<$OM!GFWJ-4s3xl*$s|)u`IL8%HlzojL2PURSmm@}hebBgoz`PMV(Ifih0_|9hx7-L z;YB(h>DbsLnDxQvE#A1>$OAFAAmst(Reewf^2#|}O(qN05uIcWigOed0Y7o3xPL_o zUSu{8JJ0#1%=(ZYeS}kHBOf8#5mM>goS_J`dIB9nU8MVkP2|D%(X2?_OH=uV@YT30 za4Kr#iX2nDz0QZ&kSYx5zArJJ9=)IYqNxN>=Vg7F8YRkMPKXw~If=Jd%B-K0XQ%Q9 zhRB3g8AtQb3;u)>H)CC(6_)E$ux#21Nv!6f3oJoIFMoAbDK)+H4Rvm8d*r#<*ZOBN zSv7GbeDs6M7i$^p-WTTAZy(>eIij?AJQ;k?ykvXLRpzMEo>RN+ZQ=QHgu}`~mU~gV7B`zf}Tut2qpQBf{$CN>Pc2m1Vc+N?&V74*;dpUxs zVr!)O84{cJ8?iRTBsX{=Wj1Z*94)3EK_dU2Z2NJf&ftQG{n5~1M!`J?u(&pau?6-+ zirW@bW@UyH0uuL9_sWJ-(9RvB8Efit5VZrpfXt%`gyVM0$bCHi$3cJp8YvOE6#Qqb|_PzB_-zUFrw1KnjaTUGp^lx_Z&S%+9K|MD8;m8EzzC z$*#D&Zq+A=(r2IFA+-d|(#tNaEM!uwT0o))qNaPg>0`m66L))Es9f_4;hMLxo+dA) z%Z<$BQ$6m{ld5E8AlJN{zJ`$sAyyKF6-_NE{e90Z!(Hp)ytUReVC8@3AK|BM6{d~3 rz16wfzE(B`pw<_PZo5XlS=yh_8QyGt^|2lK3jhh62!BRY3y8 literal 0 HcmV?d00001 diff --git a/docs/assets/martian-mono.woff2 b/docs/assets/martian-mono.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..435b3490de7ec3066e1fe853c00c546f09ffd81b GIT binary patch literal 21640 zcmV)0K+eB+Pew8T0RR91091$o6aWAK0Iz%i08|+O0RR9100000000000000000000 z0000QfpQyzdK`&-KS)+VQi3!FU_Vn-K~#YzCn^AhW-nwB2nzpv=2r`ZA^7ECe70hIj`c3F$ zta>XrEaAjVsn=sPIECoY)9NJ%r!Soe9<*iE8Q_j;)M?MtY4hG+C2q1oy*&Uqs0Y$L zJLjIc!}Hth8HFg@j6(QCDJ7VIfK&_Ggh7<3U~hM4&Q-bFu3X0TD(`exF8U%@*KRl0 zr-p4#Lb;Y8c9_ikJ^m>!_Wlao_)(@oz)1pmmU$RiGYKvTy4iNmSd7PzO!EKh^y@wl zJ=v_V!#^|00Pq5EQEgF@qx`c|bh|~j}SHD8aPKE-*Mv1Qou5=|?Y}rmgDki`GcbYSjVKY~6k@0~fCy`lusx6^P{-P|c7ky-y4a6-pvhlWJ%Gr>d?vex6(^Ef*@K^QE<6A=COYWEqbC038lTC=e*c z0-;i0SX?N%HA1FsP-aSRYiC+1Tc%8z{4z|=GPQBcIJCbvQ*HkP1Q9Ai%hka;AKN>IwAoRs1_ zkfT|W4oAuXim9?n=g@_siJ@sdu3VO`Jm&e|Z&?399%xu!i-NyagTgIiF^>4hcNWgD-7%G5r)k^6o#EX5r&5zB7{9g zcV9G_I zK6@KL;lxrEY5@6Y+M^SYB!{{1@ZAs!lBPGtrbQEdaal)ZfSLhN8|4ol05pgI4~Z`1 zl1iRUWey_Hp@i@l@?{LFhdh*^0xeWQ4Oo>eaHM&2SPRuMK)2e8%R$~xRfGLP3o0G2 zf+h#{mEyIeR(L z0J2j$Kj^THt>@7RF}cMnhl>p*yDcoa8u&NFYlNr7lrTwq_ijojh{(jGVmO;O?a+hr zn>X*+h1#@-Y|*K6N8G#ozyn)r+66R3Xv5S;JQRvqrV@#%Ltyq&S_%&?p+D{;1x`WfZmg z8WhMZf=>Jg`!A452y}{?28)?yxT>7D$s^54boYf72J1{_9vj#>w927@3OYoB5Bv}V z0SI#TApoK(X|TXLGeOA#C+PqQP5{w&A5e<;b^`LnN;!5 zqADX%fh@Tg4?i~L*wkawj?HpxRb6r8l$_*(7<7aT z{&18uqY7a(mKEr-)F@mp+I;vLWm1Lr~?qtaQ()$0V-iBhE-+q%lH9qS3?HKvE=3CDRj+sR4#;LY9=BjBfjSji3>8Z24sc{BB_y;Qv(> zS6TnR!z;sU0f6v3JSIFlTq~Ral%XI;}f9CFGpqYeZLDx?^`qC})LlvLEJ7@1U%vuf6$kwcSvS_o>@rd>C; z9u%#7<$@$tL@0t#1)c?MqP8dV@Ppw^NYbUJ zSHe=~g&{<>G2TJ)UID@n;XWCR*h&{gxH~Y2yjGU4lR}&ahG~3#bpatsf{H+LzDTU? zZyH9Ca4RuZVN4eB)C9_>BDAqJ_ccP;r(_wV0r_~~crH1{x88&}9#J2t&LJ~!S524@ zV42L}u|a#g*Q!v_WlLKz4XevV8nOQb-boYTNKT@XzU+Z5oWM)k6KS&5<}zetwQl?; zBROv_y#qxoNwh;mDS@ZPoqt4^OTsqrUyfvgbaQ<3!g=Tup*NkSF=#QFnnvWwZ!G)IV%w#B#dNQ@**&VW@J3U{mxracG&0az{W_z?65)39KH^TiGZJ zD^FZ`&F9YXl#i15fd@uWcpOOqWFl|A*8N7<);VUg9~27rK12ECr%~+`%@)cih#5qL z3ga3T2_=@uGjjv57wH=mBMG}>+1!v-mF=;~#UjUTq9~?;HB!jYa+7fdcp<%S*$& z8;=&w$S1`OhKjMnAA_>$y#?E}F!i6+R(6g zRT{$(eWvF;Vw##=N2gW2-JPQlU|Brj*V|##%6i2cKyo+l(9$HX~W16I@|MJeg`60(j6y-WUAvn7-adUUWp7k@#y`l>Qo zjBuq>88JCv>`&$!$x5=a&p|I=1j@wiYAL2#)pN|3JhM8*)T|vhTqz`FczAO^;S)KS zZ6?OiPk4ynuE8k0E-Wv#vA#QH+BctAH{4IGxFuuHItOT&YDMiA9%gUCQ&hywZZXYD zmkmoYy`P@j$P=4%3koFHjtPGu9v6UuD_gni3NV_|Ec8wERe$2+{j@|Smx5)f!su^^ zg`vj~Bj@q;+HlQ&FmttFsFbV1Z>?Ac!s#dPsp7fdERLV({F+vyz^$MN@^AEM6@yi+ z{jp8N;#OQ1MVr`wm1k{V#FpWs%CQ%zZ)(b*@uVci!j(%IQJ2~mZU=s%+Q5)C7b~@I z2!liBE=qv7-Mz5fy)}2rY^wsMB28XdQR%1gz55Z zPP+O-LArWtwN`0GUFAdPz1WnRc>y$*QCy+fxyGMA`m~J3psV$@w9eW&7Q>-$AN1ol z8grPw@8{mrX|nJOr6DOFxuRg-T+;bij6B^s^u4R4wz}pKPI>Ufr&y!{b&Er{UY2Zm zuSq*o+Y!KyVokd1G5%o?jchx=v6VupOug^92)84CoBU-`Vtln0r`PlncrjB&Qe|?GA3o0v*A;76NG=b)!N_~6g%`t?ePJ*(5Kq+BvXSY?+TA))P*ES?#Yn~lrtW&A>Al8{$c z>sH*UOFFJqm{0#j+&eFD(dE__poIa+!Ci9{#HbK7f+Wp)V7N7a^>#>Mn&QjyJEAL;UhMjlBRINKU=VWYP=I~AnyhxjYd4{aXD`Xa+*hTPSNL+64bJ0X0AjdLFEg!!bC$Ny8Fc7 z^n`y%$YR~*s82x`#7NAyt#gtRDCo=8n1E51{G(?+jl0V1D$}=07Q1?^ZL=b0{zX>-V2e)@c# zPS3XXoH8WwJecVp|EagJsZg$-coow$yh0Yc^m*CAT+atsL`a;2b@II!3#0ik6U$_S ziZ854Jox@baPWkkXtC>;Oldwje$&#XpZOYc>c_Qh*nlVgfS_5w-Pn%Xt=05Jcfs}c zci~vSBx`uSjr!f%OQt0<9wX}o75_z2_4{d|&5G)>0rv21qdR?(eIi|Dw!Hi0 zK2JX$x>v?f?^+IcoR?G(NsKT$ZMO-@U~96&)iOMi$nlNTzwG0EVZcB3;5v*1Wl#lZ zy{5q=MQdv`I8a9EHHk@AQ|>rl7D+ZmHJNF;RXf>Qg)<4=7klyshQSq+8*{>!B}>m* z`D8SDHe!0hiW->z{^#;ab8$aH!-Fl|nj@0Q~r)&HT6d34YC6-%OG6G0ud;E@WpSg#xu&y!zGs2XDCBZ+MBM`W0+qIu z!}+mP3qSy|a>X~7F0J`yogpL^4Mtf!33W!R*it<6*DCQnq2U_qM@SfHP_ zY?+*x2#vP1cmrPds&!-Tm8Zu9;Oo3u-e2knJG{)e<#YX8U@w@l_|EvT=lX8N+JtKX zFYj_C&?YWea`~%^Yp2%ggF;bHbd@(zudfs|t1Zr2~4 zA&6ZL1z)5meK6;pVbYt(QShtbLP$3Gw{=$o(EOX z+3&B%M?9Zy`w@W!v1awu#fwr{qwA}^=E|}0aTLrj(R%%`kI>hA+hIaXU-lKD56?^e zhF~eF^rn>e+S^5F(axSlonj<2OMPGcySlk^=4{4hCNrkuywHhs8LYde7S;vr1cce2 zAuE1ujVXxS4+f2Sn%0t1w?ZLgYq4gN`h#tyGAWN2ily5o`hst7D&~3=a#oT$m}*E$ zLGnW;n7@!m`b7~06W2T25QNaS7x7(kv7ouVSo3Zz?S_B;5B>wk#sw;IaS1@k% zm(k@VLYZF5r|of7!(DSd?F~wiw})#mbeBlHkt+YJDN&>}%J}r%HPvwU98b`u6nZ;3 zdP7&fq$xrS2%r4vQ~Cb<1VmMbf{03egHjo+m54yb=;+FUfsGsevRoYue?M$HH026y z6Yy?=STDp+gCC0L#k^e{6YtzDNNbA5L0dV=@%-d1%|i;x&h=k9<%yI?nmY@0ZGG*Y<-Q_Ry9QTWWXPdv^VPP7nuO-%!P+VK zmHN5XRA>KxVa<|B zq2nMDGKZ-U>=gRQB-ja8tj`;)FRyC%5F5!QG74K!QKMB=*ecV&sEes53Q$D>Lx6!| z>IqDBi-xY7IPfz=tq)tIL)(G>KO%&{nEid4fQ=+5wjs)O>wq zyR+F8P#0@Ne>ftgWln!FU?bFi4R3j4BLpaQo}K`q7y(0|D6h~HGn_4ppHA{ng9?Pc zODkO7U==U!QfpG)yt{jDS4c#y;41UGhO5@l*DKuOu?6~RuA{P5tCgGsD7GSxXictk zc$3xm2Qc`sjYsT|d!%Yp!0t1(>)2}6D%W4KS~sJtqDL)Q>1Yrx=~kC(ee#k;jqx$o zHBRNQ-BI{V><&yXOc$0}ydGPfw?4Amei=`oK4x)#bNvP?lN5YUM~P9>PA{v<@x0VC zI10T=B1G}j7^>1ID;cV-FB$g9l{7VuhGGRarqvr93MF~<+E6NfZ9uyrKtTEB=v+a4 z5!)dh3AofEO<9>(qjrH+wei!Rq_VpAIM4;nu#gP#I*b%3egLc>!?T;r{QH)so~`TQ#7q~~4A zO;q+x%De7UDjVf``2DI0(4rQEsaGRf-qZIgO}}Pq;%g75Wo9AFD(##GIx@3tz!BF}We2VaC{Q$Ky4BNZ+Sz%H zsgs>(?_;)8Z~@@XgD$5ExHB<3N!Fh?f3{f^fMQWIC&^me}dPUor$PANoO=$KgFEXR(P2SYx84Qd`~M+#VWfjcB%C)fNc^;v9RrDbf7( zz$rGlsLHl}Pm~4lbxI$X>sMCkLgIvZc3NeTxWwTo7IpNm8qx$r)iRqfU!dfcmdXp! zO&p0%ClTxQVh#{JdS|RFky>y#hYCN@7}??p+04x?&CFrf@H;?N9YsegLsR+Y#(!V? zU)MH|^$(2E(x_US*s;MH;x|sNdD4jM!eF{^`?aUc#vRLy+7UT>QFZ6G|6p7H3w&O^ z3oLF|9mo?TPr!;}HgIBK-U*h#-Veq&u)Mc0aB%>6gwsEIcNuKi%DX)$m>&{{UYqJX zrms%{adp?m(=wF3r<3sA0iIr5ps6-R>Fw`-osqit;KdbSe)aiNuajVJxIRB6fOnHP zk3`A8p-CvaaONjC+~o*fOsz?8NltsIs4%O9XmasWmoFOw+iYC#A=OLpw}W) zfe3@5qpMV@3-Sf68l8T`z?pep7Wp0k=T(Ww6)IL6yE$cTVcM2BiAgES6{0yLu1d+b zdaXjOxUfVg6-g_#396O|qcqgZGigFa!e&{Sq<+Pm*F|=KNrJxa_I2M6-gj@D``&>w z@lnUnAf`KX&$s2m(>T01jVN)8xZMV$==DyyHngla-q-qEBjD3TIe1-uK29kl(V4QG z3^y<%^t}>kpP`iT8e4NR?TwT3X1AXqQUwg(c~)(axSS%j_+IpIWQOp1UWGnCrJ5~(qJS-3}J9k9m~_; zD?#0({QHlef8Y6)t@F#PR$DC^MyItwXLPo9n!tO}mDZ2Zm|b8PHB)#=M2J3#b_FjQHUf>x!rWM|W}vR-CWR1`EU zJtH?8J#ML_*Qph`B6JM_D!mu`2PU_P_XQiiv*?!V<&{CdUkc^AZqQIj3Z)Xg6fzkC zq1tipU`;$L_~pl|JU8H`?Iusp7xjLv1dv0^{w&p%7C6^t{mnuH3C)+`bPrVnaThqr ze5Fn#sW2$YDn!+lPDLh8j>8mSQZR3n1Iu-~{7$BXn^Sbk3uXAO97byyphFpN7S|o^ z_1)2>0LyncO-6nFf;;{>dD)UH_21nf zLI3!1T$LCu3?y`n_W7mmVr~P!0Hyq|?)lwi?8j_#au)JKO}X!H5Ya#T=BmZ!^ z=NEAspH=%J>yh2O(VM{XuBEBTQqka&Y2fmYVDmwl*eWhb;K$~FOK^cZ)>oiq-jj}7 zkg@btM|4*LsgIzzD^Q&j82ZSOiJXRl89vXlT<(p#E#fA7JDUGYB z_y^WmsEL>IiUiHfP{+=$P zU>+?=x+F^MzQB=X)VX|;Gcf`jtR1!=Q5>-o=76}I!zxEWz8F9lGH6R0h7aZE^67{g zq%MazLRi>24GZn9u>@>2ySHc68C~IP?0;_c@4w<+n>sF;I(CqI?#=FV8`^dbigpfw zQrFk(Tys1XxKsPTHJF!V=t~+gg5g`9^}YJLTeoTNtm$?2_ODxh*N;W5;>lG@M@Lml z<-Ap>dbwHF(s6m>tKJ)JSkau7)_&34%o++#UvI|gC}h0OT#wfS9D?6iP}IOLAyn~% zDz=jLy%dX+VX!Tf^lukri0%v`_cdXJbA{MqT7{8bl&{Un)fO=E%A>M81@jX@E@o3E zMpP{=98GBS!Rw3HSNhwy0LO;zTknsg@r3jyeKEVWWBxantuMZ(V5+e(L?@?0$Q-1L zB+1aW$OPOb#e7<1WL~kXsA?gymtpr3<aeJ!=r*5Zxu^!eJG8$K_a^1g)J#v{sT z1h6F457kO`_w4;+(O~vupCNmg{W+Vgv!iBkt9c0%`$d#yHDum@ti^-gkB;n zb1CME6fre4s+P$lK}(nntrBP%tlN!mki<$F@JrqPl>Kq3`#o;yNaXrt?$M;|iK9n= zWrA&FFv?kMh5-bdUCv+{*eqswAXv6EX;oT!r8F(|~Z`W17~8nh5@ zw>uzeh71tV^v)Z#Eag~>i>(}v2wt0GCe3CVQ&F*~Ef3T17=xK>65hacXMu#SwLjklz^YjAOjvGe{aHR*6)GT$W-_KEY430#-=7(uzDgjR}=TMSF z2b09PYEg{{4qxD#6*Sq{06NI#%jQda!<1XLe4Fy&T+xFE_CHO5DA!(S2Oo4UE8AP^ z?pFe}AKPQ?F>|91+9>VoPr!I&`>kKL02PG<9JChXzW@0H`-9Kzs-ziX{mfVYA}#); zvNkR4M!qGsTwljO*Kr?bi3tI$-ItSIodJSiXO@LK`Zpl+6G17Wq@sl3meppe#Rj2J zX0NsfY66VJ77Y|}2nyI&!QwIk>e8mh?M++Dl-l~Ls!&ksgu<3_giJn?k-0lB-97sw zA*Ij>UPlgR0jm022=g!r2?ci?J@KV%l^`bE9uCf4A>Qavg^8JV`y7Gaj=ZJRSl%Zc zB@&O4w4~i2aqGL$#ZGK}|0%b;oiF4tnPTVbql?mxr=}fCd%VTewE=odhl;x39!N(dvqzxDX`VZb)a}s&U5vdowsEB@Q8&88b2u}mT z002h;3QQtrtpKShrOhA^*dQa0Vx@_Iqlp2a$xbDQ!8L-^N|T)haIF@yZ)4vM=+v5$ zL|@7bKuQ%*Tils&O~%4Mc$!?3Q&O8o0LfJLM-*p4(UL19C_hOKo}}as*SEq6AV+JG znocc)BbGS?kg-7}Bv+a$`b4`zGLSS|#jw2^nvUq0PUw`*=$tNKS%}6E>oSaB3=^2b z4Cb&P%YzcZ9st0H;o5K##6dJ}Gw2PKuUpi90OVi=Plk@D*;@Do$pYMwdv3%5rxeTp z0ASiH&bvX3gRXfbTmwZw1Xoscb031DBVbt~&)Ai+=;7BU zUr2^m+FL|Ev=gYB?$+gmCavHf{EwK>XA?2*#P%EQjX0WQ9@3@Ki7p3=KLZUJ|4o3q zyC1m@fiUP9dmlh9;4#y!+db`}Bp0ggi$+E^OaQoLZ#@tr(9mma#g#pJWyK9jf?CJ5 zk`M?H46CEsJ)#F{LhCv(avstHPv@&wal=Xp1+=T$gKsZK!@elQ?xPFpC=~Cm!fJrq z3DZF+#_JC??TeDY3j*4swS*kH4eGR4PqnLrJ;@66I;yz}hxSJ@?c`So=?zR4>9^&c zJ4^Ym{h)Wj>oK#_DgS!Ep!>&5@KcaJRQnMkJ)YKs(*}}?^qkz|XDNEszS%p&UO2NO zDSGKWLHCoFphHr63O7^t)dVw}=PfWOo9_n@COKlBMJVL?6&n`%-vggqiqfd@hNa$gA`4ZZ8X9)5SLgw~qHi2v8ZY2=ZD>y? z_%eSM=|zFiiw3b`>=;MHA4!$G5?X4Kw$H6Ag=jy&4yaI{}Ndx?y#&!|~S-N6Yy4;L-LFTn@LuJ@7Vo zH+&er6}}gK8-6zdSbsum!uC{(-j64;5?}kvL8Ky@5c?3Ze!BCzXXqayGDI|uSYo{N zRPszPSDH7yQc?kLX>WCJ7w;*Zk`wh-`fBJ($>kdZANhW2XaA|@)B?Uw(<0C3zXIXzEGm!I?q1gAki0|N&rqXAF}m>+*UvUT6k z3fQq!Hi;dlGpxbd!=n>8pZ`dn6?}H~y?aB$(F_JCnx4)(6#w(7GW6|;XYrqZCMS

9`;5K}MXKo_CvaM^imT?Q@sm8WCt> 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 BY-SA 4.0' +docs_dir: docs +nav: + - Modules: + - Modules: index.md + - counter: mod-clk/README.md + - compressor: mod-comp/README.md + - delay: mod-delay/README.md + - envelope: mod-env/README.md + - EQ: mod-eq/README.md + - input 6.3: mod-in-63/README.md + - jacket 3.5: mod-jacket/README.md + - stylo: mod-key/README.md + - lowpass gate: mod-lpg/README.md + - midi→cv: mod-midi/README.md + - vca mixer: mod-mix/README.md + - noise + s&h: mod-noise/README.md + - output 3.5: mod-out-35/README.md + - output 6.3: mod-out-63/README.md + - saturator: mod-sat/README.md + - sequencer: mod-seq/README.md + - filter: mod-vcf/README.md + - oscillator: mod-vco/README.md diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..643418b --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +mkdocs==1.6.1 +mkdocs-material==9.7.1 diff --git a/scripts/convert_admonitions.py b/scripts/convert_admonitions.py new file mode 100644 index 0000000..a8c41b2 --- /dev/null +++ b/scripts/convert_admonitions.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 +""" +Convert GitHub-flavored markdown blockquotes to MkDocs admonition syntax. + +GitHub format: +> **Title** +> +> Some message content +> spanning multiple lines + +MkDocs format: +!!! note "Title" + Some message content + spanning multiple lines +""" + +import re +import sys + + +def convert_blockquotes_to_admonitions(content: str) -> str: + """Convert GitHub blockquotes to MkDocs admonitions.""" + lines = content.split('\n') + result = [] + i = 0 + + while i < len(lines): + line = lines[i] + + # Check if this is the start of a blockquote with a bold title + # Pattern: > **Title** or > ⚠️ **Title** + title_match = re.match(r'^>\s*(?:⚠️\s*)?\*\*([^*]+)\*\*\s*$', line) + + if title_match: + title = title_match.group(1).strip() + + # Determine admonition type from title + admon_type = get_admonition_type(title) + + # Collect all subsequent blockquote lines + content_lines = [] + i += 1 + + while i < len(lines): + current = lines[i] + + # Check if still in blockquote + if current.startswith('>'): + # Remove the > prefix and one optional space + text = re.sub(r'^>\s?', '', current) + content_lines.append(text) + i += 1 + elif current.strip() == '': + # Empty line - check if next line continues blockquote + if i + 1 < len(lines) and lines[i + 1].startswith('>'): + content_lines.append('') + i += 1 + else: + break + else: + break + + # Build admonition + result.append(f'!!! {admon_type} "{title}"') + + # Add content with proper indentation + for content_line in content_lines: + if content_line.strip(): + result.append(f' {content_line}') + else: + result.append('') + + continue + + result.append(line) + i += 1 + + return '\n'.join(result) + + +def get_admonition_type(title: str) -> str: + """Map title keywords to MkDocs admonition types.""" + title_lower = title.lower() + + if any(kw in title_lower for kw in ['tip', 'hint']): + return 'tip' + elif any(kw in title_lower for kw in ['warning', 'important', 'caution']): + return 'warning' + elif any(kw in title_lower for kw in ['danger', 'error']): + return 'danger' + elif 'example' in title_lower: + return 'example' + elif any(kw in title_lower for kw in ['note', 'info', 'licensing', 'open', 'source']): + return 'info' + else: + return 'note' + + +def main(): + if len(sys.argv) > 1: + with open(sys.argv[1], 'r') as f: + content = f.read() + else: + content = sys.stdin.read() + + converted = convert_blockquotes_to_admonitions(content) + print(converted, end='') + + +if __name__ == '__main__': + main() diff --git a/scripts/update_nav.py b/scripts/update_nav.py new file mode 100644 index 0000000..8581ca8 --- /dev/null +++ b/scripts/update_nav.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python3 +""" +Update mkdocs.yml navigation with modules from master branch. +Scans docs/mod-*/README.md and extracts H1 titles for nav entries. +""" + +import os +import re +import yaml +from pathlib import Path + +def get_h1_title(readme_path): + """Extract the H1 title from a README.md file.""" + try: + with open(readme_path, 'r', encoding='utf-8') as f: + content = f.read() + + # Match first H1 heading + match = re.search(r'^#\s+(.+)$', content, re.MULTILINE) + if match: + return match.group(1).strip() + except Exception as e: + print(f" Warning: Could not read {readme_path}: {e}") + + return None + +def get_modules(): + """Scan docs/ for module directories and extract titles.""" + docs_dir = Path("docs") + modules = [] + + if not docs_dir.exists(): + print(f"Warning: {docs_dir} does not exist") + return modules + + # Find all mod-* directories + for mod_dir in sorted(docs_dir.glob("mod-*")): + if not mod_dir.is_dir(): + continue + + readme_path = mod_dir / "README.md" + if not readme_path.exists(): + print(f" Warning: No README.md in {mod_dir}") + continue + + # Get title from H1 + title = get_h1_title(readme_path) + if not title: + # Fallback to folder name + title = mod_dir.name.replace("mod-", "").replace("-", " ") + + modules.append({ + 'title': title, + 'path': f"{mod_dir.name}/README.md" + }) + print(f" Found: {title} -> {mod_dir.name}") + + return modules + +def update_mkdocs_nav(modules): + """Update the Modules section in mkdocs.yml with discovered modules.""" + mkdocs_path = Path("mkdocs.yml") + + if not mkdocs_path.exists(): + print("Error: mkdocs.yml not found") + return False + + with open(mkdocs_path, 'r', encoding='utf-8') as f: + config = yaml.safe_load(f) + + nav = config.get('nav', []) + + # Find and update the Modules section + for i, section in enumerate(nav): + if isinstance(section, dict) and 'Modules' in section: + # Build new modules nav + modules_nav = [{'Modules': 'index.md'}] + for mod in modules: + modules_nav.append({mod['title']: mod['path']}) + + nav[i] = {'Modules': modules_nav} + break + + config['nav'] = nav + + # Write back with preserved formatting + with open(mkdocs_path, 'w', encoding='utf-8') as f: + yaml.dump(config, f, default_flow_style=False, allow_unicode=True, sort_keys=False) + + return True + +def main(): + print("Scanning for modules...") + modules = get_modules() + + if not modules: + print("No modules found!") + return + + print(f"\nFound {len(modules)} modules") + print("Updating mkdocs.yml navigation...") + + if update_mkdocs_nav(modules): + print("Successfully updated mkdocs.yml") + else: + print("Failed to update mkdocs.yml") + +if __name__ == "__main__": + main() From dcdc8740066bbfe4dc59d947616965c4fc7dff10 Mon Sep 17 00:00:00 2001 From: MICRORACK Date: Thu, 25 Dec 2025 02:54:00 +0400 Subject: [PATCH 2/2] Change icon --- docs/assets/extra.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/assets/extra.js b/docs/assets/extra.js index 7a1470c..5193bb6 100644 --- a/docs/assets/extra.js +++ b/docs/assets/extra.js @@ -26,7 +26,7 @@ document.addEventListener('DOMContentLoaded', function() { link.textContent.trim() === 'Modules' ); if (modulesTab) { - const icon = ''; + const icon = ''; modulesTab.innerHTML = icon + 'Modules'; }