zensical 0.0.12__cp310-abi3-musllinux_1_2_i686.whl → 0.0.17__cp310-abi3-musllinux_1_2_i686.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of zensical might be problematic. Click here for more details.
- zensical/__init__.py +2 -2
- zensical/__main__.py +2 -2
- zensical/bootstrap/zensical.toml +3 -3
- zensical/config.py +111 -34
- zensical/extensions/__init__.py +2 -2
- zensical/extensions/emoji.py +2 -2
- zensical/extensions/links.py +2 -2
- zensical/extensions/preview.py +2 -2
- zensical/extensions/search.py +3 -3
- zensical/extensions/utilities/__init__.py +2 -2
- zensical/extensions/utilities/filter.py +2 -2
- zensical/main.py +3 -3
- zensical/markdown.py +64 -4
- zensical/templates/.icons/lucide/LICENSE +39 -0
- zensical/templates/.icons/lucide/ampersand.svg +1 -1
- zensical/templates/.icons/lucide/anchor.svg +1 -1
- zensical/templates/.icons/lucide/balloon.svg +1 -0
- zensical/templates/.icons/lucide/birdhouse.svg +1 -0
- zensical/templates/.icons/lucide/book-search.svg +1 -0
- zensical/templates/.icons/lucide/brush-cleaning.svg +1 -1
- zensical/templates/.icons/lucide/bubbles.svg +1 -1
- zensical/templates/.icons/lucide/calendar-fold.svg +1 -1
- zensical/templates/.icons/lucide/calendars.svg +1 -0
- zensical/templates/.icons/lucide/cannabis-off.svg +1 -0
- zensical/templates/.icons/lucide/chess-bishop.svg +1 -0
- zensical/templates/.icons/lucide/chess-king.svg +1 -0
- zensical/templates/.icons/lucide/chess-knight.svg +1 -0
- zensical/templates/.icons/lucide/chess-pawn.svg +1 -0
- zensical/templates/.icons/lucide/chess-queen.svg +1 -0
- zensical/templates/.icons/lucide/chess-rook.svg +1 -0
- zensical/templates/.icons/lucide/circle-pile.svg +1 -0
- zensical/templates/.icons/lucide/clock-check.svg +1 -0
- zensical/templates/.icons/lucide/cloud-backup.svg +1 -0
- zensical/templates/.icons/lucide/cloud-sync.svg +1 -0
- zensical/templates/.icons/lucide/file-archive.svg +1 -1
- zensical/templates/.icons/lucide/file-audio-2.svg +1 -1
- zensical/templates/.icons/lucide/file-audio.svg +1 -1
- zensical/templates/.icons/lucide/file-axis-3-d.svg +1 -1
- zensical/templates/.icons/lucide/file-axis-3d.svg +1 -1
- zensical/templates/.icons/lucide/file-badge-2.svg +1 -1
- zensical/templates/.icons/lucide/file-badge.svg +1 -1
- zensical/templates/.icons/lucide/file-bar-chart-2.svg +1 -1
- zensical/templates/.icons/lucide/file-bar-chart.svg +1 -1
- zensical/templates/.icons/lucide/file-box.svg +1 -1
- zensical/templates/.icons/lucide/file-braces-corner.svg +1 -0
- zensical/templates/.icons/lucide/file-braces.svg +1 -0
- zensical/templates/.icons/lucide/file-chart-column-increasing.svg +1 -1
- zensical/templates/.icons/lucide/file-chart-column.svg +1 -1
- zensical/templates/.icons/lucide/file-chart-line.svg +1 -1
- zensical/templates/.icons/lucide/file-chart-pie.svg +1 -1
- zensical/templates/.icons/lucide/file-check-2.svg +1 -1
- zensical/templates/.icons/lucide/file-check-corner.svg +1 -0
- zensical/templates/.icons/lucide/file-check.svg +1 -1
- zensical/templates/.icons/lucide/file-clock.svg +1 -1
- zensical/templates/.icons/lucide/file-code-2.svg +1 -1
- zensical/templates/.icons/lucide/file-code-corner.svg +1 -0
- zensical/templates/.icons/lucide/file-code.svg +1 -1
- zensical/templates/.icons/lucide/file-cog-2.svg +1 -1
- zensical/templates/.icons/lucide/file-cog.svg +1 -1
- zensical/templates/.icons/lucide/file-diff.svg +1 -1
- zensical/templates/.icons/lucide/file-digit.svg +1 -1
- zensical/templates/.icons/lucide/file-down.svg +1 -1
- zensical/templates/.icons/lucide/file-edit.svg +1 -1
- zensical/templates/.icons/lucide/file-exclamation-point.svg +1 -0
- zensical/templates/.icons/lucide/file-headphone.svg +1 -0
- zensical/templates/.icons/lucide/file-heart.svg +1 -1
- zensical/templates/.icons/lucide/file-image.svg +1 -1
- zensical/templates/.icons/lucide/file-input.svg +1 -1
- zensical/templates/.icons/lucide/file-json-2.svg +1 -1
- zensical/templates/.icons/lucide/file-json.svg +1 -1
- zensical/templates/.icons/lucide/file-key-2.svg +1 -1
- zensical/templates/.icons/lucide/file-key.svg +1 -1
- zensical/templates/.icons/lucide/file-line-chart.svg +1 -1
- zensical/templates/.icons/lucide/file-lock-2.svg +1 -1
- zensical/templates/.icons/lucide/file-lock.svg +1 -1
- zensical/templates/.icons/lucide/file-minus-2.svg +1 -1
- zensical/templates/.icons/lucide/file-minus-corner.svg +1 -0
- zensical/templates/.icons/lucide/file-minus.svg +1 -1
- zensical/templates/.icons/lucide/file-music.svg +1 -1
- zensical/templates/.icons/lucide/file-output.svg +1 -1
- zensical/templates/.icons/lucide/file-pen-line.svg +1 -1
- zensical/templates/.icons/lucide/file-pen.svg +1 -1
- zensical/templates/.icons/lucide/file-pie-chart.svg +1 -1
- zensical/templates/.icons/lucide/file-play.svg +1 -1
- zensical/templates/.icons/lucide/file-plus-2.svg +1 -1
- zensical/templates/.icons/lucide/file-plus-corner.svg +1 -0
- zensical/templates/.icons/lucide/file-plus.svg +1 -1
- zensical/templates/.icons/lucide/file-question-mark.svg +1 -1
- zensical/templates/.icons/lucide/file-question.svg +1 -1
- zensical/templates/.icons/lucide/file-scan.svg +1 -1
- zensical/templates/.icons/lucide/file-search-2.svg +1 -1
- zensical/templates/.icons/lucide/file-search-corner.svg +1 -0
- zensical/templates/.icons/lucide/file-search.svg +1 -1
- zensical/templates/.icons/lucide/file-signal.svg +1 -0
- zensical/templates/.icons/lucide/file-signature.svg +1 -1
- zensical/templates/.icons/lucide/file-sliders.svg +1 -1
- zensical/templates/.icons/lucide/file-spreadsheet.svg +1 -1
- zensical/templates/.icons/lucide/file-symlink.svg +1 -1
- zensical/templates/.icons/lucide/file-terminal.svg +1 -1
- zensical/templates/.icons/lucide/file-text.svg +1 -1
- zensical/templates/.icons/lucide/file-type-2.svg +1 -1
- zensical/templates/.icons/lucide/file-type-corner.svg +1 -0
- zensical/templates/.icons/lucide/file-type.svg +1 -1
- zensical/templates/.icons/lucide/file-up.svg +1 -1
- zensical/templates/.icons/lucide/file-user.svg +1 -1
- zensical/templates/.icons/lucide/file-video-2.svg +1 -1
- zensical/templates/.icons/lucide/file-video-camera.svg +1 -1
- zensical/templates/.icons/lucide/file-video.svg +1 -1
- zensical/templates/.icons/lucide/file-volume-2.svg +1 -1
- zensical/templates/.icons/lucide/file-volume.svg +1 -1
- zensical/templates/.icons/lucide/file-warning.svg +1 -1
- zensical/templates/.icons/lucide/file-x-2.svg +1 -1
- zensical/templates/.icons/lucide/file-x-corner.svg +1 -0
- zensical/templates/.icons/lucide/file-x.svg +1 -1
- zensical/templates/.icons/lucide/file.svg +1 -1
- zensical/templates/.icons/lucide/files.svg +1 -1
- zensical/templates/.icons/lucide/fingerprint-pattern.svg +1 -0
- zensical/templates/.icons/lucide/fishing-hook.svg +1 -0
- zensical/templates/.icons/lucide/flashlight-off.svg +1 -1
- zensical/templates/.icons/lucide/flashlight.svg +1 -1
- zensical/templates/.icons/lucide/folder-git-2.svg +1 -1
- zensical/templates/.icons/lucide/form.svg +1 -0
- zensical/templates/.icons/lucide/gamepad-directional.svg +1 -0
- zensical/templates/.icons/lucide/git-branch-minus.svg +1 -0
- zensical/templates/.icons/lucide/hd.svg +1 -0
- zensical/templates/.icons/lucide/helicopter.svg +1 -0
- zensical/templates/.icons/lucide/layers-plus.svg +1 -0
- zensical/templates/.icons/lucide/memory-stick.svg +1 -1
- zensical/templates/.icons/lucide/microchip.svg +1 -1
- zensical/templates/.icons/lucide/mouse-pointer-2-off.svg +1 -0
- zensical/templates/.icons/lucide/paint-bucket.svg +1 -1
- zensical/templates/.icons/lucide/plug.svg +1 -1
- zensical/templates/.icons/lucide/ruler-dimension-line.svg +1 -1
- zensical/templates/.icons/lucide/scale.svg +1 -1
- zensical/templates/.icons/lucide/scissors-square-dashed-bottom.svg +1 -1
- zensical/templates/.icons/lucide/scissors-square.svg +1 -1
- zensical/templates/.icons/lucide/scooter.svg +1 -0
- zensical/templates/.icons/lucide/search-alert.svg +1 -0
- zensical/templates/.icons/lucide/shredder.svg +1 -1
- zensical/templates/.icons/lucide/solar-panel.svg +1 -0
- zensical/templates/.icons/lucide/square-bottom-dashed-scissors.svg +1 -1
- zensical/templates/.icons/lucide/square-scissors.svg +1 -1
- zensical/templates/.icons/lucide/sticker.svg +1 -1
- zensical/templates/.icons/lucide/sticky-note.svg +1 -1
- zensical/templates/.icons/lucide/stone.svg +1 -0
- zensical/templates/.icons/lucide/thermometer-sun.svg +1 -1
- zensical/templates/.icons/lucide/thumbs-down.svg +1 -1
- zensical/templates/.icons/lucide/thumbs-up.svg +1 -1
- zensical/templates/.icons/lucide/tickets-plane.svg +1 -1
- zensical/templates/.icons/lucide/tickets.svg +1 -1
- zensical/templates/.icons/lucide/toolbox.svg +1 -0
- zensical/templates/.icons/lucide/van.svg +1 -0
- zensical/templates/.icons/lucide/waves-arrow-down.svg +1 -0
- zensical/templates/.icons/lucide/waves-arrow-up.svg +1 -0
- zensical/templates/.icons/lucide/weight-tilde.svg +1 -0
- zensical/templates/.icons/octicons/boolean-off-16.svg +1 -0
- zensical/templates/.icons/octicons/boolean-off-24.svg +1 -0
- zensical/templates/.icons/octicons/boolean-on-16.svg +1 -0
- zensical/templates/.icons/octicons/boolean-on-24.svg +1 -0
- zensical/templates/.icons/octicons/compose-16.svg +1 -0
- zensical/templates/.icons/octicons/compose-24.svg +1 -0
- zensical/templates/.icons/octicons/crosshairs-16.svg +1 -0
- zensical/templates/.icons/octicons/crosshairs-24.svg +1 -0
- zensical/templates/.icons/octicons/dice-16.svg +1 -0
- zensical/templates/.icons/octicons/dice-24.svg +1 -0
- zensical/templates/.icons/octicons/exclamation-16.svg +1 -0
- zensical/templates/.icons/octicons/exclamation-24.svg +1 -0
- zensical/templates/.icons/octicons/file-check-16.svg +1 -0
- zensical/templates/.icons/octicons/file-check-24.svg +1 -0
- zensical/templates/.icons/octicons/flowchart-16.svg +1 -0
- zensical/templates/.icons/octicons/flowchart-24.svg +1 -0
- zensical/templates/.icons/octicons/focus-center-16.svg +1 -0
- zensical/templates/.icons/octicons/focus-center-24.svg +1 -0
- zensical/templates/.icons/octicons/git-branch-check-16.svg +1 -0
- zensical/templates/.icons/octicons/git-branch-check-24.svg +1 -0
- zensical/templates/.icons/octicons/graph-bar-horizontal-16.svg +1 -0
- zensical/templates/.icons/octicons/graph-bar-horizontal-24.svg +1 -0
- zensical/templates/.icons/octicons/graph-bar-vertical-16.svg +1 -0
- zensical/templates/.icons/octicons/graph-bar-vertical-24.svg +1 -0
- zensical/templates/.icons/octicons/inbox-fill-16.svg +1 -0
- zensical/templates/.icons/octicons/inbox-fill-24.svg +1 -0
- zensical/templates/.icons/octicons/node-16.svg +1 -0
- zensical/templates/.icons/octicons/node-24.svg +1 -0
- zensical/templates/.icons/octicons/pencil-ai-16.svg +1 -0
- zensical/templates/.icons/octicons/pencil-ai-24.svg +1 -0
- zensical/templates/.icons/octicons/smiley-frown-16.svg +1 -0
- zensical/templates/.icons/octicons/smiley-frown-24.svg +1 -0
- zensical/templates/.icons/octicons/smiley-frustrated-16.svg +1 -0
- zensical/templates/.icons/octicons/smiley-frustrated-24.svg +1 -0
- zensical/templates/.icons/octicons/smiley-grin-16.svg +1 -0
- zensical/templates/.icons/octicons/smiley-grin-24.svg +1 -0
- zensical/templates/.icons/octicons/smiley-neutral-16.svg +1 -0
- zensical/templates/.icons/octicons/smiley-neutral-24.svg +1 -0
- zensical/templates/.icons/octicons/spacing-large-16.svg +1 -0
- zensical/templates/.icons/octicons/spacing-large-24.svg +1 -0
- zensical/templates/.icons/octicons/spacing-medium-16.svg +1 -0
- zensical/templates/.icons/octicons/spacing-medium-24.svg +1 -0
- zensical/templates/.icons/octicons/spacing-small-16.svg +1 -0
- zensical/templates/.icons/octicons/spacing-small-24.svg +1 -0
- zensical/templates/.icons/octicons/split-view-16.svg +1 -0
- zensical/templates/.icons/octicons/split-view-24.svg +1 -0
- zensical/templates/.icons/octicons/unwrap-16.svg +1 -0
- zensical/templates/.icons/octicons/unwrap-24.svg +1 -0
- zensical/templates/.icons/octicons/vscode-16.svg +1 -1
- zensical/templates/.icons/octicons/vscode-32.svg +1 -1
- zensical/templates/.icons/octicons/vscode-48.svg +1 -1
- zensical/templates/.icons/octicons/wrap-16.svg +1 -0
- zensical/templates/.icons/octicons/wrap-24.svg +1 -0
- zensical/templates/.icons/simple/acode.svg +1 -0
- zensical/templates/.icons/simple/apacheavro.svg +1 -0
- zensical/templates/.icons/simple/appimage.svg +1 -0
- zensical/templates/.icons/simple/appmanager.svg +1 -0
- zensical/templates/.icons/simple/autentique.svg +1 -0
- zensical/templates/.icons/simple/b4x.svg +1 -0
- zensical/templates/.icons/simple/bioconductor.svg +1 -0
- zensical/templates/.icons/simple/coolify.svg +1 -0
- zensical/templates/.icons/simple/cursor.svg +1 -0
- zensical/templates/.icons/simple/dash0.svg +1 -0
- zensical/templates/.icons/simple/dodopayments.svg +1 -0
- zensical/templates/.icons/simple/elk.svg +1 -0
- zensical/templates/.icons/simple/fishaudio.svg +1 -0
- zensical/templates/.icons/simple/ghostty.svg +1 -0
- zensical/templates/.icons/simple/glance.svg +1 -0
- zensical/templates/.icons/simple/hashcat.svg +1 -0
- zensical/templates/.icons/simple/kando.svg +1 -0
- zensical/templates/.icons/simple/labex.svg +1 -0
- zensical/templates/.icons/simple/listenhub.svg +1 -0
- zensical/templates/.icons/simple/luanti.svg +1 -0
- zensical/templates/.icons/simple/maas.svg +1 -1
- zensical/templates/.icons/simple/mailbox.svg +1 -0
- zensical/templates/.icons/simple/mangacollec.svg +1 -0
- zensical/templates/.icons/simple/mdblist.svg +1 -0
- zensical/templates/.icons/simple/minimax.svg +1 -0
- zensical/templates/.icons/simple/newgrounds.svg +1 -0
- zensical/templates/.icons/simple/nodegui.svg +1 -0
- zensical/templates/.icons/simple/openrouter.svg +1 -0
- zensical/templates/.icons/simple/passbolt.svg +1 -0
- zensical/templates/.icons/simple/plane.svg +1 -0
- zensical/templates/.icons/simple/postiz.svg +1 -0
- zensical/templates/.icons/simple/qlty.svg +1 -0
- zensical/templates/.icons/simple/rekaui.svg +1 -0
- zensical/templates/.icons/simple/retroachievements.svg +1 -0
- zensical/templates/.icons/simple/root.svg +1 -0
- zensical/templates/.icons/simple/setuptools.svg +1 -0
- zensical/templates/.icons/simple/tanstack.svg +1 -0
- zensical/templates/.icons/simple/textual.svg +1 -0
- zensical/templates/assets/javascripts/LICENSE +29 -0
- zensical/templates/assets/javascripts/bundle.8ffeb9c9.min.js +3 -0
- zensical/templates/assets/javascripts/workers/search.e2d2d235.min.js +1 -0
- zensical/templates/assets/stylesheets/classic/main.9a39631f.min.css +1 -0
- zensical/templates/assets/stylesheets/modern/main.d4922b3c.min.css +1 -0
- zensical/templates/base.html +4 -4
- zensical/zensical.abi3.so +0 -0
- zensical/zensical.pyi +2 -2
- {zensical-0.0.12.dist-info → zensical-0.0.17.dist-info}/METADATA +4 -4
- {zensical-0.0.12.dist-info → zensical-0.0.17.dist-info}/RECORD +261 -171
- {zensical-0.0.12.dist-info → zensical-0.0.17.dist-info}/WHEEL +1 -1
- {zensical-0.0.12.dist-info → zensical-0.0.17.dist-info}/licenses/LICENSE.md +1 -1
- zensical/templates/.icons/simple/aerlingus.svg +0 -1
- zensical/templates/.icons/simple/aerospike.svg +0 -1
- zensical/templates/.icons/simple/aew.svg +0 -1
- zensical/templates/.icons/simple/affinity.svg +0 -1
- zensical/templates/.icons/simple/affinitydesigner.svg +0 -1
- zensical/templates/.icons/simple/affinityphoto.svg +0 -1
- zensical/templates/.icons/simple/affinitypublisher.svg +0 -1
- zensical/templates/.icons/simple/alfaromeo.svg +0 -1
- zensical/templates/.icons/simple/allocine.svg +0 -1
- zensical/templates/.icons/simple/alteryx.svg +0 -1
- zensical/templates/.icons/simple/altiumdesigner.svg +0 -1
- zensical/templates/.icons/simple/alx.svg +0 -1
- zensical/templates/.icons/simple/authy.svg +0 -1
- zensical/templates/.icons/simple/canva.svg +0 -1
- zensical/templates/.icons/simple/codepen.svg +0 -1
- zensical/templates/.icons/simple/cognizant.svg +0 -1
- zensical/templates/.icons/simple/dbt.svg +0 -1
- zensical/templates/.icons/simple/flipkart.svg +0 -1
- zensical/templates/.icons/simple/googlefit.svg +0 -1
- zensical/templates/.icons/simple/heroku.svg +0 -1
- zensical/templates/.icons/simple/informatica.svg +0 -1
- zensical/templates/.icons/simple/invision.svg +0 -1
- zensical/templates/.icons/simple/jaguar.svg +0 -1
- zensical/templates/.icons/simple/landrover.svg +0 -1
- zensical/templates/.icons/simple/logitech.svg +0 -1
- zensical/templates/.icons/simple/logitechg.svg +0 -1
- zensical/templates/.icons/simple/mailboxdotorg.svg +0 -1
- zensical/templates/.icons/simple/minetest.svg +0 -1
- zensical/templates/.icons/simple/mulesoft.svg +0 -1
- zensical/templates/.icons/simple/musescore.svg +0 -1
- zensical/templates/.icons/simple/nexusmods.svg +0 -1
- zensical/templates/.icons/simple/openai.svg +0 -1
- zensical/templates/.icons/simple/pocket.svg +0 -1
- zensical/templates/.icons/simple/quip.svg +0 -1
- zensical/templates/.icons/simple/salesforce.svg +0 -1
- zensical/templates/.icons/simple/scribd.svg +0 -1
- zensical/templates/.icons/simple/sendgrid.svg +0 -1
- zensical/templates/.icons/simple/shutterstock.svg +0 -1
- zensical/templates/.icons/simple/slack.svg +0 -1
- zensical/templates/.icons/simple/tunein.svg +0 -1
- zensical/templates/.icons/simple/twilio.svg +0 -1
- zensical/templates/.icons/simple/walmart.svg +0 -1
- zensical/templates/.icons/simple/warnerbros.svg +0 -1
- zensical/templates/.icons/simple/westerndigital.svg +0 -1
- zensical/templates/assets/javascripts/bundle.21aa498e.min.js +0 -3
- zensical/templates/assets/javascripts/workers/search.5df7522c.min.js +0 -1
- zensical/templates/assets/stylesheets/classic/main.6f483be1.min.css +0 -1
- zensical/templates/assets/stylesheets/modern/main.09f707be.min.css +0 -1
- {zensical-0.0.12.dist-info → zensical-0.0.17.dist-info}/entry_points.txt +0 -0
zensical/__init__.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# Copyright (c) 2025 Zensical and contributors
|
|
1
|
+
# Copyright (c) 2025-2026 Zensical and contributors
|
|
2
2
|
|
|
3
3
|
# SPDX-License-Identifier: MIT
|
|
4
|
-
#
|
|
4
|
+
# All contributions are certified under the DCO
|
|
5
5
|
|
|
6
6
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
# of this software and associated documentation files (the "Software"), to
|
zensical/__main__.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# Copyright (c) 2025 Zensical and contributors
|
|
1
|
+
# Copyright (c) 2025-2026 Zensical and contributors
|
|
2
2
|
|
|
3
3
|
# SPDX-License-Identifier: MIT
|
|
4
|
-
#
|
|
4
|
+
# All contributions are certified under the DCO
|
|
5
5
|
|
|
6
6
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
# of this software and associated documentation files (the "Software"), to
|
zensical/bootstrap/zensical.toml
CHANGED
|
@@ -34,7 +34,7 @@ site_author = "<your name here>"
|
|
|
34
34
|
#
|
|
35
35
|
# Read more: https://zensical.org/docs/setup/basics/#copyright
|
|
36
36
|
copyright = """
|
|
37
|
-
Copyright ©
|
|
37
|
+
Copyright © 2026 The authors
|
|
38
38
|
"""
|
|
39
39
|
|
|
40
40
|
# Zensical supports both implicit navigation and explicitly defined navigation.
|
|
@@ -118,13 +118,13 @@ features = [
|
|
|
118
118
|
# https://zensical.org/docs/setup/header/#announcement-bar
|
|
119
119
|
"announce.dismiss",
|
|
120
120
|
|
|
121
|
-
# If you have a repository configured and turn
|
|
121
|
+
# If you have a repository configured and turn on this feature, Zensical
|
|
122
122
|
# will generate an edit button for the page. This works for common
|
|
123
123
|
# repository hosting services.
|
|
124
124
|
# https://zensical.org/docs/setup/repository/#code-actions
|
|
125
125
|
#"content.action.edit",
|
|
126
126
|
|
|
127
|
-
# If you have a repository configured and turn
|
|
127
|
+
# If you have a repository configured and turn on this feature, Zensical
|
|
128
128
|
# will generate a button that allows the user to view the Markdown
|
|
129
129
|
# code for the current page.
|
|
130
130
|
# https://zensical.org/docs/setup/repository/#code-actions
|
zensical/config.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# Copyright (c) 2025 Zensical and contributors
|
|
1
|
+
# Copyright (c) 2025-2026 Zensical and contributors
|
|
2
2
|
|
|
3
3
|
# SPDX-License-Identifier: MIT
|
|
4
|
-
#
|
|
4
|
+
# All contributions are certified under the DCO
|
|
5
5
|
|
|
6
6
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
# of this software and associated documentation files (the "Software"), to
|
|
@@ -26,6 +26,7 @@ from __future__ import annotations
|
|
|
26
26
|
import hashlib
|
|
27
27
|
import importlib
|
|
28
28
|
import os
|
|
29
|
+
from pathlib import Path
|
|
29
30
|
import pickle
|
|
30
31
|
from typing import IO, Any
|
|
31
32
|
from urllib.parse import urlparse
|
|
@@ -118,6 +119,16 @@ def get_theme_dir() -> str:
|
|
|
118
119
|
return os.path.join(path, "templates")
|
|
119
120
|
|
|
120
121
|
|
|
122
|
+
def get_custom_theme_dir(config: dict) -> str | None:
|
|
123
|
+
"""Return the custom theme directory."""
|
|
124
|
+
path = os.path.dirname(os.path.abspath(__file__))
|
|
125
|
+
if config["theme"].get("custom_dir"):
|
|
126
|
+
return os.path.join(path, config["theme"].get("custom_dir"))
|
|
127
|
+
|
|
128
|
+
# Otherwise, return no path
|
|
129
|
+
return None
|
|
130
|
+
|
|
131
|
+
|
|
121
132
|
def _apply_defaults(config: dict, path: str) -> dict:
|
|
122
133
|
"""Apply default settings in configuration.
|
|
123
134
|
|
|
@@ -161,20 +172,21 @@ def _apply_defaults(config: dict, path: str) -> dict:
|
|
|
161
172
|
repo_names = {
|
|
162
173
|
"github.com": "GitHub",
|
|
163
174
|
"gitlab.com": "Gitlab",
|
|
164
|
-
"bitbucket.org": "Bitbucket"
|
|
175
|
+
"bitbucket.org": "Bitbucket",
|
|
165
176
|
}
|
|
166
177
|
edit_uris = {
|
|
167
178
|
"github.com": f"edit/master/{docs_dir}",
|
|
168
179
|
"gitlab.com": f"edit/master/{docs_dir}",
|
|
169
|
-
"bitbucket.org": f"src/default/{docs_dir}"
|
|
180
|
+
"bitbucket.org": f"src/default/{docs_dir}",
|
|
170
181
|
}
|
|
171
182
|
repo_url = config.get("repo_url")
|
|
172
183
|
if repo_url:
|
|
173
184
|
host = urlparse(repo_url).hostname or ""
|
|
174
|
-
if not config.get("repo_name")
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
185
|
+
if not config.get("repo_name"):
|
|
186
|
+
if host in repo_names:
|
|
187
|
+
set_default(config, "repo_name", repo_names[host], str)
|
|
188
|
+
elif host:
|
|
189
|
+
config["repo_name"] = host.split(".")[0].title()
|
|
178
190
|
if host in edit_uris:
|
|
179
191
|
set_default(config, "edit_uri", edit_uris[host], str)
|
|
180
192
|
|
|
@@ -251,18 +263,12 @@ def _apply_defaults(config: dict, path: str) -> dict:
|
|
|
251
263
|
|
|
252
264
|
# Set defaults for theme admonition icons
|
|
253
265
|
admonition = set_default(icon, "admonition", {}, dict)
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
set_default(admonition, "warning", None, str)
|
|
261
|
-
set_default(admonition, "failure", None, str)
|
|
262
|
-
set_default(admonition, "danger", None, str)
|
|
263
|
-
set_default(admonition, "bug", None, str)
|
|
264
|
-
set_default(admonition, "example", None, str)
|
|
265
|
-
set_default(admonition, "quote", None, str)
|
|
266
|
+
if isinstance(admonition, dict):
|
|
267
|
+
icon["admonition"] = {
|
|
268
|
+
str(key): str(value)
|
|
269
|
+
for key, value in admonition.items()
|
|
270
|
+
if value is not None
|
|
271
|
+
}
|
|
266
272
|
|
|
267
273
|
# Set defaults for theme palette settings and normalize to list
|
|
268
274
|
palette = theme.setdefault("palette", [])
|
|
@@ -286,11 +292,15 @@ def _apply_defaults(config: dict, path: str) -> dict:
|
|
|
286
292
|
|
|
287
293
|
# Set defaults for extra settings
|
|
288
294
|
if "extra" in config and not isinstance(config["extra"], dict):
|
|
289
|
-
raise ConfigurationError(
|
|
295
|
+
raise ConfigurationError(
|
|
296
|
+
"The 'extra' setting must be a mapping/dictionary."
|
|
297
|
+
)
|
|
290
298
|
extra = set_default(config, "extra", {}, dict)
|
|
291
299
|
|
|
292
300
|
if "polyfills" in extra and not isinstance(extra["polyfills"], list):
|
|
293
|
-
raise ConfigurationError(
|
|
301
|
+
raise ConfigurationError(
|
|
302
|
+
"The 'extra.polyfills' setting must be a list."
|
|
303
|
+
)
|
|
294
304
|
set_default(extra, "polyfills", [], list)
|
|
295
305
|
|
|
296
306
|
# Ensure all non-existent values are all empty strings (for now)
|
|
@@ -368,7 +378,9 @@ def _apply_defaults(config: dict, path: str) -> dict:
|
|
|
368
378
|
tabbed = config["mdx_configs"].get("pymdownx.tabbed", {})
|
|
369
379
|
if isinstance(tabbed.get("slugify"), dict):
|
|
370
380
|
object = tabbed["slugify"].get("object", "pymdownx.slugs.slugify")
|
|
371
|
-
tabbed["slugify"] = _resolve(object)(
|
|
381
|
+
tabbed["slugify"] = _resolve(object)(
|
|
382
|
+
**tabbed["slugify"].get("kwds", {})
|
|
383
|
+
)
|
|
372
384
|
|
|
373
385
|
# Table of contents extension configuration - resolve slugification function
|
|
374
386
|
toc = config["mdx_configs"]["toc"]
|
|
@@ -382,14 +394,22 @@ def _apply_defaults(config: dict, path: str) -> dict:
|
|
|
382
394
|
if isinstance(fence.get("format"), str):
|
|
383
395
|
fence["format"] = _resolve(fence.get("format"))
|
|
384
396
|
elif isinstance(fence.get("format"), dict):
|
|
385
|
-
object = fence["format"].get(
|
|
386
|
-
|
|
397
|
+
object = fence["format"].get(
|
|
398
|
+
"object", "pymdownx.superfences.fence_code_format"
|
|
399
|
+
)
|
|
400
|
+
fence["format"] = _resolve(object)(
|
|
401
|
+
**fence["format"].get("kwds", {})
|
|
402
|
+
)
|
|
387
403
|
if isinstance(fence.get("validator"), str):
|
|
388
404
|
fence["validator"] = _resolve(fence.get("validator"))
|
|
389
405
|
elif isinstance(fence.get("validator"), dict):
|
|
390
406
|
object = fence["validator"].get("object")
|
|
391
|
-
callable_object =
|
|
392
|
-
|
|
407
|
+
callable_object = (
|
|
408
|
+
_resolve(object) if object else lambda *args, **kwargs: True
|
|
409
|
+
)
|
|
410
|
+
fence["validator"] = callable_object(
|
|
411
|
+
**fence["validator"].get("kwds", {})
|
|
412
|
+
)
|
|
393
413
|
|
|
394
414
|
# Ensure the table of contents title is initialized, as it's used inside
|
|
395
415
|
# the template, and the table of contents extension is always defined
|
|
@@ -399,7 +419,7 @@ def _apply_defaults(config: dict, path: str) -> dict:
|
|
|
399
419
|
# Convert plugins configuration
|
|
400
420
|
config["plugins"] = _convert_plugins(config.get("plugins", []), config)
|
|
401
421
|
|
|
402
|
-
# mkdocstrings
|
|
422
|
+
# Set up mkdocstrings, which touches plugins and Markdown extensions
|
|
403
423
|
if "mkdocstrings" in config["plugins"]:
|
|
404
424
|
mkdocstrings_config = config["plugins"]["mkdocstrings"]["config"]
|
|
405
425
|
if mkdocstrings_config.pop("enabled", True):
|
|
@@ -409,13 +429,21 @@ def _apply_defaults(config: dict, path: str) -> dict:
|
|
|
409
429
|
config["markdown_extensions"].append("mkdocstrings")
|
|
410
430
|
config["mdx_configs"]["mkdocstrings"] = mkdocstrings_config
|
|
411
431
|
|
|
432
|
+
# List all source files for mkdocstrings
|
|
433
|
+
config["source_files"] = _list_sources(config, path)
|
|
434
|
+
|
|
435
|
+
# Hash all templates, so we rebuild if something changes
|
|
436
|
+
config["template_hash"] = _hash(_list_templates(config))
|
|
412
437
|
return config
|
|
413
438
|
|
|
414
439
|
|
|
415
440
|
def set_default(
|
|
416
441
|
entry: dict, key: str, default: Any, data_type: type | None = None
|
|
417
442
|
) -> Any:
|
|
418
|
-
"""Set a key to a default value if it isn't set
|
|
443
|
+
"""Set a key to a default value if it isn't set.
|
|
444
|
+
|
|
445
|
+
Optionally cast it to the specified data type.
|
|
446
|
+
"""
|
|
419
447
|
if key in entry and entry[key] is None:
|
|
420
448
|
del entry[key]
|
|
421
449
|
|
|
@@ -441,8 +469,56 @@ def _hash(data: Any) -> int:
|
|
|
441
469
|
return int(hash.hexdigest(), 16) % (2**64)
|
|
442
470
|
|
|
443
471
|
|
|
472
|
+
def _list_sources(config: dict, config_file: str) -> list[tuple[str, int]]:
|
|
473
|
+
"""List all absolute links to source files for mkdocstrings."""
|
|
474
|
+
python_paths = (
|
|
475
|
+
config["plugins"]
|
|
476
|
+
.get("mkdocstrings", {})
|
|
477
|
+
.get("config", {})
|
|
478
|
+
.get("handlers", {})
|
|
479
|
+
.get("python", {})
|
|
480
|
+
.get("paths", ())
|
|
481
|
+
)
|
|
482
|
+
roots_with_hash = []
|
|
483
|
+
for python_path in python_paths:
|
|
484
|
+
path = Path(config_file).parent.joinpath(python_path).resolve()
|
|
485
|
+
|
|
486
|
+
# Collect all files under this root with modification times to detect
|
|
487
|
+
# changes. We'll replace this with proper dependency tracking later.
|
|
488
|
+
files = [(path, int(os.path.getmtime(path)))]
|
|
489
|
+
if path.is_dir():
|
|
490
|
+
for subpath in path.rglob("*"):
|
|
491
|
+
files.extend([(subpath, int(os.path.getmtime(subpath)))])
|
|
492
|
+
roots_with_hash.append((str(path), _hash(files)))
|
|
493
|
+
|
|
494
|
+
return sorted(roots_with_hash)
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
def _list_templates(config: dict) -> list[tuple[str, int]]:
|
|
498
|
+
"""List all template files in the theme directories."""
|
|
499
|
+
dirs = [get_theme_dir()]
|
|
500
|
+
if "custom_dir" in config["theme"]:
|
|
501
|
+
custom_dir = get_custom_theme_dir(config)
|
|
502
|
+
if custom_dir is not None:
|
|
503
|
+
dirs.append(custom_dir)
|
|
504
|
+
|
|
505
|
+
# Collect file paths and their mtimes
|
|
506
|
+
files_with_mtime = []
|
|
507
|
+
for directory in dirs:
|
|
508
|
+
for path, _, files in os.walk(directory):
|
|
509
|
+
if ".icons" in path:
|
|
510
|
+
continue
|
|
511
|
+
for file in files:
|
|
512
|
+
file_path = os.path.join(path, file)
|
|
513
|
+
mtime = int(os.path.getmtime(file_path))
|
|
514
|
+
files_with_mtime.append((file_path, mtime))
|
|
515
|
+
|
|
516
|
+
# Sort by file path for deterministic order
|
|
517
|
+
return sorted(files_with_mtime)
|
|
518
|
+
|
|
519
|
+
|
|
444
520
|
def _convert_extra(data: dict | list) -> dict | list:
|
|
445
|
-
"""Recursively convert
|
|
521
|
+
"""Recursively convert None values in a dictionary/list to empty strings."""
|
|
446
522
|
if isinstance(data, dict):
|
|
447
523
|
# Process each key-value pair in the dictionary
|
|
448
524
|
return {
|
|
@@ -478,7 +554,7 @@ def _convert_nav(nav: list) -> list:
|
|
|
478
554
|
|
|
479
555
|
|
|
480
556
|
def _convert_nav_item(item: str | dict | list) -> dict | list:
|
|
481
|
-
"""Convert MkDocs shorthand navigation structure into something
|
|
557
|
+
"""Convert MkDocs shorthand navigation structure into something manageable.
|
|
482
558
|
|
|
483
559
|
We need to annotate each item with a title, URL, icon, and children.
|
|
484
560
|
"""
|
|
@@ -559,7 +635,7 @@ def _convert_extra_javascript(value: list) -> list:
|
|
|
559
635
|
|
|
560
636
|
|
|
561
637
|
def _convert_markdown_extensions(value: Any) -> tuple[list[str], dict]:
|
|
562
|
-
"""Convert Markdown extensions
|
|
638
|
+
"""Convert Markdown extensions to what Python Markdown expects."""
|
|
563
639
|
markdown_extensions = ["toc", "tables"]
|
|
564
640
|
mdx_configs: dict[str, dict[str, Any]] = {"toc": {}, "tables": {}}
|
|
565
641
|
|
|
@@ -674,7 +750,7 @@ def _convert_plugins(value: Any, config: dict) -> dict:
|
|
|
674
750
|
def _yaml_load(
|
|
675
751
|
source: IO, loader: type[BaseLoader] | None = None
|
|
676
752
|
) -> dict[str, Any]:
|
|
677
|
-
"""Load configuration file
|
|
753
|
+
"""Load configuration file, resolve environment variables and parent files.
|
|
678
754
|
|
|
679
755
|
Note that INHERIT is only a bandaid that was introduced to allow for some
|
|
680
756
|
degree of modularity, but with serious shortcomings. Zensical will use a
|
|
@@ -706,7 +782,8 @@ def _yaml_load(
|
|
|
706
782
|
)
|
|
707
783
|
if not os.path.exists(abspath):
|
|
708
784
|
raise ConfigurationError(
|
|
709
|
-
f"Inherited config file '{relpath}'
|
|
785
|
+
f"Inherited config file '{relpath}' "
|
|
786
|
+
f"doesn't exist at '{abspath}'."
|
|
710
787
|
)
|
|
711
788
|
with open(abspath, encoding="utf-8") as fd:
|
|
712
789
|
parent = _yaml_load(fd, loader)
|
zensical/extensions/__init__.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# Copyright (c) 2025 Zensical and contributors
|
|
1
|
+
# Copyright (c) 2025-2026 Zensical and contributors
|
|
2
2
|
|
|
3
3
|
# SPDX-License-Identifier: MIT
|
|
4
|
-
#
|
|
4
|
+
# All contributions are certified under the DCO
|
|
5
5
|
|
|
6
6
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
# of this software and associated documentation files (the "Software"), to
|
zensical/extensions/emoji.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# Copyright (c) 2025 Zensical and contributors
|
|
1
|
+
# Copyright (c) 2025-2026 Zensical and contributors
|
|
2
2
|
|
|
3
3
|
# SPDX-License-Identifier: MIT
|
|
4
|
-
#
|
|
4
|
+
# All contributions are certified under the DCO
|
|
5
5
|
|
|
6
6
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
# of this software and associated documentation files (the "Software"), to
|
zensical/extensions/links.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# Copyright (c) 2025 Zensical and contributors
|
|
1
|
+
# Copyright (c) 2025-2026 Zensical and contributors
|
|
2
2
|
|
|
3
3
|
# SPDX-License-Identifier: MIT
|
|
4
|
-
#
|
|
4
|
+
# All contributions are certified under the DCO
|
|
5
5
|
|
|
6
6
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
# of this software and associated documentation files (the "Software"), to
|
zensical/extensions/preview.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# Copyright (c) 2025 Zensical and contributors
|
|
1
|
+
# Copyright (c) 2025-2026 Zensical and contributors
|
|
2
2
|
|
|
3
3
|
# SPDX-License-Identifier: MIT
|
|
4
|
-
#
|
|
4
|
+
# All contributions are certified under the DCO
|
|
5
5
|
|
|
6
6
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
# of this software and associated documentation files (the "Software"), to
|
zensical/extensions/search.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# Copyright (c) 2025 Zensical and contributors
|
|
1
|
+
# Copyright (c) 2025-2026 Zensical and contributors
|
|
2
2
|
|
|
3
3
|
# SPDX-License-Identifier: MIT
|
|
4
|
-
#
|
|
4
|
+
# All contributions are certified under the DCO
|
|
5
5
|
|
|
6
6
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
# of this software and associated documentation files (the "Software"), to
|
|
@@ -34,7 +34,7 @@ from markdown.postprocessors import Postprocessor
|
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
class SearchProcessor(Postprocessor):
|
|
37
|
-
"""Post processor
|
|
37
|
+
"""Post processor to extract searchable content from the rendered HTML."""
|
|
38
38
|
|
|
39
39
|
def __init__(self, md: Markdown) -> None:
|
|
40
40
|
super().__init__(md)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# Copyright (c) 2025 Zensical and contributors
|
|
1
|
+
# Copyright (c) 2025-2026 Zensical and contributors
|
|
2
2
|
|
|
3
3
|
# SPDX-License-Identifier: MIT
|
|
4
|
-
#
|
|
4
|
+
# All contributions are certified under the DCO
|
|
5
5
|
|
|
6
6
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
# of this software and associated documentation files (the "Software"), to
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# Copyright (c) 2025 Zensical and contributors
|
|
1
|
+
# Copyright (c) 2025-2026 Zensical and contributors
|
|
2
2
|
|
|
3
3
|
# SPDX-License-Identifier: MIT
|
|
4
|
-
#
|
|
4
|
+
# All contributions are certified under the DCO
|
|
5
5
|
|
|
6
6
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
# of this software and associated documentation files (the "Software"), to
|
zensical/main.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# Copyright (c) 2025 Zensical and contributors
|
|
1
|
+
# Copyright (c) 2025-2026 Zensical and contributors
|
|
2
2
|
|
|
3
3
|
# SPDX-License-Identifier: MIT
|
|
4
|
-
#
|
|
4
|
+
# All contributions are certified under the DCO
|
|
5
5
|
|
|
6
6
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
# of this software and associated documentation files (the "Software"), to
|
|
@@ -135,7 +135,7 @@ def execute_serve(config_file: str | None, **kwargs: Any) -> None:
|
|
|
135
135
|
required=False,
|
|
136
136
|
)
|
|
137
137
|
def new_project(directory: str | None, **kwargs: Any) -> None: # noqa: ARG001
|
|
138
|
-
"""Create a new template project in the current
|
|
138
|
+
"""Create a new template project in the current or given directory.
|
|
139
139
|
|
|
140
140
|
Raises:
|
|
141
141
|
ClickException: if the directory already contains a zensical.toml or a
|
zensical/markdown.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# Copyright (c) 2025 Zensical and contributors
|
|
1
|
+
# Copyright (c) 2025-2026 Zensical and contributors
|
|
2
2
|
|
|
3
3
|
# SPDX-License-Identifier: MIT
|
|
4
|
-
#
|
|
4
|
+
# All contributions are certified under the DCO
|
|
5
5
|
|
|
6
6
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
# of this software and associated documentation files (the "Software"), to
|
|
@@ -28,7 +28,9 @@ from datetime import date, datetime
|
|
|
28
28
|
from typing import TYPE_CHECKING, Any
|
|
29
29
|
|
|
30
30
|
import yaml
|
|
31
|
+
from markdown import Extension as MarkdownExtension
|
|
31
32
|
from markdown import Markdown
|
|
33
|
+
from markdown.preprocessors import Preprocessor
|
|
32
34
|
from yaml import SafeLoader
|
|
33
35
|
|
|
34
36
|
from zensical.config import get_config
|
|
@@ -51,12 +53,46 @@ FRONT_MATTER_RE = re.compile(
|
|
|
51
53
|
Regex pattern to extract front matter.
|
|
52
54
|
"""
|
|
53
55
|
|
|
56
|
+
|
|
57
|
+
# ----------------------------------------------------------------------------
|
|
58
|
+
# Classes
|
|
59
|
+
# ----------------------------------------------------------------------------
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class CurrentPageData(Preprocessor):
|
|
63
|
+
"""Preprocessor to store current page URL and path."""
|
|
64
|
+
|
|
65
|
+
def __init__(self, md: Markdown, url: str, path: str):
|
|
66
|
+
super().__init__(md)
|
|
67
|
+
self.url = url
|
|
68
|
+
self.path = path
|
|
69
|
+
|
|
70
|
+
def run(self, lines: list[str]) -> list[str]:
|
|
71
|
+
return lines
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class CurrentPageExtension(MarkdownExtension):
|
|
75
|
+
"""Markdown extension to store current page URL and path."""
|
|
76
|
+
|
|
77
|
+
def __init__(self, url: str, path: str):
|
|
78
|
+
super().__init__()
|
|
79
|
+
self.url = url
|
|
80
|
+
self.path = path
|
|
81
|
+
|
|
82
|
+
def extendMarkdown(self, md: Markdown) -> None: # noqa: N802
|
|
83
|
+
md.preprocessors.register(
|
|
84
|
+
CurrentPageData(md, self.url, self.path),
|
|
85
|
+
"zensical_current_page",
|
|
86
|
+
0,
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
|
|
54
90
|
# ----------------------------------------------------------------------------
|
|
55
91
|
# Functions
|
|
56
92
|
# ----------------------------------------------------------------------------
|
|
57
93
|
|
|
58
94
|
|
|
59
|
-
def render(content: str, path: str) -> dict:
|
|
95
|
+
def render(content: str, path: str, url: str) -> dict:
|
|
60
96
|
"""Render Markdown and return HTML.
|
|
61
97
|
|
|
62
98
|
This function returns rendered HTML as well as the table of contents and
|
|
@@ -66,9 +102,14 @@ def render(content: str, path: str) -> dict:
|
|
|
66
102
|
"""
|
|
67
103
|
config = get_config()
|
|
68
104
|
|
|
105
|
+
# Insert current page extension at the beginning
|
|
106
|
+
extensions = [CurrentPageExtension(url, path)] + config[
|
|
107
|
+
"markdown_extensions"
|
|
108
|
+
]
|
|
109
|
+
|
|
69
110
|
# Initialize Markdown parser
|
|
70
111
|
md = Markdown(
|
|
71
|
-
extensions=
|
|
112
|
+
extensions=extensions,
|
|
72
113
|
extension_configs=config["mdx_configs"],
|
|
73
114
|
)
|
|
74
115
|
|
|
@@ -113,6 +154,24 @@ def render(content: str, path: str) -> dict:
|
|
|
113
154
|
if meta.get("search", {}).get("exclude", False):
|
|
114
155
|
search_processor.data = []
|
|
115
156
|
|
|
157
|
+
# Extract URL map from extension if available
|
|
158
|
+
for extension in md.registeredExtensions:
|
|
159
|
+
if type(extension).__qualname__ == "MkdocstringsExtension":
|
|
160
|
+
autorefs = {
|
|
161
|
+
"primary": extension._autorefs._primary_url_map, # type: ignore[attr-defined]
|
|
162
|
+
"secondary": extension._autorefs._secondary_url_map, # type: ignore[attr-defined]
|
|
163
|
+
"inventory": extension._autorefs._abs_url_map, # type: ignore[attr-defined]
|
|
164
|
+
"titles": extension._autorefs._title_map, # type: ignore[attr-defined]
|
|
165
|
+
}
|
|
166
|
+
break
|
|
167
|
+
else:
|
|
168
|
+
autorefs = {
|
|
169
|
+
"primary": {},
|
|
170
|
+
"secondary": {},
|
|
171
|
+
"inventory": {},
|
|
172
|
+
"titles": {},
|
|
173
|
+
}
|
|
174
|
+
|
|
116
175
|
# Return Markdown with metadata
|
|
117
176
|
return {
|
|
118
177
|
"meta": meta,
|
|
@@ -120,6 +179,7 @@ def render(content: str, path: str) -> dict:
|
|
|
120
179
|
"search": search_processor.data,
|
|
121
180
|
"title": "",
|
|
122
181
|
"toc": [_convert_toc(item) for item in getattr(md, "toc_tokens", [])],
|
|
182
|
+
"autorefs": autorefs,
|
|
123
183
|
}
|
|
124
184
|
|
|
125
185
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) for portions of Lucide are held by Cole Bemis 2013-2023 as part of Feather (MIT). All other copyright (c) for Lucide are held by Lucide Contributors 2025.
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
10
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
11
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
12
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
13
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
14
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
15
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
The MIT License (MIT) (for portions derived from Feather)
|
|
20
|
+
|
|
21
|
+
Copyright (c) 2013-2023 Cole Bemis
|
|
22
|
+
|
|
23
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
24
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
25
|
+
in the Software without restriction, including without limitation the rights
|
|
26
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
27
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
28
|
+
furnished to do so, subject to the following conditions:
|
|
29
|
+
|
|
30
|
+
The above copyright notice and this permission notice shall be included in all
|
|
31
|
+
copies or substantial portions of the Software.
|
|
32
|
+
|
|
33
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
34
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
35
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
36
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
37
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
38
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
39
|
+
SOFTWARE.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-ampersand" viewBox="0 0 24 24"><path d="
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-ampersand" viewBox="0 0 24 24"><path d="M16 12h3M17.5 12a8 8 0 0 1-8 8A4.5 4.5 0 0 1 5 15.5c0-6 8-4 8-8.5a3 3 0 1 0-6 0c0 3 2.5 8.5 12 13"/></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-anchor" viewBox="0 0 24 24"><path d="M12
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-anchor" viewBox="0 0 24 24"><path d="M12 6v16M19 13l2-1a9 9 0 0 1-18 0l2 1M9 11h6"/><circle cx="12" cy="4" r="2"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-balloon" viewBox="0 0 24 24"><path d="M12 16v1a2 2 0 0 0 2 2h1a2 2 0 0 1 2 2v1M12 6a2 2 0 0 1 2 2"/><path d="M18 8c0 4-3.5 8-6 8s-6-4-6-8a6 6 0 0 1 12 0"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-birdhouse" viewBox="0 0 24 24"><path d="M12 18v4M17 18l1.956-11.468M3 8l7.82-5.615a2 2 0 0 1 2.36 0L21 8M4 18h16M7 18 5.044 6.532"/><circle cx="12" cy="10" r="2"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-book-search" viewBox="0 0 24 24"><path d="M11 22H5.5a1 1 0 0 1 0-5h4.501M21 22l-1.879-1.878"/><path d="M3 19.5v-15A2.5 2.5 0 0 1 5.5 2H18a1 1 0 0 1 1 1v8"/><circle cx="17" cy="18" r="3"/></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-brush-cleaning" viewBox="0 0 24 24"><path d="m16 22-1-4M19
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-brush-cleaning" viewBox="0 0 24 24"><path d="m16 22-1-4M19 14a1 1 0 0 0 1-1v-1a2 2 0 0 0-2-2h-3a1 1 0 0 1-1-1V4a2 2 0 0 0-4 0v5a1 1 0 0 1-1 1H6a2 2 0 0 0-2 2v1a1 1 0 0 0 1 1"/><path d="M19 14H5l-1.973 6.767A1 1 0 0 0 4 22h16a1 1 0 0 0 .973-1.233zM8 22l1-4"/></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-bubbles" viewBox="0 0 24 24"><path d="M7.
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-bubbles" viewBox="0 0 24 24"><path d="M7.001 15.085A1.5 1.5 0 0 1 9 16.5"/><circle cx="18.5" cy="8.5" r="3.5"/><circle cx="7.5" cy="16.5" r="5.5"/><circle cx="7.5" cy="4.5" r="2.5"/></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-calendar-fold" viewBox="0 0 24 24"><path d="
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-calendar-fold" viewBox="0 0 24 24"><path d="M3 20a2 2 0 0 0 2 2h10a2.4 2.4 0 0 0 1.706-.706l3.588-3.588A2.4 2.4 0 0 0 21 16V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2z"/><path d="M15 22v-5a1 1 0 0 1 1-1h5M8 2v4M16 2v4M3 10h18"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-calendars" viewBox="0 0 24 24"><path d="M12 2v2M15.726 21.01A2 2 0 0 1 14 22H4a2 2 0 0 1-2-2V10a2 2 0 0 1 2-2M18 2v2M2 13h2M8 8h14"/><rect width="14" height="14" x="8" y="3" rx="2"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-cannabis-off" viewBox="0 0 24 24"><path d="M12 22v-4c1.5 1.5 3.5 3 6 3 0-1.5-.5-3.5-2-5M13.988 8.327C13.902 6.054 13.365 3.82 12 2a9.3 9.3 0 0 0-1.445 2.9M17.375 11.725C18.882 10.53 21 7.841 21 6c-2.324 0-5.08 1.296-6.662 2.684M2 2l20 20M21.024 15.378A15 15 0 0 0 22 15c-.426-1.279-2.67-2.557-4.25-2.907M6.995 6.992C5.714 6.4 4.29 6 3 6c0 2 2.5 5 4 6-1.5 0-4.5 1.5-5 3 3.5 1.5 6 1 6 1-1.5 1.5-2 3.5-2 5 2.5 0 4.5-1.5 6-3"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-chess-bishop" viewBox="0 0 24 24"><path d="M5 20a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v1a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1zM15 18c1.5-.615 3-2.461 3-4.923C18 8.769 14.5 4.462 12 2 9.5 4.462 6 8.77 6 13.077 6 15.539 7.5 17.385 9 18M16 7l-2.5 2.5M9 2h6"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-chess-king" viewBox="0 0 24 24"><path d="M4 20a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v1a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1zM6.7 18l-1-1C4.35 15.682 3 14.09 3 12a5 5 0 0 1 4.95-5c1.584 0 2.7.455 4.05 1.818C13.35 7.455 14.466 7 16.05 7A5 5 0 0 1 21 12c0 2.082-1.359 3.673-2.7 5l-1 1M10 4h4M12 2v6.818"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-chess-knight" viewBox="0 0 24 24"><path d="M5 20a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v1a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1zM16.5 18c1-2 2.5-5 2.5-9a7 7 0 0 0-7-7H6.635a1 1 0 0 0-.768 1.64L7 5l-2.32 5.802a2 2 0 0 0 .95 2.526l2.87 1.456M15 5l1.425-1.425M17 8l1.53-1.53M9.713 12.185 7 18"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-chess-pawn" viewBox="0 0 24 24"><path d="M5 20a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v1a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1zM14.5 10l1.5 8M7 10h10M8 18l1.5-8"/><circle cx="12" cy="6" r="4"/></svg>
|