Browse Source

Add Material for MkDocs Insiders features and cards (#9748)

*  Add dependencies for MkDocs Insiders

* 🙈 Add Insider's .cache to .gitignore

* 🔧 Update MkDocs configs for Insiders

* 💄 Add custom Insiders card layout, while the custom logo is provided from upstream

* 🔨 Update docs.py script to dynamically enable insiders if it's installed

* 👷 Add cache for MkDocs Material Insiders' cards

* 🔊 Add a small log to the docs CLI

* 🔊 Tweak logs, only after exporting languages

* 🐛 Fix accessing non existing env var

* 🔧 Invalidate deps cache

* 🔧 Tweak cache IDs

* 👷 Update cache for installing insiders

* 🔊 Log insiders

* 💚 Invalidate cache

* 👷 Tweak cache keys

* 👷 Trigger CI and test cache

* 🔥 Remove cache comment

* ️ Optimize cache usage for first runs of docs

* 👷 Tweak cache for MkDocs Material cards

* 💚 Trigger CI to test cache
pull/9749/head
Sebastián Ramírez 2 years ago
committed by GitHub
parent
commit
ed297bb2e0
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 12
      .github/workflows/build-docs.yml
  2. 1
      .gitignore
  3. 228
      docs/en/layouts/custom.yml
  4. 7
      docs/en/mkdocs.insiders.yml
  5. 3
      docs/en/mkdocs.maybe-insiders.yml
  6. 0
      docs/en/mkdocs.no-insiders.yml
  7. 10
      docs/en/mkdocs.yml
  8. 6
      requirements-docs.txt
  9. 20
      scripts/docs.py

12
.github/workflows/build-docs.yml

@ -44,10 +44,14 @@ jobs:
id: cache id: cache
with: with:
path: ${{ env.pythonLocation }} path: ${{ env.pythonLocation }}
key: ${{ runner.os }}-python-docs-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml', 'requirements-docs.txt') }}-v03 key: ${{ runner.os }}-python-docs-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml', 'requirements-docs.txt') }}-v05
- name: Install docs extras - name: Install docs extras
if: steps.cache.outputs.cache-hit != 'true' if: steps.cache.outputs.cache-hit != 'true'
run: pip install -r requirements-docs.txt run: pip install -r requirements-docs.txt
# Install MkDocs Material Insiders here just to put it in the cache for the rest of the steps
- name: Install Material for MkDocs Insiders
if: ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false ) && steps.cache.outputs.cache-hit != 'true'
run: pip install git+https://${{ secrets.ACTIONS_TOKEN }}@github.com/squidfunk/mkdocs-material-insiders.git
- name: Export Language Codes - name: Export Language Codes
id: show-langs id: show-langs
run: | run: |
@ -76,7 +80,7 @@ jobs:
id: cache id: cache
with: with:
path: ${{ env.pythonLocation }} path: ${{ env.pythonLocation }}
key: ${{ runner.os }}-python-docs-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml', 'requirements-docs.txt') }}-v03 key: ${{ runner.os }}-python-docs-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml', 'requirements-docs.txt') }}-v05
- name: Install docs extras - name: Install docs extras
if: steps.cache.outputs.cache-hit != 'true' if: steps.cache.outputs.cache-hit != 'true'
run: pip install -r requirements-docs.txt run: pip install -r requirements-docs.txt
@ -85,6 +89,10 @@ jobs:
run: pip install git+https://${{ secrets.ACTIONS_TOKEN }}@github.com/squidfunk/mkdocs-material-insiders.git run: pip install git+https://${{ secrets.ACTIONS_TOKEN }}@github.com/squidfunk/mkdocs-material-insiders.git
- name: Update Languages - name: Update Languages
run: python ./scripts/docs.py update-languages run: python ./scripts/docs.py update-languages
- uses: actions/cache@v3
with:
key: mkdocs-cards-${{ matrix.lang }}-${{ github.ref }}
path: docs/${{ matrix.lang }}/.cache
- name: Build Docs - name: Build Docs
run: python ./scripts/docs.py build-lang ${{ matrix.lang }} run: python ./scripts/docs.py build-lang ${{ matrix.lang }}
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v3

1
.gitignore

@ -24,3 +24,4 @@ archive.zip
# vim temporary files # vim temporary files
*~ *~
.*.sw? .*.sw?
.cache

228
docs/en/layouts/custom.yml

@ -0,0 +1,228 @@
# Copyright (c) 2016-2023 Martin Donath <[email protected]>
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
# -----------------------------------------------------------------------------
# Configuration
# -----------------------------------------------------------------------------
# The same default card with a a configurable logo
# Definitions
definitions:
# Background image
- &background_image >-
{{ layout.background_image or "" }}
# Background color (default: indigo)
- &background_color >-
{%- if layout.background_color -%}
{{ layout.background_color }}
{%- else -%}
{%- set palette = config.theme.palette or {} -%}
{%- if not palette is mapping -%}
{%- set palette = palette | first -%}
{%- endif -%}
{%- set primary = palette.get("primary", "indigo") -%}
{%- set primary = primary.replace(" ", "-") -%}
{{ {
"red": "#ef5552",
"pink": "#e92063",
"purple": "#ab47bd",
"deep-purple": "#7e56c2",
"indigo": "#4051b5",
"blue": "#2094f3",
"light-blue": "#02a6f2",
"cyan": "#00bdd6",
"teal": "#009485",
"green": "#4cae4f",
"light-green": "#8bc34b",
"lime": "#cbdc38",
"yellow": "#ffec3d",
"amber": "#ffc105",
"orange": "#ffa724",
"deep-orange": "#ff6e42",
"brown": "#795649",
"grey": "#757575",
"blue-grey": "#546d78",
"black": "#000000",
"white": "#ffffff"
}[primary] or "#4051b5" }}
{%- endif -%}
# Text color (default: white)
- &color >-
{%- if layout.color -%}
{{ layout.color }}
{%- else -%}
{%- set palette = config.theme.palette or {} -%}
{%- if not palette is mapping -%}
{%- set palette = palette | first -%}
{%- endif -%}
{%- set primary = palette.get("primary", "indigo") -%}
{%- set primary = primary.replace(" ", "-") -%}
{{ {
"red": "#ffffff",
"pink": "#ffffff",
"purple": "#ffffff",
"deep-purple": "#ffffff",
"indigo": "#ffffff",
"blue": "#ffffff",
"light-blue": "#ffffff",
"cyan": "#ffffff",
"teal": "#ffffff",
"green": "#ffffff",
"light-green": "#ffffff",
"lime": "#000000",
"yellow": "#000000",
"amber": "#000000",
"orange": "#000000",
"deep-orange": "#ffffff",
"brown": "#ffffff",
"grey": "#ffffff",
"blue-grey": "#ffffff",
"black": "#ffffff",
"white": "#000000"
}[primary] or "#ffffff" }}
{%- endif -%}
# Font family (default: Roboto)
- &font_family >-
{%- if layout.font_family -%}
{{ layout.font_family }}
{%- elif config.theme.font != false -%}
{{ config.theme.font.get("text", "Roboto") }}
{%- else -%}
Roboto
{%- endif -%}
# Site name
- &site_name >-
{{ config.site_name }}
# Page title
- &page_title >-
{{ page.meta.get("title", page.title) }}
# Page title with site name
- &page_title_with_site_name >-
{%- if not page.is_homepage -%}
{{ page.meta.get("title", page.title) }} - {{ config.site_name }}
{%- else -%}
{{ page.meta.get("title", page.title) }}
{%- endif -%}
# Page description
- &page_description >-
{{ page.meta.get("description", config.site_description) or "" }}
# Start of custom modified logic
# Logo
- &logo >-
{%- if layout.logo -%}
{{ layout.logo }}
{%- elif config.theme.logo -%}
{{ config.docs_dir }}/{{ config.theme.logo }}
{%- endif -%}
# End of custom modified logic
# Logo (icon)
- &logo_icon >-
{{ config.theme.icon.logo or "" }}
# Meta tags
tags:
# Open Graph
og:type: website
og:title: *page_title_with_site_name
og:description: *page_description
og:image: "{{ image.url }}"
og:image:type: "{{ image.type }}"
og:image:width: "{{ image.width }}"
og:image:height: "{{ image.height }}"
og:url: "{{ page.canonical_url }}"
# Twitter
twitter:card: summary_large_image
twitter.title: *page_title_with_site_name
twitter:description: *page_description
twitter:image: "{{ image.url }}"
# -----------------------------------------------------------------------------
# Specification
# -----------------------------------------------------------------------------
# Card size and layers
size: { width: 1200, height: 630 }
layers:
# Background
- background:
image: *background_image
color: *background_color
# Logo
- size: { width: 144, height: 144 }
offset: { x: 992, y: 64 }
background:
image: *logo
icon:
value: *logo_icon
color: *color
# Site name
- size: { width: 832, height: 42 }
offset: { x: 64, y: 64 }
typography:
content: *site_name
color: *color
font:
family: *font_family
style: Bold
# Page title
- size: { width: 832, height: 310 }
offset: { x: 62, y: 160 }
typography:
content: *page_title
align: start
color: *color
line:
amount: 3
height: 1.25
font:
family: *font_family
style: Bold
# Page description
- size: { width: 832, height: 64 }
offset: { x: 64, y: 512 }
typography:
content: *page_description
align: start
color: *color
line:
amount: 2
height: 1.5
font:
family: *font_family
style: Regular

7
docs/en/mkdocs.insiders.yml

@ -0,0 +1,7 @@
plugins:
social:
cards_layout_dir: ../en/layouts
cards_layout: custom
cards_layout_options:
logo: ../en/docs/img/icon-white.svg
typeset:

3
docs/en/mkdocs.maybe-insiders.yml

@ -0,0 +1,3 @@
# Define this here and not in the main mkdocs.yml file because that one is auto
# updated and written, and the script would remove the env var
INHERIT: !ENV [INSIDERS_FILE, '../en/mkdocs.no-insiders.yml']

0
docs/en/mkdocs.no-insiders.yml

10
docs/en/mkdocs.yml

@ -1,3 +1,4 @@
INHERIT: ../en/mkdocs.maybe-insiders.yml
site_name: FastAPI site_name: FastAPI
site_description: FastAPI framework, high performance, easy to learn, fast to code, ready for production site_description: FastAPI framework, high performance, easy to learn, fast to code, ready for production
site_url: https://fastapi.tiangolo.com/ site_url: https://fastapi.tiangolo.com/
@ -24,6 +25,11 @@ theme:
- search.highlight - search.highlight
- content.tabs.link - content.tabs.link
- navigation.indexes - navigation.indexes
- content.tooltips
- navigation.path
- content.code.annotate
- content.code.copy
- content.code.select
icon: icon:
repo: fontawesome/brands/github-alt repo: fontawesome/brands/github-alt
logo: img/icon-white.svg logo: img/icon-white.svg
@ -33,8 +39,8 @@ repo_name: tiangolo/fastapi
repo_url: https://github.com/tiangolo/fastapi repo_url: https://github.com/tiangolo/fastapi
edit_uri: '' edit_uri: ''
plugins: plugins:
- search search: null
- markdownextradata: markdownextradata:
data: ../en/data data: ../en/data
nav: nav:
- FastAPI: index.md - FastAPI: index.md

6
requirements-docs.txt

@ -6,3 +6,9 @@ mkdocs-markdownextradata-plugin >=0.1.7,<0.3.0
typer-cli >=0.0.13,<0.0.14 typer-cli >=0.0.13,<0.0.14
typer[all] >=0.6.1,<0.8.0 typer[all] >=0.6.1,<0.8.0
pyyaml >=5.3.1,<7.0.0 pyyaml >=5.3.1,<7.0.0
# For Material for MkDocs, Chinese search
jieba==0.42.1
# For image processing by Material for MkDocs
pillow==9.5.0
# For image processing by Material for MkDocs
cairosvg==2.7.0

20
scripts/docs.py

@ -4,7 +4,9 @@ import os
import re import re
import shutil import shutil
import subprocess import subprocess
from functools import lru_cache
from http.server import HTTPServer, SimpleHTTPRequestHandler from http.server import HTTPServer, SimpleHTTPRequestHandler
from importlib import metadata
from multiprocessing import Pool from multiprocessing import Pool
from pathlib import Path from pathlib import Path
from typing import Any, Dict, List, Optional, Union from typing import Any, Dict, List, Optional, Union
@ -34,6 +36,12 @@ site_path = Path("site").absolute()
build_site_path = Path("site_build").absolute() build_site_path = Path("site_build").absolute()
@lru_cache()
def is_mkdocs_insiders() -> bool:
version = metadata.version("mkdocs-material")
return "insiders" in version
def get_en_config() -> Dict[str, Any]: def get_en_config() -> Dict[str, Any]:
return mkdocs.utils.yaml_load(en_config_path.read_text(encoding="utf-8")) return mkdocs.utils.yaml_load(en_config_path.read_text(encoding="utf-8"))
@ -59,6 +67,14 @@ def complete_existing_lang(incomplete: str):
yield lang_path.name yield lang_path.name
@app.callback()
def callback() -> None:
if is_mkdocs_insiders():
os.environ["INSIDERS_FILE"] = "../en/mkdocs.insiders.yml"
# For MacOS with insiders and Cairo
os.environ["DYLD_FALLBACK_LIBRARY_PATH"] = "/opt/homebrew/lib"
@app.command() @app.command()
def new_lang(lang: str = typer.Argument(..., callback=lang_callback)): def new_lang(lang: str = typer.Argument(..., callback=lang_callback)):
""" """
@ -93,6 +109,10 @@ def build_lang(
""" """
Build the docs for a language. Build the docs for a language.
""" """
insiders_env_file = os.environ.get("INSIDERS_FILE")
print(f"Insiders file {insiders_env_file}")
if is_mkdocs_insiders():
print("Using insiders")
lang_path: Path = Path("docs") / lang lang_path: Path = Path("docs") / lang
if not lang_path.is_dir(): if not lang_path.is_dir():
typer.echo(f"The language translation doesn't seem to exist yet: {lang}") typer.echo(f"The language translation doesn't seem to exist yet: {lang}")

Loading…
Cancel
Save