jekyll-obsidian-site 0.2.0

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.
Files changed (191) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +133 -0
  4. data/website/_config.yml +21 -0
  5. data/website/_includes/website/archive-timeline.html +8 -0
  6. data/website/_includes/website/blog-ledger.html +19 -0
  7. data/website/_includes/website/blog-navigation.html +7 -0
  8. data/website/_includes/website/comments.html +22 -0
  9. data/website/_includes/website/contact-icon.html +14 -0
  10. data/website/_includes/website/context-tags.html +7 -0
  11. data/website/_includes/website/context.html +3 -0
  12. data/website/_includes/website/dialogs.html +71 -0
  13. data/website/_includes/website/docs-navigation.html +7 -0
  14. data/website/_includes/website/docs-tree.html +8 -0
  15. data/website/_includes/website/footer.html +14 -0
  16. data/website/_includes/website/github-icon.html +3 -0
  17. data/website/_includes/website/head.html +41 -0
  18. data/website/_includes/website/header.html +35 -0
  19. data/website/_includes/website/language-switcher.html +16 -0
  20. data/website/_includes/website/local-graph.html +25 -0
  21. data/website/_includes/website/note-header.html +35 -0
  22. data/website/_includes/website/outline.html +9 -0
  23. data/website/_includes/website/page-actions.html +34 -0
  24. data/website/_includes/website/portfolio-grid.html +36 -0
  25. data/website/_includes/website/portfolio-topics.html +4 -0
  26. data/website/_includes/website/post-cards.html +16 -0
  27. data/website/_includes/website/related-articles.html +7 -0
  28. data/website/_includes/website/relations.html +16 -0
  29. data/website/_includes/website/source-actions.html +28 -0
  30. data/website/_includes/website/system-page.html +31 -0
  31. data/website/_includes/website/tab-collection.html +28 -0
  32. data/website/_includes/website/tag-filter.html +12 -0
  33. data/website/_layouts/website-docs.html +20 -0
  34. data/website/_layouts/website-minimal.html +93 -0
  35. data/website/_layouts/website-redirect.html +17 -0
  36. data/website/assets/chunks/abnfDiagram-N423BO3Z-TSORAEI2.js +1 -0
  37. data/website/assets/chunks/architecture-TIHT7OUA-OUC5PEC7.js +1 -0
  38. data/website/assets/chunks/architectureDiagram-T3A2C74G-6P5MB2DJ.js +36 -0
  39. data/website/assets/chunks/blockDiagram-VBNYF7ZC-ZWINYROZ.js +132 -0
  40. data/website/assets/chunks/c4Diagram-5PPSVZJV-R5RMEAOT.js +10 -0
  41. data/website/assets/chunks/chunk-22DRK7VS.js +1 -0
  42. data/website/assets/chunks/chunk-25REBZ7M.js +2 -0
  43. data/website/assets/chunks/chunk-2RQCUDTG.js +1 -0
  44. data/website/assets/chunks/chunk-34FHPXU4.js +1 -0
  45. data/website/assets/chunks/chunk-57XXJOQN.js +10 -0
  46. data/website/assets/chunks/chunk-6DCNDVBX.js +2 -0
  47. data/website/assets/chunks/chunk-6DHFEWGX.js +1 -0
  48. data/website/assets/chunks/chunk-6VQ47JJS.js +2 -0
  49. data/website/assets/chunks/chunk-7CSIRG7W.js +127 -0
  50. data/website/assets/chunks/chunk-A43YELH5.js +1 -0
  51. data/website/assets/chunks/chunk-AIX6IH4O.js +1 -0
  52. data/website/assets/chunks/chunk-B3K7RH5O.js +88 -0
  53. data/website/assets/chunks/chunk-CBGUD2NP.js +1 -0
  54. data/website/assets/chunks/chunk-D3WOCELE.js +1 -0
  55. data/website/assets/chunks/chunk-D6FURU6X.js +1 -0
  56. data/website/assets/chunks/chunk-DGEGT77F.js +1 -0
  57. data/website/assets/chunks/chunk-DN52R6U7.js +1 -0
  58. data/website/assets/chunks/chunk-E3T3IFAC.js +1 -0
  59. data/website/assets/chunks/chunk-EIBFAW37.js +1 -0
  60. data/website/assets/chunks/chunk-ERWOH47R.js +1 -0
  61. data/website/assets/chunks/chunk-ETOVTYWF.js +1 -0
  62. data/website/assets/chunks/chunk-GHD3PFWA.js +231 -0
  63. data/website/assets/chunks/chunk-GMBKQ7NZ.js +1 -0
  64. data/website/assets/chunks/chunk-GQM25EPP.js +156 -0
  65. data/website/assets/chunks/chunk-GSOU4UTT.js +1 -0
  66. data/website/assets/chunks/chunk-HEMELP7J.js +1 -0
  67. data/website/assets/chunks/chunk-HZ5I5NJO.js +1 -0
  68. data/website/assets/chunks/chunk-IP56FOSI.js +70 -0
  69. data/website/assets/chunks/chunk-L7BMR7WL.js +1 -0
  70. data/website/assets/chunks/chunk-LGUG3SQB.js +1 -0
  71. data/website/assets/chunks/chunk-LOMHZYS2.js +1 -0
  72. data/website/assets/chunks/chunk-MII4VZEB.js +3 -0
  73. data/website/assets/chunks/chunk-MYMJLHQL.js +62 -0
  74. data/website/assets/chunks/chunk-NBH7YOBD.js +15 -0
  75. data/website/assets/chunks/chunk-NCOVM3YF.js +1 -0
  76. data/website/assets/chunks/chunk-OAGTSILX.js +1 -0
  77. data/website/assets/chunks/chunk-OCX5OCIU.js +321 -0
  78. data/website/assets/chunks/chunk-OE3NOVIH.js +1 -0
  79. data/website/assets/chunks/chunk-PLP5XUTJ.js +1 -0
  80. data/website/assets/chunks/chunk-PNOERP6G.js +1 -0
  81. data/website/assets/chunks/chunk-QBPQ7DPE.js +1 -0
  82. data/website/assets/chunks/chunk-RWFFDL53.js +1 -0
  83. data/website/assets/chunks/chunk-SEGIW3MP.js +1 -0
  84. data/website/assets/chunks/chunk-SZDMZNUS.js +1 -0
  85. data/website/assets/chunks/chunk-T2QBAPVT.js +1 -0
  86. data/website/assets/chunks/chunk-UE533OZ7.js +1 -0
  87. data/website/assets/chunks/chunk-UTWOJE2A.js +1 -0
  88. data/website/assets/chunks/chunk-VOCDYA3H.js +1 -0
  89. data/website/assets/chunks/chunk-VYZZPKGK.js +161 -0
  90. data/website/assets/chunks/chunk-WWLZIRS6.js +1 -0
  91. data/website/assets/chunks/chunk-XNXYDBKX.js +32 -0
  92. data/website/assets/chunks/chunk-XQUIO562.js +1 -0
  93. data/website/assets/chunks/chunk-Y2XVFW7T.js +2 -0
  94. data/website/assets/chunks/chunk-YORIST7Z.js +1 -0
  95. data/website/assets/chunks/chunk-Z2WBQPVY.js +206 -0
  96. data/website/assets/chunks/classDiagram-JCYQIIEL-OFDVDDIM.js +1 -0
  97. data/website/assets/chunks/classDiagram-v2-OCEON4UE-E36B6BGQ.js +1 -0
  98. data/website/assets/chunks/cose-bilkent-JH36ORCC-CBAW64AB.js +1 -0
  99. data/website/assets/chunks/cynefin-VYW2F7L2-CBO6DLNV.js +1 -0
  100. data/website/assets/chunks/cynefinDiagram-MW4NZA55-DFINLOUY.js +62 -0
  101. data/website/assets/chunks/dagre-VZM6K2ZE-BZFBSZAH.js +4 -0
  102. data/website/assets/chunks/diagram-7IWD3JNH-XQHTVOU2.js +30 -0
  103. data/website/assets/chunks/diagram-B4RE2ZJO-FTSXBZJR.js +3 -0
  104. data/website/assets/chunks/diagram-LBJQPF4R-ZSZW4OLH.js +24 -0
  105. data/website/assets/chunks/diagram-Q27KOJAE-2IV5TVCJ.js +24 -0
  106. data/website/assets/chunks/diagram-UB23O5K3-D6PDUTFL.js +41 -0
  107. data/website/assets/chunks/ebnfDiagram-BXEA7PRR-C6MAER3M.js +1 -0
  108. data/website/assets/chunks/erDiagram-JOGREHBK-EDAD2H5M.js +85 -0
  109. data/website/assets/chunks/eventmodeling-45OFAUF4-4K577DMF.js +1 -0
  110. data/website/assets/chunks/flowDiagram-UKHOOZJN-545F4YX3.js +1 -0
  111. data/website/assets/chunks/ganttDiagram-PKOTCBZU-7A7EKMY3.js +292 -0
  112. data/website/assets/chunks/gitGraph-TEB2WS4Q-3WUB7WYQ.js +1 -0
  113. data/website/assets/chunks/gitGraphDiagram-DS77QQ5N-A5UWV5FF.js +106 -0
  114. data/website/assets/chunks/info-DKCQHKI2-EOOHI7XS.js +1 -0
  115. data/website/assets/chunks/infoDiagram-6WML65LV-CWIOOWJP.js +2 -0
  116. data/website/assets/chunks/ishikawaDiagram-WSZJBQD7-CEASQVDL.js +70 -0
  117. data/website/assets/chunks/journeyDiagram-NVQOT4AX-LYG3S2AW.js +139 -0
  118. data/website/assets/chunks/kanban-definition-27J2QSJJ-HCC6KAYI.js +89 -0
  119. data/website/assets/chunks/katex-F4MQ6FB3.js +257 -0
  120. data/website/assets/chunks/mindmap-definition-FAOFIHXS-JMGSM3RE.js +96 -0
  121. data/website/assets/chunks/packet-7NZHBO7P-W3SJA3MY.js +1 -0
  122. data/website/assets/chunks/pegDiagram-VL7TDLO6-4JO3Y3Z3.js +1 -0
  123. data/website/assets/chunks/pie-RZYD4A2V-YOIQBTY7.js +1 -0
  124. data/website/assets/chunks/pieDiagram-7S7Q4E2Y-VFQ7SE46.js +39 -0
  125. data/website/assets/chunks/quadrantDiagram-CIZ2JOQS-JISDI2S6.js +7 -0
  126. data/website/assets/chunks/radar-I7S5WNFK-NMKP5AZO.js +1 -0
  127. data/website/assets/chunks/railroad-3IZDKUUU-7MOIV7CI.js +1 -0
  128. data/website/assets/chunks/railroad-abnf-AHOZXSZD-HXNH5SLO.js +1 -0
  129. data/website/assets/chunks/railroad-ebnf-EBAXGLYW-OWDJEWMK.js +1 -0
  130. data/website/assets/chunks/railroad-peg-LSFZ7HO6-ASSINGP5.js +1 -0
  131. data/website/assets/chunks/railroadDiagram-AXF67PYL-AFV5VP5F.js +1 -0
  132. data/website/assets/chunks/requirementDiagram-LRYGKXZP-RNRPEHHN.js +84 -0
  133. data/website/assets/chunks/sankeyDiagram-W5VNT64P-O54R2L3E.js +40 -0
  134. data/website/assets/chunks/sequenceDiagram-SI44F4Z6-42WISKJ7.js +162 -0
  135. data/website/assets/chunks/sizeCapture-X5ZJPWSS-LRN2Q37T.js +1 -0
  136. data/website/assets/chunks/stateDiagram-OKZ733FA-BWIBJXIR.js +1 -0
  137. data/website/assets/chunks/stateDiagram-v2-UEYNNEHI-L73LHL3L.js +1 -0
  138. data/website/assets/chunks/swimlanes-SLNWSIFB-ECOAE7LQ.js +1 -0
  139. data/website/assets/chunks/swimlanesDiagram-ULZ7WXOC-3CKKKFZZ.js +8 -0
  140. data/website/assets/chunks/timeline-definition-Z64GVDOM-HR2OL5G7.js +120 -0
  141. data/website/assets/chunks/treeView-QDETBFTQ-C6D5WFJA.js +1 -0
  142. data/website/assets/chunks/treemap-6X3UGDF4-JFCDMSCA.js +1 -0
  143. data/website/assets/chunks/vennDiagram-T6HMQDX7-62WAAPTF.js +34 -0
  144. data/website/assets/chunks/wardley-OPB4EBWU-RQIOII7I.js +1 -0
  145. data/website/assets/chunks/wardleyDiagram-T6FBY63Y-KUXO3NHV.js +78 -0
  146. data/website/assets/chunks/xychartDiagram-ELKLHX3M-I54W4HJ7.js +7 -0
  147. data/website/assets/color-scheme-bootstrap-4H4ZR4BW.js +1 -0
  148. data/website/assets/docs-3WBBQT6K.css +1 -0
  149. data/website/assets/docs-W3D5DWQF.js +1 -0
  150. data/website/assets/docs-navigation-75ALFYBA.js +1 -0
  151. data/website/assets/graph-QWL54LWD.js +1 -0
  152. data/website/assets/manifest.json +314 -0
  153. data/website/assets/math-7JTH4OWZ.js +21 -0
  154. data/website/assets/mermaid-RXC6URG4.js +10 -0
  155. data/website/assets/minimal-3NPTDWQX.js +1 -0
  156. data/website/assets/minimal-E2VATXXS.css +1 -0
  157. data/website/assets/previews-FMHOX7UX.js +1 -0
  158. data/website/assets/search-BH73JZDU.js +1 -0
  159. data/website/assets/search-worker-SM4IM4J7.js +1 -0
  160. data/website/exe/jekyll-obsidian +5 -0
  161. data/website/lib/jekyll_obsidian/adapter.rb +733 -0
  162. data/website/lib/jekyll_obsidian/built_in_themes.rb +855 -0
  163. data/website/lib/jekyll_obsidian/cli.rb +84 -0
  164. data/website/lib/jekyll_obsidian/content_policy.rb +194 -0
  165. data/website/lib/jekyll_obsidian/destination_registry.rb +39 -0
  166. data/website/lib/jekyll_obsidian/directory_indexes.rb +30 -0
  167. data/website/lib/jekyll_obsidian/external_media.rb +371 -0
  168. data/website/lib/jekyll_obsidian/front_matter.rb +453 -0
  169. data/website/lib/jekyll_obsidian/github_markdown.rb +664 -0
  170. data/website/lib/jekyll_obsidian/html_publication.rb +206 -0
  171. data/website/lib/jekyll_obsidian/initializer.rb +68 -0
  172. data/website/lib/jekyll_obsidian/localized_compiler.rb +1044 -0
  173. data/website/lib/jekyll_obsidian/media_policy.rb +41 -0
  174. data/website/lib/jekyll_obsidian/ofm_scanner.rb +493 -0
  175. data/website/lib/jekyll_obsidian/output_text.rb +13 -0
  176. data/website/lib/jekyll_obsidian/preview.rb +93 -0
  177. data/website/lib/jekyll_obsidian/published_markdown.rb +32 -0
  178. data/website/lib/jekyll_obsidian/raw_html_manifest.rb +66 -0
  179. data/website/lib/jekyll_obsidian/runtime.rb +197 -0
  180. data/website/lib/jekyll_obsidian/site_compilation.rb +147 -0
  181. data/website/lib/jekyll_obsidian/site_navigation.rb +517 -0
  182. data/website/lib/jekyll_obsidian/url_builder.rb +163 -0
  183. data/website/lib/jekyll_obsidian/value_objects.rb +198 -0
  184. data/website/lib/jekyll_obsidian/vault_compiler.rb +2771 -0
  185. data/website/lib/jekyll_obsidian/version.rb +6 -0
  186. data/website/lib/jekyll_obsidian/workspace_layout.rb +104 -0
  187. data/website/lib/jekyll_obsidian.rb +22 -0
  188. data/website/scripts/audit-site.rb +120 -0
  189. data/website/scripts/templates/pages.yml +55 -0
  190. data/website/scripts/verify-site-urls.rb +585 -0
  191. metadata +319 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 11839f61289760fc9100f97551010f90a86f033a3c250c56896f6204533631ed
4
+ data.tar.gz: 542071f78218cbd4dcab030c37c80e42768d9dbd94b7a73816fa3747798c6ff3
5
+ SHA512:
6
+ metadata.gz: 4727e71d96d4a1a72ed668962449298f8edd7d1f10baad3dde4b0c38ed08a2add5c95d18cd2bef820911d2ab6e17c5c7c30298fbc4a6cdbd94319688382fa615
7
+ data.tar.gz: 62e9c18af18b75fd91cd0cc77355e11c44c30f2ab68f57dc8edfee24527168c8eb36cd40a91f060c4ea642b113392d6abf1cf016d6dd68ea73eea86b8199878f
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 jekyll-obsidian contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,133 @@
1
+ # jekyll-obsidian
2
+
3
+ English | [简体中文](README.zh-CN.md)
4
+
5
+ `jekyll-obsidian` turns a Markdown folder, including an Obsidian vault, into a blog or documentation site. Keep writing in your editor and push to GitHub; Actions builds and publishes the site. Add a configuration file and a workflow to your repository. The implementation is installed as the `jekyll-obsidian-site` Ruby gem.
6
+
7
+ Live preview: [sinputer.top/jekyll-obsidian](https://sinputer.top/jekyll-obsidian/)
8
+
9
+ Choose one built-in theme for each build:
10
+
11
+ - `minimal` combines an authored Home page with recent posts, a full Blog, documentation, and explicit custom sections for personal or organization sites.
12
+ - `docs` provides a document tree and previous or next links.
13
+
14
+ Both themes enable search, wiki-link reading previews, the page outline, note relations, and an interactive local graph by default. A note participating in a link or embed relation with another public note keeps its local graph at the top of the right-hand context rail; isolated and self-link-only notes omit it. Its two controls open the complete public graph or an expanded view of the current note's neighbourhood. The complete graph still contains every public note, and `/graph/` is not a generated route.
15
+
16
+ Switching themes does not change note URLs.
17
+ The default build and deployment theme is `minimal`. Both themes can publish locale overlays from `_translations/<locale>/` and attach GitHub Discussions comments to posts. When the corresponding mapping is present and omits `enabled`, localization defaults on only for `docs`, while comments default on only for `minimal`.
18
+
19
+ See [Localization](website/jekyll-obsidian-docs/docs/Localization.md) for locale manifests, which content controls site structure, fallback pages, and SEO behavior.
20
+
21
+ Minimal also provides Blog, tags, Atom feeds, contacts, source actions, and an automatically detected Portfolio with project cards. A project wrapper can use a public GitHub Markdown file as its body. Both themes generate Search and Graph data, canonical metadata, a sitemap, a 404 page, and frontmatter-free Markdown resources. Optional traffic measurement supports either Cloudflare Web Analytics or Google Analytics and stays off until configured.
22
+
23
+ ## Before you publish
24
+
25
+ Deploying with GitHub Pages does not require Ruby, Node.js, Bundler, npm, or a browser on your computer. The generated GitHub Actions workflow installs the build toolchain.
26
+
27
+ [GitHub Pages is available for public repositories on GitHub Free](https://docs.github.com/en/pages/quickstart#who-can-use-this-feature), so a public `jekyll-obsidian` site needs no paid hosting.
28
+
29
+ The publication policy controls what enters the generated site. It does not make other committed files private. Anyone who can read the repository can read unpublished notes too, so do not commit secrets, personal records, or other private material.
30
+
31
+ Canvas and Bases files become downloads when a public note links to them. Inspect them before committing because they can contain excerpts or references to unpublished material.
32
+
33
+ ## Add it to your repository
34
+
35
+ 1. Create `.github/jekyll-obsidian.yml`, using [the example configuration](examples/jekyll-obsidian.yml):
36
+
37
+ ```yaml
38
+ title: My Site
39
+ website:
40
+ source: docs
41
+ theme: minimal
42
+ ```
43
+
44
+ 2. Copy [the Pages workflow](examples/pages.yml) to `.github/workflows/pages.yml`.
45
+ 3. Put a Markdown note with `publish: true` in `docs/`, then select **Settings > Pages > Build and deployment > Source > GitHub Actions** and push.
46
+
47
+ The content directory can also be `website/docs/` or another repository-relative directory. Edit `website.source` to select it. No local Ruby, Node.js, or build command is needed for Actions.
48
+
49
+ For local initialization, install Ruby 4.0.x and run:
50
+
51
+ ```sh
52
+ gem install jekyll-obsidian-site
53
+ jekyll-obsidian init --source docs
54
+ ```
55
+
56
+ `init` creates the same configuration and workflow. It adds a public welcome note only when the content directory is absent or empty. Existing conflicting files are left unchanged. See [Host Integration](website/jekyll-obsidian-docs/docs/Integration.md) for Bundler, updates, and existing repositories.
57
+
58
+ ## Preview the deployed site
59
+
60
+ Wait for the **Build and deploy Pages** workflow on the default branch to succeed. GitHub reports the deployed URL in the workflow's `deploy` job and in **Settings → Pages**.
61
+
62
+ Without a custom domain, the expected URL is:
63
+
64
+ - `https://<owner>.github.io/<repository>/` for a normal project repository.
65
+ - `https://<owner>.github.io/` when the repository itself is named `<owner>.github.io`.
66
+
67
+ If you configure a custom domain, use the URL shown in **Settings → Pages**. The workflow reads GitHub Pages metadata and builds links for that URL automatically. See [Deployment](website/jekyll-obsidian-docs/docs/Deployment.md) for the workflow and custom-domain details.
68
+
69
+ ## Configure and publish
70
+
71
+ Edit `.github/jekyll-obsidian.yml` to configure the title, language, content directory, theme, and features. All entries are directly editable. Changing `website.source` or `website.theme` takes effect on the next build; the workflow does not need to be regenerated.
72
+
73
+ The configuration interface is the root `website:` mapping.
74
+
75
+ Both themes can store post comments in GitHub Discussions through Giscus. Comments use the publication repository by default and can point at a separate public repository. When `website.comments` exists and omits `enabled`, `minimal` enables comments by default; `docs` requires `website.comments.enabled: true`. Enabling comments before Discussions or the Giscus App is ready does not fail the build; incomplete Giscus configuration produces a warning and a non-interactive fallback. See [Comments](website/jekyll-obsidian-docs/docs/Comments.md) for repository setup, thread identity, privacy boundaries, and troubleshooting.
76
+
77
+ Open your content directory in Obsidian or any Markdown editor. By default, a note enters the site only when its frontmatter contains the YAML boolean `publish: true`:
78
+
79
+ ```yaml
80
+ ---
81
+ publish: true
82
+ title: A public note
83
+ tags:
84
+ - example
85
+ ---
86
+ ```
87
+
88
+ The strings `"true"` and `"yes"` are not accepted. To publish a whole folder recursively, list its path under `website.content.publish_by_default`; use `.` to select the complete content tree. A note can opt out of either default with the YAML boolean `publish: false`. Obsidian's `.obsidian/` state and `.trash/` are excluded from the content snapshot.
89
+
90
+ `index.md` is optional at the content root and in every nested folder. When a folder has no physical `index.md`, a published sibling named exactly `README.md` becomes its index. A physical `index.md` keeps priority even when it is unpublished; in that case, `README.md` remains an ordinary note. A selected README keeps its source path and source actions but publishes at the folder route. Minimal places the selected public root index above the six most recent posts on Home; without one, Home can still show the post stream. A folder without a public selected index links to its first ordered public page. A content directory with no public notes still fails the build.
91
+
92
+ Trusted standalone HTML slides can also publish at explicit routes without a theme or Liquid pass. Map one `.html` file or a directory bundle containing `index.html`; a bundle publishes its regular files with their relative structure intact, except Markdown and compiler locale manifests such as `_locale.yml`:
93
+
94
+ ```yaml
95
+ website:
96
+ html:
97
+ slides/product-tour: /slides/product-tour/
98
+ ```
99
+
100
+ HTML mappings are an explicit publication boundary independent of Markdown defaults. Raw pages stay out of navigation, Search, Graph, feeds, and sitemap, and they execute as trusted same-origin code. Review the complete bundle before publishing. See [Customization](website/jekyll-obsidian-docs/docs/Customization.md#standalone-html-slides) and the [working slide source](website/jekyll-obsidian-docs/slides/jekyll-obsidian/index.html).
101
+
102
+ Update the Action version in your workflow to use a new release. For a local gem installation, run `gem update jekyll-obsidian-site`; for Bundler, run `bundle update jekyll-obsidian-site` and commit the lockfile. Your content and configuration remain in your repository.
103
+
104
+ ## Optional local preview
105
+
106
+ With Ruby 4.0.x on macOS, Linux, or WSL:
107
+
108
+ ```sh
109
+ gem install jekyll-obsidian-site
110
+ jekyll-obsidian dev
111
+ ```
112
+
113
+ Open `http://127.0.0.1:58000/`. Content and configuration changes trigger a complete rebuild. A failed rebuild leaves the last successful site available. Run `jekyll-obsidian dev --help` for host, port, base path, and theme options.
114
+
115
+ Build for another host with `jekyll-obsidian build --url https://example.com --baseurl /project`. Output is written to `.jekyll-obsidian-cache/site/`. `jekyll-obsidian clean` removes this project's cache and output. The gem includes frontend assets, so local use does not require Node.js.
116
+
117
+ ## Guides
118
+
119
+ - [Host Integration](website/jekyll-obsidian-docs/docs/Integration.md) covers installation and updates in another repository.
120
+ - [Getting Started](website/jekyll-obsidian-docs/docs/Getting%20Started.md) covers GitHub Actions publishing, authoring, and optional local preview.
121
+ - [Syntax](website/jekyll-obsidian-docs/docs/Syntax.md) documents the supported Obsidian-flavored Markdown.
122
+ - [Customization](website/jekyll-obsidian-docs/docs/Customization.md) covers site identity, themes, navigation, and features.
123
+ - [Portfolio](website/jekyll-obsidian-docs/docs/Portfolio.md) covers project collections and public GitHub Markdown bodies.
124
+ - [Analytics](website/jekyll-obsidian-docs/docs/Analytics.md) covers optional Cloudflare and Google traffic measurement.
125
+ - [Comments](website/jekyll-obsidian-docs/docs/Comments.md) covers GitHub Discussions setup and privacy boundaries.
126
+ - [Localization](website/jekyll-obsidian-docs/docs/Localization.md) covers translations, fallback pages, and localized SEO.
127
+ - [Deployment](website/jekyll-obsidian-docs/docs/Deployment.md) covers GitHub Pages, URL paths, and custom domains.
128
+
129
+ Contributors can continue with the [Developer Guide](website/jekyll-obsidian-docs/docs/development/index.md).
130
+
131
+ ## License
132
+
133
+ MIT
@@ -0,0 +1,21 @@
1
+ title: My Site
2
+ description: ""
3
+ lang: en
4
+ url: ""
5
+ baseurl: ""
6
+
7
+ website:
8
+ source: docs
9
+ syntax_profile: ofm@1
10
+ theme: minimal
11
+ repository: ""
12
+ edit_branch: main
13
+ content:
14
+ publish_by_default: []
15
+ default_type: page
16
+ directories:
17
+ post:
18
+ - blog
19
+ doc:
20
+ - docs
21
+ features: {}
@@ -0,0 +1,8 @@
1
+ {% if include.timeline and include.timeline.size > 0 %}
2
+ {% assign ui = page.website.i18n.messages %}
3
+ {% if page.website.theme == 'minimal' %}{% assign filter_url = page.website.routes.blog %}{% unless filter_url %}{% assign filter_url = '/blog/' | relative_url %}{% endunless %}{% else %}{% assign filter_url = page.website.routes.tags %}{% unless filter_url %}{% assign filter_url = '/tags/' | relative_url %}{% endunless %}{% endif %}
4
+ <nav class="archive-timeline" data-timeline-nav aria-labelledby="archive-timeline-title">
5
+ <h2 class="relation-section__title" id="archive-timeline-title">{{ ui.chronology | default: 'Chronology' | escape }}</h2>
6
+ {% for group in include.timeline %}<section class="archive-timeline__year"><h3><a href="{{ filter_url | escape }}?year={{ group.year | url_encode }}" data-year-filter-option data-filter-year="{{ group.year | escape }}"><span>{{ group.year | escape }}</span><span class="archive-timeline__count">{{ group.count }}</span></a></h3><ul>{% for month in group.months %}<li><a href="{{ filter_url | escape }}?month={{ month.key | url_encode }}" data-month-filter-option data-filter-month="{{ month.key | escape }}"><span>{{ month.label | escape }}</span><span class="archive-timeline__count">{{ month.count }}</span></a></li>{% endfor %}</ul></section>{% endfor %}
7
+ </nav>
8
+ {% endif %}
@@ -0,0 +1,19 @@
1
+ {% if include.posts and include.posts.size > 0 %}
2
+ {% assign ui = page.website.i18n.messages %}
3
+ {% assign blog_url = page.website.routes.blog %}{% unless blog_url %}{% assign blog_url = '/blog/' | relative_url %}{% endunless %}
4
+ <section class="blog-ledger"{% if include.compact %} aria-label="{{ ui.dated_posts | default: 'Dated posts' | escape }}"{% else %} aria-labelledby="dispatches-title"{% endif %}>
5
+ {% unless include.compact %}<header class="section-heading"><h2 id="dispatches-title">{{ ui.field_dispatches | default: 'Field dispatches' | escape }}</h2></header>{% endunless %}
6
+ <ol>
7
+ {% for post in include.posts %}
8
+ <li{% if include.filterable %} data-filter-item data-topic-anchors="{{ post.topic_anchors | join: ' ' | escape }}"{% if post.filter_month %} data-filter-month="{{ post.filter_month | escape }}"{% endif %}{% endif %}>
9
+ <div class="blog-ledger__meta"><time datetime="{{ post.published_at | escape }}">{{ post.published_at | date: "%Y-%m-%d" }}</time></div>
10
+ <div class="blog-ledger__content">
11
+ <a class="blog-ledger__main" href="{{ post.url | escape }}"><strong>{{ post.title | escape }}</strong>{% if post.summary and post.summary != '' %}<span class="blog-ledger__description">{{ post.summary | escape }}</span>{% endif %}</a>
12
+ {% if post.topics and post.topics.size > 0 %}<ul class="blog-ledger__topics" aria-label="{{ ui.topics | default: 'Topics' | escape }}">{% for topic in post.topics %}<li><a href="{{ blog_url | escape }}?topic={{ topic.anchor | url_encode }}" data-topic-filter-option data-topic-anchor="{{ topic.anchor | escape }}">{{ topic.name | escape }}</a></li>{% endfor %}</ul>{% endif %}
13
+ </div>
14
+ </li>
15
+ {% endfor %}
16
+ </ol>
17
+ {% unless include.compact %}<a class="ledger-archive-link" href="{{ blog_url | escape }}">{{ ui.view_all | default: 'View all' | escape }} <span aria-hidden="true">→</span></a>{% endunless %}
18
+ </section>
19
+ {% endif %}
@@ -0,0 +1,7 @@
1
+ {% if page.website.theme_data.previous or page.website.theme_data.next %}
2
+ {% assign ui = page.website.i18n.messages %}
3
+ <nav class="sequence-navigation" aria-label="{{ ui.post_sequence | default: 'Post sequence' | escape }}">
4
+ {% if page.website.theme_data.previous %}<a rel="prev" href="{{ page.website.theme_data.previous.url | escape }}"><span>{{ ui.previous | default: 'Previous' | escape }}</span><strong>{{ page.website.theme_data.previous.title | escape }}</strong></a>{% endif %}
5
+ {% if page.website.theme_data.next %}<a rel="next" href="{{ page.website.theme_data.next.url | escape }}"><span>{{ ui.next | default: 'Next' | escape }}</span><strong>{{ page.website.theme_data.next.title | escape }}</strong></a>{% endif %}
6
+ </nav>
7
+ {% endif %}
@@ -0,0 +1,22 @@
1
+ {% assign comments = page.website.comments %}
2
+ {% if comments %}
3
+ {% assign ui = page.website.i18n.messages %}
4
+ <section class="website-comments" aria-labelledby="website-comments-title"{% if comments.load %} data-website-comments-load data-website-comments-repository="{{ comments.repository | escape }}" data-website-comments-repository-id="{{ comments.repository_id | escape }}" data-website-comments-category="{{ comments.category | escape }}" data-website-comments-category-id="{{ comments.category_id | escape }}" data-website-comments-term="{{ comments.term | escape }}" data-website-comments-language="{{ comments.language | escape }}" data-website-comments-unavailable="{{ ui.comments_unavailable | default: 'Comments could not be loaded. You can continue the conversation on GitHub.' | escape }}"{% endif %}>
5
+ <header class="website-comments__header">
6
+ <h2 id="website-comments-title">{{ ui.comments | default: 'Comments' | escape }}</h2>
7
+ </header>
8
+ {% if comments.load %}
9
+ <p class="website-comments__status" data-website-comments-status aria-live="polite">{{ ui.comments_loading | default: 'Loading comments…' | escape }}</p>
10
+ <div class="giscus website-comments__embed" data-website-comments-container></div>
11
+ {% elsif comments.configured %}
12
+ <p class="website-comments__status">{{ ui.comments_development | default: 'Comments load only on the published site.' | escape }}</p>
13
+ {% else %}
14
+ <p class="website-comments__status">{{ ui.comments_setup_pending | default: 'Comments are not available yet. You can finish the GitHub Discussions setup later.' | escape }}</p>
15
+ {% endif %}
16
+ {% if comments.configured %}
17
+ <p class="website-comments__fallback">{{ ui.comments_stored | default: 'Comments are stored in GitHub Discussions.' | escape }} <a href="{{ comments.discussion_url | escape }}">{{ ui.open_discussions | default: 'Open discussions on GitHub' | escape }}</a>.</p>
18
+ {% else %}
19
+ <p class="website-comments__fallback"><a href="{{ comments.repository_url | escape }}">{{ ui.open_comments_repository | default: 'Open the comments repository on GitHub' | escape }}</a>.</p>
20
+ {% endif %}
21
+ </section>
22
+ {% endif %}
@@ -0,0 +1,14 @@
1
+ {% case include.icon %}
2
+ {% when 'email' %}<svg class="minimal-contact__icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><rect x="3" y="5" width="18" height="14" rx="2"></rect><path d="m3 7 9 6 9-6"></path></svg>
3
+ {% when 'phone' %}<svg class="minimal-contact__icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M22 16.9v3a2 2 0 0 1-2.2 2 19.8 19.8 0 0 1-8.6-3.1 19.5 19.5 0 0 1-6-6A19.8 19.8 0 0 1 2.1 4.2 2 2 0 0 1 4.1 2h3a2 2 0 0 1 2 1.7c.1 1 .4 2 .7 2.9a2 2 0 0 1-.4 2.1L8.1 10a16 16 0 0 0 6 6l1.3-1.3a2 2 0 0 1 2.1-.4c.9.3 1.9.6 2.9.7a2 2 0 0 1 1.6 1.9Z"></path></svg>
4
+ {% when 'github' %}{% include website/github-icon.html class='minimal-contact__icon minimal-contact__icon--brand' %}
5
+ {% when 'linkedin' %}<svg class="minimal-contact__icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><rect x="3" y="3" width="18" height="18" rx="2"></rect><path d="M8 10v7M8 7v.01M12 17v-7M12 13a4 4 0 0 1 8 0v4"></path></svg>
6
+ {% when 'x' %}<svg class="minimal-contact__icon minimal-contact__icon--brand" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M18.24 2.25h3.31l-7.23 8.26 8.51 11.24h-6.66l-5.21-6.82-5.97 6.82H1.68l7.73-8.84L1.25 2.25h6.83l4.71 6.23 5.45-6.23Zm-1.16 17.52h1.84L7.08 4.13H5.12l11.96 15.64Z"></path></svg>
7
+ {% when 'mastodon' %}<svg class="minimal-contact__icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 17V9a4 4 0 0 1 7-2.6A4 4 0 0 1 19 9v6c0 4-3 6-7 6-2.2 0-4-.5-5.2-1.5"></path><path d="M9 15V9.5a1.5 1.5 0 0 1 3 0V15M12 9.5a1.5 1.5 0 0 1 3 0V15"></path></svg>
8
+ {% when 'bluesky' %}<svg class="minimal-contact__icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12 11c-1.7-3-5.8-6-7.6-4.7-1.7 1.3-.7 5.7 2 7.3 1.2.7 2.7.7 4 .2-2.1.4-4.2 1.7-3.5 3.7.8 2.4 3.9 1.3 5.1-.9 1.2 2.2 4.3 3.3 5.1.9.7-2-1.4-3.3-3.5-3.7 1.3.5 2.8.5 4-.2 2.7-1.6 3.7-6 2-7.3C17.8 5 13.7 8 12 11Z"></path></svg>
9
+ {% when 'instagram' %}<svg class="minimal-contact__icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><rect x="3" y="3" width="18" height="18" rx="5"></rect><circle cx="12" cy="12" r="4"></circle><path d="M17.5 6.5h.01"></path></svg>
10
+ {% when 'youtube' %}<svg class="minimal-contact__icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M21 8.2a2.8 2.8 0 0 0-2-2C17.2 5.7 12 5.7 12 5.7s-5.2 0-7 .5a2.8 2.8 0 0 0-2 2A29 29 0 0 0 2.5 12 29 29 0 0 0 3 15.8a2.8 2.8 0 0 0 2 2c1.8.5 7 .5 7 .5s5.2 0 7-.5a2.8 2.8 0 0 0 2-2 29 29 0 0 0 .5-3.8 29 29 0 0 0-.5-3.8Z"></path><path d="m10 9 5 3-5 3Z"></path></svg>
11
+ {% when 'telegram' %}<svg class="minimal-contact__icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="m21 4-3 16-6-4-3 3-1-5-5-2Z"></path><path d="m8 14 9-7-6 9"></path></svg>
12
+ {% when 'rss' %}<svg class="minimal-contact__icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="5" cy="19" r="1"></circle><path d="M4 11a9 9 0 0 1 9 9M4 4a16 16 0 0 1 16 16"></path></svg>
13
+ {% when 'website' %}<svg class="minimal-contact__icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="9"></circle><path d="M3 12h18M12 3a14 14 0 0 1 0 18M12 3a14 14 0 0 0 0 18"></path></svg>
14
+ {% endcase %}
@@ -0,0 +1,7 @@
1
+ {% assign ui = page.website.i18n.messages %}
2
+ {% assign topic_summaries = include.summaries | default: page.website.tag_summaries %}
3
+ {% if page.website.theme == 'minimal' %}{% assign tags_title = ui.topics | default: 'Topics' %}{% assign filter_url = page.website.routes.blog %}{% unless filter_url %}{% assign filter_url = '/blog/' | relative_url %}{% endunless %}{% else %}{% assign tags_title = ui.tags | default: 'Tags' %}{% assign filter_url = page.website.routes.tags %}{% unless filter_url %}{% assign filter_url = '/tags/' | relative_url %}{% endunless %}{% endif %}
4
+ <section class="relation-section context-tags" aria-labelledby="context-tags-title-{{ include.location }}">
5
+ <h2 class="relation-section__title" id="context-tags-title-{{ include.location }}">{{ tags_title | escape }}</h2>
6
+ <ul class="context-tag-list">{% for topic in topic_summaries %}<li><a href="{% if page.website.theme == 'minimal' %}{{ filter_url | escape }}?topic={{ topic.anchor | url_encode }}{% elsif topic.url %}{{ topic.url | escape }}{% else %}{{ filter_url | escape }}#{{ topic.anchor | escape }}{% endif %}" aria-label="{{ topic.name | escape }} — {{ topic.count }} {{ ui.notes | default: 'notes' | escape }}"><span class="context-tag__name" aria-hidden="true">{{ topic.name | escape }}</span><span class="context-tag__count" aria-hidden="true">{{ topic.count }}</span></a></li>{% endfor %}</ul>
7
+ </section>
@@ -0,0 +1,3 @@
1
+ {% if page.website.features.graph and page.website.local_graph %}{% include website/local-graph.html location=include.location %}{% endif %}
2
+ {% if page.website.features.outline and page.website.outline.size > 0 %}{% include website/outline.html location=include.location %}{% endif %}
3
+ {% if page.website.features.relations %}{% include website/relations.html location=include.location %}{% elsif page.website.tag_summaries and page.website.tag_summaries.size > 0 %}{% include website/context-tags.html location=include.location %}{% endif %}
@@ -0,0 +1,71 @@
1
+ {% assign ui = page.website.i18n.messages %}
2
+ {% if page.website.features.search %}
3
+ <dialog class="website-dialog" data-dialog="search" aria-labelledby="search-dialog-title"{% if ui.search_loading %} data-search-loading="{{ ui.search_loading | escape }}"{% endif %}{% if ui.search_prompt %} data-search-prompt="{{ ui.search_prompt | escape }}"{% endif %}{% if ui.search_unavailable %} data-search-unavailable="{{ ui.search_unavailable | escape }}"{% endif %}{% if ui.search_no_results %} data-search-no-results="{{ ui.search_no_results | escape }}"{% endif %}{% if ui.search_result_one %} data-search-result-one="{{ ui.search_result_one | escape }}"{% endif %}{% if ui.search_result_many %} data-search-result-many="{{ ui.search_result_many | escape }}"{% endif %}>
4
+ <div class="website-dialog__sheet">
5
+ <header class="website-dialog__header">
6
+ <h2 class="website-dialog__title" id="search-dialog-title">{{ ui.search_title | default: 'Search this site' | escape }}</h2>
7
+ <button class="website-dialog__close" type="button" data-dialog-close aria-label="{{ ui.close_search | default: 'Close search' | escape }}">&times;</button>
8
+ </header>
9
+ <div class="website-dialog__body">
10
+ <label class="search-box"><span aria-hidden="true">⌕</span><span class="visually-hidden">{{ ui.search_pages | default: 'Search pages' | escape }}</span><input type="search" inputmode="search" autocomplete="off" placeholder="{{ ui.search_placeholder | default: 'Title, tag, or phrase' | escape }}" data-search-input><kbd>⌘K</kbd></label>
11
+ {% if page.website.navigation.size > 0 %}
12
+ <nav class="search-navigation" aria-label="{{ ui.primary_navigation | default: 'Primary navigation' | escape }}" data-search-navigation>
13
+ <ul class="search-navigation__list">
14
+ {% for item in page.website.navigation %}<li data-navigation-id="{{ item.id | escape }}"><a href="{{ item.url | escape }}"{% if item.id == page.website.active_navigation_id %} aria-current="page"{% endif %}>{{ item.label | escape }}</a></li>{% endfor %}
15
+ </ul>
16
+ </nav>
17
+ {% endif %}
18
+ <p class="search-status" data-search-status aria-live="polite">{{ ui.search_initial | default: 'The index loads when search opens.' | escape }}</p>
19
+ <ol class="search-results" data-search-results></ol>
20
+ </div>
21
+ </div>
22
+ </dialog>
23
+ {% endif %}
24
+
25
+ <template data-dialog-template="browse">
26
+ <nav aria-label="{{ ui.primary_navigation | default: 'Primary navigation' | escape }}">
27
+ <ul class="relation-list">
28
+ {% for item in page.website.navigation %}<li data-navigation-id="{{ item.id | escape }}"><a href="{{ item.url | escape }}"{% if item.id == page.website.active_navigation_id %} aria-current="page"{% endif %}>{{ item.label | escape }}</a></li>{% endfor %}
29
+ </ul>
30
+ </nav>
31
+ {% assign browse_has_docs_tree = false %}{% if include.theme == 'docs' or page.website.content_type == 'doc' %}{% if page.website.theme_data.docs_tree.size > 0 %}{% assign browse_has_docs_tree = true %}{% endif %}{% endif %}
32
+ {% if browse_has_docs_tree %}
33
+ <nav class="docs-tree docs-tree--dialog" aria-label="{{ ui.documentation | default: 'Documentation' | escape }}">
34
+ {% include website/docs-tree.html nodes=page.website.theme_data.docs_tree %}
35
+ </nav>
36
+ {% endif %}
37
+ </template>
38
+ <dialog class="website-dialog" data-dialog="browse" aria-labelledby="browse-dialog-title"><div class="website-dialog__sheet"><header class="website-dialog__header"><h2 class="website-dialog__title" id="browse-dialog-title">{{ ui.browse | default: 'Browse' | escape }}</h2><button class="website-dialog__close" type="button" data-dialog-close aria-label="{{ ui.close_browse | default: 'Close browse menu' | escape }}">&times;</button></header><div class="website-dialog__body" data-dialog-content></div></div></dialog>
39
+
40
+ {% assign has_timeline_context = false %}{% if page.website.kind == 'blog-index' and page.website.theme_data.timeline.size > 0 %}{% assign has_timeline_context = true %}{% endif %}
41
+ {% assign has_context_dialog = has_timeline_context %}{% if page.website.kind == 'home' %}{% if page.website.theme_data.topic_summaries.size > 0 or page.website.has_context %}{% assign has_context_dialog = true %}{% endif %}{% elsif page.website.kind == 'note' and page.website.has_context %}{% assign has_context_dialog = true %}{% endif %}
42
+ {% if has_context_dialog %}
43
+ <dialog class="website-dialog" data-dialog="context" aria-labelledby="context-dialog-title"><div class="website-dialog__sheet"><header class="website-dialog__header"><h2 class="website-dialog__title" id="context-dialog-title">{% if has_timeline_context %}{{ ui.chronology | default: 'Chronology' | escape }}{% elsif page.website.kind == 'home' and page.website.has_context %}{{ ui.context | default: 'Context' | escape }}{% elsif page.website.kind == 'home' %}{{ ui.topics | default: 'Topics' | escape }}{% elsif page.website.features.outline and page.website.features.relations == false and page.website.local_graph == nil %}{{ ui.on_this_page | default: 'On this page' | escape }}{% else %}{{ ui.context | default: 'Context' | escape }}{% endif %}</h2><button class="website-dialog__close" type="button" data-dialog-close aria-label="{{ ui.close_context | default: 'Close page context' | escape }}">&times;</button></header><div class="website-dialog__body" data-dialog-content></div></div></dialog>
44
+ {% endif %}
45
+
46
+ {% assign graph_page = false %}
47
+ {% if page.website.kind == 'note' %}{% assign graph_page = true %}{% endif %}
48
+ {% if page.website.kind == 'home' and page.website.id %}{% assign graph_page = true %}{% endif %}
49
+ {% assign has_graph_dialogs = false %}
50
+ {% if graph_page and page.website.features.graph and page.website.local_graph %}{% assign has_graph_dialogs = true %}{% endif %}
51
+ {% if has_graph_dialogs %}
52
+ <dialog class="website-dialog website-dialog--graph" data-dialog="graph-global" aria-labelledby="global-graph-dialog-title"><div class="website-dialog__sheet"><header class="website-dialog__header"><h2 class="website-dialog__title" id="global-graph-dialog-title">{{ ui.full_graph | default: 'Full graph' | escape }}</h2><button class="website-dialog__close" type="button" data-dialog-close aria-label="{{ ui.close_full_graph | default: 'Close full graph' | escape }}">&times;</button></header><div class="website-dialog__body"><div class="graph-view graph-view--global" data-graph-dialog-view="global" data-graph-mode="global" data-current-note-id="{{ page.website.id | escape }}" data-graph-too-large="{{ ui.graph_too_large | default: 'This complete graph is too large to render interactively. Use local graphs or search instead.' | escape }}"{% if ui.graph_loading %} data-graph-loading="{{ ui.graph_loading | escape }}"{% endif %}{% if ui.graph_unavailable %} data-graph-unavailable="{{ ui.graph_unavailable | escape }}"{% endif %}{% if ui.graph_summary %} data-graph-summary="{{ ui.graph_summary | escape }}"{% endif %}{% if ui.graph_node_label %} data-graph-node-label="{{ ui.graph_node_label | escape }}"{% endif %}{% if ui.graph_title %} data-graph-title="{{ ui.graph_title | escape }}"{% endif %}{% if ui.graph_description %} data-graph-description="{{ ui.graph_description | escape }}"{% endif %}><p class="graph-status" data-graph-status aria-live="polite">{{ ui.graph_loading | default: 'Loading graph…' | escape }}</p></div></div></div></dialog>
53
+ <dialog class="website-dialog website-dialog--graph" data-dialog="graph-local" aria-labelledby="expanded-graph-dialog-title"><div class="website-dialog__sheet"><header class="website-dialog__header"><h2 class="website-dialog__title" id="expanded-graph-dialog-title">{{ ui.local_graph | default: 'Local graph' | escape }}</h2><button class="website-dialog__close" type="button" data-dialog-close aria-label="{{ ui.close_local_graph | default: 'Close local graph' | escape }}">&times;</button></header><div class="website-dialog__body"><div class="graph-view graph-view--expanded" data-graph-dialog-view="local" data-graph-mode="expanded" data-current-note-id="{{ page.website.id | escape }}"{% if ui.graph_loading %} data-graph-loading="{{ ui.graph_loading | escape }}"{% endif %}{% if ui.graph_unavailable %} data-graph-unavailable="{{ ui.graph_unavailable | escape }}"{% endif %}{% if ui.graph_summary %} data-graph-summary="{{ ui.graph_summary | escape }}"{% endif %}{% if ui.graph_node_label %} data-graph-node-label="{{ ui.graph_node_label | escape }}"{% endif %}{% if ui.graph_title %} data-graph-title="{{ ui.graph_title | escape }}"{% endif %}{% if ui.graph_description %} data-graph-description="{{ ui.graph_description | escape }}"{% endif %}><p class="graph-status" data-graph-status aria-live="polite">{{ ui.graph_loading | default: 'Loading graph…' | escape }}</p></div></div></div></dialog>
54
+ {% endif %}
55
+
56
+ {% capture default_media_zoom_level %}Zoom: {percent}%{% endcapture %}
57
+ <dialog class="website-dialog website-dialog--media" data-dialog="media" data-media-zoom-level="{{ ui.zoom_level | default: default_media_zoom_level | escape }}" aria-labelledby="media-dialog-title">
58
+ <div class="website-dialog__sheet">
59
+ <header class="website-dialog__header">
60
+ <h2 class="website-dialog__title" id="media-dialog-title" data-media-dialog-title>{{ ui.image | default: 'Image' | escape }}</h2>
61
+ <div class="media-dialog__controls">
62
+ <button type="button" data-media-zoom-out aria-label="{{ ui.zoom_out | default: 'Zoom out' | escape }}" title="{{ ui.zoom_out | default: 'Zoom out' | escape }}"><span aria-hidden="true">−</span></button>
63
+ <output data-media-zoom-status aria-live="polite"></output>
64
+ <button type="button" data-media-zoom-in aria-label="{{ ui.zoom_in | default: 'Zoom in' | escape }}" title="{{ ui.zoom_in | default: 'Zoom in' | escape }}"><span aria-hidden="true">+</span></button>
65
+ <button type="button" data-media-zoom-reset aria-label="{{ ui.reset_zoom | default: 'Reset zoom' | escape }}" title="{{ ui.reset_zoom | default: 'Reset zoom' | escape }}"><span aria-hidden="true">↺</span></button>
66
+ <button class="website-dialog__close" type="button" data-dialog-close aria-label="{{ ui.close_image | default: 'Close image' | escape }}">×</button>
67
+ </div>
68
+ </header>
69
+ <div class="website-dialog__body media-dialog__body"><div class="media-dialog__viewport" data-media-dialog-viewport tabindex="0" role="group" aria-label="{{ ui.image | default: 'Image' | escape }}"><div class="media-dialog__canvas" data-media-dialog-canvas></div></div></div>
70
+ </div>
71
+ </dialog>
@@ -0,0 +1,7 @@
1
+ {% if page.website.theme_data.previous or page.website.theme_data.next %}
2
+ {% assign ui = page.website.i18n.messages %}
3
+ <nav class="sequence-navigation" aria-label="{{ ui.documentation_sequence | default: 'Documentation sequence' | escape }}">
4
+ {% if page.website.theme_data.previous %}<a rel="prev" href="{{ page.website.theme_data.previous.url | escape }}"><span>{{ ui.previous | default: 'Previous' | escape }}</span><strong>{{ page.website.theme_data.previous.title | escape }}</strong></a>{% endif %}
5
+ {% if page.website.theme_data.next %}<a rel="next" href="{{ page.website.theme_data.next.url | escape }}"><span>{{ ui.next | default: 'Next' | escape }}</span><strong>{{ page.website.theme_data.next.title | escape }}</strong></a>{% endif %}
6
+ </nav>
7
+ {% endif %}
@@ -0,0 +1,8 @@
1
+ <ul class="docs-tree__list">
2
+ {% for node in include.nodes %}
3
+ <li class="docs-tree__item">
4
+ {% if node.url %}<a href="{{ node.url | escape }}"{% if node.url == page.website.href %} aria-current="page"{% endif %}>{{ node.title | escape }}</a>{% else %}<span>{{ node.title | escape }}</span>{% endif %}
5
+ {% if node.children and node.children.size > 0 %}{% include website/docs-tree.html nodes=node.children %}{% endif %}
6
+ </li>
7
+ {% endfor %}
8
+ </ul>
@@ -0,0 +1,14 @@
1
+ <footer class="site-footer">
2
+ {% assign ui = page.website.i18n.messages %}
3
+ <div class="site-footer__inner">
4
+ <span>{{ ui.built_by | default: 'Built by' | escape }}</span>
5
+ <a class="site-footer__github" href="https://github.com/wowfun/jekyll-obsidian" aria-label="{{ ui.project_on_github | default: 'Jekyll Obsidian on GitHub' | escape }}">
6
+ {% include website/github-icon.html %}
7
+ <span>Jekyll Obsidian</span>
8
+ </a>
9
+ <span aria-hidden="true">·</span>
10
+ <span>MIT License</span>
11
+ <span aria-hidden="true">·</span>
12
+ <time datetime="{{ site.time | date: "%Y" }}">{{ site.time | date: "%Y" }}</time>
13
+ </div>
14
+ </footer>
@@ -0,0 +1,3 @@
1
+ <svg{% if include.class %} class="{{ include.class | escape }}"{% endif %} viewBox="0 0 16 16" aria-hidden="true" focusable="false">
2
+ <path d="M8 0C3.58 0 0 3.64 0 8.13c0 3.59 2.29 6.64 5.47 7.72.4.08.55-.18.55-.39 0-.19-.01-.83-.01-1.51-2.01.38-2.53-.5-2.69-.96-.09-.23-.48-.96-.82-1.15-.28-.15-.68-.53-.01-.54.63-.01 1.08.59 1.23.83.72 1.23 1.87.88 2.33.67.07-.53.28-.88.51-1.08-1.78-.21-3.64-.9-3.64-4.01 0-.88.31-1.61.82-2.18-.08-.2-.36-1.04.08-2.15 0 0 .67-.22 2.2.83A7.4 7.4 0 0 1 8 3.94c.68 0 1.36.09 2 .27 1.53-1.05 2.2-.83 2.2-.83.44 1.11.16 1.95.08 2.15.51.57.82 1.3.82 2.18 0 3.12-1.87 3.8-3.65 4.01.29.25.54.74.54 1.5 0 1.08-.01 1.95-.01 2.22 0 .21.15.47.55.39A8.16 8.16 0 0 0 16 8.13C16 3.64 12.42 0 8 0Z"></path>
3
+ </svg>
@@ -0,0 +1,41 @@
1
+ <meta charset="utf-8">
2
+ <meta name="viewport" content="width=device-width, initial-scale=1">
3
+ <meta name="color-scheme" content="light dark">
4
+ {% if page.website.comments.load %}
5
+ <meta http-equiv="Content-Security-Policy" data-page-csp content="default-src 'self'; base-uri 'self'; form-action 'self'; script-src 'self'{% for source in page.website.content_security.script_sources %} {{ source | escape }}{% endfor %} https://giscus.app; style-src 'self' 'unsafe-inline' https://giscus.app; img-src 'self' https:; media-src 'self'{% for source in page.website.content_security.media_sources %} {{ source | escape }}{% endfor %}; object-src 'self'; font-src 'self'; connect-src 'self'{% for source in page.website.content_security.connect_sources %} {{ source | escape }}{% endfor %}; frame-src 'self'{% for source in page.website.content_security.frame_sources %} {{ source | escape }}{% endfor %} https://giscus.app">
6
+ {% else %}
7
+ <meta http-equiv="Content-Security-Policy" data-page-csp content="default-src 'self'; base-uri 'self'; form-action 'self'; script-src 'self'{% for source in page.website.content_security.script_sources %} {{ source | escape }}{% endfor %}; style-src 'self' 'unsafe-inline'; img-src 'self' https:; media-src 'self'{% for source in page.website.content_security.media_sources %} {{ source | escape }}{% endfor %}; object-src 'self'; font-src 'self'; connect-src 'self'{% for source in page.website.content_security.connect_sources %} {{ source | escape }}{% endfor %}; frame-src 'self'{% for source in page.website.content_security.frame_sources %} {{ source | escape }}{% endfor %}">
8
+ {% endif %}
9
+ {% if page.website.analytics.load %}<meta name="website:analytics" data-provider="{{ page.website.analytics.provider | escape }}" content="{{ page.website.analytics.identifier | escape }}">{% endif %}
10
+ <title data-page-head>{% if page.title and page.title != site.title %}{{ page.title | escape }} · {% endif %}{{ site.title | escape }}</title>
11
+ <meta name="description" content="{{ page.description | default: site.description | escape }}" data-page-head>
12
+ {% assign canonical_url = page.website.canonical_url | default: page.website.absolute_url %}
13
+ {% if canonical_url %}
14
+ <link rel="canonical" href="{{ canonical_url | escape }}" data-page-head>
15
+ <meta property="og:url" content="{{ page.website.absolute_url | escape }}" data-page-head>
16
+ {% endif %}
17
+ {% if page.website.robots %}<meta name="robots" content="{{ page.website.robots | escape }}" data-page-head>{% endif %}
18
+ {% for alternate in page.website.alternates %}<link rel="alternate" hreflang="{{ alternate.hreflang | escape }}" href="{{ alternate.href | escape }}" data-page-head>{% endfor %}
19
+ <meta property="og:title" content="{{ page.title | default: site.title | escape }}" data-page-head>
20
+ <meta property="og:description" content="{{ page.description | default: site.description | escape }}" data-page-head>
21
+ {% if page.image %}<meta property="og:image" content="{{ page.image | escape }}" data-page-head>{% endif %}
22
+ <meta property="og:type" content="{% if page.website.content_type == 'post' %}article{% else %}website{% endif %}" data-page-head>
23
+ {% if page.website.features.search %}<meta name="website:search" content="{% if page.website.resources.search %}{{ page.website.resources.search | escape }}{% else %}{{ '/assets/website/search.v1.json' | relative_url }}{% endif %}">{% endif %}
24
+ {% if page.website.features.search and site.data.website_assets.features.search.worker %}{% assign search_worker = '/assets/website/' | append: site.data.website_assets.features.search.worker %}<meta name="website:search-worker" content="{{ search_worker | relative_url }}">{% endif %}
25
+ {% if page.website.features.previews %}<meta name="website:catalog" content="{% if page.website.resources.catalog %}{{ page.website.resources.catalog | escape }}{% else %}{{ '/assets/website/catalog.v1.json' | relative_url }}{% endif %}"><meta name="website:preview" content="{% if page.website.resources.preview %}{{ page.website.resources.preview | escape }}{% else %}{{ '/assets/website/catalog.v1.json' | relative_url }}{% endif %}">{% endif %}
26
+ {% if page.website.features.graph %}<meta name="website:graph" content="{% if page.website.resources.graph %}{{ page.website.resources.graph | escape }}{% else %}{{ '/assets/website/graph.v1.json' | relative_url }}{% endif %}">{% endif %}
27
+ {% if page.website.features.feed and site.data.website_feed_available %}<link rel="alternate" type="application/atom+xml" title="{{ site.title | escape }} · {{ page.website.i18n.messages.feed | default: 'Feed' | escape }}" href="{% if page.website.resources.feed %}{{ page.website.resources.feed | escape }}{% else %}{{ '/feed.xml' | relative_url }}{% endif %}">{% endif %}
28
+ {% if page.website.comments.load %}<meta name="giscus:backlink" content="{{ page.website.absolute_url | escape }}" data-page-head>{% endif %}
29
+ {% assign website_entry = include.entry %}
30
+ {% if website_entry.color_scheme %}
31
+ {% assign color_scheme_js = '/assets/website/' | append: website_entry.color_scheme %}
32
+ <script src="{{ color_scheme_js | relative_url }}"></script>
33
+ {% endif %}
34
+ {% if website_entry.css %}
35
+ {% assign website_css = '/assets/website/' | append: website_entry.css %}
36
+ <link rel="stylesheet" href="{{ website_css | relative_url }}">
37
+ {% endif %}
38
+ {% if website_entry.js %}
39
+ {% assign website_js = '/assets/website/' | append: website_entry.js %}
40
+ <script type="module" src="{{ website_js | relative_url }}"></script>
41
+ {% endif %}
@@ -0,0 +1,35 @@
1
+ <header class="site-header">
2
+ {% assign ui = page.website.i18n.messages %}
3
+ {% assign home_url = page.website.home_url | default: page.website.routes.home %}
4
+ {% unless home_url %}{% assign home_url = '/' | relative_url %}{% endunless %}
5
+ <div class="site-header__inner">
6
+ <a class="site-mark" href="{{ home_url | escape }}" aria-label="{{ site.title | escape }} — {{ ui.home | default: 'Home' | escape }}">
7
+ <span class="site-mark__glyph" aria-hidden="true">{% if include.theme == 'minimal' %}¶{% else %}⌁{% endif %}</span>
8
+ <span class="site-mark__name">{{ site.title | escape }}</span>
9
+ </a>
10
+
11
+ <nav class="site-navigation" aria-label="{{ ui.primary_navigation | default: 'Primary navigation' | escape }}" data-priority-navigation>
12
+ <ul class="site-navigation__list" data-priority-navigation-list>
13
+ {% for item in page.website.navigation %}
14
+ <li data-priority-navigation-item data-navigation-id="{{ item.id | escape }}"><a href="{{ item.url | escape }}"{% if item.id == page.website.active_navigation_id %} aria-current="page"{% endif %}>{{ item.label | escape }}</a></li>
15
+ {% endfor %}
16
+ </ul>
17
+ <details class="site-navigation__more" data-priority-navigation-more hidden>
18
+ <summary>{{ ui.more | default: 'More' | escape }}</summary>
19
+ <ul class="site-navigation__overflow" data-priority-navigation-overflow></ul>
20
+ </details>
21
+ </nav>
22
+
23
+ <div class="site-actions">
24
+ {% if page.website.features.search %}
25
+ <button class="site-action" type="button" data-search-open aria-label="{{ ui.search | default: 'Search' | escape }}">
26
+ <span class="site-action__label">{{ ui.search | default: 'Search' | escape }}</span><kbd class="site-action__shortcut" aria-hidden="true">⌘K</kbd>
27
+ </button>
28
+ {% endif %}
29
+ {% include website/language-switcher.html %}
30
+ <button class="site-action" type="button" data-color-scheme-toggle data-scheme-use-light="{{ ui.use_light_scheme | default: 'Use light color scheme' | escape }}" data-scheme-use-dark="{{ ui.use_dark_scheme | default: 'Use dark color scheme' | escape }}" data-scheme-light="{{ ui.light_scheme | default: 'Light' | escape }}" data-scheme-dark="{{ ui.dark_scheme | default: 'Dark' | escape }}" aria-label="{{ ui.toggle_scheme | default: 'Toggle color scheme' | escape }}">
31
+ <span data-color-scheme-label>{{ ui.scheme | default: 'Scheme' | escape }}</span>
32
+ </button>
33
+ </div>
34
+ </div>
35
+ </header>
@@ -0,0 +1,16 @@
1
+ {% if page.website.i18n.localizations and page.website.i18n.localizations.size > 1 %}
2
+ {% assign ui = page.website.i18n.messages %}
3
+ <details class="language-switcher" data-language-switcher>
4
+ <summary class="site-action" aria-label="{{ ui.language | default: 'Language' | escape }}: {{ page.website.i18n.name | escape }}">
5
+ <span>{{ page.website.i18n.name | escape }}</span>
6
+ <span aria-hidden="true">⌄</span>
7
+ </summary>
8
+ <nav class="language-switcher__panel" aria-label="{{ ui.language | default: 'Language' | escape }}">
9
+ <ul>
10
+ {% for localization in page.website.i18n.localizations %}
11
+ <li><a href="{{ localization.href | escape }}" lang="{{ localization.locale | escape }}" hreflang="{{ localization.hreflang | escape }}" dir="{{ localization.dir | escape }}"{% if localization.locale == page.website.i18n.locale %} aria-current="page"{% endif %}>{{ localization.name | escape }}{% if localization.fallback %}<span class="visually-hidden"> — {{ ui.translation_missing | default: 'Translation unavailable' | escape }}</span>{% endif %}</a></li>
12
+ {% endfor %}
13
+ </ul>
14
+ </nav>
15
+ </details>
16
+ {% endif %}
@@ -0,0 +1,25 @@
1
+ {% assign ui = page.website.i18n.messages %}
2
+ {% assign local_graph = page.website.local_graph %}
3
+ <section class="local-graph" data-local-graph-section aria-labelledby="local-graph-title-{{ include.location }}">
4
+ <header class="local-graph__header">
5
+ <h2 class="relation-section__title" id="local-graph-title-{{ include.location }}">{{ ui.interactive_graph | default: 'Interactive graph' | escape }}</h2>
6
+ <div class="local-graph__actions">
7
+ <button type="button" data-graph-open="global" aria-label="{{ ui.open_full_graph | default: 'Open full graph' | escape }}" title="{{ ui.open_full_graph | default: 'Open full graph' | escape }}">
8
+ <svg viewBox="0 0 20 20" aria-hidden="true"><circle cx="5" cy="5" r="2"></circle><circle cx="15" cy="4" r="2"></circle><circle cx="10" cy="15" r="2"></circle><path d="M6.8 5.2 13 4.4M6.1 6.7 9 13.2m4.8-7.4-2.7 7.4"></path></svg>
9
+ </button>
10
+ <button type="button" data-graph-open="local" aria-label="{{ ui.open_local_graph | default: 'Expand local graph' | escape }}" title="{{ ui.open_local_graph | default: 'Expand local graph' | escape }}">
11
+ <svg viewBox="0 0 20 20" aria-hidden="true"><path d="M8 4H4v4m8-4h4v4M8 16H4v-4m8 4h4v-4M4.5 7.5 8 4m4 0 3.5 3.5M4.5 12.5 8 16m4 0 3.5-3.5"></path></svg>
12
+ </button>
13
+ </div>
14
+ </header>
15
+ <div class="graph-view graph-view--compact" data-graph-view data-graph-mode="compact" data-current-note-id="{{ local_graph.current_id | escape }}"{% if ui.graph_loading %} data-graph-loading="{{ ui.graph_loading | escape }}"{% endif %}{% if ui.graph_unavailable %} data-graph-unavailable="{{ ui.graph_unavailable | escape }}"{% endif %}{% if ui.graph_summary %} data-graph-summary="{{ ui.graph_summary | escape }}"{% endif %}{% if ui.graph_node_label %} data-graph-node-label="{{ ui.graph_node_label | escape }}"{% endif %}{% if ui.graph_title %} data-graph-title="{{ ui.graph_title | escape }}"{% endif %}{% if ui.graph_description %} data-graph-description="{{ ui.graph_description | escape }}"{% endif %}>
16
+ <p class="graph-status" data-graph-status aria-live="polite">{{ ui.graph_loading | default: 'Loading graph…' | escape }}</p>
17
+ </div>
18
+ <template data-local-graph-data>
19
+ {% for node in local_graph.nodes %}<i data-graph-node data-node-id="{{ node.id | escape }}" data-node-title="{{ node.title | escape }}" data-node-url="{{ node.url | escape }}" data-node-degree="{{ node.degree }}"></i>{% endfor %}
20
+ {% for edge in local_graph.edges %}<i data-graph-edge data-edge-source="{{ edge.source | escape }}" data-edge-target="{{ edge.target | escape }}" data-edge-kind="{{ edge.kind | escape }}" data-edge-count="{{ edge.count }}"></i>{% endfor %}
21
+ </template>
22
+ <div class="local-graph__fallback" data-graph-fallback>
23
+ <ul class="relation-list">{% for node in local_graph.nodes %}{% unless node.id == local_graph.current_id %}<li><a href="{{ node.url | escape }}">{{ node.title | escape }}</a></li>{% endunless %}{% endfor %}</ul>
24
+ </div>
25
+ </section>
@@ -0,0 +1,35 @@
1
+ {% assign show_note_header = false %}
2
+ {% assign show_note_title = false %}
3
+ {% unless page.website.has_h1 %}
4
+ {% unless page.website.directory_index %}{% assign show_note_title = true %}{% endunless %}
5
+ {% endunless %}
6
+ {% if page.website.kind == 'note' %}{% assign show_note_header = true %}{% endif %}
7
+ {% if page.website.kind == 'home' and page.website.id %}
8
+ {% if show_note_title %}{% assign show_note_header = true %}{% endif %}
9
+ {% if page.website.subtitle %}{% assign show_note_header = true %}{% endif %}
10
+ {% endif %}
11
+ {% if show_note_header %}
12
+ {% assign ui = page.website.i18n.messages %}
13
+ <header class="note-header" lang="{{ page.website.i18n.content_lang | default: page.website.i18n.locale | default: site.lang | default: 'en' | escape }}" dir="{{ page.website.i18n.content_dir | default: page.website.i18n.dir | default: 'ltr' | escape }}">
14
+ {% if show_note_title %}<h1 class="note-title">{{ page.title | escape }}</h1>{% endif %}
15
+ {% if page.website.kind == 'note' and page.website.content_type == 'post' and page.website.authors.size > 0 %}<p class="note-byline">{{ ui.posted_by | default: 'Posted by' | escape }} {% for author in page.website.authors %}{% if author.url %}<a href="{{ author.url | escape }}">{{ author.name | escape }}</a>{% else %}{{ author.name | escape }}{% endif %}{% unless forloop.last %}, {% endunless %}{% endfor %}</p>{% endif %}
16
+ {% if page.website.subtitle %}<p class="note-subtitle">{{ page.website.subtitle | escape }}</p>{% elsif page.website.kind == 'note' and page.description %}<p class="note-description">{{ page.description | escape }}</p>{% endif %}
17
+ {% if page.website.theme == 'minimal' %}{% include website/portfolio-topics.html topics=page.website.theme_data.portfolio_topics url=page.website.routes.portfolio %}{% endif %}
18
+ {% if page.website.kind == 'note' %}
19
+ <div class="note-meta">
20
+ {% if page.website.content_type == 'post' and page.website.published_at %}<time datetime="{{ page.website.published_at | escape }}">{{ ui.published | default: 'Published' | escape }} {{ page.website.published_at | date: "%Y-%m-%d" }}</time>{% endif %}
21
+ {% if page.website.theme == 'minimal' and page.website.content_type == 'post' and page.website.features.tags and page.website.topic_links.size > 0 %}
22
+ {% assign blog_url = page.website.routes.blog %}{% unless blog_url %}{% assign blog_url = '/blog/' | relative_url %}{% endunless %}
23
+ <span class="note-meta__topics" aria-label="{{ ui.topics | default: 'Topics' | escape }}" lang="{{ page.website.i18n.locale | default: site.lang | default: 'en' | escape }}" dir="{{ page.website.i18n.dir | default: 'ltr' | escape }}">{% for topic in page.website.topic_links %}<a class="tag-chip" href="{{ blog_url | escape }}?topic={{ topic.anchor | url_encode }}" lang="{{ page.website.i18n.content_lang | default: page.website.i18n.locale | default: site.lang | default: 'en' | escape }}" dir="{{ page.website.i18n.content_dir | default: page.website.i18n.dir | default: 'ltr' | escape }}">{{ topic.name | escape }}</a>{% endfor %}</span>
24
+ {% endif %}
25
+ {% if page.website.updated %}<time datetime="{{ page.website.updated | escape }}">{{ ui.updated | default: 'Updated' | escape }} {{ page.website.updated | date: "%Y-%m-%d" }}</time>{% endif %}
26
+ {% if page.website.features.tags %}
27
+ {% unless page.website.theme == 'minimal' and page.website.content_type == 'post' %}
28
+ {% if page.website.theme == 'minimal' %}{% assign tags_url = page.website.routes.blog %}{% unless tags_url %}{% assign tags_url = '/blog/' | relative_url %}{% endunless %}{% else %}{% assign tags_url = page.website.routes.tags %}{% unless tags_url %}{% assign tags_url = '/tags/' | relative_url %}{% endunless %}{% endif %}
29
+ {% for tag in page.website.tag_links %}<a class="tag-chip" href="{{ tags_url | escape }}{% if page.website.theme == 'docs' %}#{{ tag.anchor | escape }}{% else %}?topic={{ tag.anchor | url_encode }}{% endif %}">{{ tag.name | escape }}</a>{% endfor %}
30
+ {% endunless %}
31
+ {% endif %}
32
+ </div>
33
+ {% endif %}
34
+ </header>
35
+ {% endif %}