mirror of
https://github.com/squidfunk/mkdocs-material.git
synced 2024-06-14 11:52:32 +03:00
Merge branch 'master' into fix/instant-loading
This commit is contained in:
commit
15538b0a39
41
.github/workflows/build.yml
vendored
41
.github/workflows/build.yml
vendored
@ -36,7 +36,35 @@ permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
npm:
|
||||
npm-build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Node.js runtime
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
|
||||
- name: Set up Node.js dependency cache
|
||||
uses: actions/cache@v3
|
||||
id: cache
|
||||
with:
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
|
||||
path: node_modules
|
||||
|
||||
- name: Set up Node.js dependencies
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: npm install
|
||||
|
||||
- name: Build project
|
||||
run: |
|
||||
npm run build
|
||||
git diff --name-only
|
||||
|
||||
npm-check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
@ -62,12 +90,7 @@ jobs:
|
||||
- name: Check project
|
||||
run: npm run check
|
||||
|
||||
- name: Build project
|
||||
run: |
|
||||
npm run build
|
||||
git diff --name-only
|
||||
|
||||
pypi:
|
||||
python:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
@ -78,6 +101,10 @@ jobs:
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
cache: pip
|
||||
cache-dependency-path: |
|
||||
pyproject.toml
|
||||
requirements.txt
|
||||
|
||||
- name: Set up Python dependencies
|
||||
run: pip install --upgrade build twine
|
||||
|
54
.github/workflows/documentation.yml
vendored
54
.github/workflows/documentation.yml
vendored
@ -29,6 +29,8 @@ env:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
id-token: write
|
||||
pages: write
|
||||
|
||||
jobs:
|
||||
documentation:
|
||||
@ -40,20 +42,25 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
sparse-checkout: |
|
||||
docs
|
||||
includes
|
||||
material/overrides
|
||||
src/templates/partials/languages
|
||||
|
||||
- name: Set up Python runtime
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
|
||||
- name: Set the date environmental variable
|
||||
run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
|
||||
cache: pip
|
||||
cache-dependency-path: |
|
||||
pyproject.toml
|
||||
requirements.txt
|
||||
|
||||
- name: Set up build cache
|
||||
uses: actions/cache@v3
|
||||
id: cache
|
||||
uses: actions/cache/restore@v3
|
||||
with:
|
||||
key: mkdocs-material-${{ env.cache_id }}
|
||||
key: mkdocs-material-${{ hashfiles('.cache/**') }}
|
||||
path: .cache
|
||||
restore-keys: |
|
||||
mkdocs-material-
|
||||
@ -63,15 +70,8 @@ jobs:
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
pip install \
|
||||
"cairosvg>=2.5" \
|
||||
"mkdocs-git-committers-plugin-2>=1.1.1" \
|
||||
"mkdocs-git-revision-date-localized-plugin>=1.0" \
|
||||
"mkdocs-minify-plugin>=0.3" \
|
||||
"mkdocs-rss-plugin>=1.2" \
|
||||
"mkdocs-redirects>=1.0" \
|
||||
"lxml" \
|
||||
"pillow<10"
|
||||
pip install mkdocs-material
|
||||
pip install mkdocs-material[recommended,git,imaging]
|
||||
|
||||
- name: Install Insiders build
|
||||
if: github.event.repository.fork == false
|
||||
@ -88,10 +88,30 @@ jobs:
|
||||
rm -rf material
|
||||
cp -r mkdocs-material-insiders/material material
|
||||
|
||||
- name: Deploy documentation
|
||||
- name: Build documentation
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
GOOGLE_ANALYTICS_KEY: ${{ secrets.GOOGLE_ANALYTICS_KEY }}
|
||||
run: |
|
||||
mkdocs gh-deploy --force
|
||||
mkdocs build --clean
|
||||
mkdocs --version
|
||||
|
||||
- name: Adjust permissions
|
||||
run: |
|
||||
chmod -c -R +rX site/ | while read line; do
|
||||
echo "::warning title=Invalid file permissions automatically fixed::$line"
|
||||
done
|
||||
|
||||
- name: Upload to GitHub Pages
|
||||
uses: actions/upload-pages-artifact@v2
|
||||
with:
|
||||
path: site
|
||||
|
||||
- name: Deploy to GitHub Pages
|
||||
uses: actions/deploy-pages@v2
|
||||
|
||||
- name: Save build cache
|
||||
uses: actions/cache/save@v3
|
||||
with:
|
||||
key: mkdocs-material-${{ hashfiles('.cache/**') }}
|
||||
path: .cache
|
||||
|
100
docs/blog/posts/git-sparse-checkout.md
Normal file
100
docs/blog/posts/git-sparse-checkout.md
Normal file
@ -0,0 +1,100 @@
|
||||
---
|
||||
date: 2023-09-22
|
||||
authors: [squidfunk]
|
||||
categories:
|
||||
- Build
|
||||
- Performance
|
||||
links:
|
||||
- publishing-your-site.md#with-github-actions
|
||||
- creating-your-site.md#building-your-site
|
||||
---
|
||||
|
||||
# Using `git sparse-checkout` for faster documentation builds
|
||||
|
||||
__Leveraging `git sparse-checkout` in GitHub Actions enabled us to speed up
|
||||
documentation builds in our repository, cutting checkout times from 20 to 30
|
||||
seconds to just 2 seconds.__
|
||||
|
||||
Developing an efficient approach to build documentation in CI workflows is
|
||||
essential, especially when working in large repositories with thousands of
|
||||
commits, like ours. Of course, we want to build documentation quickly and
|
||||
efficiently, ensuring fast and productive workflows. When using both the
|
||||
wonderful [`git-committers`][git-committers] and [`git-revision-date-localized`]
|
||||
[git-revision-date-localized] plugins to display [document contributors] and
|
||||
[dates] at the bottom of each page, we are required to set `fetch-depth: 0`,
|
||||
which resulted in checkout times of 20 to 30 seconds on our repository. By
|
||||
leveraging [`git sparse-checkout`][git sparse-checkout] within [GitHub Actions],
|
||||
check out time was brought down to 2 seconds.
|
||||
|
||||
[git sparse-checkout]: https://git-scm.com/docs/git-sparse-checkout
|
||||
[GitHub Actions]: ../../publishing-your-site.md#with-github-actions
|
||||
[git-revision-date-localized]: https://github.com/timvink/mkdocs-git-revision-date-localized-plugin
|
||||
[git-committers]: https://github.com/ojacques/mkdocs-git-committers-plugin-2
|
||||
[document contributors]: ../../setup/adding-a-git-repository.md#document-contributors
|
||||
[dates]: ../../setup/adding-a-git-repository.md#document-dates
|
||||
|
||||
<!-- more -->
|
||||
|
||||
## A Primer
|
||||
|
||||
[`git sparse-checkout`][git sparse-checkout] allows you to check out only a
|
||||
subset of the files in a repository, making it incredibly useful for large
|
||||
repositories where a full checkout takes long and includes many files that are
|
||||
not relevant when building documentation.
|
||||
|
||||
## GitHub Actions
|
||||
|
||||
To enable [`git sparse-checkout`][git sparse-checkout] within [GitHub Actions]
|
||||
and ensure that you are only building the documentation that you need, add the
|
||||
following lines to your workflow file:
|
||||
|
||||
``` yaml
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
sparse-checkout: |
|
||||
docs
|
||||
includes
|
||||
```
|
||||
|
||||
[`git sparse-checkout`][git sparse-checkout] always checks out all files
|
||||
residing in the repository’s root. This means that regardless of the specified
|
||||
paths or directories for sparse checkout, the files located in the root of the
|
||||
repository will always be included in the checkout process.
|
||||
|
||||
Thus, you only need to specify the directories that are necessary for building
|
||||
documentation. In our case, we only need the `docs` and `includes` folders,
|
||||
but if you need additional directories, you can just add them to the end of the
|
||||
list. A complete example workflow for [GitHub Actions]:
|
||||
|
||||
``` yaml hl_lines="13-18"
|
||||
name: documentation
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
permissions:
|
||||
contents: write
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
sparse-checkout: |
|
||||
docs
|
||||
includes
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.x
|
||||
- run: pip install mkdocs-material
|
||||
- run: mkdocs gh-deploy --force
|
||||
```
|
||||
|
||||
## Conclusion
|
||||
|
||||
That's all there is! We're super happy with the results and hope that this will
|
||||
help you to speed up your documentation builds in [GitHub Actions] as well. As
|
||||
always, feel free to share your thoughts and experiences in the comments below.
|
@ -21,7 +21,7 @@
|
||||
import os
|
||||
import re
|
||||
|
||||
from glob import glob
|
||||
from glob import iglob
|
||||
from mkdocs.config.defaults import MkDocsConfig
|
||||
from mkdocs.structure.pages import Page
|
||||
from urllib.parse import urlencode, urlparse
|
||||
@ -40,7 +40,7 @@ def on_page_markdown(markdown: str, *, page: Page, config: MkDocsConfig, files):
|
||||
# Collect all existing languages
|
||||
names: dict[str, str] = {}
|
||||
known: dict[str, dict[str, str]] = {}
|
||||
for path in glob("src/templates/partials/languages/*.html"):
|
||||
for path in iglob("src/templates/partials/languages/*.html"):
|
||||
with open(path, "r", encoding = "utf-8") as f:
|
||||
data = f.read()
|
||||
|
||||
|
29
material/templates/assets/javascripts/bundle.5827baa9.min.js
vendored
Normal file
29
material/templates/assets/javascripts/bundle.5827baa9.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -44,7 +44,7 @@
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block styles %}
|
||||
<link rel="stylesheet" href="{{ 'assets/stylesheets/main.72749a73.min.css' | url }}">
|
||||
<link rel="stylesheet" href="{{ 'assets/stylesheets/main.d451bc0e.min.css' | url }}">
|
||||
{% if config.theme.palette %}
|
||||
{% set palette = config.theme.palette %}
|
||||
<link rel="stylesheet" href="{{ 'assets/stylesheets/palette.a5377069.min.css' | url }}">
|
||||
@ -250,7 +250,7 @@
|
||||
</script>
|
||||
{% endblock %}
|
||||
{% block scripts %}
|
||||
<script src="{{ 'assets/javascripts/bundle.73f771f6.min.js' | url }}"></script>
|
||||
<script src="{{ 'assets/javascripts/bundle.5827baa9.min.js' | url }}"></script>
|
||||
{% for script in config.extra_javascript %}
|
||||
{{ script | script_tag }}
|
||||
{% endfor %}
|
||||
|
@ -8,7 +8,7 @@
|
||||
<div class="md-sidebar md-sidebar--post" data-md-component="sidebar" data-md-type="navigation">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner md-post">
|
||||
<nav class="md-nav">
|
||||
<nav class="md-nav md-nav--primary">
|
||||
<div class="md-post__back">
|
||||
<div class="md-nav__title md-nav__container">
|
||||
<a href="{{ page.parent.url | url }}" class="md-nav__link">
|
||||
@ -35,62 +35,66 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
<ul class="md-post__meta md-nav__list">
|
||||
<li class="md-nav__item md-nav__title">
|
||||
<div class="md-nav__link">
|
||||
<li class="md-nav__item md-nav__item--section">
|
||||
<div class="md-post__title">
|
||||
<span class="md-ellipsis">
|
||||
{{ lang.t("blog.meta") }}
|
||||
</span>
|
||||
</div>
|
||||
<nav class="md-nav">
|
||||
<ul class="md-nav__list">
|
||||
<li class="md-nav__item">
|
||||
<div class="md-nav__link">
|
||||
{% include ".icons/material/calendar.svg" %}
|
||||
<time datetime="{{ page.config.date.created }}" class="md-ellipsis">
|
||||
{{- page.config.date.created | date -}}
|
||||
</time>
|
||||
</div>
|
||||
</li>
|
||||
{% if page.config.date.updated %}
|
||||
<li class="md-nav__item">
|
||||
<div class="md-nav__link">
|
||||
{% include ".icons/material/calendar-clock.svg" %}
|
||||
<time datetime="{{ page.config.date.updated }}" class="md-ellipsis">
|
||||
{{- page.config.date.updated | date -}}
|
||||
</time>
|
||||
</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if page.categories %}
|
||||
<li class="md-nav__item">
|
||||
<div class="md-nav__link">
|
||||
{% include ".icons/material/bookshelf.svg" %}
|
||||
<span class="md-ellipsis">
|
||||
{{ lang.t("blog.categories.in") }}
|
||||
{% for category in page.categories %}
|
||||
<a href="{{ category.url | url }}">
|
||||
{{- category.title -}}
|
||||
</a>
|
||||
{%- if loop.revindex > 1 %}, {% endif -%}
|
||||
{% endfor -%}
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if page.config.readtime %}
|
||||
{% set time = page.config.readtime %}
|
||||
<li class="md-nav__item">
|
||||
<div class="md-nav__link">
|
||||
{% include ".icons/material/clock-outline.svg" %}
|
||||
<span class="md-ellipsis">
|
||||
{% if time == 1 %}
|
||||
{{ lang.t("readtime.one") }}
|
||||
{% else %}
|
||||
{{ lang.t("readtime.other") | replace("#", time) }}
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<div class="md-nav__link">
|
||||
{% include ".icons/material/calendar.svg" %}
|
||||
<time datetime="{{ page.config.date.created }}" class="md-ellipsis">
|
||||
{{- page.config.date.created | date -}}
|
||||
</time>
|
||||
</div>
|
||||
</li>
|
||||
{% if page.config.date.updated %}
|
||||
<li class="md-nav__item">
|
||||
<div class="md-nav__link">
|
||||
{% include ".icons/material/calendar-clock.svg" %}
|
||||
<time datetime="{{ page.config.date.updated }}" class="md-ellipsis">
|
||||
{{- page.config.date.updated | date -}}
|
||||
</time>
|
||||
</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if page.categories %}
|
||||
<li class="md-nav__item">
|
||||
<div class="md-nav__link">
|
||||
{% include ".icons/material/bookshelf.svg" %}
|
||||
<span class="md-ellipsis">
|
||||
{{ lang.t("blog.categories.in") }}
|
||||
{% for category in page.categories %}
|
||||
<a href="{{ category.url | url }}">
|
||||
{{- category.title -}}
|
||||
</a>
|
||||
{%- if loop.revindex > 1 %}, {% endif -%}
|
||||
{% endfor -%}
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if page.config.readtime %}
|
||||
{% set time = page.config.readtime %}
|
||||
<li class="md-nav__item">
|
||||
<div class="md-nav__link">
|
||||
{% include ".icons/material/clock-outline.svg" %}
|
||||
<span class="md-ellipsis">
|
||||
{% if time == 1 %}
|
||||
{{ lang.t("readtime.one") }}
|
||||
{% else %}
|
||||
{{ lang.t("readtime.other") | replace("#", time) }}
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
{% if "toc.integrate" in features %}
|
||||
|
@ -47,6 +47,7 @@
|
||||
"select.language": "Izberi jezik",
|
||||
"select.version": "Izberi različico",
|
||||
"source": "Pojdi na repozitorij",
|
||||
"source.file.contributors": "Soavtorji",
|
||||
"source.file.date.created": "Ustvarjeno",
|
||||
"source.file.date.updated": "Zadnja posodobitev",
|
||||
"tabs": "Zavihki",
|
||||
|
@ -48,25 +48,26 @@
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if "navigation.sections" in features and level == 1 + (
|
||||
"navigation.tabs" in features
|
||||
) %}
|
||||
{% set tabs = "navigation.tabs" in features %}
|
||||
{% set sections = "navigation.sections" in features %}
|
||||
{% if tabs and level == 1 or sections and tabs >= level - 1 %}
|
||||
{% set class = class ~ " md-nav__item--section" %}
|
||||
{% set is_section = true %}
|
||||
{% elif not nav_item.active and "navigation.prune" in features %}
|
||||
{% set class = class ~ " md-nav__item--pruned" %}
|
||||
{% set prune = true %}
|
||||
{% set is_pruned = true %}
|
||||
{% endif %}
|
||||
<li class="{{ class }} md-nav__item--nested">
|
||||
{% if not prune %}
|
||||
{% set expanded = "navigation.expand" in features %}
|
||||
{% set active = nav_item.active or expanded %}
|
||||
{% if not is_pruned %}
|
||||
{% set checked = "checked" if nav_item.active %}
|
||||
{% if expanded and not checked %}
|
||||
{% set is_expanded = "navigation.expand" in features %}
|
||||
{% if is_expanded and not checked %}
|
||||
{% set indeterminate = "md-toggle--indeterminate" %}
|
||||
{% endif %}
|
||||
<input class="md-nav__toggle md-toggle {{ indeterminate }}" type="checkbox" id="{{ path }}" {{ checked }}>
|
||||
{% if not indexes %}
|
||||
<label class="md-nav__link" for="{{ path }}" id="{{ path }}_label" tabindex="0">
|
||||
{% set tabindex = "0" if not is_section %}
|
||||
<label class="md-nav__link" for="{{ path }}" id="{{ path }}_label" tabindex="{{ tabindex }}">
|
||||
{{ render_content(nav_item) }}
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
@ -78,7 +79,8 @@
|
||||
{{ render_content(index, nav_item) }}
|
||||
</a>
|
||||
{% if nav_item.children | length > 1 %}
|
||||
<label class="md-nav__link {{ class }}" for="{{ path }}">
|
||||
{% set tabindex = "0" if not is_section %}
|
||||
<label class="md-nav__link {{ class }}" for="{{ path }}" id="{{ path }}_label" tabindex="{{ tabindex }}">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
{% endif %}
|
||||
|
@ -21,7 +21,7 @@
|
||||
import os
|
||||
import re
|
||||
|
||||
from glob import glob
|
||||
from glob import iglob
|
||||
from mkdocs.config.defaults import MkDocsConfig
|
||||
from mkdocs.structure.pages import Page
|
||||
from urllib.parse import urlencode, urlparse
|
||||
@ -40,7 +40,7 @@ def on_page_markdown(markdown: str, *, page: Page, config: MkDocsConfig, files):
|
||||
# Collect all existing languages
|
||||
names: dict[str, str] = {}
|
||||
known: dict[str, dict[str, str]] = {}
|
||||
for path in glob("src/templates/partials/languages/*.html"):
|
||||
for path in iglob("src/templates/partials/languages/*.html"):
|
||||
with open(path, "r", encoding = "utf-8") as f:
|
||||
data = f.read()
|
||||
|
||||
|
@ -24,6 +24,7 @@ import {
|
||||
Observable,
|
||||
Subject,
|
||||
animationFrameScheduler,
|
||||
asyncScheduler,
|
||||
auditTime,
|
||||
combineLatest,
|
||||
defer,
|
||||
@ -36,6 +37,7 @@ import {
|
||||
ignoreElements,
|
||||
map,
|
||||
mergeMap,
|
||||
observeOn,
|
||||
takeUntil,
|
||||
tap,
|
||||
withLatestFrom
|
||||
@ -202,6 +204,7 @@ export function mountSidebar(
|
||||
.pipe(
|
||||
mergeMap(label => fromEvent(label, "click")
|
||||
.pipe(
|
||||
observeOn(asyncScheduler),
|
||||
map(() => label),
|
||||
takeUntil(done$)
|
||||
)
|
||||
|
@ -30,10 +30,12 @@ import {
|
||||
debounceTime,
|
||||
distinctUntilKeyChanged,
|
||||
endWith,
|
||||
filter,
|
||||
fromEvent,
|
||||
ignoreElements,
|
||||
map,
|
||||
of,
|
||||
sample,
|
||||
share,
|
||||
skip,
|
||||
startWith,
|
||||
@ -291,19 +293,17 @@ export function setupInstantLoading(
|
||||
popstate$.pipe(map(getLocation))
|
||||
.subscribe(location$)
|
||||
|
||||
// Intercept clicks on anchor links, and scroll document into position. As
|
||||
// we disabled scroll restoration, we need to do this manually here.
|
||||
// Intercept clicks on anchor links, and scroll document into position - as
|
||||
// we disabled scroll restoration, we need to do this manually here
|
||||
location$
|
||||
.pipe(
|
||||
startWith(getLocation()),
|
||||
bufferCount(2, 1),
|
||||
switchMap(([prev, next]) => (
|
||||
filter(([prev, next]) => (
|
||||
prev.pathname === next.pathname &&
|
||||
prev.hash !== next.hash
|
||||
)
|
||||
? of(next)
|
||||
: EMPTY
|
||||
)
|
||||
)),
|
||||
map(([, next]) => next)
|
||||
)
|
||||
.subscribe(url => {
|
||||
if (history.state !== null || !url.hash) {
|
||||
@ -315,6 +315,29 @@ export function setupInstantLoading(
|
||||
}
|
||||
})
|
||||
|
||||
// Intercept clicks on the same anchor link - we must use a distinct pipeline
|
||||
// for this, or we'd end up in a loop, setting the hash again and again
|
||||
location$
|
||||
.pipe(
|
||||
sample(instant$),
|
||||
startWith(getLocation()),
|
||||
bufferCount(2, 1),
|
||||
filter(([prev, next]) => (
|
||||
prev.pathname === next.pathname &&
|
||||
prev.hash === next.hash
|
||||
)),
|
||||
map(([, next]) => next)
|
||||
)
|
||||
.subscribe(url => {
|
||||
history.scrollRestoration = "auto"
|
||||
setLocationHash(url.hash)
|
||||
history.scrollRestoration = "manual"
|
||||
|
||||
// Hack: we need to make sure that we don't end up with multiple history
|
||||
// entries for the same anchor link, so we just remove the last entry
|
||||
history.back()
|
||||
})
|
||||
|
||||
// After parsing the document, check if the current history entry has a state.
|
||||
// This may happen when users press the back or forward button to visit a page
|
||||
// that was already seen. If there's no state, it means a new page was visited
|
||||
@ -332,9 +355,8 @@ export function setupInstantLoading(
|
||||
// the current history state whenever the scroll position changes. This must
|
||||
// be debounced and cannot be done in popstate, as popstate has already
|
||||
// removed the entry from the history.
|
||||
document$
|
||||
viewport$
|
||||
.pipe(
|
||||
switchMap(() => viewport$),
|
||||
distinctUntilKeyChanged("offset"),
|
||||
debounceTime(100)
|
||||
)
|
||||
|
@ -80,19 +80,10 @@
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
// Navigation item
|
||||
&__item {
|
||||
padding: 0 px2rem(12px);
|
||||
|
||||
// Navigation item on level 2
|
||||
& & {
|
||||
padding-inline-end: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Navigation link
|
||||
&__link {
|
||||
display: flex;
|
||||
gap: px2rem(8px);
|
||||
align-items: flex-start;
|
||||
margin-top: 0.625em;
|
||||
transition: color 125ms;
|
||||
@ -121,9 +112,9 @@
|
||||
position: relative;
|
||||
}
|
||||
|
||||
// Always align navigation icons to the right
|
||||
// Always align navigation icons to the end
|
||||
.md-icon:last-child {
|
||||
margin-left: auto;
|
||||
margin-inline-start: auto;
|
||||
}
|
||||
|
||||
// Navigation link icon
|
||||
@ -131,15 +122,10 @@
|
||||
flex-shrink: 0;
|
||||
height: 1.3em;
|
||||
fill: currentcolor;
|
||||
|
||||
// Adjust spacing of next child
|
||||
+ * {
|
||||
margin-inline-start: px2rem(8px);
|
||||
}
|
||||
}
|
||||
|
||||
// Navigation link on focus/hover
|
||||
&:not(.md-nav__container):is(:focus, :hover) {
|
||||
&:is([href], [for]):is(:focus, :hover) {
|
||||
color: var(--md-accent-fg-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
@ -177,6 +163,9 @@
|
||||
// Stretch first child
|
||||
&:first-child {
|
||||
flex-grow: 1;
|
||||
// Hack: if a very long word is used, it can push the arrow out of sight.
|
||||
// Setting this property contains the text - see https://t.ly/E02vp
|
||||
min-width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -290,7 +279,6 @@
|
||||
|
||||
// Navigation item
|
||||
.md-nav__item {
|
||||
padding: 0;
|
||||
border-top: px2rem(1px) solid var(--md-default-fg-color--lightest);
|
||||
|
||||
// Navigation link in active navigation
|
||||
@ -386,7 +374,7 @@
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
// Toggle for nested navigation
|
||||
// Hide nested navigation
|
||||
&__toggle ~ & {
|
||||
display: flex;
|
||||
opacity: 0;
|
||||
@ -475,62 +463,118 @@
|
||||
|
||||
// [tablet landscape +]: Tree-like table of contents
|
||||
@include break-from-device(tablet landscape) {
|
||||
margin-bottom: px2rem(-8px);
|
||||
|
||||
// Navigation title
|
||||
&--secondary &__title {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
// Hack: because of the hack that we need to make .md-ellipsis work in
|
||||
// Safari, we need to set `z-index` here as - see https://bit.ly/3s5M2jm
|
||||
z-index: 1;
|
||||
background: var(--md-default-bg-color);
|
||||
box-shadow: 0 0 px2rem(8px) px2rem(8px) var(--md-default-bg-color);
|
||||
// Table of contents
|
||||
&--secondary {
|
||||
|
||||
// Adjust snapping behavior
|
||||
&[for="__toc"] {
|
||||
scroll-snap-align: start;
|
||||
// Navigation title
|
||||
.md-nav__title {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
// Hack: because of the hack that we need to make .md-ellipsis work in
|
||||
// Safari, we need to set `z-index` here as - see https://bit.ly/3s5M2jm
|
||||
z-index: 1;
|
||||
background: var(--md-default-bg-color);
|
||||
box-shadow: 0 0 px2rem(8px) px2rem(8px) var(--md-default-bg-color);
|
||||
|
||||
// Adjust snapping behavior
|
||||
&[for="__toc"] {
|
||||
scroll-snap-align: start;
|
||||
}
|
||||
|
||||
// Hide navigation icon
|
||||
.md-nav__icon {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
// Hide navigation icon
|
||||
.md-nav__icon {
|
||||
display: none;
|
||||
// Adjust spacing for navigation list - same reason as below
|
||||
.md-nav__list {
|
||||
padding-inline-start: px2rem(12px);
|
||||
padding-bottom: px2rem(8px);
|
||||
}
|
||||
|
||||
// Adjust spacing for navigation link - before this change, we set spacing
|
||||
// on the left and right of a navigation item, but this led to the problem
|
||||
// of cropped focus outlines, because we must set `overflow: hidden` on
|
||||
// the navigation list for smooth expand and collapse transitions.
|
||||
.md-nav__item > .md-nav__link {
|
||||
margin-inline-end: px2rem(8px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// [screen +]: Tree-like navigation
|
||||
@include break-from-device(screen) {
|
||||
margin-bottom: px2rem(-8px);
|
||||
transition: max-height 250ms cubic-bezier(0.86, 0, 0.07, 1);
|
||||
|
||||
// Navigation title
|
||||
&--primary &__title {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
// Hack: because of the hack that we need to make .md-ellipsis work in
|
||||
// Safari, we need to set `z-index` here as - see https://bit.ly/3s5M2jm
|
||||
z-index: 1;
|
||||
background: var(--md-default-bg-color);
|
||||
box-shadow: 0 0 px2rem(8px) px2rem(8px) var(--md-default-bg-color);
|
||||
// Primary navigation
|
||||
&--primary {
|
||||
|
||||
// Adjust snapping behavior
|
||||
&[for="__drawer"] {
|
||||
scroll-snap-align: start;
|
||||
// Navigation title
|
||||
.md-nav__title {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
// Hack: because of the hack that we need to make .md-ellipsis work in
|
||||
// Safari, we need to set `z-index` here as - see https://bit.ly/3s5M2jm
|
||||
z-index: 1;
|
||||
background: var(--md-default-bg-color);
|
||||
box-shadow: 0 0 px2rem(8px) px2rem(8px) var(--md-default-bg-color);
|
||||
|
||||
// Adjust snapping behavior
|
||||
&[for="__drawer"] {
|
||||
scroll-snap-align: start;
|
||||
}
|
||||
|
||||
// Hide navigation icon
|
||||
.md-nav__icon {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
// Hide navigation icon
|
||||
.md-nav__icon {
|
||||
display: none;
|
||||
// Adjust spacing for navigation list - same reason as below
|
||||
.md-nav__list {
|
||||
padding-inline-start: px2rem(12px);
|
||||
padding-bottom: px2rem(8px);
|
||||
}
|
||||
|
||||
// Adjust spacing for navigation link - before this change, we set spacing
|
||||
// on the left and right of a navigation item, but this led to the problem
|
||||
// of cropped focus outlines, because we must set `overflow: hidden` on
|
||||
// the navigation list for smooth expand and collapse transitions.
|
||||
.md-nav__item > .md-nav__link {
|
||||
margin-inline-end: px2rem(8px);
|
||||
}
|
||||
}
|
||||
|
||||
// Hide toggle for nested navigation
|
||||
// Hide nested navigation
|
||||
&__toggle ~ & {
|
||||
display: none;
|
||||
display: grid;
|
||||
grid-template-rows: 0fr;
|
||||
visibility: collapse;
|
||||
opacity: 0;
|
||||
transition:
|
||||
grid-template-rows 250ms cubic-bezier(0.86, 0, 0.07, 1),
|
||||
opacity 250ms,
|
||||
visibility 0ms 250ms;
|
||||
|
||||
// Navigation list
|
||||
> .md-nav__list {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
// Show nested navigation when toggle is active or indeterminate
|
||||
&__toggle:is(:checked, :indeterminate) ~ & {
|
||||
display: block;
|
||||
grid-template-rows: 1fr;
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
transition:
|
||||
grid-template-rows 250ms cubic-bezier(0.86, 0, 0.07, 1),
|
||||
opacity 150ms 100ms,
|
||||
visibility 0ms;
|
||||
}
|
||||
|
||||
// Hide navigation title in nested navigation
|
||||
@ -562,8 +606,9 @@
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
// Hide naviation icon
|
||||
.md-nav__icon {
|
||||
// Hide navigation icon
|
||||
> [for],
|
||||
.md-icon {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@ -571,6 +616,9 @@
|
||||
// Navigation
|
||||
> .md-nav {
|
||||
display: block;
|
||||
margin-inline-start: px2rem(-12px);
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
|
||||
// Adjust spacing on next level item
|
||||
> .md-nav__list > .md-nav__item {
|
||||
@ -622,8 +670,7 @@
|
||||
// Modifier for when navigation tabs are rendered
|
||||
&--lifted {
|
||||
|
||||
// Hide nested level 0 navigation items and site title
|
||||
> .md-nav__list > .md-nav__item--nested,
|
||||
// Hide site title
|
||||
> .md-nav__title {
|
||||
display: none;
|
||||
}
|
||||
@ -635,16 +682,13 @@
|
||||
// Active parent navigation item
|
||||
&--active {
|
||||
display: block;
|
||||
padding: 0;
|
||||
|
||||
// Show navigation link as title
|
||||
> .md-nav__link {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
padding: 0 px2rem(12px);
|
||||
margin-top: 0;
|
||||
font-weight: 700;
|
||||
background: var(--md-default-bg-color);
|
||||
box-shadow: 0 0 px2rem(8px) px2rem(8px) var(--md-default-bg-color);
|
||||
|
||||
@ -652,12 +696,17 @@
|
||||
&:not(.md-nav__container) {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
// Hide naviation icon
|
||||
.md-nav__icon {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust spacing for navigation section
|
||||
&.md-nav__item--section {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust spacing for nested navigation
|
||||
> .md-nav {
|
||||
margin-inline-start: px2rem(-12px);
|
||||
}
|
||||
|
||||
// Make labels discernable from links
|
||||
@ -667,14 +716,11 @@
|
||||
}
|
||||
|
||||
// Hack: Always show active navigation tab on breakpoint screen, despite
|
||||
// of checkbox being checked or not. Fixes #1655.
|
||||
// of checkbox being checked or not - see https://t.ly/Qc311
|
||||
.md-nav[data-md-level="1"] {
|
||||
display: block;
|
||||
|
||||
// Adjust spacing for level 1 navigation items
|
||||
> .md-nav__list > .md-nav__item {
|
||||
padding-inline-end: px2rem(12px);
|
||||
}
|
||||
grid-template-rows: 1fr;
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -695,7 +741,15 @@
|
||||
.md-nav--secondary {
|
||||
display: block;
|
||||
margin-bottom: 1.25em;
|
||||
visibility: visible;
|
||||
border-inline-start: px2rem(1px) solid var(--md-primary-fg-color);
|
||||
opacity: 1;
|
||||
|
||||
// Navigation list
|
||||
> .md-nav__list {
|
||||
padding-bottom: 0;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
// Hide table of contents title
|
||||
> .md-nav__title {
|
||||
|
@ -53,7 +53,7 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: px2rem(12px);
|
||||
margin: 0 px2rem(12px);
|
||||
margin: 0 px2rem(12px) px2rem(24px);
|
||||
}
|
||||
|
||||
// Post metadata
|
||||
@ -70,6 +70,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Post navigation title @todo - generalize
|
||||
&__title {
|
||||
font-weight: 700;
|
||||
color: var(--md-default-fg-color--light);
|
||||
}
|
||||
|
||||
// Post excerpt
|
||||
&--excerpt {
|
||||
margin-bottom: px2rem(64px);
|
||||
@ -105,8 +111,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust spacing for navigation
|
||||
> .md-nav:first-child > .md-nav__list,
|
||||
// Add margin to table of contents
|
||||
> .md-nav--secondary {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
@ -36,7 +36,6 @@
|
||||
|
||||
// Status
|
||||
.md-status {
|
||||
margin-left: px2rem(4px);
|
||||
|
||||
// Status icon
|
||||
&::after {
|
||||
|
@ -36,7 +36,7 @@
|
||||
>
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner md-post">
|
||||
<nav class="md-nav">
|
||||
<nav class="md-nav md-nav--primary">
|
||||
|
||||
<!-- Back to overview link -->
|
||||
<div class="md-post__back">
|
||||
@ -50,7 +50,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Page authors -->
|
||||
<!-- Post authors -->
|
||||
{% if page.authors %}
|
||||
<div class="md-post__authors md-typeset">
|
||||
{% for author in page.authors %}
|
||||
@ -67,72 +67,82 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Page metadata -->
|
||||
<!-- Post metadata -->
|
||||
<ul class="md-post__meta md-nav__list">
|
||||
<li class="md-nav__item md-nav__title">
|
||||
<div class="md-nav__link">
|
||||
<li class="md-nav__item md-nav__item--section">
|
||||
<div class="md-post__title">
|
||||
<span class="md-ellipsis">
|
||||
{{ lang.t("blog.meta") }}
|
||||
</span>
|
||||
</div>
|
||||
<nav class="md-nav">
|
||||
<ul class="md-nav__list">
|
||||
|
||||
<!-- Post date -->
|
||||
<li class="md-nav__item">
|
||||
<div class="md-nav__link">
|
||||
{% include ".icons/material/calendar.svg" %}
|
||||
<time
|
||||
datetime="{{ page.config.date.created }}"
|
||||
class="md-ellipsis"
|
||||
>
|
||||
{{- page.config.date.created | date -}}
|
||||
</time>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<!-- Post date updated -->
|
||||
{% if page.config.date.updated %}
|
||||
<li class="md-nav__item">
|
||||
<div class="md-nav__link">
|
||||
{% include ".icons/material/calendar-clock.svg" %}
|
||||
<time
|
||||
datetime="{{ page.config.date.updated }}"
|
||||
class="md-ellipsis"
|
||||
>
|
||||
{{- page.config.date.updated | date -}}
|
||||
</time>
|
||||
</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
<!-- Post categories -->
|
||||
{% if page.categories %}
|
||||
<li class="md-nav__item">
|
||||
<div class="md-nav__link">
|
||||
{% include ".icons/material/bookshelf.svg" %}
|
||||
<span class="md-ellipsis">
|
||||
{{ lang.t("blog.categories.in") }}
|
||||
{% for category in page.categories %}
|
||||
<a href="{{ category.url | url }}">
|
||||
{{- category.title -}}
|
||||
</a>
|
||||
{%- if loop.revindex > 1 %}, {% endif -%}
|
||||
{% endfor -%}
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
<!-- Post readtime -->
|
||||
{% if page.config.readtime %}
|
||||
{% set time = page.config.readtime %}
|
||||
<li class="md-nav__item">
|
||||
<div class="md-nav__link">
|
||||
{% include ".icons/material/clock-outline.svg" %}
|
||||
<span class="md-ellipsis">
|
||||
{% if time == 1 %}
|
||||
{{ lang.t("readtime.one") }}
|
||||
{% else %}
|
||||
{{ lang.t("readtime.other") | replace("#", time) }}
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
|
||||
<!-- Page date -->
|
||||
<li class="md-nav__item">
|
||||
<div class="md-nav__link">
|
||||
{% include ".icons/material/calendar.svg" %}
|
||||
<time datetime="{{ page.config.date.created }}" class="md-ellipsis">
|
||||
{{- page.config.date.created | date -}}
|
||||
</time>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<!-- Page date updated -->
|
||||
{% if page.config.date.updated %}
|
||||
<li class="md-nav__item">
|
||||
<div class="md-nav__link">
|
||||
{% include ".icons/material/calendar-clock.svg" %}
|
||||
<time datetime="{{ page.config.date.updated }}" class="md-ellipsis">
|
||||
{{- page.config.date.updated | date -}}
|
||||
</time>
|
||||
</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
<!-- Page categories -->
|
||||
{% if page.categories %}
|
||||
<li class="md-nav__item">
|
||||
<div class="md-nav__link">
|
||||
{% include ".icons/material/bookshelf.svg" %}
|
||||
<span class="md-ellipsis">
|
||||
{{ lang.t("blog.categories.in") }}
|
||||
{% for category in page.categories %}
|
||||
<a href="{{ category.url | url }}">
|
||||
{{- category.title -}}
|
||||
</a>
|
||||
{%- if loop.revindex > 1 %}, {% endif -%}
|
||||
{% endfor -%}
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
<!-- Page readtime -->
|
||||
{% if page.config.readtime %}
|
||||
{% set time = page.config.readtime %}
|
||||
<li class="md-nav__item">
|
||||
<div class="md-nav__link">
|
||||
{% include ".icons/material/clock-outline.svg" %}
|
||||
<span class="md-ellipsis">
|
||||
{% if time == 1 %}
|
||||
{{ lang.t("readtime.one") }}
|
||||
{% else %}
|
||||
{{ lang.t("readtime.other") | replace("#", time) }}
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
|
@ -67,6 +67,7 @@
|
||||
"select.language": "Izberi jezik",
|
||||
"select.version": "Izberi različico",
|
||||
"source": "Pojdi na repozitorij",
|
||||
"source.file.contributors": "Soavtorji",
|
||||
"source.file.date.created": "Ustvarjeno",
|
||||
"source.file.date.updated": "Zadnja posodobitev",
|
||||
"tabs": "Zavihki",
|
||||
|
@ -101,26 +101,26 @@
|
||||
{% endif %}
|
||||
|
||||
<!-- Determine whether to render item as a section -->
|
||||
{% if "navigation.sections" in features and level == 1 + (
|
||||
"navigation.tabs" in features
|
||||
) %}
|
||||
{% set tabs = "navigation.tabs" in features %}
|
||||
{% set sections = "navigation.sections" in features %}
|
||||
{% if tabs and level == 1 or sections and tabs >= level - 1 %}
|
||||
{% set class = class ~ " md-nav__item--section" %}
|
||||
{% set is_section = true %}
|
||||
|
||||
<!-- Determine whether to prune inactive item -->
|
||||
{% elif not nav_item.active and "navigation.prune" in features %}
|
||||
{% set class = class ~ " md-nav__item--pruned" %}
|
||||
{% set prune = true %}
|
||||
{% set is_pruned = true %}
|
||||
{% endif %}
|
||||
|
||||
<!-- Nested navigation item -->
|
||||
<li class="{{ class }} md-nav__item--nested">
|
||||
{% if not prune %}
|
||||
{% set expanded = "navigation.expand" in features %}
|
||||
{% set active = nav_item.active or expanded %}
|
||||
{% if not is_pruned %}
|
||||
{% set checked = "checked" if nav_item.active %}
|
||||
|
||||
<!-- Determine checked and indeterminate state -->
|
||||
{% set checked = "checked" if nav_item.active %}
|
||||
{% if expanded and not checked %}
|
||||
{% set is_expanded = "navigation.expand" in features %}
|
||||
{% if is_expanded and not checked %}
|
||||
{% set indeterminate = "md-toggle--indeterminate" %}
|
||||
{% endif %}
|
||||
|
||||
@ -134,11 +134,12 @@
|
||||
|
||||
<!-- Toggle to expand nested items -->
|
||||
{% if not indexes %}
|
||||
{% set tabindex = "0" if not is_section %}
|
||||
<label
|
||||
class="md-nav__link"
|
||||
for="{{ path }}"
|
||||
id="{{ path }}_label"
|
||||
tabindex="0"
|
||||
tabindex="{{ tabindex }}"
|
||||
>
|
||||
{{ render_content(nav_item) }}
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
@ -158,7 +159,13 @@
|
||||
|
||||
<!-- Only render toggle if there's at least one more page -->
|
||||
{% if nav_item.children | length > 1 %}
|
||||
<label class="md-nav__link {{ class }}" for="{{ path }}">
|
||||
{% set tabindex = "0" if not is_section %}
|
||||
<label
|
||||
class="md-nav__link {{ class }}"
|
||||
for="{{ path }}"
|
||||
id="{{ path }}_label"
|
||||
tabindex="{{ tabindex }}"
|
||||
>
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
{% endif %}
|
||||
|
Loading…
Reference in New Issue
Block a user