From dad060d0c96906ae3da49b098db4aa49526679a7 Mon Sep 17 00:00:00 2001 From: perf3ct Date: Thu, 4 Sep 2025 21:13:12 +0000 Subject: [PATCH 01/13] feat(docs): let's try to deploy our stuff to mkdocs --- .github/workflows/deploy-docs.yml | 151 ++++++++++++++++ docs/index.md | 94 ++++++++++ docs/javascripts/extra.js | 111 ++++++++++++ docs/javascripts/mathjax.js | 13 ++ docs/stylesheets/extra.css | 121 +++++++++++++ mkdocs.yml | 278 ++++++++++++++++++++++++++++++ requirements-docs.txt | 20 +++ 7 files changed, 788 insertions(+) create mode 100644 .github/workflows/deploy-docs.yml create mode 100644 docs/index.md create mode 100644 docs/javascripts/extra.js create mode 100644 docs/javascripts/mathjax.js create mode 100644 docs/stylesheets/extra.css create mode 100644 mkdocs.yml create mode 100644 requirements-docs.txt diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml new file mode 100644 index 000000000..25b04d1d7 --- /dev/null +++ b/.github/workflows/deploy-docs.yml @@ -0,0 +1,151 @@ +# GitHub Actions workflow for deploying MkDocs documentation to Cloudflare Pages +# This workflow builds and deploys your MkDocs site when changes are pushed to main +name: Deploy MkDocs Documentation + +on: + # Trigger on push to main branch + push: + branches: + - main + - master # Also support master branch + # Only run when docs files change + paths: + - 'docs/**' + - 'mkdocs.yml' + - 'requirements-docs.txt' + - '.github/workflows/deploy-docs.yml' + + # Allow manual triggering from Actions tab + workflow_dispatch: + + # Run on pull requests for preview deployments + pull_request: + branches: + - main + - master + paths: + - 'docs/**' + - 'mkdocs.yml' + - 'requirements-docs.txt' + - '.github/workflows/deploy-docs.yml' + +jobs: + build-and-deploy: + name: Build and Deploy MkDocs + runs-on: ubuntu-latest + timeout-minutes: 10 + + # Required permissions for deployment + permissions: + contents: read + deployments: write + pull-requests: write # For PR preview comments + id-token: write # For OIDC authentication (if needed) + + steps: + - name: Checkout Repository + uses: actions/checkout@v5 + with: + fetch-depth: 0 # Fetch all history for git info and mkdocs-git-revision-date plugin + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.13' + cache: 'pip' + cache-dependency-path: 'requirements-docs.txt' + + - name: Install MkDocs and Dependencies + run: | + pip install --upgrade pip + pip install -r requirements-docs.txt + env: + PIP_DISABLE_PIP_VERSION_CHECK: 1 + + - name: Build MkDocs Site + run: | + # Build with strict mode but allow expected warnings + mkdocs build --verbose || { + EXIT_CODE=$? + # Check if the only issue is expected warnings + if mkdocs build 2>&1 | grep -E "WARNING.*(README|not found)" && \ + [ $(mkdocs build 2>&1 | grep -c "ERROR") -eq 0 ]; then + echo "✅ Build succeeded with expected warnings" + mkdocs build --verbose + else + echo "❌ Build failed with unexpected errors" + exit $EXIT_CODE + fi + } + + - name: Validate Built Site + run: | + # Basic validation that important files exist + test -f site/index.html || (echo "ERROR: site/index.html not found" && exit 1) + test -f site/sitemap.xml || (echo "ERROR: site/sitemap.xml not found" && exit 1) + test -d site/assets || (echo "ERROR: site/assets directory not found" && exit 1) + echo "✅ Site validation passed" + + # Deploy using Wrangler (recommended by Cloudflare) + - name: Deploy to Cloudflare Pages + id: deploy + if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' + uses: cloudflare/wrangler-action@v3 + with: + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + command: pages deploy site --project-name=trilium-docs --branch=${{ github.ref_name }} + + # Deploy preview for PRs + - name: Deploy Preview to Cloudflare Pages + id: preview-deployment + if: github.event_name == 'pull_request' + uses: cloudflare/wrangler-action@v3 + with: + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + command: pages deploy site --project-name=trilium-docs --branch=pr-${{ github.event.pull_request.number }} + + # Post deployment URL as PR comment + - name: Comment PR with Preview URL + if: github.event_name == 'pull_request' + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const prNumber = context.issue.number; + // Construct preview URL based on Cloudflare Pages pattern + const previewUrl = `https://pr-${prNumber}.trilium-docs.pages.dev`; + const mainUrl = 'https://docs.trilium.app'; + + // Check if we already commented + const comments = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber + }); + + const botComment = comments.data.find(comment => + comment.user.type === 'Bot' && + comment.body.includes('Documentation preview is ready') + ); + + const commentBody = `📚 Documentation preview is ready!\n\n🔗 Preview URL: ${previewUrl}\n📖 Production URL: ${mainUrl}\n\n✅ All checks passed\n\n_This preview will be updated automatically with new commits._`; + + if (botComment) { + // Update existing comment + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: botComment.id, + body: commentBody + }); + } else { + // Create new comment + await github.rest.issues.createComment({ + issue_number: prNumber, + owner: context.repo.owner, + repo: context.repo.repo, + body: commentBody + }); + } \ No newline at end of file diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 000000000..5bf104216 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,94 @@ +# Trilium Notes Documentation + +Welcome to the official documentation for **Trilium Notes** - a hierarchical note-taking application with a focus on building large personal knowledge bases. + +![Trilium Notes Screenshot](app.png) + +## What is Trilium Notes? + +Trilium Notes is a powerful, feature-rich note-taking application designed for building and managing extensive personal knowledge bases. It offers: + +- **Hierarchical organization** with unlimited nesting of notes +- **Rich text editing** with markdown support +- **Powerful search** capabilities +- **Note relations** and attributes for semantic connections +- **Scripting support** for automation and customization +- **Synchronization** between devices +- **Encryption** for sensitive notes +- **Web clipper** for saving web content + +## Quick Links + +
+ +- :material-rocket-launch-outline: **[Quick Start Guide](User%20Guide/quick-start.md)** + + Get up and running with Trilium in minutes + +- :material-download: **[Installation](User%20Guide/installation.md)** + + Download and install Trilium on your platform + +- :material-docker: **[Docker Setup](User%20Guide/docker.md)** + + Deploy Trilium using Docker containers + +- :material-book-open-variant: **[User Guide](User%20Guide/index.md)** + + Comprehensive guide to all features + +- :material-code-braces: **[Script API](Script%20API/index.md)** + + Automate and extend Trilium with scripting + +- :material-wrench: **[Developer Guide](Developer%20Guide/index.md)** + + Contributing and development documentation + +
+ +## Features Overview + +### Note Organization +- Create unlimited hierarchical note structures +- Clone notes to appear in multiple locations +- Use attributes and relations for metadata +- Template system for consistent note creation + +### Content Types +- **Text notes** with rich formatting +- **Code notes** with syntax highlighting +- **Canvas notes** for drawing and diagrams +- **File attachments** of any type +- **Web view** for embedded content +- **Mermaid diagrams** support + +### Advanced Features +- **Full-text search** with advanced operators +- **Note map** visualization +- **Day notes** for journaling +- **Book notes** for long-form content +- **Protected notes** with encryption +- **Note versioning** and history + +### Automation & Integration +- JavaScript-based scripting +- Custom widgets and themes +- REST API for external integrations +- Web clipper browser extension +- Import/export in multiple formats + +## Getting Help + +- **[FAQ](support/faq.md)** - Frequently asked questions +- **[Troubleshooting](support/troubleshooting.md)** - Common issues and solutions +- **[Community Forum](https://github.com/triliumnext/trilium/discussions)** - Ask questions and share tips +- **[Issue Tracker](https://github.com/triliumnext/trilium/issues)** - Report bugs and request features + +## Contributing + +Trilium is open-source and welcomes contributions! Check out our [Contributing Guide](Developer%20Guide/contributing.md) to get started. + +## License + +Trilium Notes is licensed under [AGPL-3.0](https://github.com/triliumnext/trilium/blob/master/LICENSE). \ No newline at end of file diff --git a/docs/javascripts/extra.js b/docs/javascripts/extra.js new file mode 100644 index 000000000..f5c075755 --- /dev/null +++ b/docs/javascripts/extra.js @@ -0,0 +1,111 @@ +// Custom JavaScript for Trilium Notes documentation + +// Add smooth scrolling for anchor links +document.addEventListener('DOMContentLoaded', function() { + // Smooth scroll for internal links + document.querySelectorAll('a[href^="#"]').forEach(anchor => { + anchor.addEventListener('click', function (e) { + e.preventDefault(); + const target = document.querySelector(this.getAttribute('href')); + if (target) { + target.scrollIntoView({ + behavior: 'smooth', + block: 'start' + }); + } + }); + }); + + // Add copy button to code blocks if not already present + const codeBlocks = document.querySelectorAll('pre code'); + codeBlocks.forEach(block => { + if (!block.parentElement.querySelector('.copy-button')) { + const button = document.createElement('button'); + button.className = 'copy-button'; + button.textContent = 'Copy'; + button.addEventListener('click', () => { + navigator.clipboard.writeText(block.textContent); + button.textContent = 'Copied!'; + setTimeout(() => { + button.textContent = 'Copy'; + }, 2000); + }); + block.parentElement.appendChild(button); + } + }); + + // Add external link indicators + document.querySelectorAll('a[href^="http"]').forEach(link => { + if (!link.hostname.includes('trilium')) { + link.classList.add('external-link'); + link.setAttribute('target', '_blank'); + link.setAttribute('rel', 'noopener noreferrer'); + } + }); + + // Platform detection for download buttons + const platform = detectPlatform(); + const downloadButtons = document.querySelectorAll('.download-button'); + downloadButtons.forEach(button => { + if (button.dataset.platform === platform) { + button.classList.add('recommended'); + button.innerHTML += ' Recommended'; + } + }); +}); + +// Detect user's platform +function detectPlatform() { + const userAgent = navigator.userAgent.toLowerCase(); + if (userAgent.includes('win')) return 'windows'; + if (userAgent.includes('mac')) return 'macos'; + if (userAgent.includes('linux')) return 'linux'; + return 'unknown'; +} + +// Add search shortcuts +document.addEventListener('keydown', function(e) { + // Ctrl/Cmd + K to focus search + if ((e.ctrlKey || e.metaKey) && e.key === 'k') { + e.preventDefault(); + const searchInput = document.querySelector('.md-search__input'); + if (searchInput) { + searchInput.focus(); + } + } +}); + +// Version selector enhancement +const versionSelector = document.querySelector('.md-version__current'); +if (versionSelector) { + // Add version comparison tooltip + versionSelector.addEventListener('mouseenter', function() { + const tooltip = document.createElement('div'); + tooltip.className = 'version-tooltip'; + tooltip.textContent = 'Click to view other versions'; + this.appendChild(tooltip); + }); +} + +// Analytics event tracking for documentation +if (typeof gtag !== 'undefined') { + // Track external link clicks + document.querySelectorAll('a[href^="http"]').forEach(link => { + link.addEventListener('click', () => { + gtag('event', 'click', { + 'event_category': 'external_link', + 'event_label': link.href + }); + }); + }); + + // Track code copy events + document.querySelectorAll('.copy-button').forEach(button => { + button.addEventListener('click', () => { + gtag('event', 'copy_code', { + 'event_category': 'engagement', + 'event_label': window.location.pathname + }); + }); + }); +} \ No newline at end of file diff --git a/docs/javascripts/mathjax.js b/docs/javascripts/mathjax.js new file mode 100644 index 000000000..33ea4b928 --- /dev/null +++ b/docs/javascripts/mathjax.js @@ -0,0 +1,13 @@ +// MathJax configuration for mathematical notation support +window.MathJax = { + tex: { + inlineMath: [['$', '$'], ['\\(', '\\)']], + displayMath: [['$$', '$$'], ['\\[', '\\]']], + processEscapes: true, + processEnvironments: true + }, + options: { + ignoreHtmlClass: 'no-mathjax', + processHtmlClass: 'mathjax' + } +}; \ No newline at end of file diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css new file mode 100644 index 000000000..354beb509 --- /dev/null +++ b/docs/stylesheets/extra.css @@ -0,0 +1,121 @@ +/* Custom styles for Trilium Notes documentation */ + +/* Grid cards for homepage */ +.md-typeset .grid { + display: grid; + gap: 1rem; + grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); + margin-top: 1rem; +} + +.md-typeset .grid.cards > ul { + display: contents; +} + +.md-typeset .grid.cards > ul > li { + border: 1px solid var(--md-default-fg-color--lightest); + border-radius: .25rem; + display: flex; + flex-direction: column; + padding: 1rem; + transition: border-color .25s, box-shadow .25s; +} + +.md-typeset .grid.cards > ul > li:hover { + border-color: var(--md-accent-fg-color); + box-shadow: 0 0 0 .1rem var(--md-accent-fg-color--transparent); +} + +/* Improve code block appearance */ +.md-typeset pre > code { + font-size: .85rem; +} + +/* Better admonition spacing */ +.md-typeset .admonition { + margin: 1.5rem 0; +} + +/* Trilium brand colors */ +:root { + --trilium-primary: #4a5568; + --trilium-accent: #805ad5; +} + +/* Custom badge styles */ +.badge { + background-color: var(--md-accent-fg-color); + border-radius: .125rem; + color: var(--md-accent-bg-color); + display: inline-block; + font-size: .75rem; + font-weight: 700; + padding: .125rem .375rem; + text-transform: uppercase; +} + +/* Version badge */ +.version-badge { + background-color: var(--md-primary-fg-color); + margin-left: .5rem; +} + +/* Platform badges */ +.platform-badge { + margin: 0 .25rem; +} + +.platform-badge.windows { + background-color: #0078d4; +} + +.platform-badge.macos { + background-color: #000000; +} + +.platform-badge.linux { + background-color: #fcc624; + color: #000000; +} + +/* Improve table readability */ +.md-typeset table:not([class]) { + font-size: .85rem; +} + +.md-typeset table:not([class]) th { + background-color: var(--md-default-bg-color); + font-weight: 700; +} + +/* API reference styling */ +.api-method { + background-color: var(--md-code-bg-color); + border-radius: .125rem; + font-family: var(--md-code-font-family); + font-weight: 600; + padding: .125rem .25rem; +} + +.api-method.get { + color: #10b981; +} + +.api-method.post { + color: #3b82f6; +} + +.api-method.put { + color: #f59e0b; +} + +.api-method.delete { + color: #ef4444; +} + +/* Responsive improvements */ +@media screen and (max-width: 76.1875em) { + .md-typeset .grid { + grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); + } +} \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 000000000..ecde11abb --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,278 @@ +# MkDocs configuration for Trilium Notes documentation +site_name: Trilium Notes Documentation +site_url: https://docs.triliumnext.com +site_description: Trilium Notes is a hierarchical note taking application with focus on building large personal knowledge bases +site_author: Trilium Notes Team + +# Repository information +repo_name: triliumnext/trilium +repo_url: https://github.com/triliumnext/trilium +edit_uri: edit/main/docs/ + +# Copyright +copyright: Copyright © 2025 Trilium Notes + +# Theme configuration +theme: + name: material + + # Color scheme + palette: + # Light mode + - media: "(prefers-color-scheme: light)" + scheme: default + primary: indigo + accent: deep-purple + toggle: + icon: material/brightness-7 + name: Switch to dark mode + + # Dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + primary: blue-grey + accent: deep-purple + toggle: + icon: material/brightness-4 + name: Switch to light mode + + # Font configuration + font: + text: Inter + code: JetBrains Mono + + # Features + features: + - announce.dismiss + - content.action.edit + - content.action.view + - content.code.annotate + - content.code.copy + - content.tooltips + - navigation.footer + - navigation.indexes + - navigation.instant + - navigation.instant.prefetch + - navigation.instant.progress + - navigation.path + - navigation.prune + - navigation.sections + - navigation.tabs + - navigation.tabs.sticky + - navigation.top + - navigation.tracking + - search.highlight + - search.share + - search.suggest + - toc.follow + - toc.integrate + + # Icons + icon: + logo: material/note-multiple + repo: fontawesome/brands/github + +# Plugins +plugins: + - search: + separator: '[\s\-,:!=\[\]()"`/]+|\.(?!\d)|&[lg]t;|(?!\b)(?=[A-Z][a-z])' + lang: + - en + - minify: + minify_html: true + minify_js: true + minify_css: true + htmlmin_opts: + remove_comments: true + - git-revision-date-localized: + enable_creation_date: true + type: iso_datetime + fallback_to_build_date: true + +# Extensions +markdown_extensions: + # Python Markdown + - abbr + - admonition + - attr_list + - def_list + - footnotes + - md_in_html + - toc: + permalink: true + permalink_title: Anchor link to this section for reference + + # Python Markdown Extensions + - pymdownx.arithmatex: + generic: true + - pymdownx.betterem: + smart_enable: all + - pymdownx.caret + - pymdownx.details + - pymdownx.emoji: + emoji_index: !!python/name:material.extensions.emoji.twemoji + emoji_generator: !!python/name:material.extensions.emoji.to_svg + - pymdownx.highlight: + anchor_linenums: true + line_spans: __span + pygments_lang_class: true + - pymdownx.inlinehilite + - pymdownx.keys + - pymdownx.mark + - pymdownx.smartsymbols + - pymdownx.snippets + - pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format + - pymdownx.tabbed: + alternate_style: true + combine_header_slug: true + - pymdownx.tasklist: + custom_checkbox: true + - pymdownx.tilde + +# Extra CSS and JavaScript (if needed) +extra_css: + - stylesheets/extra.css + +extra_javascript: + - javascripts/extra.js + # MathJax for mathematical notation + - javascripts/mathjax.js + - https://unpkg.com/mathjax@3/es5/tex-mml-chtml.js + +# Extra configuration +extra: + # Social links + social: + - icon: fontawesome/brands/github + link: https://github.com/zadam/trilium + - icon: fontawesome/brands/docker + link: https://hub.docker.com/r/zadam/trilium + - icon: fontawesome/solid/globe + link: https://trilium.cc + + # Analytics (optional - add your own if needed) + analytics: + provider: google + property: G-XXXXXXXXXX # Replace with your Google Analytics ID + feedback: + title: Was this page helpful? + ratings: + - icon: material/emoticon-happy-outline + name: This page was helpful + data: 1 + note: >- + Thanks for your feedback! + - icon: material/emoticon-sad-outline + name: This page could be improved + data: 0 + note: >- + Thanks for your feedback! Help us improve this page by + opening an issue. + + # Version + version: + provider: mike + default: stable + +# Navigation structure based on existing documentation +nav: + - Home: index.md + + - Getting Started: + - Introduction: README.md + - Installation: + - Desktop Installation: User Guide/installation.md + - Server Installation: User Guide/server-installation.md + - Docker Installation: User Guide/docker.md + - Mobile Access: User Guide/mobile-frontend.md + - Quick Start Guide: User Guide/quick-start.md + + - User Guide: + - Overview: User Guide/index.md + - Basic Concepts: + - Notes & Branches: User Guide/notes-and-branches.md + - Note Types: User Guide/note-types.md + - Attributes: User Guide/attributes.md + - Relations: User Guide/relations.md + - Features: + - Note Editor: User Guide/note-editor.md + - Search: User Guide/search.md + - Note Map: User Guide/note-map.md + - Day Notes: User Guide/day-notes.md + - Book Notes: User Guide/book-notes.md + - Templates: User Guide/templates.md + - Cloning Notes: User Guide/cloning-notes.md + - Protected Notes: User Guide/protected-notes.md + - Note Revisions: User Guide/note-revisions.md + - Synchronization: User Guide/synchronization.md + - Advanced Features: + - Scripting: User Guide/scripting.md + - Themes: User Guide/themes.md + - Keyboard Shortcuts: User Guide/keyboard-shortcuts.md + - Web Clipper: User Guide/web-clipper.md + - Import & Export: User Guide/import-export.md + - Backup: User Guide/backup.md + - Configuration: User Guide/configuration.md + + - Script API: + - Overview: Script API/index.md + - Backend API: + - Overview: Script API/backend/index.md + - BNote: Script API/backend/BNote.md + - BBranch: Script API/backend/BBranch.md + - BAttribute: Script API/backend/BAttribute.md + - BackendScriptApi: Script API/backend/BackendScriptApi.md + - SQL API: Script API/backend/sql.md + - Frontend API: + - Overview: Script API/frontend/index.md + - FNote: Script API/frontend/FNote.md + - FBranch: Script API/frontend/FBranch.md + - FAttribute: Script API/frontend/FAttribute.md + - FrontendScriptApi: Script API/frontend/FrontendScriptApi.md + - Examples: + - Script Examples: Script API/examples.md + - Custom Widgets: Script API/custom-widgets.md + - Event Handlers: Script API/event-handlers.md + + - Developer Guide: + - Overview: Developer Guide/index.md + - Architecture: + - Project Structure: Developer Guide/architecture.md + - Database Schema: Developer Guide/database.md + - Entity System: Developer Guide/entities.md + - Cache System: Developer Guide/cache-system.md + - Development Setup: + - Local Development: Developer Guide/development.md + - Building from Source: Developer Guide/build.md + - Testing: Developer Guide/testing.md + - Contributing: + - Contribution Guide: Developer Guide/contributing.md + - Code Style: Developer Guide/code-style.md + - Creating Plugins: Developer Guide/plugins.md + - API Development: + - REST API: Developer Guide/rest-api.md + - ETAPI: Developer Guide/etapi.md + - WebSocket API: Developer Guide/websocket.md + + - Release Notes: + - Latest Release: Release Notes/latest.md + - Version History: Release Notes/history.md + - Migration Guides: Release Notes/migration.md + + - Translations: + - Español: README.es.md + - Italiano: README.it.md + - 日本語: README.ja.md + - Русский: README.ru.md + - 简体中文: README-ZH_CN.md + - 繁體中文: README-ZH_TW.md + + - Support: + - FAQ: support/faq.md + - Troubleshooting: support/troubleshooting.md + - Community: support/community.md + - Issue Tracker: https://github.com/zadam/trilium/issues diff --git a/requirements-docs.txt b/requirements-docs.txt new file mode 100644 index 000000000..dcb76d80b --- /dev/null +++ b/requirements-docs.txt @@ -0,0 +1,20 @@ +# MkDocs and Material theme requirements for Trilium documentation +mkdocs>=1.6.0 +mkdocs-material>=9.5.0 +mkdocs-material-extensions>=1.3.0 + +# Essential plugins +mkdocs-minify-plugin>=0.8.0 +mkdocs-git-revision-date-localized-plugin>=1.2.0 + +# Optional but recommended plugins +mkdocs-redirects>=1.2.0 +mkdocs-rss-plugin>=1.12.0 +mkdocs-glightbox>=0.3.0 + +# For advanced features +pillow>=10.0.0 # For social cards generation +cairosvg>=2.7.0 # For social cards with SVG support + +# Search enhancements +mkdocs-material[imaging]>=9.5.0 \ No newline at end of file From fcd2409ee35a4092e56a5d3bc9661e41465cc08c Mon Sep 17 00:00:00 2001 From: perf3ct Date: Thu, 4 Sep 2025 21:20:01 +0000 Subject: [PATCH 02/13] feat(docs): try to get mkdocs to work again --- .github/workflows/deploy-docs.yml | 8 ++ docs/README.md | 12 +++ mkdocs.yml | 145 ++++++++++++++---------------- 3 files changed, 89 insertions(+), 76 deletions(-) create mode 100644 docs/README.md diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 25b04d1d7..3a1342f56 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -86,6 +86,12 @@ jobs: test -d site/assets || (echo "ERROR: site/assets directory not found" && exit 1) echo "✅ Site validation passed" + # Setup Node.js for Wrangler + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + # Deploy using Wrangler (recommended by Cloudflare) - name: Deploy to Cloudflare Pages id: deploy @@ -95,6 +101,7 @@ jobs: apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} command: pages deploy site --project-name=trilium-docs --branch=${{ github.ref_name }} + packageManager: npm # Explicitly use npm instead of pnpm # Deploy preview for PRs - name: Deploy Preview to Cloudflare Pages @@ -105,6 +112,7 @@ jobs: apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} command: pages deploy site --project-name=trilium-docs --branch=pr-${{ github.event.pull_request.number }} + packageManager: npm # Explicitly use npm instead of pnpm # Post deployment URL as PR comment - name: Comment PR with Preview URL diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..5675758ee --- /dev/null +++ b/docs/README.md @@ -0,0 +1,12 @@ +# Trilium Notes + +Please see the [main documentation](index.md) or visit one of our translated versions: + +- [Español](README.es.md) +- [Italiano](README.it.md) +- [日本語](README.ja.md) +- [Русский](README.ru.md) +- [简体中文](README-ZH_CN.md) +- [繁體中文](README-ZH_TW.md) + +For the full application README, please visit our [GitHub repository](https://github.com/triliumnext/trilium). \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index ecde11abb..d000e4de9 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -178,90 +178,85 @@ extra: provider: mike default: stable -# Navigation structure based on existing documentation +# Navigation structure matching actual file paths nav: - Home: index.md + - Introduction: README.md - Getting Started: - - Introduction: README.md + - Quick Start: User Guide/User Guide/Quick Start.md - Installation: - - Desktop Installation: User Guide/installation.md - - Server Installation: User Guide/server-installation.md - - Docker Installation: User Guide/docker.md - - Mobile Access: User Guide/mobile-frontend.md - - Quick Start Guide: User Guide/quick-start.md + - Desktop Installation: User Guide/User Guide/Installation & Setup/Desktop Installation.md + - Server Installation: User Guide/User Guide/Installation & Setup/Server Installation.md + - Docker: User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Using Docker.md + - Mobile Frontend: User Guide/User Guide/Installation & Setup/Mobile Frontend.md - User Guide: - - Overview: User Guide/index.md + - Overview: User Guide/User Guide.md + - Feature Highlights: User Guide/User Guide/Feature Highlights.md - Basic Concepts: - - Notes & Branches: User Guide/notes-and-branches.md - - Note Types: User Guide/note-types.md - - Attributes: User Guide/attributes.md - - Relations: User Guide/relations.md - - Features: - - Note Editor: User Guide/note-editor.md - - Search: User Guide/search.md - - Note Map: User Guide/note-map.md - - Day Notes: User Guide/day-notes.md - - Book Notes: User Guide/book-notes.md - - Templates: User Guide/templates.md - - Cloning Notes: User Guide/cloning-notes.md - - Protected Notes: User Guide/protected-notes.md - - Note Revisions: User Guide/note-revisions.md - - Synchronization: User Guide/synchronization.md - - Advanced Features: - - Scripting: User Guide/scripting.md - - Themes: User Guide/themes.md - - Keyboard Shortcuts: User Guide/keyboard-shortcuts.md - - Web Clipper: User Guide/web-clipper.md - - Import & Export: User Guide/import-export.md - - Backup: User Guide/backup.md - - Configuration: User Guide/configuration.md - - - Script API: - - Overview: Script API/index.md - - Backend API: - - Overview: Script API/backend/index.md - - BNote: Script API/backend/BNote.md - - BBranch: Script API/backend/BBranch.md - - BAttribute: Script API/backend/BAttribute.md - - BackendScriptApi: Script API/backend/BackendScriptApi.md - - SQL API: Script API/backend/sql.md - - Frontend API: - - Overview: Script API/frontend/index.md - - FNote: Script API/frontend/FNote.md - - FBranch: Script API/frontend/FBranch.md - - FAttribute: Script API/frontend/FAttribute.md - - FrontendScriptApi: Script API/frontend/FrontendScriptApi.md - - Examples: - - Script Examples: Script API/examples.md - - Custom Widgets: Script API/custom-widgets.md - - Event Handlers: Script API/event-handlers.md + - Notes: User Guide/User Guide/Basic Concepts and Features/Notes.md + - Keyboard Shortcuts: User Guide/User Guide/Basic Concepts and Features/Keyboard Shortcuts.md + - Themes: User Guide/User Guide/Basic Concepts and Features/Themes.md + - Zen Mode: User Guide/User Guide/Basic Concepts and Features/Zen mode.md + - Navigation: + - Search: User Guide/User Guide/Basic Concepts and Features/Navigation/Search.md + - Quick Search: User Guide/User Guide/Basic Concepts and Features/Navigation/Quick search.md + - Tree Concepts: User Guide/User Guide/Basic Concepts and Features/Navigation/Tree Concepts.md + - Note Navigation: User Guide/User Guide/Basic Concepts and Features/Navigation/Note Navigation.md + - Bookmarks: User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks.md + - Workspaces: User Guide/User Guide/Basic Concepts and Features/Navigation/Workspaces.md + - Note Types: + - Overview: User Guide/User Guide/Note Types.md + - Text: User Guide/User Guide/Note Types/Text.md + - Code: User Guide/User Guide/Note Types/Code.md + - Canvas: User Guide/User Guide/Note Types/Canvas.md + - File: User Guide/User Guide/Note Types/File.md + - Mermaid Diagrams: User Guide/User Guide/Note Types/Mermaid Diagrams.md + - Mind Map: User Guide/User Guide/Note Types/Mind Map.md + - Collections: User Guide/User Guide/Note Types/Collections.md + - Advanced Usage: + - Attributes: User Guide/User Guide/Advanced Usage/Attributes.md + - Templates: User Guide/User Guide/Advanced Usage/Templates.md + - Sharing: User Guide/User Guide/Advanced Usage/Sharing.md + - Database: User Guide/User Guide/Advanced Usage/Database.md + - ETAPI: User Guide/User Guide/Advanced Usage/ETAPI (REST API).md + - Installation & Setup: + - Backup: User Guide/User Guide/Installation & Setup/Backup.md + - Synchronization: User Guide/User Guide/Installation & Setup/Synchronization.md + - Web Clipper: User Guide/User Guide/Installation & Setup/Web Clipper.md + - Data Directory: User Guide/User Guide/Installation & Setup/Data directory.md + - Scripting: + - Overview: User Guide/User Guide/Scripting.md + - Script API: User Guide/User Guide/Scripting/Script API.md + - Custom Widgets: User Guide/User Guide/Scripting/Custom Widgets.md + - Events: User Guide/User Guide/Scripting/Events.md + - Troubleshooting: + - Overview: User Guide/User Guide/Troubleshooting.md + - Error Logs: User Guide/User Guide/Troubleshooting/Error logs.md + - FAQ: User Guide/User Guide/FAQ.md - Developer Guide: - - Overview: Developer Guide/index.md - - Architecture: - - Project Structure: Developer Guide/architecture.md - - Database Schema: Developer Guide/database.md - - Entity System: Developer Guide/entities.md - - Cache System: Developer Guide/cache-system.md - - Development Setup: - - Local Development: Developer Guide/development.md - - Building from Source: Developer Guide/build.md - - Testing: Developer Guide/testing.md - - Contributing: - - Contribution Guide: Developer Guide/contributing.md - - Code Style: Developer Guide/code-style.md - - Creating Plugins: Developer Guide/plugins.md - - API Development: - - REST API: Developer Guide/rest-api.md - - ETAPI: Developer Guide/etapi.md - - WebSocket API: Developer Guide/websocket.md + - Environment Setup: Developer Guide/Developer Guide/Environment Setup.md + - Project Structure: Developer Guide/Developer Guide/Project Structure.md + - Development: + - Icons: Developer Guide/Developer Guide/Development and architecture/Icons.md + - Options: Developer Guide/Developer Guide/Development and architecture/Options.md + - Themes: Developer Guide/Developer Guide/Development and architecture/Themes.md + - Database Tables: + - Notes: Developer Guide/Developer Guide/Development and architecture/Database/notes.md + - Attributes: Developer Guide/Developer Guide/Development and architecture/Database/attributes.md + - Branches: Developer Guide/Developer Guide/Development and architecture/Database/branches.md + + - Script API Documentation: + - API Reference: Script API/index.html - Release Notes: - - Latest Release: Release Notes/latest.md - - Version History: Release Notes/history.md - - Migration Guides: Release Notes/migration.md + - v0.98.1: Release Notes/Release Notes/v0.98.1.md + - v0.98.0: Release Notes/Release Notes/v0.98.0.md + - v0.97.2: Release Notes/Release Notes/v0.97.2.md + - v0.97.1: Release Notes/Release Notes/v0.97.1.md + - v0.97.0: Release Notes/Release Notes/v0.97.0.md - Translations: - Español: README.es.md @@ -272,7 +267,5 @@ nav: - 繁體中文: README-ZH_TW.md - Support: - - FAQ: support/faq.md - - Troubleshooting: support/troubleshooting.md - - Community: support/community.md - - Issue Tracker: https://github.com/zadam/trilium/issues + - GitHub Issues: https://github.com/triliumnext/trilium/issues + - Discussions: https://github.com/triliumnext/trilium/discussions From b6212c4e98499468cbfaf13e6460fe50800fd722 Mon Sep 17 00:00:00 2001 From: perf3ct Date: Thu, 4 Sep 2025 21:28:03 +0000 Subject: [PATCH 03/13] feat(docs): try to get wrangler to work... feat(docs)asdf asdf --- .github/workflows/deploy-docs.yml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 3a1342f56..aee24150f 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -86,13 +86,18 @@ jobs: test -d site/assets || (echo "ERROR: site/assets directory not found" && exit 1) echo "✅ Site validation passed" - # Setup Node.js for Wrangler + # Setup pnpm + - name: Setup pnpm + uses: pnpm/action-setup@v4 + + # Setup Node.js with pnpm - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' + cache: 'pnpm' - # Deploy using Wrangler (recommended by Cloudflare) + # Deploy using Wrangler (with pnpm) - name: Deploy to Cloudflare Pages id: deploy if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' @@ -101,7 +106,7 @@ jobs: apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} command: pages deploy site --project-name=trilium-docs --branch=${{ github.ref_name }} - packageManager: npm # Explicitly use npm instead of pnpm + packageManager: pnpm # Deploy preview for PRs - name: Deploy Preview to Cloudflare Pages @@ -112,7 +117,7 @@ jobs: apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} command: pages deploy site --project-name=trilium-docs --branch=pr-${{ github.event.pull_request.number }} - packageManager: npm # Explicitly use npm instead of pnpm + packageManager: pnpm # Post deployment URL as PR comment - name: Comment PR with Preview URL @@ -156,4 +161,4 @@ jobs: repo: context.repo.repo, body: commentBody }); - } \ No newline at end of file + } From 33c8406b8ae62c36006de98bcfeef0ca0c916952 Mon Sep 17 00:00:00 2001 From: perf3ct Date: Thu, 4 Sep 2025 21:39:07 +0000 Subject: [PATCH 04/13] feat(docs): try to make pnpm happy for mkdocs asfd asdf --- .github/workflows/deploy-docs.yml | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index aee24150f..e1fc45cf0 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -86,7 +86,7 @@ jobs: test -d site/assets || (echo "ERROR: site/assets directory not found" && exit 1) echo "✅ Site validation passed" - # Setup pnpm + # Setup pnpm - name: Setup pnpm uses: pnpm/action-setup@v4 @@ -97,7 +97,12 @@ jobs: node-version: '20' cache: 'pnpm' - # Deploy using Wrangler (with pnpm) + # Install wrangler globally to avoid workspace issues + - name: Install Wrangler + run: | + npm install -g wrangler + + # Deploy using Wrangler (use pre-installed wrangler) - name: Deploy to Cloudflare Pages id: deploy if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' @@ -105,8 +110,8 @@ jobs: with: apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} - command: pages deploy site --project-name=trilium-docs --branch=${{ github.ref_name }} - packageManager: pnpm + command: pages deploy site --project-name=triliumnext-pages --branch=${{ github.ref_name }} + wranglerVersion: '' # Use pre-installed version # Deploy preview for PRs - name: Deploy Preview to Cloudflare Pages @@ -116,8 +121,8 @@ jobs: with: apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} - command: pages deploy site --project-name=trilium-docs --branch=pr-${{ github.event.pull_request.number }} - packageManager: pnpm + command: pages deploy site --project-name=triliumnext-pages --branch=pr-${{ github.event.pull_request.number }} + wranglerVersion: '' # Use pre-installed version # Post deployment URL as PR comment - name: Comment PR with Preview URL From 791869ca9e83c0b87a4a9501fd003b75ff2749c7 Mon Sep 17 00:00:00 2001 From: perf3ct Date: Thu, 4 Sep 2025 23:30:20 +0000 Subject: [PATCH 05/13] feat(docs): try to capture all pages --- .gitignore | 5 ++- docs/.pages | 8 ++++ mkdocs.yml | 99 ++++--------------------------------------- requirements-docs.txt | 1 + 4 files changed, 21 insertions(+), 92 deletions(-) create mode 100644 docs/.pages diff --git a/.gitignore b/.gitignore index 66e9781f9..b2c4e3c46 100644 --- a/.gitignore +++ b/.gitignore @@ -45,4 +45,7 @@ upload *.tsbuildinfo /result -.svelte-kit \ No newline at end of file +.svelte-kit + +# docs +site/ diff --git a/docs/.pages b/docs/.pages new file mode 100644 index 000000000..276a4015a --- /dev/null +++ b/docs/.pages @@ -0,0 +1,8 @@ +# Control navigation order for top-level sections +nav: + - index.md + - User Guide + - Developer Guide + - Script API + - Release Notes + - ... # Include all other directories/files not explicitly listed \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index d000e4de9..03940176d 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -78,6 +78,12 @@ plugins: separator: '[\s\-,:!=\[\]()"`/]+|\.(?!\d)|&[lg]t;|(?!\b)(?=[A-Z][a-z])' lang: - en + - awesome-pages: + collapse_single_pages: false + strict: false + order: asc + sort_type: natural + order_by: title - minify: minify_html: true minify_js: true @@ -178,94 +184,5 @@ extra: provider: mike default: stable -# Navigation structure matching actual file paths -nav: - - Home: index.md - - Introduction: README.md - - - Getting Started: - - Quick Start: User Guide/User Guide/Quick Start.md - - Installation: - - Desktop Installation: User Guide/User Guide/Installation & Setup/Desktop Installation.md - - Server Installation: User Guide/User Guide/Installation & Setup/Server Installation.md - - Docker: User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Using Docker.md - - Mobile Frontend: User Guide/User Guide/Installation & Setup/Mobile Frontend.md - - - User Guide: - - Overview: User Guide/User Guide.md - - Feature Highlights: User Guide/User Guide/Feature Highlights.md - - Basic Concepts: - - Notes: User Guide/User Guide/Basic Concepts and Features/Notes.md - - Keyboard Shortcuts: User Guide/User Guide/Basic Concepts and Features/Keyboard Shortcuts.md - - Themes: User Guide/User Guide/Basic Concepts and Features/Themes.md - - Zen Mode: User Guide/User Guide/Basic Concepts and Features/Zen mode.md - - Navigation: - - Search: User Guide/User Guide/Basic Concepts and Features/Navigation/Search.md - - Quick Search: User Guide/User Guide/Basic Concepts and Features/Navigation/Quick search.md - - Tree Concepts: User Guide/User Guide/Basic Concepts and Features/Navigation/Tree Concepts.md - - Note Navigation: User Guide/User Guide/Basic Concepts and Features/Navigation/Note Navigation.md - - Bookmarks: User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks.md - - Workspaces: User Guide/User Guide/Basic Concepts and Features/Navigation/Workspaces.md - - Note Types: - - Overview: User Guide/User Guide/Note Types.md - - Text: User Guide/User Guide/Note Types/Text.md - - Code: User Guide/User Guide/Note Types/Code.md - - Canvas: User Guide/User Guide/Note Types/Canvas.md - - File: User Guide/User Guide/Note Types/File.md - - Mermaid Diagrams: User Guide/User Guide/Note Types/Mermaid Diagrams.md - - Mind Map: User Guide/User Guide/Note Types/Mind Map.md - - Collections: User Guide/User Guide/Note Types/Collections.md - - Advanced Usage: - - Attributes: User Guide/User Guide/Advanced Usage/Attributes.md - - Templates: User Guide/User Guide/Advanced Usage/Templates.md - - Sharing: User Guide/User Guide/Advanced Usage/Sharing.md - - Database: User Guide/User Guide/Advanced Usage/Database.md - - ETAPI: User Guide/User Guide/Advanced Usage/ETAPI (REST API).md - - Installation & Setup: - - Backup: User Guide/User Guide/Installation & Setup/Backup.md - - Synchronization: User Guide/User Guide/Installation & Setup/Synchronization.md - - Web Clipper: User Guide/User Guide/Installation & Setup/Web Clipper.md - - Data Directory: User Guide/User Guide/Installation & Setup/Data directory.md - - Scripting: - - Overview: User Guide/User Guide/Scripting.md - - Script API: User Guide/User Guide/Scripting/Script API.md - - Custom Widgets: User Guide/User Guide/Scripting/Custom Widgets.md - - Events: User Guide/User Guide/Scripting/Events.md - - Troubleshooting: - - Overview: User Guide/User Guide/Troubleshooting.md - - Error Logs: User Guide/User Guide/Troubleshooting/Error logs.md - - FAQ: User Guide/User Guide/FAQ.md - - - Developer Guide: - - Environment Setup: Developer Guide/Developer Guide/Environment Setup.md - - Project Structure: Developer Guide/Developer Guide/Project Structure.md - - Development: - - Icons: Developer Guide/Developer Guide/Development and architecture/Icons.md - - Options: Developer Guide/Developer Guide/Development and architecture/Options.md - - Themes: Developer Guide/Developer Guide/Development and architecture/Themes.md - - Database Tables: - - Notes: Developer Guide/Developer Guide/Development and architecture/Database/notes.md - - Attributes: Developer Guide/Developer Guide/Development and architecture/Database/attributes.md - - Branches: Developer Guide/Developer Guide/Development and architecture/Database/branches.md - - - Script API Documentation: - - API Reference: Script API/index.html - - - Release Notes: - - v0.98.1: Release Notes/Release Notes/v0.98.1.md - - v0.98.0: Release Notes/Release Notes/v0.98.0.md - - v0.97.2: Release Notes/Release Notes/v0.97.2.md - - v0.97.1: Release Notes/Release Notes/v0.97.1.md - - v0.97.0: Release Notes/Release Notes/v0.97.0.md - - - Translations: - - Español: README.es.md - - Italiano: README.it.md - - 日本語: README.ja.md - - Русский: README.ru.md - - 简体中文: README-ZH_CN.md - - 繁體中文: README-ZH_TW.md - - - Support: - - GitHub Issues: https://github.com/triliumnext/trilium/issues - - Discussions: https://github.com/triliumnext/trilium/discussions +# Navigation is automatically generated from folder structure by awesome-pages plugin +# To customize order or titles, create .pages files in directories \ No newline at end of file diff --git a/requirements-docs.txt b/requirements-docs.txt index dcb76d80b..a7fa25aec 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -4,6 +4,7 @@ mkdocs-material>=9.5.0 mkdocs-material-extensions>=1.3.0 # Essential plugins +mkdocs-awesome-pages-plugin>=2.9.0 # Auto-generate navigation from folder structure mkdocs-minify-plugin>=0.8.0 mkdocs-git-revision-date-localized-plugin>=1.2.0 From 444beb4908aa924790597b0ac1e8b6ca0d588ee2 Mon Sep 17 00:00:00 2001 From: perf3ct Date: Thu, 4 Sep 2025 23:39:40 +0000 Subject: [PATCH 06/13] feat(docs): get images to work now --- mkdocs.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mkdocs.yml b/mkdocs.yml index 03940176d..68cf7c30b 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -12,6 +12,9 @@ edit_uri: edit/main/docs/ # Copyright copyright: Copyright © 2025 Trilium Notes +# Use document-style URLs to fix image paths +use_directory_urls: false + # Theme configuration theme: name: material From 7ca21b52a08d492ae1e74cfd74c09508c7a721f6 Mon Sep 17 00:00:00 2001 From: perf3ct Date: Thu, 4 Sep 2025 23:46:50 +0000 Subject: [PATCH 07/13] feat(docs): fix references to zadam --- mkdocs.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index 68cf7c30b..3d787e9ed 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -157,9 +157,9 @@ extra: # Social links social: - icon: fontawesome/brands/github - link: https://github.com/zadam/trilium + link: https://github.com/triliumnext/trilium - icon: fontawesome/brands/docker - link: https://hub.docker.com/r/zadam/trilium + link: https://hub.docker.com/r/triliumnext/trilium - icon: fontawesome/solid/globe link: https://trilium.cc @@ -180,7 +180,7 @@ extra: data: 0 note: >- Thanks for your feedback! Help us improve this page by - opening an issue. + opening an issue. # Version version: @@ -188,4 +188,4 @@ extra: default: stable # Navigation is automatically generated from folder structure by awesome-pages plugin -# To customize order or titles, create .pages files in directories \ No newline at end of file +# To customize order or titles, create .pages files in directories From 1847fc2060d6fbcc561617c21c0b5a9cbc461434 Mon Sep 17 00:00:00 2001 From: perf3ct Date: Thu, 4 Sep 2025 23:50:22 +0000 Subject: [PATCH 08/13] feat(docs): fix nav and scripts --- .github/workflows/deploy-docs.yml | 5 ++ scripts/fix-mkdocs-structure.py | 140 ++++++++++++++++++++++++++++++ 2 files changed, 145 insertions(+) create mode 100644 scripts/fix-mkdocs-structure.py diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index e1fc45cf0..5639f58f2 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -62,6 +62,11 @@ jobs: env: PIP_DISABLE_PIP_VERSION_CHECK: 1 + - name: Fix Documentation Structure + run: | + # Fix duplicate navigation entries by moving overview pages to index.md + python scripts/fix-mkdocs-structure.py + - name: Build MkDocs Site run: | # Build with strict mode but allow expected warnings diff --git a/scripts/fix-mkdocs-structure.py b/scripts/fix-mkdocs-structure.py new file mode 100644 index 000000000..62af438fe --- /dev/null +++ b/scripts/fix-mkdocs-structure.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python3 +""" +Fix MkDocs structure by moving overview pages to index.md inside their directories. +This prevents duplicate navigation entries when a file and directory have the same name. +""" + +import os +import shutil +from pathlib import Path + +def fix_duplicate_entries(docs_dir): + """ + Find markdown files that have a corresponding directory with the same name, + and move them to index.md inside that directory. + """ + fixes_made = [] + + # Walk through all markdown files + for root, dirs, files in os.walk(docs_dir): + for file in files: + if file.endswith('.md'): + file_path = Path(root) / file + basename = file[:-3] # Remove .md extension + dir_path = Path(root) / basename + + # Check if there's a directory with the same name + if dir_path.exists() and dir_path.is_dir(): + # Check if index.md already exists in that directory + index_path = dir_path / 'index.md' + if not index_path.exists(): + # Move the file to index.md in the directory + shutil.move(str(file_path), str(index_path)) + fixes_made.append(f"Moved {file_path.relative_to(docs_dir)} -> {index_path.relative_to(docs_dir)}") + + # Also move any associated images + for img_file in Path(root).glob(f"{basename}_*"): + if img_file.is_file(): + img_dest = dir_path / img_file.name + shutil.move(str(img_file), str(img_dest)) + fixes_made.append(f"Moved {img_file.relative_to(docs_dir)} -> {img_dest.relative_to(docs_dir)}") + + # Also move any images that match the pattern exactly + for img_ext in ['.png', '.jpg', '.jpeg', '.gif', '.svg']: + img_file = Path(root) / f"{basename}{img_ext}" + if img_file.exists(): + img_dest = dir_path / img_file.name + shutil.move(str(img_file), str(img_dest)) + fixes_made.append(f"Moved {img_file.relative_to(docs_dir)} -> {img_dest.relative_to(docs_dir)}") + + return fixes_made + +def update_references(docs_dir): + """ + Update references in markdown files to point to the new locations. + """ + updates_made = [] + + for root, dirs, files in os.walk(docs_dir): + for file in files: + if file.endswith('.md'): + file_path = Path(root) / file + content_changed = False + + with open(file_path, 'r', encoding='utf-8') as f: + content = f.read() + original_content = content + + # Update references to moved files + # This is a simplified approach - you might need more sophisticated regex + # for complex cases + + # Look for markdown links like [text](path.md) + import re + pattern = r'\[([^\]]*)\]\(([^)]+\.md)\)' + + def fix_link(match): + text = match.group(1) + link = match.group(2) + + # If the link doesn't contain a slash, it's a local reference + if '/' not in link and not link.startswith('http'): + # Check if this might be a moved file + basename = link[:-3] # Remove .md + # If there's a directory with this name, update the link + possible_dir = Path(root) / basename + if possible_dir.exists() and possible_dir.is_dir(): + # Point to the directory (which will serve index.md) + return f'[{text}]({basename}/)' + + return match.group(0) + + content = re.sub(pattern, fix_link, content) + + if content != original_content: + with open(file_path, 'w', encoding='utf-8') as f: + f.write(content) + updates_made.append(f"Updated references in {file_path.relative_to(docs_dir)}") + + return updates_made + +def main(): + # Get the docs directory + script_dir = Path(__file__).parent + project_root = script_dir.parent + docs_dir = project_root / 'docs' + + if not docs_dir.exists(): + print(f"Error: docs directory not found at {docs_dir}") + return 1 + + print(f"Fixing MkDocs structure in {docs_dir}") + print("-" * 50) + + # Fix duplicate entries + fixes = fix_duplicate_entries(docs_dir) + if fixes: + print("Files reorganized:") + for fix in fixes: + print(f" - {fix}") + else: + print("No duplicate entries found that need fixing") + + print() + + # Update references + updates = update_references(docs_dir) + if updates: + print("References updated:") + for update in updates: + print(f" - {update}") + else: + print("No references needed updating") + + print("-" * 50) + print(f"Structure fix complete: {len(fixes)} files moved, {len(updates)} files updated") + + return 0 + +if __name__ == '__main__': + exit(main()) \ No newline at end of file From 94089113ef770a2470c94879420cd49094c804ad Mon Sep 17 00:00:00 2001 From: perf3ct Date: Thu, 4 Sep 2025 21:55:28 -0700 Subject: [PATCH 09/13] feat(docs): try to handle moved files too in script --- scripts/fix-mkdocs-structure.py | 52 ++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/scripts/fix-mkdocs-structure.py b/scripts/fix-mkdocs-structure.py index 62af438fe..2b0bd0af3 100644 --- a/scripts/fix-mkdocs-structure.py +++ b/scripts/fix-mkdocs-structure.py @@ -66,26 +66,56 @@ def update_references(docs_dir): original_content = content # Update references to moved files - # This is a simplified approach - you might need more sophisticated regex - # for complex cases - # Look for markdown links like [text](path.md) import re + from urllib.parse import unquote, quote pattern = r'\[([^\]]*)\]\(([^)]+\.md)\)' def fix_link(match): text = match.group(1) link = match.group(2) - # If the link doesn't contain a slash, it's a local reference - if '/' not in link and not link.startswith('http'): - # Check if this might be a moved file - basename = link[:-3] # Remove .md - # If there's a directory with this name, update the link - possible_dir = Path(root) / basename + # Skip external links + if link.startswith('http'): + return match.group(0) + + # Decode URL-encoded paths for processing + decoded_link = unquote(link) + + # Resolve the link path relative to current file + current_dir = Path(root) + + # For any .md link, check if there's a directory with index.md + # that should be used instead + if not decoded_link.startswith('/'): + # Resolve relative to current directory + resolved_path = (current_dir / decoded_link).resolve() + + # Check if this points to a file that should be a directory + # Remove .md extension to get the potential directory name + if resolved_path.suffix == '.md': + potential_dir = resolved_path.with_suffix('') + potential_index = potential_dir / 'index.md' + + # If a directory with index.md exists, update the link + if potential_index.exists(): + # Calculate relative path from current file to the directory + new_path = os.path.relpath(potential_dir, current_dir) + # Return link pointing to directory (MkDocs will serve index.md) + # Replace backslashes with forward slashes for consistency + new_path = new_path.replace('\\', '/') + # Re-encode spaces in the path for URL compatibility + new_path = new_path.replace(' ', '%20') + return f'[{text}]({new_path}/)' + + # Also handle local references (same directory) + elif '/' not in decoded_link: + basename = decoded_link[:-3] # Remove .md + possible_dir = current_dir / basename if possible_dir.exists() and possible_dir.is_dir(): - # Point to the directory (which will serve index.md) - return f'[{text}]({basename}/)' + # Re-encode spaces for URL compatibility + encoded_basename = basename.replace(' ', '%20') + return f'[{text}]({encoded_basename}/)' return match.group(0) From e8ca4436977ac29a2245fd9a0c5b29b249b23717 Mon Sep 17 00:00:00 2001 From: perf3ct Date: Thu, 4 Sep 2025 22:16:43 -0700 Subject: [PATCH 10/13] feat(docs): try to fix local doc links --- scripts/fix-mkdocs-structure.py | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/scripts/fix-mkdocs-structure.py b/scripts/fix-mkdocs-structure.py index 2b0bd0af3..4dea44e91 100644 --- a/scripts/fix-mkdocs-structure.py +++ b/scripts/fix-mkdocs-structure.py @@ -84,6 +84,24 @@ def update_references(docs_dir): # Resolve the link path relative to current file current_dir = Path(root) + current_file = Path(root) / file + + # Check if the current file is an index.md that was moved + # If so, we need to adjust relative paths + is_index = file == 'index.md' + + # Special case: if we're in index.md and the link starts with the parent directory name + # This happens when a file was converted to index.md and had links to siblings + if is_index and '/' in decoded_link: + path_parts = decoded_link.split('/') + # Check if first part matches the parent directory name + if path_parts[0] == current_dir.name: + # This is a self-referential path, strip the first part + fixed_link = '/'.join(path_parts[1:]) + # Re-encode spaces for URL compatibility before recursing + fixed_link_encoded = fixed_link.replace(' ', '%20') + # Recursively process the fixed link + return fix_link(re.match(pattern, f'[{text}]({fixed_link_encoded})')) # For any .md link, check if there's a directory with index.md # that should be used instead @@ -99,17 +117,26 @@ def update_references(docs_dir): # If a directory with index.md exists, update the link if potential_index.exists(): + # If we're in an index.md file and linking to a file that's now + # in a sibling directory, adjust the path + if is_index: + # Check if they share the same parent directory + if potential_dir.parent == current_dir.parent: + # It's a sibling - just use directory name + dir_name = potential_dir.name + dir_name = dir_name.replace(' ', '%20') + return f'[{text}]({dir_name}/)' + # Calculate relative path from current file to the directory new_path = os.path.relpath(potential_dir, current_dir) - # Return link pointing to directory (MkDocs will serve index.md) # Replace backslashes with forward slashes for consistency new_path = new_path.replace('\\', '/') # Re-encode spaces in the path for URL compatibility new_path = new_path.replace(' ', '%20') return f'[{text}]({new_path}/)' - # Also handle local references (same directory) - elif '/' not in decoded_link: + # Also handle local references (same directory) - should be 'if', not 'elif' + if '/' not in decoded_link: basename = decoded_link[:-3] # Remove .md possible_dir = current_dir / basename if possible_dir.exists() and possible_dir.is_dir(): From 9b0e817635abd4534cef7585d5a11afea93e5501 Mon Sep 17 00:00:00 2001 From: perf3ct Date: Fri, 5 Sep 2025 15:09:27 +0000 Subject: [PATCH 11/13] feat(docs): transition from python to ts --- .github/workflows/deploy-docs.yml | 37 ++-- scripts/fix-mkdocs-structure.ts | 308 ++++++++++++++++++++++++++++++ 2 files changed, 330 insertions(+), 15 deletions(-) create mode 100644 scripts/fix-mkdocs-structure.ts diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 5639f58f2..96e4850fc 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -14,6 +14,7 @@ on: - 'mkdocs.yml' - 'requirements-docs.txt' - '.github/workflows/deploy-docs.yml' + - 'scripts/fix-mkdocs-structure.ts' # Allow manual triggering from Actions tab workflow_dispatch: @@ -28,6 +29,7 @@ on: - 'mkdocs.yml' - 'requirements-docs.txt' - '.github/workflows/deploy-docs.yml' + - 'scripts/fix-mkdocs-structure.ts' jobs: build-and-deploy: @@ -62,10 +64,26 @@ jobs: env: PIP_DISABLE_PIP_VERSION_CHECK: 1 + # Setup pnpm before fixing docs structure + - name: Setup pnpm + uses: pnpm/action-setup@v4 + + # Setup Node.js with pnpm + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'pnpm' + + # Install Node.js dependencies for the TypeScript script + - name: Install Dependencies + run: | + pnpm install --frozen-lockfile + - name: Fix Documentation Structure run: | # Fix duplicate navigation entries by moving overview pages to index.md - python scripts/fix-mkdocs-structure.py + pnpm run chore:fix-mkdocs-structure - name: Build MkDocs Site run: | @@ -91,17 +109,6 @@ jobs: test -d site/assets || (echo "ERROR: site/assets directory not found" && exit 1) echo "✅ Site validation passed" - # Setup pnpm - - name: Setup pnpm - uses: pnpm/action-setup@v4 - - # Setup Node.js with pnpm - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: '20' - cache: 'pnpm' - # Install wrangler globally to avoid workspace issues - name: Install Wrangler run: | @@ -115,7 +122,7 @@ jobs: with: apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} - command: pages deploy site --project-name=triliumnext-pages --branch=${{ github.ref_name }} + command: pages deploy site --project-name=trilium-docs --branch=${{ github.ref_name }} wranglerVersion: '' # Use pre-installed version # Deploy preview for PRs @@ -126,7 +133,7 @@ jobs: with: apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} - command: pages deploy site --project-name=triliumnext-pages --branch=pr-${{ github.event.pull_request.number }} + command: pages deploy site --project-name=trilium-docs --branch=pr-${{ github.event.pull_request.number }} wranglerVersion: '' # Use pre-installed version # Post deployment URL as PR comment @@ -139,7 +146,7 @@ jobs: const prNumber = context.issue.number; // Construct preview URL based on Cloudflare Pages pattern const previewUrl = `https://pr-${prNumber}.trilium-docs.pages.dev`; - const mainUrl = 'https://docs.trilium.app'; + const mainUrl = 'https://docs.triliumnotes.org'; // Check if we already commented const comments = await github.rest.issues.listComments({ diff --git a/scripts/fix-mkdocs-structure.ts b/scripts/fix-mkdocs-structure.ts new file mode 100644 index 000000000..e0df764d6 --- /dev/null +++ b/scripts/fix-mkdocs-structure.ts @@ -0,0 +1,308 @@ +#!/usr/bin/env node +/** + * Fix MkDocs structure by moving overview pages to index.md inside their directories. + * This prevents duplicate navigation entries when a file and directory have the same name. + */ + +import * as fs from 'fs'; +import * as path from 'path'; + +interface FixResult { + message: string; +} + +/** + * Find markdown files that have a corresponding directory with the same name, + * and move them to index.md inside that directory. + */ +function fixDuplicateEntries(docsDir: string): FixResult[] { + const fixesMade: FixResult[] = []; + + function walkDir(dir: string): void { + let files: string[]; + try { + files = fs.readdirSync(dir); + } catch (err) { + console.warn(`Warning: Unable to read directory ${dir}: ${err.message}`); + return; + } + + for (const file of files) { + const filePath = path.join(dir, file); + let stat: fs.Stats; + + try { + stat = fs.statSync(filePath); + } catch (err) { + // File might have been moved already, skip it + continue; + } + + if (stat.isDirectory()) { + walkDir(filePath); + } else if (file.endsWith('.md')) { + const basename = file.slice(0, -3); // Remove .md extension + const dirPath = path.join(dir, basename); + + // Check if there's a directory with the same name + if (fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory()) { + const indexPath = path.join(dirPath, 'index.md'); + + // Check if index.md already exists in that directory + if (!fs.existsSync(indexPath)) { + // Move the file to index.md in the directory + fs.renameSync(filePath, indexPath); + fixesMade.push({ + message: `Moved ${path.relative(docsDir, filePath)} -> ${path.relative(docsDir, indexPath)}` + }); + + // Move associated images with pattern basename_* + try { + const dirFiles = fs.readdirSync(dir); + for (const imgFile of dirFiles) { + if (imgFile.startsWith(`${basename}_`)) { + const imgSrc = path.join(dir, imgFile); + try { + if (!fs.statSync(imgSrc).isDirectory()) { + const imgDest = path.join(dirPath, imgFile); + fs.renameSync(imgSrc, imgDest); + fixesMade.push({ + message: `Moved ${path.relative(docsDir, imgSrc)} -> ${path.relative(docsDir, imgDest)}` + }); + } + } catch (err) { + // File might have been moved already, skip it + } + } + } + } catch (err) { + // Directory might not exist anymore, skip it + } + + // Move exact match images + const imgExtensions = ['.png', '.jpg', '.jpeg', '.gif', '.svg']; + for (const ext of imgExtensions) { + const imgFile = path.join(dir, `${basename}${ext}`); + if (fs.existsSync(imgFile)) { + const imgDest = path.join(dirPath, `${basename}${ext}`); + fs.renameSync(imgFile, imgDest); + fixesMade.push({ + message: `Moved ${path.relative(docsDir, imgFile)} -> ${path.relative(docsDir, imgDest)}` + }); + } + } + } + } + } + } + } + + walkDir(docsDir); + return fixesMade; +} + +/** + * Update references in markdown files to point to the new locations. + */ +function updateReferences(docsDir: string): FixResult[] { + const updatesMade: FixResult[] = []; + + function fixLink(match: string, text: string, link: string, currentDir: string, isIndex: boolean): string { + // Skip external links + if (link.startsWith('http')) { + return match; + } + + // Decode URL-encoded paths for processing + // Use decodeURIComponent which is equivalent to Python's unquote + let decodedLink: string; + try { + decodedLink = decodeURIComponent(link); + } catch (err) { + // If decoding fails, use the original link + decodedLink = link; + } + + // Special case: if we're in index.md and the link starts with the parent directory name + if (isIndex && decodedLink.includes('/')) { + const pathParts = decodedLink.split('/'); + const parentDirName = path.basename(currentDir); + + // Check if first part matches the parent directory name + if (pathParts[0] === parentDirName) { + // This is a self-referential path, strip the first part + const fixedLink = pathParts.slice(1).join('/'); + // Continue processing with the fixed link + const decodedFixedLink = fixedLink; + + // Check if this fixed link points to a directory with index.md + if (!decodedFixedLink.startsWith('/')) { + const resolvedPath = path.resolve(currentDir, decodedFixedLink); + + if (resolvedPath.endsWith('.md')) { + const potentialDir = resolvedPath.slice(0, -3); + const potentialIndex = path.join(potentialDir, 'index.md'); + + if (fs.existsSync(potentialIndex)) { + // Check if they share the same parent directory + if (path.dirname(potentialDir) === path.dirname(currentDir)) { + // It's a sibling - just use directory name + const dirName = path.basename(potentialDir).replace(/ /g, '%20'); + return `[${text}](${dirName}/)`; + } + + // Calculate relative path from current file to the directory + const newPath = path.relative(currentDir, potentialDir).replace(/\\/g, '/').replace(/ /g, '%20'); + return `[${text}](${newPath}/)`; + } + } + } + + // If no special handling needed for the fixed link, return it as-is + const fixedLinkEncoded = fixedLink.replace(/ /g, '%20'); + return `[${text}](${fixedLinkEncoded})`; + } + } + + // For any .md link, check if there's a directory with index.md + if (!decodedLink.startsWith('/')) { + const resolvedPath = path.resolve(currentDir, decodedLink); + + // Check if this points to a file that should be a directory + if (resolvedPath.endsWith('.md')) { + const potentialDir = resolvedPath.slice(0, -3); + const potentialIndex = path.join(potentialDir, 'index.md'); + + // If a directory with index.md exists, update the link + if (fs.existsSync(potentialIndex)) { + if (isIndex) { + // Check if they share the same parent directory + if (path.dirname(potentialDir) === path.dirname(currentDir)) { + // It's a sibling - just use directory name + const dirName = path.basename(potentialDir).replace(/ /g, '%20'); + return `[${text}](${dirName}/)`; + } + } + + // Calculate relative path from current file to the directory + const newPath = path.relative(currentDir, potentialDir).replace(/\\/g, '/').replace(/ /g, '%20'); + return `[${text}](${newPath}/)`; + } + } + } + + // Also handle local references (same directory) - should be 'if', not 'elif' + // This is intentional to handle both absolute and relative paths + if (!decodedLink.includes('/')) { + const basename = decodedLink.slice(0, -3); // Remove .md + const possibleDir = path.join(currentDir, basename); + + if (fs.existsSync(possibleDir) && fs.statSync(possibleDir).isDirectory()) { + const encodedBasename = basename.replace(/ /g, '%20'); + return `[${text}](${encodedBasename}/)`; + } + } + + return match; + } + + function walkDir(dir: string): void { + let files: string[]; + try { + files = fs.readdirSync(dir); + } catch (err) { + console.warn(`Warning: Unable to read directory ${dir}: ${err.message}`); + return; + } + + for (const file of files) { + const filePath = path.join(dir, file); + let stat: fs.Stats; + + try { + stat = fs.statSync(filePath); + } catch (err) { + // File might have been moved already, skip it + continue; + } + + if (stat.isDirectory()) { + walkDir(filePath); + } else if (file.endsWith('.md')) { + let content = fs.readFileSync(filePath, 'utf-8'); + const originalContent = content; + + const isIndex = file === 'index.md'; + const currentDir = path.dirname(filePath); + + // Update markdown links: [text](path.md) + const pattern = /\[([^\]]*)\]\(([^)]+\.md)\)/g; + content = content.replace(pattern, (match, text, link) => { + return fixLink(match, text, link, currentDir, isIndex); + }); + + if (content !== originalContent) { + fs.writeFileSync(filePath, content, 'utf-8'); + updatesMade.push({ + message: `Updated references in ${path.relative(docsDir, filePath)}` + }); + } + } + } + } + + walkDir(docsDir); + return updatesMade; +} + +function main(): number { + // Get the docs directory + const scriptDir = path.dirname(new URL(import.meta.url).pathname); + const projectRoot = path.dirname(scriptDir); + const docsDir = path.join(projectRoot, 'docs'); + + // Handle Windows paths (remove leading slash if on Windows) + const normalizedDocsDir = process.platform === 'win32' && docsDir.startsWith('/') + ? docsDir.substring(1) + : docsDir; + + if (!fs.existsSync(normalizedDocsDir)) { + console.error(`Error: docs directory not found at ${normalizedDocsDir}`); + return 1; + } + + console.log(`Fixing MkDocs structure in ${normalizedDocsDir}`); + console.log('-'.repeat(50)); + + // Fix duplicate entries + const fixes = fixDuplicateEntries(normalizedDocsDir); + if (fixes.length > 0) { + console.log('Files reorganized:'); + for (const fix of fixes) { + console.log(` - ${fix.message}`); + } + } else { + console.log('No duplicate entries found that need fixing'); + } + + console.log(); + + // Update references + const updates = updateReferences(normalizedDocsDir); + if (updates.length > 0) { + console.log('References updated:'); + for (const update of updates) { + console.log(` - ${update.message}`); + } + } else { + console.log('No references needed updating'); + } + + console.log('-'.repeat(50)); + console.log(`Structure fix complete: ${fixes.length} files moved, ${updates.length} files updated`); + + return 0; +} + +// Run the main function +process.exit(main()); \ No newline at end of file From 667cfb999bc32e2084a5e08b1811e58ed2fc717b Mon Sep 17 00:00:00 2001 From: perf3ct Date: Fri, 5 Sep 2025 15:11:48 +0000 Subject: [PATCH 12/13] feat(docs): oops forgot to add it to the package.json --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 6eafcf347..5b3d3c3f1 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "chore:generate-openapi": "tsx ./scripts/generate-openapi.ts", "chore:update-build-info": "tsx ./scripts/update-build-info.ts", "chore:update-version": "tsx ./scripts/update-version.ts", + "chore:fix-mkdocs-structure": "tsx ./scripts/fix-mkdocs-structure.ts", "edit-docs:edit-docs": "pnpm run --filter edit-docs edit-docs", "edit-docs:edit-demo": "pnpm run --filter edit-docs edit-demo", "test:all": "pnpm test:parallel && pnpm test:sequential", From 5c1595b1fdffb1da65ee2c4be8c044a614781344 Mon Sep 17 00:00:00 2001 From: perf3ct Date: Fri, 5 Sep 2025 15:15:12 +0000 Subject: [PATCH 13/13] feat(docs): remove unused python --- scripts/fix-mkdocs-structure.py | 197 -------------------------------- 1 file changed, 197 deletions(-) delete mode 100644 scripts/fix-mkdocs-structure.py diff --git a/scripts/fix-mkdocs-structure.py b/scripts/fix-mkdocs-structure.py deleted file mode 100644 index 4dea44e91..000000000 --- a/scripts/fix-mkdocs-structure.py +++ /dev/null @@ -1,197 +0,0 @@ -#!/usr/bin/env python3 -""" -Fix MkDocs structure by moving overview pages to index.md inside their directories. -This prevents duplicate navigation entries when a file and directory have the same name. -""" - -import os -import shutil -from pathlib import Path - -def fix_duplicate_entries(docs_dir): - """ - Find markdown files that have a corresponding directory with the same name, - and move them to index.md inside that directory. - """ - fixes_made = [] - - # Walk through all markdown files - for root, dirs, files in os.walk(docs_dir): - for file in files: - if file.endswith('.md'): - file_path = Path(root) / file - basename = file[:-3] # Remove .md extension - dir_path = Path(root) / basename - - # Check if there's a directory with the same name - if dir_path.exists() and dir_path.is_dir(): - # Check if index.md already exists in that directory - index_path = dir_path / 'index.md' - if not index_path.exists(): - # Move the file to index.md in the directory - shutil.move(str(file_path), str(index_path)) - fixes_made.append(f"Moved {file_path.relative_to(docs_dir)} -> {index_path.relative_to(docs_dir)}") - - # Also move any associated images - for img_file in Path(root).glob(f"{basename}_*"): - if img_file.is_file(): - img_dest = dir_path / img_file.name - shutil.move(str(img_file), str(img_dest)) - fixes_made.append(f"Moved {img_file.relative_to(docs_dir)} -> {img_dest.relative_to(docs_dir)}") - - # Also move any images that match the pattern exactly - for img_ext in ['.png', '.jpg', '.jpeg', '.gif', '.svg']: - img_file = Path(root) / f"{basename}{img_ext}" - if img_file.exists(): - img_dest = dir_path / img_file.name - shutil.move(str(img_file), str(img_dest)) - fixes_made.append(f"Moved {img_file.relative_to(docs_dir)} -> {img_dest.relative_to(docs_dir)}") - - return fixes_made - -def update_references(docs_dir): - """ - Update references in markdown files to point to the new locations. - """ - updates_made = [] - - for root, dirs, files in os.walk(docs_dir): - for file in files: - if file.endswith('.md'): - file_path = Path(root) / file - content_changed = False - - with open(file_path, 'r', encoding='utf-8') as f: - content = f.read() - original_content = content - - # Update references to moved files - # Look for markdown links like [text](path.md) - import re - from urllib.parse import unquote, quote - pattern = r'\[([^\]]*)\]\(([^)]+\.md)\)' - - def fix_link(match): - text = match.group(1) - link = match.group(2) - - # Skip external links - if link.startswith('http'): - return match.group(0) - - # Decode URL-encoded paths for processing - decoded_link = unquote(link) - - # Resolve the link path relative to current file - current_dir = Path(root) - current_file = Path(root) / file - - # Check if the current file is an index.md that was moved - # If so, we need to adjust relative paths - is_index = file == 'index.md' - - # Special case: if we're in index.md and the link starts with the parent directory name - # This happens when a file was converted to index.md and had links to siblings - if is_index and '/' in decoded_link: - path_parts = decoded_link.split('/') - # Check if first part matches the parent directory name - if path_parts[0] == current_dir.name: - # This is a self-referential path, strip the first part - fixed_link = '/'.join(path_parts[1:]) - # Re-encode spaces for URL compatibility before recursing - fixed_link_encoded = fixed_link.replace(' ', '%20') - # Recursively process the fixed link - return fix_link(re.match(pattern, f'[{text}]({fixed_link_encoded})')) - - # For any .md link, check if there's a directory with index.md - # that should be used instead - if not decoded_link.startswith('/'): - # Resolve relative to current directory - resolved_path = (current_dir / decoded_link).resolve() - - # Check if this points to a file that should be a directory - # Remove .md extension to get the potential directory name - if resolved_path.suffix == '.md': - potential_dir = resolved_path.with_suffix('') - potential_index = potential_dir / 'index.md' - - # If a directory with index.md exists, update the link - if potential_index.exists(): - # If we're in an index.md file and linking to a file that's now - # in a sibling directory, adjust the path - if is_index: - # Check if they share the same parent directory - if potential_dir.parent == current_dir.parent: - # It's a sibling - just use directory name - dir_name = potential_dir.name - dir_name = dir_name.replace(' ', '%20') - return f'[{text}]({dir_name}/)' - - # Calculate relative path from current file to the directory - new_path = os.path.relpath(potential_dir, current_dir) - # Replace backslashes with forward slashes for consistency - new_path = new_path.replace('\\', '/') - # Re-encode spaces in the path for URL compatibility - new_path = new_path.replace(' ', '%20') - return f'[{text}]({new_path}/)' - - # Also handle local references (same directory) - should be 'if', not 'elif' - if '/' not in decoded_link: - basename = decoded_link[:-3] # Remove .md - possible_dir = current_dir / basename - if possible_dir.exists() and possible_dir.is_dir(): - # Re-encode spaces for URL compatibility - encoded_basename = basename.replace(' ', '%20') - return f'[{text}]({encoded_basename}/)' - - return match.group(0) - - content = re.sub(pattern, fix_link, content) - - if content != original_content: - with open(file_path, 'w', encoding='utf-8') as f: - f.write(content) - updates_made.append(f"Updated references in {file_path.relative_to(docs_dir)}") - - return updates_made - -def main(): - # Get the docs directory - script_dir = Path(__file__).parent - project_root = script_dir.parent - docs_dir = project_root / 'docs' - - if not docs_dir.exists(): - print(f"Error: docs directory not found at {docs_dir}") - return 1 - - print(f"Fixing MkDocs structure in {docs_dir}") - print("-" * 50) - - # Fix duplicate entries - fixes = fix_duplicate_entries(docs_dir) - if fixes: - print("Files reorganized:") - for fix in fixes: - print(f" - {fix}") - else: - print("No duplicate entries found that need fixing") - - print() - - # Update references - updates = update_references(docs_dir) - if updates: - print("References updated:") - for update in updates: - print(f" - {update}") - else: - print("No references needed updating") - - print("-" * 50) - print(f"Structure fix complete: {len(fixes)} files moved, {len(updates)} files updated") - - return 0 - -if __name__ == '__main__': - exit(main()) \ No newline at end of file