Compare commits

...

15 Commits

Author SHA1 Message Date
Xin
d58a8b5469 feat: exclude page from sidebar (#209)
* feat: allow excluding page from sidebar

* chore: tidy up

* docs: add instruction for excluding a page from sidebar

* feat: allow hiding sidebar for pages

* chore: add comment
2023-11-17 23:00:05 +00:00
Xin
64ac97b2d6 feat: allow overriding poweredBy in footer (#207) 2023-11-17 02:03:40 +00:00
Xin
27c976bcc1 feat: display author avatar images in blog post (#204)
* feat: support displaying author images in blog post

* chore: fix typo

* chore: run build:css

* refactor: support both plain author list

* chore: run build:css

* chore: add support for local avatar images

* chore: update css classes
2023-11-17 01:49:18 +00:00
Xin
d675d3bc7b feat: support separator in sidebar (#199)
* feat: support adding pages as separator for sidebar

* Update sidebar.html
2023-11-12 14:03:30 +00:00
456c96921a typo: fix typos in sidebar.html (#203)
@OliverWu515 finds this issue, I help pr this. Hope it helps. The theme helps a lot for our org to build our documents. We found this issue when we use it.
2023-11-12 13:47:20 +00:00
Xin
c2d7ba8ce5 fix: code copy issue for code blocks in shortcode (#201)
* chore: add translation key for copy code button title

* chore: remove id from code block elements

* fix: copy the correct code target in code-copy.js

* chore: update details.md

* chore: remove console.log :)

* chore: remove `$` in shell commands

* chore: update docs
2023-11-12 01:14:39 +00:00
Xin
8801a04ebe feat: add include shortcode (#198) 2023-11-11 00:10:32 +00:00
Xin
21b0acdec5 chore: improve cards compatibility with steps (#197) 2023-11-10 23:45:42 +00:00
Xin
c0a1bc32dd fix: ensure relref in search index is properly rendered (#196)
* fix: ensure relref in search index is properly rendered

* chore: remove empty whitespace
2023-11-10 22:21:54 +00:00
Xin
4ea18168e3 fix: correctly set editURL in front-matter (#195) 2023-11-10 22:03:08 +00:00
Xin
23c84e124c fix: navbar url for multi-lang site (#193)
* fix: image URL in feature card

* fix: use relLangURL of pageRef for navbar entries
2023-11-10 17:45:44 +00:00
Xin
678f0b86ee fix: htmlUnescape toc title (#190) 2023-11-05 10:26:00 +00:00
defc9bc11b fix(docs): showcase starter template URL (#189)
* Update URl for Hextra Starter Template

* Update index.md

---------

Co-authored-by: Saurabh Mishra <saurabh.m@mailfence.com>
Co-authored-by: Xin <xin@imfing.com>
2023-11-05 10:09:58 +00:00
Xin
363c8c91ee fix: scroll bug due to incorrect toggle state (#186)
* fix: add mobile menu overlay to toggle body scroll

* chore: update styles
2023-11-03 20:39:36 +00:00
Xin
088e9f7821 fix(style): add backdrop to code copy button (#185)
* fix(style): add backdrop to code copy button

* chore: run build:css
2023-11-02 22:43:50 +00:00
25 changed files with 262 additions and 91 deletions

View File

@ -499,6 +499,9 @@ video {
.pointer-events-none { .pointer-events-none {
pointer-events: none; pointer-events: none;
} }
.fixed {
position: fixed;
}
.absolute { .absolute {
position: absolute; position: absolute;
} }
@ -508,6 +511,9 @@ video {
.sticky { .sticky {
position: sticky; position: sticky;
} }
.inset-0 {
inset: 0px;
}
.inset-x-0 { .inset-x-0 {
left: 0px; left: 0px;
right: 0px; right: 0px;
@ -543,6 +549,9 @@ video {
.top-full { .top-full {
top: 100%; top: 100%;
} }
.z-10 {
z-index: 10;
}
.z-20 { .z-20 {
z-index: 20; z-index: 20;
} }
@ -625,6 +634,9 @@ video {
.ml-4 { .ml-4 {
margin-left: 1rem; margin-left: 1rem;
} }
.mr-1 {
margin-right: 0.25rem;
}
.mr-2 { .mr-2 {
margin-right: 0.5rem; margin-right: 0.5rem;
} }
@ -839,6 +851,9 @@ video {
.flex-col { .flex-col {
flex-direction: column; flex-direction: column;
} }
.flex-wrap {
flex-wrap: wrap;
}
.items-start { .items-start {
align-items: flex-start; align-items: flex-start;
} }
@ -869,6 +884,17 @@ video {
.gap-4 { .gap-4 {
gap: 1rem; gap: 1rem;
} }
.gap-x-1 {
-moz-column-gap: 0.25rem;
column-gap: 0.25rem;
}
.gap-x-1\.5 {
-moz-column-gap: 0.375rem;
column-gap: 0.375rem;
}
.gap-y-2 {
row-gap: 0.5rem;
}
.overflow-auto { .overflow-auto {
overflow: auto; overflow: auto;
} }
@ -966,6 +992,9 @@ video {
--tw-border-opacity: 1; --tw-border-opacity: 1;
border-color: rgb(254 249 195 / var(--tw-border-opacity)); border-color: rgb(254 249 195 / var(--tw-border-opacity));
} }
.bg-black\/80 {
background-color: rgb(0 0 0 / 0.8);
}
.bg-black\/\[\.05\] { .bg-black\/\[\.05\] {
background-color: rgb(0 0 0 / .05); background-color: rgb(0 0 0 / .05);
} }
@ -1396,8 +1425,8 @@ video {
-webkit-hyphens: auto; -webkit-hyphens: auto;
hyphens: auto; hyphens: auto;
} }
.\[text-underline-position\:from-font\] { .\[transition\:background-color_1\.5s_ease\] {
text-underline-position: from-font; transition: background-color 1.5s ease;
} }
.\[word-break\:break-word\] { .\[word-break\:break-word\] {
word-break: break-word; word-break: break-word;
@ -2501,6 +2530,19 @@ nav .search-wrapper {
--tw-shadow-color: rgb(115 115 115 / 0.4); --tw-shadow-color: rgb(115 115 115 / 0.4);
--tw-shadow: var(--tw-shadow-colored); --tw-shadow: var(--tw-shadow-colored);
} }
@supports (
((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px)))
) {
.code-copy-btn {
--tw-bg-opacity: .85;
--tw-backdrop-blur: blur(12px);
-webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
}
:is(html[class~="dark"] .code-copy-btn) {
--tw-bg-opacity: 0.8;
}
}
html { html {
font-size: 1rem; font-size: 1rem;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
@ -2707,6 +2749,9 @@ body {
--tw-rotate: 90deg; --tw-rotate: 90deg;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
} }
.group:hover .group-hover\:underline {
text-decoration-line: underline;
}
.group\/code:hover .group-hover\/code\:opacity-100 { .group\/code:hover .group-hover\/code\:opacity-100 {
opacity: 1; opacity: 1;
} }
@ -2977,6 +3022,9 @@ body {
:is(html[class~="dark"] .dark\:border-yellow-200\/30) { :is(html[class~="dark"] .dark\:border-yellow-200\/30) {
border-color: rgb(254 240 138 / 0.3); border-color: rgb(254 240 138 / 0.3);
} }
:is(html[class~="dark"] .dark\:bg-black\/60) {
background-color: rgb(0 0 0 / 0.6);
}
:is(html[class~="dark"] .dark\:bg-blue-900\/30) { :is(html[class~="dark"] .dark\:bg-blue-900\/30) {
background-color: rgb(30 58 138 / 0.3); background-color: rgb(30 58 138 / 0.3);
} }

View File

@ -0,0 +1,7 @@
@supports (
(-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))
) {
.code-copy-btn {
@apply backdrop-blur-md bg-opacity-[.85] dark:bg-opacity-80;
}
}

View File

@ -8,6 +8,7 @@
@import "components/sidebar.css"; @import "components/sidebar.css";
@import "components/navbar.css"; @import "components/navbar.css";
@import "components/scrollbar.css"; @import "components/scrollbar.css";
@import "components/code-copy.css";
html { html {
@apply text-base antialiased; @apply text-base antialiased;

View File

@ -33,8 +33,8 @@ document.addEventListener('DOMContentLoaded', function () {
// Add click event listener for copy button // Add click event listener for copy button
button.addEventListener('click', function (e) { button.addEventListener('click', function (e) {
e.preventDefault(); e.preventDefault();
const targetId = button.getAttribute('data-clipboard-target'); // Get the code target
const target = document.querySelector(targetId); const target = button.parentElement.previousElementSibling;
let codeElement; let codeElement;
if (target.tagName === 'CODE') { if (target.tagName === 'CODE') {
codeElement = target; codeElement = target;
@ -44,9 +44,12 @@ document.addEventListener('DOMContentLoaded', function () {
codeElement = codeElements[codeElements.length - 1]; codeElement = codeElements[codeElements.length - 1];
} }
if (codeElement) { if (codeElement) {
let code = codeElement.innerText;
// Replace double newlines with single newlines in the innerText // Replace double newlines with single newlines in the innerText
// as each line inside <span> has trailing newline '\n' // as each line inside <span> has trailing newline '\n'
const code = codeElement.innerText.replace(/\n\n/g, '\n'); if ("lang" in codeElement.dataset) {
code = code.replace(/\n\n/g, '\n');
}
navigator.clipboard.writeText(code).then(function () { navigator.clipboard.writeText(code).then(function () {
button.classList.add('copied'); button.classList.add('copied');
setTimeout(function () { setTimeout(function () {

View File

@ -1,19 +1,49 @@
// Hamburger menu for mobile navigation // Hamburger menu for mobile navigation
const menu = document.querySelector('.hamburger-menu'); document.addEventListener('DOMContentLoaded', function () {
const menu = document.querySelector('.hamburger-menu');
menu.addEventListener('click', (e) => { const overlay = document.querySelector('.mobile-menu-overlay');
e.preventDefault();
const sidebarContainer = document.querySelector('.sidebar-container'); const sidebarContainer = document.querySelector('.sidebar-container');
// Toggle the hamburger menu // Initialize the overlay
menu.querySelector('svg').classList.toggle('open'); const overlayClasses = ['fixed', 'inset-0', 'z-10', 'bg-black/80', 'dark:bg-black/60'];
overlay.classList.add('bg-transparent');
overlay.classList.remove("hidden", ...overlayClasses);
// When the menu is open, we want to show the navigation sidebar function toggleMenu() {
sidebarContainer.classList.toggle('max-md:[transform:translate3d(0,-100%,0)]'); // Toggle the hamburger menu
sidebarContainer.classList.toggle('max-md:[transform:translate3d(0,0,0)]'); menu.querySelector('svg').classList.toggle('open');
// When the menu is open, we want to prevent the body from scrolling // When the menu is open, we want to show the navigation sidebar
document.body.classList.toggle('overflow-hidden'); sidebarContainer.classList.toggle('max-md:[transform:translate3d(0,-100%,0)]');
document.body.classList.toggle('md:overflow-auto'); sidebarContainer.classList.toggle('max-md:[transform:translate3d(0,0,0)]');
// When the menu is open, we want to prevent the body from scrolling
document.body.classList.toggle('overflow-hidden');
document.body.classList.toggle('md:overflow-auto');
}
menu.addEventListener('click', (e) => {
e.preventDefault();
toggleMenu();
if (overlay.classList.contains('bg-transparent')) {
// Show the overlay
overlay.classList.add(...overlayClasses);
overlay.classList.remove('bg-transparent');
} else {
// Hide the overlay
overlay.classList.remove(...overlayClasses);
overlay.classList.add('bg-transparent');
}
});
overlay.addEventListener('click', (e) => {
e.preventDefault();
toggleMenu();
// Hide the overlay
overlay.classList.remove(...overlayClasses);
overlay.classList.add('bg-transparent');
});
}); });

View File

@ -2,8 +2,12 @@
title: Markdown Syntax Guide title: Markdown Syntax Guide
date: 2020-01-01 date: 2020-01-01
authors: authors:
- name: John Doe - name: imfing
link: https://example.com/johndoe link: https://github.com/imfing
image: https://github.com/imfing.png
- name: Octocat
link: https://github.com/octocat
image: https://github.com/octocat.png
tags: tags:
- Markdown - Markdown
- Example - Example

View File

@ -47,8 +47,8 @@ The primary color of the theme can be customized by setting the `--primary-hue`
List of available syntax highlighting themes are available at [Chroma Styles Gallery](https://xyproto.github.io/splash/docs/all.html). The stylesheet can be generated using the command: List of available syntax highlighting themes are available at [Chroma Styles Gallery](https://xyproto.github.io/splash/docs/all.html). The stylesheet can be generated using the command:
```bash ```shell
$ hugo gen chromastyles --style=github hugo gen chromastyles --style=github
``` ```
To override the default syntax highlighting theme, we can add the generated styles to the custom CSS file. To override the default syntax highlighting theme, we can add the generated styles to the custom CSS file.
@ -70,4 +70,4 @@ For further information, refer to the [Hugo Templates](https://gohugo.io/templat
## Further Customization ## Further Customization
Didn't find what you were looking for? Feel free to [open an issue](https://github.com/imfing/hextra/issues) or make a contribution to the theme! Didn't find what you were looking for? Feel free to [open a discussion](https://github.com/imfing/hextra/discussions) or make a contribution to the theme!

View File

@ -43,18 +43,18 @@ Before starting, you need to have the following software installed:
### Initialize a new Hugo site ### Initialize a new Hugo site
```shell ```shell
$ hugo new site my-site --format=yaml hugo new site my-site --format=yaml
``` ```
### Configure Hextra theme via module ### Configure Hextra theme via module
```shell ```shell
# initialize hugo module # initialize hugo module
$ cd my-site cd my-site
$ hugo mod init github.com/username/my-site hugo mod init github.com/username/my-site
# add Hextra theme # add Hextra theme
$ hugo mod get github.com/imfing/hextra hugo mod get github.com/imfing/hextra
``` ```
Configure `hugo.yaml` to use Hextra theme by adding the following: Configure `hugo.yaml` to use Hextra theme by adding the following:
@ -70,14 +70,14 @@ module:
Create new content page for the home page and the documentation page: Create new content page for the home page and the documentation page:
```shell ```shell
$ hugo new content/_index.md hugo new content/_index.md
$ hugo new content/docs/_index.md hugo new content/docs/_index.md
``` ```
### Preview the site locally ### Preview the site locally
```shell ```shell
$ hugo server --buildDrafts --disableFastRender hugo server --buildDrafts --disableFastRender
``` ```
Voila, your new site preview is available at `http://localhost:1313/`. Voila, your new site preview is available at `http://localhost:1313/`.
@ -90,7 +90,7 @@ Voila, your new site preview is available at `http://localhost:1313/`.
To update all Hugo modules in your project to their latest versions, run the following command: To update all Hugo modules in your project to their latest versions, run the following command:
```shell ```shell
$ hugo mod get -u hugo mod get -u
``` ```
To update Hextra to the [latest released version](https://github.com/imfing/hextra/releases), run the following command: To update Hextra to the [latest released version](https://github.com/imfing/hextra/releases), run the following command:
@ -119,7 +119,7 @@ Before starting, you need to have the following software installed:
### Initialize a new Hugo site ### Initialize a new Hugo site
```shell ```shell
$ hugo new site my-site --format=yaml hugo new site my-site --format=yaml
``` ```
### Add Hextra theme as a Git submodule ### Add Hextra theme as a Git submodule
@ -139,14 +139,14 @@ theme: hextra
Create new content page for the home page and the documentation page: Create new content page for the home page and the documentation page:
```shell ```shell
$ hugo new content/_index.md hugo new content/_index.md
$ hugo new content/docs/_index.md hugo new content/docs/_index.md
``` ```
### Preview the site locally ### Preview the site locally
```shell ```shell
$ hugo server --buildDrafts --disableFastRender hugo server --buildDrafts --disableFastRender
``` ```
Your new site preview is available at `http://localhost:1313/`. Your new site preview is available at `http://localhost:1313/`.
@ -168,7 +168,7 @@ Failure to run this command results in the theme folder not being populated with
To update all submodules in your repository to their latest commits, run the following command: To update all submodules in your repository to their latest commits, run the following command:
```shell ```shell
$ git submodule update --remote git submodule update --remote
``` ```
To update Hextra to the latest commit, run the following command: To update Hextra to the latest commit, run the following command:

View File

@ -90,6 +90,16 @@ params:
For the main sidebar, it is automatically generated from the structure of the content directory. For the main sidebar, it is automatically generated from the structure of the content directory.
See the [Organize Files](/docs/guide/organize-files) page for more details. See the [Organize Files](/docs/guide/organize-files) page for more details.
To exclude a single page from the left sidebar, set the `sidebar.exclude` parameter in the front matter of the page:
```yaml {filename="content/docs/guide/configuration.md"}
---
title: Configuration
sidebar:
exclude: true
---
```
### Extra Links ### Extra Links
Sidebar extra links are defined under the `menu.sidebar` section in the config file: Sidebar extra links are defined under the `menu.sidebar` section in the config file:

View File

@ -24,7 +24,7 @@ This will be hidden by default.
## Usage ## Usage
```` ````markdown
{{%/* details title="Details" */%}} {{%/* details title="Details" */%}}
This is the content of the details. This is the content of the details.
@ -34,7 +34,7 @@ Markdown is **supported**.
{{%/* /details */%}} {{%/* /details */%}}
```` ````
```` ````markdown
{{%/* details title="Click me to reveal" closed="true" */%}} {{%/* details title="Click me to reveal" closed="true" */%}}
This will be hidden by default. This will be hidden by default.

View File

@ -14,5 +14,5 @@ Open source projects powered by Hextra.
{{< cards >}} {{< cards >}}
{{< card link="https://getporter.org/" title="Porter" image="https://repository-images.githubusercontent.com/155893691/aa249c80-fcf3-11ea-93b0-30079e8d7de4" imageStyle="object-fit:cover; aspect-ratio:16/9;" >}} {{< card link="https://getporter.org/" title="Porter" image="https://repository-images.githubusercontent.com/155893691/aa249c80-fcf3-11ea-93b0-30079e8d7de4" imageStyle="object-fit:cover; aspect-ratio:16/9;" >}}
{{< card link="https://lutheranconfessions.org/" title="LutheranConfessions" image="https://github.com/imfing/hextra/assets/5097752/ad6625e4-88cd-4cad-b102-5399997d0359" imageStyle="object-fit:cover; aspect-ratio:16/9;" >}} {{< card link="https://lutheranconfessions.org/" title="LutheranConfessions" image="https://github.com/imfing/hextra/assets/5097752/ad6625e4-88cd-4cad-b102-5399997d0359" imageStyle="object-fit:cover; aspect-ratio:16/9;" >}}
{{< card link="/" title="Hextra Starter Template" image="https://user-images.githubusercontent.com/5097752/263551418-c403b9a9-a76c-47a6-8466-513d772ef0b7.jpg" imageStyle="object-fit:cover; aspect-ratio:16/9;" >}} {{< card link="https://github.com/imfing/hextra-starter-template/" title="Hextra Starter Template" image="https://user-images.githubusercontent.com/5097752/263551418-c403b9a9-a76c-47a6-8466-513d772ef0b7.jpg" imageStyle="object-fit:cover; aspect-ratio:16/9;" >}}
{{< /cards >}} {{< /cards >}}

View File

@ -66,7 +66,7 @@
"[-webkit-touch-callout:none]", "[-webkit-touch-callout:none]",
"[counter-reset:step]", "[counter-reset:step]",
"[hyphens:auto]", "[hyphens:auto]",
"[text-underline-position:from-font]", "[transition:background-color_1.5s_ease]",
"[word-break:break-word]", "[word-break:break-word]",
"absolute", "absolute",
"active:bg-gray-400/20", "active:bg-gray-400/20",
@ -90,6 +90,7 @@
"before:pointer-events-none", "before:pointer-events-none",
"before:transition-transform", "before:transition-transform",
"before:w-px", "before:w-px",
"bg-black/80",
"bg-black/[.05]", "bg-black/[.05]",
"bg-blue-100", "bg-blue-100",
"bg-clip-text", "bg-clip-text",
@ -159,6 +160,7 @@
"cursor-pointer", "cursor-pointer",
"dark:before:bg-neutral-800", "dark:before:bg-neutral-800",
"dark:before:invert", "dark:before:invert",
"dark:bg-black/60",
"dark:bg-blue-900/30", "dark:bg-blue-900/30",
"dark:bg-dark", "dark:bg-dark",
"dark:bg-dark/50", "dark:bg-dark/50",
@ -235,8 +237,10 @@
"ease-in", "ease-in",
"filename", "filename",
"first:mt-0", "first:mt-0",
"fixed",
"flex", "flex",
"flex-col", "flex-col",
"flex-wrap",
"focus:bg-white", "focus:bg-white",
"focus:outline-none", "focus:outline-none",
"focus:ring-4", "focus:ring-4",
@ -254,6 +258,8 @@
"gap-1", "gap-1",
"gap-2", "gap-2",
"gap-4", "gap-4",
"gap-x-1.5",
"gap-y-2",
"grid", "grid",
"grid-cols-1", "grid-cols-1",
"group", "group",
@ -262,6 +268,7 @@
"group-data-[theme=dark]:hidden", "group-data-[theme=dark]:hidden",
"group-data-[theme=light]:hidden", "group-data-[theme=light]:hidden",
"group-hover/code:opacity-100", "group-hover/code:opacity-100",
"group-hover:underline",
"group-open:before:rotate-90", "group-open:before:rotate-90",
"group/code", "group/code",
"group/copybtn", "group/copybtn",
@ -311,6 +318,7 @@
"inline", "inline",
"inline-block", "inline-block",
"inline-flex", "inline-flex",
"inset-0",
"inset-x-0", "inset-x-0",
"inset-y-0", "inset-y-0",
"items-center", "items-center",
@ -401,6 +409,8 @@
"min-w-full", "min-w-full",
"ml-1", "ml-1",
"ml-4", "ml-4",
"mobile-menu-overlay",
"mr-1",
"mr-2", "mr-2",
"mt-1", "mt-1",
"mt-1.5", "mt-1.5",
@ -585,6 +595,7 @@
"w-screen", "w-screen",
"whitespace-nowrap", "whitespace-nowrap",
"xl:block", "xl:block",
"z-10",
"z-20", "z-20",
"z-[-1]" "z-[-1]"
], ],

View File

@ -1,6 +1,7 @@
backToTop: "Scroll to top" backToTop: "Scroll to top"
changeLanguage: "Change language" changeLanguage: "Change language"
changeTheme: "Change theme" changeTheme: "Change theme"
copyCode: "Copy code"
copyright: "© 2023 Hextra Project." copyright: "© 2023 Hextra Project."
dark: "Dark" dark: "Dark"
editThisPage: "Edit this page on GitHub →" editThisPage: "Edit this page on GitHub →"

View File

@ -1,6 +1,7 @@
{{- $class := .Attributes.class | default "" -}} {{- $class := .Attributes.class | default "" -}}
{{- $filename := .Attributes.filename | default "" -}} {{- $filename := .Attributes.filename | default "" -}}
{{- $lang := .Attributes.lang | default .Type -}} {{- $lang := .Attributes.lang | default .Type -}}
{{- $copyCode := (T "copyCode") | default "Copy code" -}}
<div class="code-block relative mt-6 first:mt-0 group/code"> <div class="code-block relative mt-6 first:mt-0 group/code">
@ -8,17 +9,14 @@
<div class="filename">{{ $filename }}</div> <div class="filename">{{ $filename }}</div>
{{- end -}} {{- end -}}
{{- if transform.CanHighlight $lang -}} {{- if transform.CanHighlight $lang -}}
<div id="code-block-{{ .Ordinal }}"> <div>{{- highlight .Inner $lang .Options -}}</div>
{{- highlight .Inner $lang .Options -}}
</div>
{{- else -}} {{- else -}}
<pre><code id="code-block-{{ .Ordinal }}">{{ .Inner }}</code></pre> <pre><code>{{ .Inner }}</code></pre>
{{- end -}} {{- end -}}
<div class="opacity-0 transition group-hover/code:opacity-100 flex gap-1 absolute m-[11px] right-0 {{ if $filename }}top-8{{ else }}top-0{{ end }}"> <div class="opacity-0 transition group-hover/code:opacity-100 flex gap-1 absolute m-[11px] right-0 {{ if $filename }}top-8{{ else }}top-0{{ end }}">
<button <button
class="code-copy-btn group/copybtn transition-all active:opacity-50 bg-primary-700/5 border border-black/5 text-gray-600 hover:text-gray-900 rounded-md p-1.5 dark:bg-primary-300/10 dark:border-white/10 dark:text-gray-400 dark:hover:text-gray-50" class="code-copy-btn group/copybtn transition-all active:opacity-50 bg-primary-700/5 border border-black/5 text-gray-600 hover:text-gray-900 rounded-md p-1.5 dark:bg-primary-300/10 dark:border-white/10 dark:text-gray-400 dark:hover:text-gray-50"
title="Copy code" title="{{ $copyCode }}"
data-clipboard-target="#code-block-{{ .Ordinal }}"
> >
<div class="group-[.copied]/copybtn:hidden copy-icon pointer-events-none h-4 w-4"></div> <div class="group-[.copied]/copybtn:hidden copy-icon pointer-events-none h-4 w-4"></div>
<div class="hidden group-[.copied]/copybtn:block success-icon pointer-events-none h-4 w-4"></div> <div class="hidden group-[.copied]/copybtn:block success-icon pointer-events-none h-4 w-4"></div>

View File

@ -1,13 +1,13 @@
{{- $alt := .PlainText | safeHTML -}} {{- $alt := .PlainText | safeHTML -}}
{{- $lazyLoading := .Page.Site.Params.enableImagelazyLoading | default true -}} {{- $lazyLoading := .Page.Site.Params.enableImageLazyLoading | default true -}}
{{- $dest := .Destination -}} {{- $dest := .Destination -}}
{{- $isRemote := not (urls.Parse $dest).Scheme -}} {{- $isLocal := not (urls.Parse $dest).Scheme -}}
{{- $isPage := and (eq .Page.Kind "page") (not .Page.BundleType) -}} {{- $isPage := and (eq .Page.Kind "page") (not .Page.BundleType) -}}
{{- $startsWithSlash := hasPrefix $dest "/" -}} {{- $startsWithSlash := hasPrefix $dest "/" -}}
{{- $startsWithRelative := hasPrefix $dest "../" -}} {{- $startsWithRelative := hasPrefix $dest "../" -}}
{{- if and $dest $isRemote -}} {{- if and $dest $isLocal -}}
{{- if $startsWithSlash -}} {{- if $startsWithSlash -}}
{{/* Images under static directory */}} {{/* Images under static directory */}}
{{- $dest = (relURL (strings.TrimPrefix "/" $dest)) -}} {{- $dest = (relURL (strings.TrimPrefix "/" $dest)) -}}

View File

@ -1,27 +1,40 @@
{{ define "main" }} {{ define "main" }}
<div class='mx-auto flex {{ partial "utils/page-width" . }}'> <div class="mx-auto flex {{ partial `utils/page-width` . }}">
{{ partial "sidebar.html" (dict "context" . "disableSidebar" true "displayPlaceholder" true) }} {{ partial "sidebar.html" (dict "context" . "disableSidebar" true "displayPlaceholder" true) }}
{{ partial "toc.html" . }} {{ partial "toc.html" . }}
<article class="w-full break-words flex min-h-[calc(100vh-var(--navbar-height))] min-w-0 justify-center pb-8 pr-[calc(env(safe-area-inset-right)-1.5rem)]"> <article class="w-full break-words flex min-h-[calc(100vh-var(--navbar-height))] min-w-0 justify-center pb-8 pr-[calc(env(safe-area-inset-right)-1.5rem)]">
<main class="w-full min-w-0 max-w-6xl px-6 pt-4 md:px-12"> <main class="w-full min-w-0 max-w-6xl px-6 pt-4 md:px-12">
{{ partial "breadcrumb.html" . }} {{ partial "breadcrumb.html" . }}
<h1 class="mt-2 text-4xl font-bold tracking-tight text-slate-900 dark:text-slate-100">{{ .Title }}</h1> <h1 class="mt-2 text-4xl font-bold tracking-tight text-slate-900 dark:text-slate-100">{{ .Title }}</h1>
{{ with $date := .Date }} <div class="mt-4 mb-16 text-gray-500 text-sm flex items-center flex-wrap gap-y-2">
<div class="mt-4 mb-16 text-gray-500 text-sm"> {{- with $date := .Date }}<span class="mr-1">{{ partial "utils/format-date" $date }}</span>{{ end -}}
{{ partial "utils/format-date" $date }} {{- $lazyLoading := site.Params.enableImageLazyLoading | default true -}}
{{- if $.Params.authors }}&nbsp;by&nbsp;{{ end -}} {{ if and .Date .Params.authors }}<span class="mx-1">·</span>{{ end -}}
{{- with $.Params.authors -}} {{- with $.Params.authors -}}
{{- range $i, $author := . -}} {{- range $i, $author := . -}}
{{- if $i }},{{ end -}} {{- if reflect.IsMap $author -}}
{{- if $author.link -}} {{- if and $i (not $author.image) }}<span class="mr-1">,</span>{{ end -}}
<a href="{{ $author.link }}" target="_blank" class="mx-1 text-current underline [text-underline-position:from-font] decoration-from-font">{{ $author.name }}</a> <a
{{- else -}} {{ with $author.link }}href="{{ . }}" target="_blank"{{ end }}
<span>{{ $author.name }}</span> class="group inline-flex items-center text-current gap-x-1.5 mx-1"
{{- end -}} {{ with $author.name }}title="{{ . }}"{{ end }}
>
{{- with $image := $author.image }}
{{- $isLocal := not (urls.Parse $image).Scheme -}}
{{- $startsWithSlash := hasPrefix $image "/" -}}
{{- if and $isLocal $startsWithSlash }}
{{- $image = (relURL (strings.TrimPrefix "/" $image)) -}}
{{ end -}}
<img src="{{ $image | safeURL }}" alt="{{ $author.name }}" class="inline-block h-4 w-4 rounded-full" {{ if $lazyLoading }}loading="lazy"{{ end }} />
{{ end -}}
<div class="group-hover:underline">{{ $author.name }}</div>
</a>
{{- else -}}
{{- if $i }}<span class="mr-1">,</span>{{ end -}}<span class="mx-1">{{ $author }}</span>
{{- end -}} {{- end -}}
{{- end -}} {{- end -}}
</div> {{- end -}}
{{ end }} </div>
<div class="content"> <div class="content">
{{ .Content }} {{ .Content }}
</div> </div>

View File

@ -36,9 +36,11 @@
{{- define "theme-credit" -}} {{- define "theme-credit" -}}
<a class="flex text-sm items-center gap-1 text-current" target="_blank" rel="noopener noreferrer" title="Hextra GitHub Homepage" href="https://github.com/imfing/hextra"> <a class="flex text-sm items-center gap-1 text-current" target="_blank" rel="noopener noreferrer" title="Hextra GitHub Homepage" href="https://github.com/imfing/hextra">
<span <span>
>{{ . | safeHTML }} {{- . | markdownify -}}
{{- partial "utils/icon.html" (dict "name" "hextra" "attributes" "height=1em class=\"inline-block ml-1 align-text-bottom\"") -}} {{- if strings.Contains . "Hextra" -}}
{{- partial "utils/icon.html" (dict "name" "hextra" "attributes" `height=1em class="inline-block ml-1 align-text-bottom"`) -}}
{{- end -}}
</span> </span>
</a> </a>
{{- end -}} {{- end -}}

View File

@ -32,10 +32,17 @@
{{- if eq .Params.type "search" -}} {{- if eq .Params.type "search" -}}
{{- partial "search.html" (dict "params" .Params) -}} {{- partial "search.html" (dict "params" .Params) -}}
{{- else -}} {{- else -}}
{{- $external := strings.HasPrefix .URL "http" -}} {{- $link := .URL -}}
{{- $external := strings.HasPrefix $link "http" -}}
{{- with .PageRef -}}
{{- if hasPrefix . "/" -}}
{{- $link = relLangURL (strings.TrimPrefix "/" .) -}}
{{- end -}}
{{- end -}}
{{/* Display icon menu item */}} {{/* Display icon menu item */}}
{{- if .Params.icon -}} {{- if .Params.icon -}}
<a class="p-2 text-current" {{ if $external }}target="_blank" rel="noreferer"{{ end }} href="{{ .URL | relLangURL }}" title="{{ or (T .Identifier) .Name | safeHTML }}"> <a class="p-2 text-current" {{ if $external }}target="_blank" rel="noreferer"{{ end }} href="{{ $link }}" title="{{ or (T .Identifier) .Name | safeHTML }}">
{{- partial "utils/icon.html" (dict "name" .Params.icon "attributes" "height=24") -}} {{- partial "utils/icon.html" (dict "name" .Params.icon "attributes" "height=24") -}}
<span class="sr-only">{{ or (T .Identifier) .Name | safeHTML }}</span> <span class="sr-only">{{ or (T .Identifier) .Name | safeHTML }}</span>
</a> </a>
@ -44,7 +51,7 @@
{{- $activeClass := cond $active "font-medium" "text-gray-600 hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-200" -}} {{- $activeClass := cond $active "font-medium" "text-gray-600 hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-200" -}}
<a <a
title="{{ or (T .Identifier) .Name | safeHTML }}" title="{{ or (T .Identifier) .Name | safeHTML }}"
href="{{ .URL | relLangURL }}" href="{{ $link }}"
{{ if $external }}target="_blank" rel="noreferer"{{ end }} {{ if $external }}target="_blank" rel="noreferer"{{ end }}
class="text-sm contrast-more:text-gray-700 contrast-more:dark:text-gray-100 relative -ml-2 hidden whitespace-nowrap p-2 md:inline-block {{ $activeClass }}" class="text-sm contrast-more:text-gray-700 contrast-more:dark:text-gray-100 relative -ml-2 hidden whitespace-nowrap p-2 md:inline-block {{ $activeClass }}"
> >

View File

@ -6,10 +6,16 @@
{{- $sidebarClass := cond $disableSidebar (cond $displayPlaceholder "md:hidden xl:block" "md:hidden") "md:sticky" -}} {{- $sidebarClass := cond $disableSidebar (cond $displayPlaceholder "md:hidden xl:block" "md:hidden") "md:sticky" -}}
{{- $navRoot := cond (eq site.Home.Type "docs") site.Home $context.FirstSection -}} {{- $navRoot := cond (eq site.Home.Type "docs") site.Home $context.FirstSection -}}
{{- $navPages := union $navRoot.RegularPages $navRoot.Sections -}}
{{- $pageURL := $context.RelPermalink -}} {{- $pageURL := $context.RelPermalink -}}
{{/* EXPERIMENTAL */}}
{{- if .context.Params.sidebar.hide -}}
{{- $disableSidebar = true -}}
{{- $displayPlaceholder = true -}}
{{- end -}}
<div class="mobile-menu-overlay [transition:background-color_1.5s_ease] fixed inset-0 z-10 bg-black/80 dark:bg-black/60 hidden"></div>
<aside class="sidebar-container flex flex-col print:hidden md:top-16 md:shrink-0 md:w-64 md:self-start max-md:[transform:translate3d(0,-100%,0)] {{ $sidebarClass }}"> <aside class="sidebar-container flex flex-col print:hidden md:top-16 md:shrink-0 md:w-64 md:self-start max-md:[transform:translate3d(0,-100%,0)] {{ $sidebarClass }}">
<!-- Search bar on small screen --> <!-- Search bar on small screen -->
<div class="px-4 pt-4 md:hidden"> <div class="px-4 pt-4 md:hidden">
@ -67,17 +73,24 @@
{{- $toc := .toc | default false -}} {{- $toc := .toc | default false -}}
{{- with $items := union .context.RegularPages .context.Sections -}} {{- with $items := union .context.RegularPages .context.Sections -}}
{{- $items = where $items "Params.sidebar.exclude" "!=" true -}}
{{- if eq $level 0 -}} {{- if eq $level 0 -}}
{{- range $items.ByWeight }} {{- range $items.ByWeight }}
{{- $active := eq $pageURL .RelPermalink -}} {{- if .Params.sidebar.separator -}}
{{- $shouldOpen := or (.Params.sidebar.open) (.IsAncestor $page) $active | default true }} <li class="[word-break:break-word] mt-5 mb-2 px-2 py-1.5 text-sm font-semibold text-gray-900 first:mt-0 dark:text-gray-100">
<li class="{{ if $shouldOpen }}open{{ end }}"> <span class="cursor-default">{{ .LinkTitle }}</span>
{{- template "sidebar-item-link" dict "context" . "active" $active "title" .LinkTitle "link" .RelPermalink -}} </li>
{{- if and $toc $active -}} {{- else -}}
{{- template "sidebar-toc" dict "page" . -}} {{- $active := eq $pageURL .RelPermalink -}}
{{- end -}} {{- $shouldOpen := or (.Params.sidebar.open) (.IsAncestor $page) $active | default true }}
{{- template "sidebar-tree" dict "context" . "page" $page "pageURL" $pageURL "level" (add $level 1) "toc" $toc -}} <li class="{{ if $shouldOpen }}open{{ end }}">
</li> {{- template "sidebar-item-link" dict "context" . "active" $active "title" .LinkTitle "link" .RelPermalink -}}
{{- if and $toc $active -}}
{{- template "sidebar-toc" dict "page" . -}}
{{- end -}}
{{- template "sidebar-tree" dict "context" . "page" $page "pageURL" $pageURL "level" (add $level 1) "toc" $toc -}}
</li>
{{- end -}}
{{- end -}} {{- end -}}
{{- else -}} {{- else -}}
<div class="ltr:pr-0 overflow-hidden"> <div class="ltr:pr-0 overflow-hidden">
@ -110,7 +123,7 @@
<li> <li>
<a <a
href="#{{ anchorize .ID }}" href="#{{ anchorize .ID }}"
class="flex rounded px-2 py-1.5 text-sm transition-colors [word-break:break-word] cursor-pointer [-webkit-tap-highlight-color:transparent] [-webkit-touch-callout:none] contrast-more:border flex gap-2 before:opacity-25 before:content-['#'] text-gray-500 hover:bg-gray-100 hover:text-gray-900 dark:text-neutral-400 dark:hover:bg-primary-100/5 dark:hover:text-gray-50 contrast-more:text-gray-900 contrast-more:dark:text-gray-50 contrast-more:border-transparent contrast-more:hover:border-gray-900 contrast-more:dark:hover:border-gray-50" class="flex rounded px-2 py-1.5 text-sm transition-colors [word-break:break-word] cursor-pointer [-webkit-tap-highlight-color:transparent] [-webkit-touch-callout:none] contrast-more:border gap-2 before:opacity-25 before:content-['#'] text-gray-500 hover:bg-gray-100 hover:text-gray-900 dark:text-neutral-400 dark:hover:bg-primary-100/5 dark:hover:text-gray-50 contrast-more:text-gray-900 contrast-more:dark:text-gray-50 contrast-more:border-transparent contrast-more:hover:border-gray-900 contrast-more:dark:hover:border-gray-50"
> >
{{- .Title -}} {{- .Title -}}
</a> </a>
@ -152,17 +165,13 @@
{{- with .context }} {{- with .context }}
{{- if or .RegularPages .Sections }} {{- if or .RegularPages .Sections }}
<span class="hextra-sidebar-collapsible-button"> <span class="hextra-sidebar-collapsible-button">
{{- template "sidebear-collapsible-button" -}} {{- template "sidebar-collapsible-button" -}}
</span> </span>
{{- end }} {{- end }}
{{ end -}} {{ end -}}
</a> </a>
{{- end -}} {{- end -}}
{{- define "sidebar-separator" -}} {{- define "sidebar-collapsible-button" -}}
<div class="mt-4 border-t py-4 dark:border-neutral-800 contrast-more:border-neutral-400 dark:contrast-more:border-neutral-400" />
{{- end -}}
{{- define "sidebear-collapsible-button" -}}
<svg fill="none" viewBox="0 0 24 24" stroke="currentColor" class="h-[18px] min-w-[18px] rounded-sm p-0.5 hover:bg-gray-800/5 dark:hover:bg-gray-100/5"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" class="origin-center transition-transform rtl:-rotate-180"></path></svg> <svg fill="none" viewBox="0 0 24 24" stroke="currentColor" class="h-[18px] min-w-[18px] rounded-sm p-0.5 hover:bg-gray-800/5 dark:hover:bg-gray-100/5"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" class="origin-center transition-transform rtl:-rotate-180"></path></svg>
{{- end -}} {{- end -}}

View File

@ -27,7 +27,7 @@
{{- if site.Params.editURL.enable -}} {{- if site.Params.editURL.enable -}}
{{- $editURL := site.Params.editURL.base | default "" -}} {{- $editURL := site.Params.editURL.base | default "" -}}
{{- with .File -}}{{ $editURL = urls.JoinPath $editURL (replace .Path "\\" "/") }}{{- end -}} {{- with .File -}}{{ $editURL = urls.JoinPath $editURL (replace .Path "\\" "/") }}{{- end -}}
{{- with .Params.editURL -}}{{ $editURL = .Params.editURL }}{{- end -}} {{- with .Params.editURL -}}{{ $editURL = . }}{{- end -}}
<a class="text-xs font-medium text-gray-500 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-100 contrast-more:text-gray-800 contrast-more:dark:text-gray-50" href="{{ $editURL }}" target="_blank" rel="noreferer">{{ $editThisPage }}</a> <a class="text-xs font-medium text-gray-500 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-100 contrast-more:text-gray-800 contrast-more:dark:text-gray-50" href="{{ $editURL }}" target="_blank" rel="noreferer">{{ $editThisPage }}</a>
{{- end -}} {{- end -}}
{{/* Scroll To Top */}} {{/* Scroll To Top */}}
@ -59,7 +59,7 @@
{{- if .Title }} {{- if .Title }}
<li class="my-2 scroll-my-6 scroll-py-6"> <li class="my-2 scroll-my-6 scroll-py-6">
<a class="{{ $class }} inline-block text-gray-500 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-300 contrast-more:text-gray-900 contrast-more:underline contrast-more:dark:text-gray-50 w-full break-words" href="#{{ anchorize .ID }}"> <a class="{{ $class }} inline-block text-gray-500 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-300 contrast-more:text-gray-900 contrast-more:underline contrast-more:dark:text-gray-50 w-full break-words" href="#{{ anchorize .ID }}">
{{- .Title | safeHTML | plainify }} {{- .Title | safeHTML | plainify | htmlUnescape }}
</a> </a>
</li> </li>
{{- end -}} {{- end -}}

View File

@ -35,12 +35,12 @@
{{ $headingTitle := index $headingTitles $i }} {{ $headingTitle := index $headingTitles $i }}
{{ if eq $i 0 }} {{ if eq $i 0 }}
{{ $data = $data | merge (dict $headingKey ($content | markdownify | plainify | htmlUnescape | chomp)) }} {{ $data = $data | merge (dict $headingKey ($content | $page.RenderString | plainify | htmlUnescape | chomp)) }}
{{ else }} {{ else }}
{{ $parts := split $content (printf "\n%s\n" $headingTitle) }} {{ $parts := split $content (printf "\n%s\n" $headingTitle) }}
{{ $lastPart := index $parts (sub (len $parts) 1) }} {{ $lastPart := index $parts (sub (len $parts) 1) }}
{{ $data = $data | merge (dict $headingKey ($lastPart | markdownify | plainify | htmlUnescape | chomp)) }} {{ $data = $data | merge (dict $headingKey ($lastPart | $page.RenderString | plainify | htmlUnescape | chomp)) }}
{{ $content = strings.TrimSuffix $lastPart $content }} {{ $content = strings.TrimSuffix $lastPart $content }}
{{ $content = strings.TrimSuffix (printf "\n%s\n" $headingTitle) $content }} {{ $content = strings.TrimSuffix (printf "\n%s\n" $headingTitle) $content }}
{{ end }} {{ end }}

View File

@ -79,3 +79,4 @@
<div class="line-clamp-3 text-sm font-normal text-gray-500 dark:text-gray-400 px-4 mb-4 mt-2">{{- $subtitle | markdownify -}}</div> <div class="line-clamp-3 text-sm font-normal text-gray-500 dark:text-gray-400 px-4 mb-4 mt-2">{{- $subtitle | markdownify -}}</div>
{{- end -}} {{- end -}}
</a> </a>
{{- /* Strip trailing newline. */ -}}

View File

@ -1,5 +1,5 @@
{{ $rows := .Get "rows" | default "3" }} {{ $rows := .Get "rows" | default "3" }}
<div class="hextra-cards mt-4 gap-4 grid not-prose" style="--rows: {{ $rows }};"> <div class="hextra-cards mt-4 gap-4 grid not-prose" style="--rows: {{ $rows }};">
{{ .Inner }} {{- .Inner -}}
</div> </div>

View File

@ -10,6 +10,10 @@
{{- $external := hasPrefix $link "http" -}} {{- $external := hasPrefix $link "http" -}}
{{- $href := cond (strings.HasPrefix $link "/") ($link | relURL) $link -}} {{- $href := cond (strings.HasPrefix $link "/") ($link | relURL) $link -}}
{{- if hasPrefix $image "/" -}}
{{- $image = relURL (strings.TrimPrefix "/" $image) -}}
{{- end -}}
<a <a
{{ with $link }}href="{{ $href }}" {{ with $external }} target="_blank" rel="noreferrer"{{ end }}{{ end }} {{ with $link }}href="{{ $href }}" {{ with $external }} target="_blank" rel="noreferrer"{{ end }}{{ end }}
{{ with $style }}style="{{ . | safeCSS }}"{{ end }} {{ with $style }}style="{{ . | safeCSS }}"{{ end }}

View File

@ -0,0 +1,22 @@
{{- /*
https://github.com/gohugoio/gohugoioTheme/blob/master/layouts/shortcodes/include.html
Renders the page using the RenderShortcode method on the Page object.
You must call this shortcode using the {{% %}} notation.
@param {string} (postional parameter 0) The path to the page, relative to the content directory.
@returns template.HTML
@example {{% include "functions/_common/glob-patterns" %}}
*/}}
{{- with .Get 0 }}
{{- with site.GetPage . }}
{{- .RenderShortcodes }}
{{- else }}
{{- errorf "The %q shortcode was unable to find %q. See %s" $.Name . $.Position }}
{{- end }}
{{- else }}
{{- errorf "The %q shortcode requires a positional parameter indicating the path of the file to include. See %s" .Name .Position }}
{{- end }}