Compare commits

..

58 Commits

Author SHA1 Message Date
Raymundo Vásquez Ruiz
19538934d9 fix: breadcrumb y navbar links
Some checks failed
Deploy Hextra docs site to Pages / build (push) Failing after 13s
Deploy Hextra docs site to Pages / deploy (push) Has been skipped
2026-03-23 12:36:13 +01:00
Raymundo Vásquez Ruiz
cf25c397a9 Merge branch 'main' of https://github.com/imfing/hextra
Some checks failed
Deploy Hextra docs site to Pages / build (push) Failing after 32s
Deploy Hextra docs site to Pages / deploy (push) Has been skipped
2026-03-23 12:15:33 +01:00
Raymundo Vásquez Ruiz
8d62eaf0d5 feat: an "end" partial
Some checks failed
Deploy Hextra docs site to Pages / build (push) Failing after 1m19s
Deploy Hextra docs site to Pages / deploy (push) Has been skipped
2026-03-23 12:09:50 +01:00
Raymundo Vásquez Ruiz
4f547d63e2 feat: disable toc by default 2026-03-21 20:17:17 +01:00
Raymundo Vásquez Ruiz
f02859dc4d feat: sidebar oculto por defecto 2026-03-17 12:02:03 -06:00
Xin
339a2cebbe chore(build): bump MAIN_VERSION to v0.12.1 2026-03-09 09:55:18 +00:00
Xin
cd5f0055e1 test(ci): separate mobile menu checks from a11y suite 2026-03-06 23:51:37 +00:00
Xin
c2417dc24f fix(menu): prevent mobile dropdown click from auto-focusing search 2026-03-06 23:04:41 +00:00
Xin
1317e5697f fix(sidebar): include URL menu.main items in mobile sidebar 2026-03-06 22:58:13 +00:00
Xin
e12d3b98cc refactor(search): support local/mirrored FlexSearch assets (#956)
* feat(search): support local and mirrored FlexSearch assets

Add params.search.flexsearch.base/js overrides in search script loading.

Document offline/local and mirror-based script asset configuration examples.

* refactor(scripts): normalize remote asset URL joins

* docs(config): clarify local asset examples

* docs(i18n): add local asset config guidance
2026-03-06 22:41:40 +00:00
Copilot
792c750dec fix: revert unintentional Go 1.26 hard dependency to Go 1.21 (#950)
* Initial plan

* fix: downgrade go.mod version from 1.26 to 1.21

Co-authored-by: imfing <5097752+imfing@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: imfing <5097752+imfing@users.noreply.github.com>
2026-02-25 20:56:19 +00:00
MioYi Sama
a90429d991 fix(render-image): use page resources for relative images in i18n page bundles (#938)
* fix(layout): Images missing (404) in multilingual (i18n) Page Bundles due to Markdown render hook

* fix(layout): Changed to .PageInner based on PR review to support included shortcodes correctly

* refactor(render-image): simplify i18n page bundle resource lookup

Use single PathUnescape + TrimPrefix expression instead of six
Get attempts; keep same behavior for bundle images and fallback.

* refactor: simplify resource path handling in render-image.html

* Add comment for multilingual permalink handling

Added comment for multilingual permalink resolution in render-image.html

---------

Co-authored-by: Xin <5097752+imfing@users.noreply.github.com>
2026-02-23 22:42:09 +00:00
Floren Munteanu
e8f5f51cd8 fix: greedy trim (#946)
Co-authored-by: Floren Munteanu <19806136+fmunteanu@users.noreply.github.com>
2026-02-23 20:26:55 +00:00
yuri
af8fd2185e fix(docs): target Glossary section directly (#943) 2026-02-23 18:23:14 +00:00
Xin
3748917003 chore(build): point MAIN_VERSION to commit 2e709bf
Reference the combined doc-fix commit instead of the v0.12.0 tag.
2026-02-20 23:35:55 +00:00
Xin
2e709bf92d fix(docs): correct imageZoom and {markdown_url} config in v0.12 release blog
- Use nested imageZoom.enable: true instead of scalar imageZoom: true
- Use {markdown_url} (snake_case) placeholder matching the actual template-url
  utility key, not {markdownUrl} (camelCase) which would silently not substitute
2026-02-20 23:35:44 +00:00
Xin
8c059f7776 chore(build): bump main docs site tag to v0.12.0 2026-02-20 23:15:38 +00:00
Xin
089c2fb5e1 chore: release blog for Hextra v0.12
* chore: release blog for Hextra v0.12

* Add v0.12 blog translations and proofreading updates

* Merge main into plan-release-v0.12.0 and update build script versions

* Update build environment versions in netlify.toml to HUGO 0.156.0, GO 1.26.0, and NODE 24.13.1

* chore: update banner messages in multiple languages to reflect the release of Hextra **v0.12** in hugo.yaml

* docs(blog): align v0.12 tabs example with image (Photos/Music/Videos)

* docs(blog): fix page context menu wording (dropdown, not right-click)

* docs(hugo): update version link from v0.9 to v0.11 in menu
2026-02-20 23:08:33 +00:00
Xin
d2c650a490 chore(build): update MAIN_VERSION to v0.11.3 2026-02-20 21:45:59 +00:00
Xin
18d01a23fc chore(deps): remove unused serve package to fix security vulnerabilities
Removes the unused `serve` devDependency which was pulling in vulnerable
transitive dependencies (minimatch ReDoS high, ajv ReDoS moderate).
2026-02-20 20:40:28 +00:00
Xin
8421201672 chore: bump Hugo, Go, and Node.js to latest versions
- Hugo: 0.147.7 → 0.156.0
- Go: 1.24 → 1.26 (CI workflows and go.mod files)
- Node.js: 22 → 24 (LTS) in accessibility workflow
2026-02-20 20:40:28 +00:00
Xin
8f6aa1db5b refactor(layout): keep content width fixed and document CSS var override (#934)
* fix(layout): split page and content width configuration

* refactor(layout): consolidate page width settings and update documentation

- Removed separate content width configuration from `hugo.yaml` and set a default value of `72rem` in CSS.
- Updated documentation in multiple languages to reflect the changes in page and content width settings, emphasizing the new fixed content width and customization options.
2026-02-19 23:54:43 +00:00
Antonin P
55659bb9c1 fix(navbar): align mobile sidebar ordering and labels with menu.main (#883)
* fix(navbar): navbar on small screen now follow menu.main from hugo.yaml

* fix(navbar): align mobile sidebar with menu.main order and labels

* refactor(sidebar): simplify mobile menu item selection logic

* fix(sidebar): avoid empty nested containers in mobile nav tree

* fix(sidebar): align nested chevrons with top-level items

* chore(css): update compiled CSS

---------

Co-authored-by: Xin <5097752+imfing@users.noreply.github.com>
Co-authored-by: Xin <xin@imfing.com>
2026-02-19 23:34:06 +00:00
Quan-feng WU
9b2809eb24 fix: Site.Author -> Site.Params.Author for Hugo v1.156.0 (#933) 2026-02-19 08:16:29 +00:00
Xin
62196dd666 feat(tabs): add icon support for tabs (#926)
* feat(tabs): add icon support for tabs

- Introduced an `icon` property for tabs to display icons alongside tab labels.
- Updated the tabs shortcode and HTML partials to accommodate the new icon feature.
- Enhanced documentation for tabs to include examples of using icons in tab definitions.

* chore: rebuild css

* doc(tabs): add icon support in tab documentation for multiple languages

- Enhanced documentation for tabs to include examples of using the `icon` parameter in Persian, Japanese, and Simplified Chinese.
- Updated the tab shortcode examples to demonstrate how to display icons alongside tab labels.

* chore: regenerate compiled css

* fix(a11y): add aria-hidden to decorative tab icons

Add aria-hidden="true" to tab icon SVGs so screen readers skip
decorative icons and only announce the tab name. Update @example
docblock in tab.html to demonstrate the icon parameter.

* doc(tabs): improve icon section with better examples and icon page link

Rename "Tabs With Icons" heading to "Add Icons" for consistency with
other action-oriented section titles. Replace JSON/YAML/TOML icon
example with Photos/Music/Videos using photograph, music-note, and
film icons that naturally match their labels. Add link to the Icon
shortcode page so users can discover available icon names.
2026-02-14 21:23:25 +00:00
Xin
88aa6098f0 refactor(a11y): comprehensive WCAG 2.2 AA accessibility improvements (#924)
* refactor(a11y): comprehensive WCAG 2.2 AA accessibility improvements

Add skip-to-content link, landmark regions, ARIA attributes, keyboard
navigation, focus styles, reduced-motion support, and i18n keys across
all layouts, partials, shortcodes, and JS components.

- Add skip nav link in baseof.html and id="content" on all <main> tags
- Fix 404 page lang/dir attributes and add <main> landmark
- Add aria-label to banner close, PDF iframe, search input/results
- Remove aria-hidden from back-to-top button
- Add aria-hidden to decorative external link icon
- Add role="tablist" to tabs, aria-expanded to filetree/dropdowns
- Wrap mermaid diagrams in role="img", asciinema in role="region"
- Change theme toggle <p> items to <button role="menuitem"> with
  full keyboard navigation (Arrow/Home/End/Escape)
- Add arrow-key keyboard navigation to tabs component
- Separate sidebar collapsible button from link for independent
  keyboard access with aria-expanded sync
- Sync aria-expanded on all dropdown toggles (theme, lang, navbar,
  hamburger, page context menu)
- Add aria-live search status announcements
- Add 13 new i18n keys, replace hardcoded aria-label strings
- Add prefers-reduced-motion CSS override and focus-visible base styles
- Add aria-label swap on code copy ("Copied!" feedback for AT)
- Add aria-current to active TOC links
- Wrap filetree in <ul> container for proper list semantics
- Add unique aria-label to blog "Read more" links
- Document accessibility guidelines in AGENTS.md

* feat(a11y): enhance focus styles and accessibility for various components

- Add focus-visible styles to badges, buttons, and links for improved keyboard navigation.
- Update breadcrumb, sidebar, and TOC components to include focus-visible outlines.
- Introduce new classes for focus states in the badge and tabs shortcodes.
- Ensure consistent focus styles across all interactive elements to meet WCAG 2.2 AA standards.

* feat(a11y): implement new focus-visible utilities and enhance accessibility styles

- Introduce new utility classes for focus-visible states to improve keyboard navigation.
- Update various components including badges, buttons, and search inputs to utilize new focus-visible styles.
- Refactor existing focus styles to ensure consistency and compliance with accessibility standards.
- Enhance breadcrumb, sidebar, and TOC components with updated focus-visible classes for better user experience.

* chore: add .gitattributes to collapse generated files in PR diffs

* fix: enhance accessibility and improve documentation

- Added alt attributes to images in multiple language documentation files for better accessibility.
- Updated the navbar title partial to remove unnecessary title attribute.
- Improved search input accessibility by adding autocomplete="off".
- Enhanced search partials in both navbar and sidebar with location context.
- Updated SVG icons in various components to include aria-hidden and focusable attributes for improved accessibility compliance.

* fix: improve giscus theme toggle functionality

- Updated the theme toggle options selector to use a data attribute for better specificity.
- Modified the event listener to use a setTimeout for the theme update, ensuring smoother transitions when the theme switcher is clicked.

* fix: resolve axe-core WCAG AA violations across docs pages

Add aria-labels to Hugo task list checkboxes, fix asciinema player
timer accessible names, make Jupyter output cells keyboard-focusable,
and add missing heading hierarchy in shortcodes docs for fa/ja/zh-cn.

* feat: integrate accessibility testing with Playwright and enhance CI workflow

- Added Playwright configuration for accessibility testing.
- Implemented accessibility tests using axe-core for all English pages.
- Created a GitHub Actions workflow to automate accessibility tests on pull requests.
- Updated package dependencies to include @axe-core/playwright and @playwright/test.
- Enhanced sidebar component with data attributes for improved accessibility styling.

* fix: update base URL and improve accessibility labels across multiple languages

- Changed the base URL in Playwright configuration and CI workflow from localhost:3000 to localhost:1313.
- Added accessibility labels for screen readers in various language files, enhancing user experience for visually impaired users.
- Updated the Asciinema script to dynamically set the playback time label for better accessibility compliance.

* refactor: reorganize accessibility tests and update test directory structure

- Moved accessibility tests from the e2e directory to a new tests directory for better organization.
- Updated the test directory path in Playwright configuration.
- Refactored the accessibility test implementation to improve code clarity and maintainability.

* chore: update .gitignore to include Playwright test output directories

- Added entries for 'playwright-report/' and 'test-results/' to the .gitignore file to prevent cluttering the repository with test artifacts.

* refactor: enhance accessibility and improve focus styles across components

- Removed unused utility for focus visibility in CSS and consolidated focus-visible styles for better maintainability.
- Updated various components to use `role` attributes for improved accessibility, including menu items and buttons.
- Enhanced theme toggle and language switch components with appropriate ARIA roles and attributes for better screen reader support.
- Improved the handling of focus states in the navigation and context menus to ensure a consistent user experience.

* chore: update dependencies and enhance accessibility features

- Updated the 'serve' package version in package.json and package-lock.json for improved performance.
- Removed unused 'xml2js' dependency to streamline the project.
- Enhanced the Playwright configuration to better manage the web server setup for testing.
- Improved accessibility in the language switcher and navigation menu by refining focus management and keyboard interactions.
- Updated the back-to-top button to manage tabindex for better accessibility compliance.

* feat: enhance mobile menu accessibility and keyboard interactions

- Added ARIA attributes to manage visibility of the sidebar on mobile devices.
- Implemented focus management for the sidebar when the menu is toggled.
- Introduced keyboard support to close the menu with the Escape key.
- Improved overall accessibility for the hamburger menu and sidebar interactions.

* fix: refine mobile menu keyboard interaction and enhance navbar accessibility

- Updated the Escape key functionality to close the menu only on mobile devices.
- Added a new ARIA attribute to the hamburger menu button for improved accessibility.
2026-02-14 20:06:35 +00:00
Tyler
04803c4071 feat: archives page (#922)
* feat: archives page

* fix: empty archive show 'no posts found' message
* Add ToC partials for structural consistency
* Fix empty archive showing blank page

* fix: rename archive to archives

* chore: enhance archives and additional pages support

- Updated the menu structure in hugo.yaml to include new sections for 'About', 'Archives', and 'Glossary' under 'More'.
- Added new archive index files for multiple languages (Farsi, Japanese, Simplified Chinese) to support multilingual content.
- Created additional pages documentation for glossary and archives in multiple languages.
- Updated references in existing documentation to point to the new additional pages structure.
- Improved the archives layout to display a user-friendly message when no posts are found.

* fix: update date format in archives layout

- Changed the date format in the archives layout from a partial to a direct format for improved readability, displaying dates as "Jan 02".

* feat: add archive date format customization

- Introduced a new parameter in hugo.yaml for customizing the date format of archive items, defaulting to "Jan 02".
- Updated documentation in multiple languages to reflect the new optional date format feature for archives.

---------

Co-authored-by: Xin <xin@imfing.com>
2026-02-08 11:45:29 +00:00
Xin
2d5adf0e40 fix: prevent relref double base-prefix in render-link (#920)
* Fix announcement relrefs and add doc

* Revert glossary inline relref example

* Fix relref links with subdirectory baseURL

Co-authored-by: Max Mehl <max.mehl@deutschebahn.com>

* Simplify relref base-prefix guard in render-link

---------

Co-authored-by: Max Mehl <max.mehl@deutschebahn.com>
2026-02-05 22:38:00 +00:00
Xin
6d613d28a3 chore: rename CLAUDE.md to AGENTS.md and remove taskfile
- Rename CLAUDE.md to AGENTS.md for agent-agnostic naming
- Create CLAUDE.md symlink pointing to AGENTS.md
- Remove taskfile.yaml in favor of npm scripts
- Update content: add npm install setup step, update shortcodes list, fix JS component paths
2026-02-02 20:43:06 +00:00
Daniel Seijo
9362f7c3fc feat(lastUpdated): introduce last modified author using GitInfo (#857)
* feat(lastUpdated): introduce last modified author using GitInfo

* feat: change by string for just •

* docs: add documentation for displayUpdatedAuthor parameter

Document the new displayUpdatedAuthor config option in all language
versions (en, zh-cn, ja, fa). Also disable it by default in the
example hugo.yaml.

---------

Co-authored-by: Xin <5097752+imfing@users.noreply.github.com>
Co-authored-by: Xin <xin@imfing.com>
2026-02-01 15:02:15 +00:00
Matheus Flausino
744e843880 feat(llms): add option to exclude pages and sections from llms.txt (#918)
* feat: improve section filtering in llms.txt

* fix(llms): correct where syntax and add page exclusion filter

- Fix invalid Hugo template syntax in where clause
- Use boolean comparison instead of string for llms param
- Add filtering to recursive llms-section-tree template
- Document llms exclusion feature in all languages (en, ja, fa, zh-cn)

---------

Co-authored-by: Xin <xin@imfing.com>
2026-01-29 21:06:12 +00:00
Christian Galeffi
50b9c927c2 feat(i18n): add Italian localization strings for various UI elements (#915) 2026-01-29 00:07:43 +00:00
yuri
fe81bc3087 fix(glossary): make Glossary optional (#916) 2026-01-29 00:06:13 +00:00
ghac101
7e56f0578a feat(pagination): add option to disable prev/next navigation
* Feature: disable next/previous pagination buttons site-wide

* Moved the displayPagination to the layout level and adjusted the documentation.

* fix: improve pagination docs and layout whitespace

- Fix indentation in docs layout templates
- Add pagination documentation for all languages (fa, ja, zh-cn)
- Simplify documentation to be more succinct

---------

Co-authored-by: Xin <xin@imfing.com>
2026-01-24 12:42:49 +00:00
Xin
05e28a716d feat(navbar): enhance active link detection for multilingual section landing pages (#913)
- Added logic to normalize trailing slashes for section landing pages in multilingual sites, improving the accuracy of active link detection in the navbar.
- This enhancement ensures that the correct link is highlighted as active, providing a better user experience across different languages.
2026-01-24 12:27:37 +00:00
Xin
162f3a3fa7 fix(tabs): prevent markdown blockquote parsing when nested in steps (#912)
* fix(tabs): prevent markdown blockquote parsing when nested in steps

Consolidate HTML attributes onto single lines and add proper whitespace
trimming to prevent `>` characters on separate lines from being
interpreted as markdown blockquotes when tabs are nested inside the
steps shortcode.

Fixes #876

* chore: add comment explaining single-line HTML requirement
2026-01-24 12:00:47 +00:00
Xin
02cca4cd0b fix(layout): make content width respect page.width config (#911)
Fixes #886 - The content area in `<main>` was hardcoded to `hx:max-w-6xl`
(72rem), ignoring the `params.page.width` setting. Added a new CSS
variable `--hextra-max-content-width` that responds to the page width
config, so users can now get full-width or wide content as expected.
2026-01-24 00:02:50 +00:00
Xin
fa8f8554ea feat(context-menu): add page context menu for copy/view Markdown (#908)
* feat(context-menu): implement page context menu for copy Markdown

- Added a context menu to Markdown pages allowing users to copy content as Markdown or view it in a new tab.
- Introduced new layout files for Markdown rendering and updated existing layouts to include the context menu.
- Enhanced configuration options to enable or disable the context menu globally or per page.
- Updated internationalization files to support new context menu actions.
- Improved documentation to guide users on the new features and their usage.

* feat(context-menu): enhance dropdown positioning and responsiveness

- Updated the context menu dropdown to use responsive positioning classes for better alignment on different screen sizes.
- Added new CSS classes to ensure the dropdown appears correctly on smaller devices, improving user experience.

* refactor(context-menu): adjust button styles for improved layout and usability

- Modified button classes in the page context menu to enhance spacing and alignment.
- Reduced padding and gap sizes for a more compact design, improving overall user experience.

* refactor(styles): update CSS classes for improved layout and consistency

- Removed outdated ring classes and adjusted padding and border styles in various components for a cleaner design.
- Enhanced hover effects and gap sizes for better user experience across language switcher, navbar, and theme toggle elements.
- Standardized rounded styles to maintain visual consistency throughout the interface.

* feat(context-menu): add custom links to page context menu

- Introduced new configuration options for custom links in the page context menu, allowing users to open documentation in ChatGPT and Claude.
- Updated the context menu layout to include a separator and display the new links with appropriate styling.
- Enhanced the CSS classes for better visual integration with existing context menu elements.

* feat(icons): add new AI icons and update context menu links

- Introduced new icons for AI tools including ChatGPT, Claude, Gemini, and others in the icons.yaml file.
- Enhanced the page context menu in multiple languages to include links for opening documentation in ChatGPT and Claude, improving user accessibility to AI resources.
- Updated internationalization files to reflect new context menu options and additional copy functionalities.

* refactor(layouts): simplify page structure in glossary and section layouts

- Removed the conditional rendering of page links in the glossary and section layouts to streamline the markup.
- Adjusted the blog and docs list layouts to ensure consistent closing of HTML tags and improved formatting.

* feat(context-menu): add outbound icons to external links

Add arrow-up-right icons to "View as Markdown" and custom links
in the page context menu to indicate they open in new tabs.

* Revert "feat(context-menu): add outbound icons to external links"

This reverts commit 670175e200f091ed89b15bd16f44a585355db57d.

* chore: rebuild css

* chore: update stats json

* chore: rename project and update context menu structure

- Changed project name from "wizardly-wing" to "hextra" in package-lock.json.
- Refactored context menu structure in hugo.yaml to improve organization and consistency across multiple languages.
- Updated context menu links to ensure proper functionality and accessibility.

* feat(context-menu): enhance clipboard functionality and pre-fetching

- Implemented pre-fetching of markdown content for copy buttons to improve performance and avoid clipboard access issues in Safari.
- Updated click event handlers to utilize cached content for clipboard operations, with a fallback to fetch content if not pre-fetched.
- Added checks to ensure elements exist before performing actions, enhancing robustness of the context menu interactions.

* fix(context-menu): improve hover effects and border styles

- Enhanced the context menu's border styles with transition effects for better visual feedback on hover.
- Updated CSS classes to ensure consistent styling across different themes, improving user experience.

* feat(context-menu): add page context menu functionality across multiple languages

- Introduced a page context menu that allows users to copy content as Markdown or view the raw Markdown source, enhancing usability for documentation sites.
- Added configuration options to enable the context menu globally and control it on a per-page basis.
- Implemented support for custom links in the context menu, allowing integration with external services.
- Updated documentation in Persian, Japanese, Chinese, and English to reflect these new features.

* fix(icons): update SVG definitions for Gemini and add fill attribute

- Updated the SVG definition for the Gemini icon to include the 'fill' attribute for better rendering.
- Ensured consistency in the SVG structure for the Gemini icon while maintaining the existing definitions for ChatGPT and Claude.

* chore: rebuild css

* chore: remove Claude links from context menu in multiple languages

- Removed the "Open in Claude" option from the context menu for Persian, Japanese, and Simplified Chinese languages to streamline the user experience.

* fix(context-menu): update cursor styles for buttons in context menu

- Changed cursor style from default to pointer for buttons in the page context menu to enhance user interaction feedback.
2026-01-23 23:40:29 +00:00
Xin
e81447e7ae feat(image-zoom): add image zoom functionality and documentation (#907)
* feat(image-zoom): add image zoom functionality and documentation

- Introduced a new `imageZoom` parameter in the configuration to enable click-to-zoom for Markdown images.
- Updated the `render-image.html` layout to support zoom functionality by adding a `data-zoomable` attribute to images.
- Created a new `medium-zoom.html` script to handle the zoom effect, with options for CDN or local asset loading.
- Enhanced documentation in `configuration.md` and `markdown.md` to guide users on enabling and configuring image zoom.

* docs(image-zoom): add image zoom documentation in multiple languages

- Added sections for image zoom functionality in Persian, Japanese, and Simplified Chinese documentation.
- Included configuration examples for enabling and disabling image zoom in specific pages.
- Updated related documentation to ensure consistency across languages.
2026-01-20 22:55:41 +00:00
Xin
6a13f17326 fix(sidebar): update transform syntax for improved compatibility 2026-01-19 23:03:28 +00:00
Xin
8e1e446cb8 fix: migrate tabs shortcode to new standard syntax (#906)
* doc(tabs): update shortcode syntax to use new syntax

- Changed tab shortcode syntax from `items` to `name` for better clarity and consistency in multiple language documentation.
- Updated related examples in Persian, Japanese, and Simplified Chinese to reflect the new syntax.
- Adjusted the sidebar CSS to correct a z-index value for improved layout behavior on mobile devices.

* fix(sidebar, toc): update CSS classes for improved layout and text wrapping

- Adjusted the sidebar CSS class to use a new transform syntax for better compatibility.
- Updated the table of contents link class to ensure proper text wrapping behavior.

* chore: recompile css

* fix(css): update CSS classes for improved text wrapping

- Changed `break-words` to `wrap-break-word` in multiple CSS files to enhance text wrapping behavior.
- Adjusted the `.hextra-code-filename` and typography styles for better compatibility and consistency.
2026-01-19 22:50:49 +00:00
yuri
5028140432 feat(glossary): provide basic term glossary (#869)
* feat(glossary): provide basic term glossary

Enabled a site-wide terminology glossary.

* Added the `term` shortcode displaying term definition.
* Added the /glossary page showing all term definitions.
* Enabled a simplistic search of term definitions.

* refactor(glossary): update glossary page links and add callout for Hugo support

- Removed the glossary entry from the menu and adjusted weights for subsequent items.
- Added informational callouts in the glossary documentation for multiple languages, directing users to the Hugo Glossary Quick Reference.
- Updated links in the glossary documentation to point to the correct pages.

* fix(glossary): update links to glossary page format across multiple languages

- Changed links in the glossary documentation to use Hugo's relref format for consistency.
- Updated links in Persian, Japanese, English, and Simplified Chinese glossary pages.

---------

Co-authored-by: Xin <5097752+imfing@users.noreply.github.com>
Co-authored-by: Xin <xin@imfing.com>
2026-01-19 22:33:09 +00:00
Illia Volochii
66a9d98630 fix: respect search.enable in the sidebar (#904) 2026-01-19 22:25:42 +00:00
Illia Volochii
1e4338cd97 fix: respect the page parameter toc in the mobile dropdown (#905) 2026-01-19 22:21:41 +00:00
Xin
a9ef7ad57d fix(flexsearch): enhance match highlighting and safe DOM manipulation (#903)
- Replaced the highlightMatches function with appendHighlightedText to improve match highlighting using safe text nodes.
- Updated DOM manipulation for search results to create elements directly instead of using innerHTML, enhancing security and performance.
- Ensured consistent handling of empty text and query cases in the new highlighting function.
2026-01-18 19:59:09 +00:00
Xin
2b00f92a42 chore: update dependencies in package.json and package-lock.json
- Upgraded @tailwindcss/postcss, prettier, and tailwindcss to version 4.1.18 and 3.8.0 respectively.
- Updated @jridgewell/gen-mapping and other related packages to their latest versions.
- Removed deprecated entries and ensured consistency across package versions.
2026-01-18 10:58:06 +00:00
Antonin P
c35d7b3a9e fix(card): ensure subtitle stays at bottom by wrapping title/subtitle… (#877)
* fix(card): ensure subtitle stays at bottom by wrapping title/subtitle in container

* Update layouts/_partials/shortcodes/card.html

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Xin <5097752+imfing@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-17 12:14:55 +00:00
Xin
447acb7df3 fix(og-image): handle leading slashes in image paths for subpath deployments (#901)
* fix(og-image): handle leading slashes in image paths for subpath deployments

Fix Open Graph image paths not working correctly when deploying to subpaths
(e.g., https://example.com/docs/). The issue occurred when image paths with
leading slashes were specified in configuration, causing the subpath to be
ignored.

The fix follows the established pattern used throughout the theme by stripping
leading slashes before applying relURL, ensuring paths respect the baseURL
subpath configuration.

- Update opengraph.html to process image paths consistently
- Update configuration examples to remove leading slashes
- Add investigation document explaining the issue and fix

* chore: remove issue summary
2026-01-17 12:14:15 +00:00
Mark Alexander
c4a39472eb fix: work around flexsearch returning fewer than expected result pages (#847)
Co-authored-by: Xin <5097752+imfing@users.noreply.github.com>
2026-01-06 16:28:18 +00:00
Torbjørn Pedersen
1391ebe04b feat: support page bundle images in OpenGraph metadata (#892)
* Support page bundle images in OpenGraph metadata

* Fix file permissions

---------

Co-authored-by: Xin <5097752+imfing@users.noreply.github.com>
2026-01-04 17:25:53 +00:00
Xin
a128fabaf1 feat: add optional alt parameter to card shortcode (#899)
Add support for custom alt text on card images to improve accessibility.
The alt parameter is optional and defaults to the card title if not provided,
maintaining backward compatibility with existing implementations.

Fixes #896
2026-01-04 17:23:33 +00:00
yuri
9466af337f chore(docs): link KaTeX (#860) 2025-11-28 01:04:09 +00:00
PrintN
0e8982876a chore: Update Beginner Privacy showcase image and add PrintN website (#859) 2025-11-28 01:03:00 +00:00
Keith Stockdale
3551a56b8c feat: support GoatCounter analytics (#814)
* feat: support GoatCounter analytics

* docs: add docs for GoatCounter analytics

refactor: move analytics documentation into its own section since there are now 4 supported analytics solutions

* fix: addressing issues raised in PR

* refactor: simplifying goat counter setting logic.
refactor: simplify error handling with goat counter

* fix: fixing goat counter erroring when a code is provided

* fix: Applying suggested fixes

* Update layouts/_partials/components/analytics/goat-counter.html

---------

Co-authored-by: Xin <5097752+imfing@users.noreply.github.com>
2025-10-13 22:50:19 +01:00
Bubbler
bfeae19076 docs(details): change details shortcode calls to angle brackets (#855)
Co-authored-by: Xin <5097752+imfing@users.noreply.github.com>
2025-10-12 23:07:24 +01:00
Paul Marrapese
b7f4bffce6 feat(shortcode): added markdown attribute support for headers (#851)
docs: added "no-step-marker" example for steps
2025-10-11 23:13:04 +01:00
Kowyo
708358de80 fix: enhance table readability (#826)
* feat: enhance table readability

* use v0.9.0 table style

* Update table styles

---------

Co-authored-by: Xin <xin@imfing.com>
2025-09-15 21:59:05 +01:00
ghac101
8699deb1dd fix(analytics): change default umami analytics file to script.js (#835)
Co-authored-by: Xin <5097752+imfing@users.noreply.github.com>
2025-09-15 21:28:27 +01:00
198 changed files with 5800 additions and 1070 deletions

3
.gitattributes vendored Normal file
View File

@@ -0,0 +1,3 @@
# Mark generated files so they are collapsed by default in GitHub diffs
assets/css/compiled/main.css linguist-generated=true
docs/hugo_stats.json linguist-generated=true

View File

@@ -31,7 +31,7 @@ jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: env:
HUGO_VERSION: 0.147.7 HUGO_VERSION: 0.156.0
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -43,7 +43,7 @@ jobs:
- name: Setup Go - name: Setup Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: "1.24" go-version: "1.26"
- name: Setup Pages - name: Setup Pages
id: pages id: pages

View File

@@ -0,0 +1,62 @@
name: Accessibility Tests
on:
pull_request:
branches: [main]
concurrency:
group: accessibility-${{ github.head_ref || github.ref_name }}
cancel-in-progress: true
defaults:
run:
shell: bash
jobs:
a11y:
runs-on: ubuntu-latest
environment: accessibility
env:
HUGO_VERSION: 0.156.0
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: recursive
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: "1.26"
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "24"
cache: npm
- name: Setup Hugo
run: |
wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \
&& sudo dpkg -i ${{ runner.temp }}/hugo.deb
- name: Install dependencies
run: npm ci
- name: Install Playwright Chromium
run: npx playwright install chromium
- name: Build site
run: npm run build
- name: Run accessibility tests
run: npm run test:a11y
- name: Upload report
if: always()
uses: actions/upload-artifact@v4
with:
name: accessibility-report
path: playwright-report/
retention-days: 14

61
.github/workflows/test-mobile-menu.yml vendored Normal file
View File

@@ -0,0 +1,61 @@
name: Mobile Menu Tests
on:
pull_request:
branches: [main]
concurrency:
group: mobile-menu-${{ github.head_ref || github.ref_name }}
cancel-in-progress: true
defaults:
run:
shell: bash
jobs:
mobile-menu:
runs-on: ubuntu-latest
env:
HUGO_VERSION: 0.156.0
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: recursive
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: "1.26"
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "24"
cache: npm
- name: Setup Hugo
run: |
wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \
&& sudo dpkg -i ${{ runner.temp }}/hugo.deb
- name: Install dependencies
run: npm ci
- name: Install Playwright Chromium
run: npx playwright install chromium
- name: Build site
run: npm run build
- name: Run mobile menu tests
run: npm run test:mobile-menu
- name: Upload report
if: always()
uses: actions/upload-artifact@v4
with:
name: mobile-menu-report
path: playwright-report/
retention-days: 14

4
.gitignore vendored
View File

@@ -3,3 +3,7 @@ public/
resources/ resources/
.hugo_build.lock .hugo_build.lock
# Playwright
playwright-report/
test-results/

193
AGENTS.md Normal file
View File

@@ -0,0 +1,193 @@
# AGENTS.md
This file provides guidance to AI coding agents when working with code in this repository.
## Project Overview
Hextra is a modern, responsive Hugo theme designed for creating documentation websites, technical blogs, and static sites. Built with Tailwind CSS, it offers features like full-text search, dark mode, multi-language support, and extensive customization options.
## Development Commands
### Initial Setup
When working in a new worktree or fresh clone without `node_modules`, run `npm install` first to install dependencies:
```bash
npm install
```
### Development Server
```bash
# Start development server with theme reloading (recommended for theme development)
npm run dev:theme
```
### Building
```bash
# Build the example site
npm run build
# Build CSS assets only
npm run build:css
```
## Architecture Overview
### Hugo Theme Structure
- **Base Layout**: `layouts/baseof.html` wraps all pages
- **Specialized Layouts**: `layouts/docs/`, `layouts/blog/`, `layouts/hextra-home.html`
- **Partials**: Reusable components in `layouts/_partials/`
- Core UI: `navbar.html`, `sidebar.html`, `footer.html`, `breadcrumb.html`, `toc.html`
- Utilities: `layouts/_partials/utils/` for helper functions
- Custom overrides: `layouts/_partials/custom/` for user customizations
- **Shortcodes**: Custom Markdown extensions in `layouts/_shortcodes/`
- **Render Hooks**: Custom Markdown rendering in `layouts/_markup/` for codeblocks, headings, images, and links
### Asset Organization
```
assets/
├── css/
│ ├── styles.css # Main stylesheet (Tailwind entry point)
│ ├── compiled/main.css # Built CSS output (generated)
│ ├── components/ # Component-specific styles
│ ├── chroma/ # Syntax highlighting themes
│ └── custom.css # User customization entry point
└── js/
├── core/ # Core JS components
└── flexsearch.js # Search functionality
```
### Key Components
- **Search**: FlexSearch-powered full-text search (`assets/js/flexsearch.js`)
- **Navigation**: Responsive navbar and auto-generated sidebar
- **Theme Toggle**: Dark/light mode switching
- **Internationalization**: 20+ language support in `i18n/`
### Content Features
- **Shortcodes**: `callout`, `card`, `cards`, `tabs`, `tab`, `details`, `steps`, `filetree`, `jupyter`, `badge`, `icon`, `pdf`, `include`, `asciinema`, `term`
- **Code Features**: Syntax highlighting (Chroma), copy buttons, line numbers via render hooks
- **SEO**: Open Graph, Twitter Cards, structured data
- **Performance**: Minimal JavaScript, optimized CSS with Tailwind
## Development Workflow
### Example Site Development
The `docs/` directory serves as both documentation and testing ground:
- Test new features here before releasing
- Configuration examples in `docs/hugo.yaml` showing multi-language setup
- Content examples demonstrate all theme capabilities
- Run from docs with: `hugo server --themesDir=../..`
### CSS Development Workflow
- Source: `assets/css/styles.css` (main stylesheet)
- Build process: Tailwind CSS → PostCSS → `assets/css/compiled/main.css`
- Component styles organized in `assets/css/components/`
- Chroma syntax highlighting themes in `assets/css/chroma/`
- CSS compilation requires Node.js dependencies (PostCSS, Tailwind CSS v4+)
#### Rebuilding CSS after template changes
Tailwind CSS relies on `docs/hugo_stats.json` to know which HTML tags, classes, and IDs are actually used in the built site, so it can tree-shake unused styles. When you modify layouts, partials, or shortcodes you must **regenerate `hugo_stats.json` first**, then rebuild the CSS:
1. **Generate `docs/hugo_stats.json`** — Run Hugo with the `dev.toml` config (which sets `build.buildStats.enable = true`):
```bash
# Using npm (starts a dev server that writes hugo_stats.json on every rebuild):
npm run dev:theme
# Or a one-shot build using the raw Hugo command:
hugo --config=hugo.yaml,../dev.toml --themesDir=../.. --source=docs
```
2. **Build the CSS** — With an up-to-date `hugo_stats.json` in place, compile the stylesheet:
```bash
npm run build:css
```
> **Why two steps?** `dev.toml` mounts `docs/hugo_stats.json` into the Hugo asset pipeline (`assets/notwatching/hugo_stats.json`) and configures a cache-buster so that changes to the stats file trigger a CSS recompile during `dev:theme`. When running outside the dev server you need to perform these steps manually in order.
### Customization Points
- Custom partials: `layouts/_partials/custom/`
- Custom CSS: `assets/css/custom.css`
- Site-specific overrides: Copy any layout to your site's `layouts/` directory
## Configuration & Requirements
### Theme Requirements
- Hugo minimum version: 0.146.0 (extended version required - see `theme.toml`)
- Go 1.20+ (as specified in `go.mod`)
- Node.js for CSS compilation (PostCSS, Tailwind CSS v4+)
### Key Configuration Files
- `docs/hugo.yaml` - Example Hugo configuration with multi-language setup
- `postcss.config.mjs` - PostCSS configuration for CSS processing
- `package.json` - Node.js dependencies and build scripts
### Development Environment
- Default Hugo development server: Port 1313
- Development server runs with `--disableFastRender -D` for better development experience
- Theme development uses `--logLevel=debug` for detailed logging
### Multi-language Support
- Configure languages in `hugo.yaml` (supports 20+ languages including RTL)
- Translation files in `i18n/` directory (e.g., `en.yaml`, `fa.yaml`, `ja.yaml`, `zh-cn.yaml`)
- Example supports English, Persian (RTL), Japanese, and Simplified Chinese
## Theme Development Guidelines
### Hugo Theme Conventions
- Theme files in this repository override Hugo defaults
- Follow Hugo's theme development guidelines for compatibility
- Maintain backward compatibility with existing configurations
### JavaScript & Performance
- All JavaScript components are designed to have minimal footprint
- Core JS components in `assets/js/core/`: `theme.js`, `nav-menu.js`, `code-copy.js`, `sidebar.js`, `tabs.js`, etc.
- FlexSearch powers offline full-text search (`assets/js/flexsearch.js`)
### CSS Architecture
- Uses Tailwind CSS v4+ with PostCSS processing
- Component-based CSS organization in `assets/css/components/`
- Compiled output goes to `assets/css/compiled/main.css`
- Prettier formatting for Go templates and code consistency
### Accessibility (WCAG Compliance)
All new features and UI changes must follow the [Web Content Accessibility Guidelines (WCAG) 2.2](https://www.w3.org/TR/WCAG22/) at the **AA** conformance level. Key requirements:
- **Semantic HTML**: Use appropriate elements (`<nav>`, `<main>`, `<aside>`, `<button>`, `<ul>`, etc.) instead of generic `<div>`/`<span>` where applicable.
- **ARIA attributes**: Add `aria-label`, `aria-expanded`, `aria-controls`, `aria-current`, `role`, and other ARIA attributes to interactive components (menus, toggles, dropdowns, modals) so screen readers can interpret them.
- **Keyboard navigation**: All interactive elements must be reachable and operable via keyboard (`Tab`, `Enter`, `Escape`, arrow keys). Manage focus appropriately when opening/closing menus, modals, and drawers.
- **Focus indicators**: Never remove visible focus outlines. Use the existing `hextra-focus` utility or equivalent visible focus ring styles.
- **Color contrast**: Text and interactive elements must meet WCAG AA contrast ratios (4.5:1 for normal text, 3:1 for large text). Verify in both light and dark modes.
- **Images and icons**: Decorative SVGs/icons should have `aria-hidden="true"`. Meaningful images need descriptive `alt` text.
- **Skip links and landmarks**: Preserve existing skip-navigation links and ARIA landmark roles (`role="navigation"`, `role="search"`, etc.).
- **Live regions**: Use `aria-live` for dynamic content updates (e.g., search results, status messages) so assistive technology announces changes.
- **Form controls**: Associate `<label>` elements with inputs. Provide accessible names for buttons that contain only icons.
When introducing a new component or modifying an existing one, verify it works with keyboard-only navigation and review the rendered HTML for proper semantics and ARIA usage.
### Testing & Quality Assurance
- Test all changes in `docs/` before releasing
- Use `npm run dev:theme` for theme development with hot reloading
- Format code with `npx prettier --write .` before committing
- Verify multi-language functionality across supported languages

161
CLAUDE.md
View File

@@ -1,161 +0,0 @@
# CLAUDE.md
This file provides guidance to [Claude Code](claude.ai/code) when working with code in this repository.
## Project Overview
Hextra is a modern, responsive Hugo theme designed for creating documentation websites, technical blogs, and static sites. Built with Tailwind CSS and inspired by Nextra, it offers features like full-text search, dark mode, multi-language support, and extensive customization options.
## Development Commands
### Development Server
```bash
# Start development server with theme reloading (recommended for theme development)
npm run dev:theme
# Using Task runner
task dev
```
### Building
```bash
# Build the example site
npm run build
# or
task build
# Build CSS assets only
npm run build:css
# or
task css
```
### Alternative Task Commands
The project uses Task runner (`taskfile.yaml`) for simplified commands:
- `task dev` - Start development server (runs `npm run dev:theme`)
- `task build` - Build example site
- `task css` - Compile CSS (depends on build)
## Architecture Overview
### Hugo Theme Structure
- **Base Layout**: `layouts/baseof.html` wraps all pages
- **Specialized Layouts**: `layouts/docs/`, `layouts/blog/`, `layouts/hextra-home.html`
- **Partials**: Reusable components in `layouts/_partials/`
- Core UI: `navbar.html`, `sidebar.html`, `footer.html`, `breadcrumb.html`, `toc.html`
- Utilities: `layouts/_partials/utils/` for helper functions
- Custom overrides: `layouts/_partials/custom/` for user customizations
- **Shortcodes**: Custom Markdown extensions in `layouts/_shortcodes/`
- **Render Hooks**: Custom Markdown rendering in `layouts/_markup/` for codeblocks, headings, images, and links
### Asset Organization
```
assets/
├── css/
│ ├── styles.css # Main stylesheet
│ ├── compiled/main.css # Built CSS output (generated)
│ ├── components/ # Component-specific styles
│ └── chroma/ # Syntax highlighting themes
├── js/ # JavaScript components
└── lib/ # External libraries
```
### Key Components
- **Search**: FlexSearch-powered full-text search (`assets/js/flexsearch.js`)
- **Navigation**: Responsive navbar and auto-generated sidebar
- **Theme Toggle**: Dark/light mode switching
- **Internationalization**: 20+ language support in `i18n/`
### Content Features
- **Shortcodes**: `callout`, `card`, `cards`, `tabs`, `details`, `steps`, `jupyter`, `filetree`
- **Code Features**: Syntax highlighting (Chroma), copy buttons, line numbers via render hooks
- **SEO**: Open Graph, Twitter Cards, structured data
- **Performance**: Minimal JavaScript, optimized CSS with Tailwind
## Development Workflow
### Example Site Development
The `docs/` directory serves as both documentation and testing ground:
- Test new features here before releasing
- Configuration examples in `docs/hugo.yaml` showing multi-language setup
- Content examples demonstrate all theme capabilities
- Run from docs with: `hugo server --themesDir=../..`
### CSS Development Workflow
- Source: `assets/css/styles.css` (main stylesheet)
- Build process: Tailwind CSS → PostCSS → `assets/css/compiled/main.css`
- Component styles organized in `assets/css/components/`
- Chroma syntax highlighting themes in `assets/css/chroma/`
- CSS compilation requires Node.js dependencies (PostCSS, Tailwind CSS v4+)
### Customization Points
- Custom partials: `layouts/_partials/custom/`
- Custom CSS: `assets/css/custom.css`
- Site-specific overrides: Copy any layout to your site's `layouts/` directory
## Configuration & Requirements
### Theme Requirements
- Hugo minimum version: 0.146.0 (extended version required - see `theme.toml`)
- Go 1.20+ (as specified in `go.mod`)
- Node.js for CSS compilation (PostCSS, Tailwind CSS v4+)
### Key Configuration Files
- `docs/hugo.yaml` - Example Hugo configuration with multi-language setup
- `postcss.config.mjs` - PostCSS configuration for CSS processing
- `package.json` - Node.js dependencies and build scripts
- `taskfile.yaml` - Task runner configuration
### Development Environment
- Default Hugo development server: Port 1313
- Development server runs with `--disableFastRender -D` for better development experience
- Theme development uses `--logLevel=debug` for detailed logging
### Multi-language Support
- Configure languages in `hugo.yaml` (supports 20+ languages including RTL)
- Translation files in `i18n/` directory (e.g., `en.yaml`, `fa.yaml`, `ja.yaml`, `zh-cn.yaml`)
- Example supports English, Persian (RTL), Japanese, and Simplified Chinese
## Theme Development Guidelines
### Hugo Theme Conventions
- Theme files in this repository override Hugo defaults
- Follow Hugo's theme development guidelines for compatibility
- Maintain backward compatibility with existing configurations
### JavaScript & Performance
- All JavaScript components are designed to have minimal footprint
- Core JS components: `theme.js`, `search.js`, `nav-menu.js`, `code-copy.js`
- FlexSearch powers offline full-text search functionality
### CSS Architecture
- Uses Tailwind CSS v4+ with PostCSS processing
- Component-based CSS organization in `assets/css/components/`
- Compiled output goes to `assets/css/compiled/main.css`
- Prettier formatting for Go templates and code consistency
### Testing & Quality Assurance
- Test all changes in `docs/` before releasing
- Use `npm run dev:theme` for theme development with hot reloading
- Format code with `npx prettier --write .` before committing
- Verify multi-language functionality across supported languages

1
CLAUDE.md Symbolic link
View File

@@ -0,0 +1 @@
AGENTS.md

View File

@@ -23,6 +23,7 @@
- **جستجوی متن کامل** - جستجوی متن کاملا آفلاین داخلی طراحی شده توسط FlexSearch، بدون نیاز به پیکربندی اضافی. - **جستجوی متن کامل** - جستجوی متن کاملا آفلاین داخلی طراحی شده توسط FlexSearch، بدون نیاز به پیکربندی اضافی.
- **امکانات کامل** - برای بهتر کردن محتوای شما مارک‌داون، برجسته‌کردن سینتکس، فرمول‌های ریاضی LaTeX، نمودارها و عناصر Shortcodeها را شامل میشه. فهرست مطالب، بردکرامب، صفحه‌بندی، پیمایش نوار کناری و موارد دیگر همه به صورت خودکار تولید می‌شوند. - **امکانات کامل** - برای بهتر کردن محتوای شما مارک‌داون، برجسته‌کردن سینتکس، فرمول‌های ریاضی LaTeX، نمودارها و عناصر Shortcodeها را شامل میشه. فهرست مطالب، بردکرامب، صفحه‌بندی، پیمایش نوار کناری و موارد دیگر همه به صورت خودکار تولید می‌شوند.
- **چند زبانه و سئو آماده** - سایت‌های چند زبانه با حالت چند زبانه Hugo راحت ساخته می‌شوند. پشتیبانی خارج از جعبه برای برچسب‌های سئو، Open Graph و کارت‌های توییتر گنجانده شده است. - **چند زبانه و سئو آماده** - سایت‌های چند زبانه با حالت چند زبانه Hugo راحت ساخته می‌شوند. پشتیبانی خارج از جعبه برای برچسب‌های سئو، Open Graph و کارت‌های توییتر گنجانده شده است.
- **پشتیبانی از دسترس‌پذیری** - اجزای تعاملی از نشانه‌گذاری معنایی، رفتار سازگار با صفحه‌کلید و بررسی‌های خودکار دسترس‌پذیری استفاده می‌کنند تا رابط کاربری در گردش‌کارهای رایج فناوری‌های کمکی قابل استفاده بماند.
## شروع کنید ## شروع کنید

View File

@@ -23,6 +23,7 @@ Demo → [imfing.github.io/hextra](https://imfing.github.io/hextra/)
- **Full-text Search** - Built-in offline full-text search powered by FlexSearch, no extra configuration required. - **Full-text Search** - Built-in offline full-text search powered by FlexSearch, no extra configuration required.
- **Battery-included** - Markdown, syntax highlighting, LaTeX math formulae, diagrams and Shortcodes elements to enhance your content. Table of contents, breadcrumbs, pagination, sidebar navigation and more are all automatically generated. - **Battery-included** - Markdown, syntax highlighting, LaTeX math formulae, diagrams and Shortcodes elements to enhance your content. Table of contents, breadcrumbs, pagination, sidebar navigation and more are all automatically generated.
- **Multi-language and SEO Ready** - Multi-language sites made easy with Hugo's multilingual mode. Out-of-the-box support is included for SEO tags, Open Graph, and Twitter Cards. - **Multi-language and SEO Ready** - Multi-language sites made easy with Hugo's multilingual mode. Out-of-the-box support is included for SEO tags, Open Graph, and Twitter Cards.
- **Accessibility Support** - Interactive components use semantic markup, keyboard-friendly behavior, and automated accessibility checks to keep the UI usable across common assistive workflows.
## Quick Start ## Quick Start

View File

@@ -23,6 +23,7 @@
- **全文搜索** - 集成了 Flexsearch 的全文搜索, 无需额外的配置. - **全文搜索** - 集成了 Flexsearch 的全文搜索, 无需额外的配置.
- **功能齐全** - Markdown, 代码高亮, LaTex 数学公式, diagrams 图表和 Shortcodes 都可以用于丰富你的内容. 目录, 面包屑导航, 分页, 侧边栏等均由 Hextra 自动生成。 - **功能齐全** - Markdown, 代码高亮, LaTex 数学公式, diagrams 图表和 Shortcodes 都可以用于丰富你的内容. 目录, 面包屑导航, 分页, 侧边栏等均由 Hextra 自动生成。
- **多语言和 SEO Ready** - Hugo 的多语言模式使得构建多语言网站更简单. 具有 SEO tags, Open Graph, 和 Twitter Cards 等诸多开箱即用的功能. - **多语言和 SEO Ready** - Hugo 的多语言模式使得构建多语言网站更简单. 具有 SEO tags, Open Graph, 和 Twitter Cards 等诸多开箱即用的功能.
- **无障碍支持** - 交互组件使用语义化标记、友好的键盘交互以及自动化无障碍检查,以便在常见辅助技术工作流中保持良好的可用性。
## 快速开始 ## 快速开始

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,3 @@
.hextra-archive-timeline {
@apply hx:border-l-2 hx:border-black/15 hx:dark:border-white/15;
}

View File

@@ -1,3 +1,3 @@
.hextra-badge { .hextra-badge {
@apply hx:inline-flex hx:items-center; @apply hx:inline-flex hx:items-center;
} }

View File

@@ -1,8 +1,8 @@
.hextra-search-wrapper { .hextra-search-wrapper {
li { li {
@apply hx:mx-2.5 hx:break-words hx:rounded-md hx:contrast-more:border hx:text-gray-800 hx:contrast-more:border-transparent hx:dark:text-gray-300; @apply hx:mx-2.5 hx:wrap-break-word hx:rounded-md hx:contrast-more:border hx:text-gray-800 hx:contrast-more:border-transparent hx:dark:text-gray-300;
a { a {
@apply hx:focus-visible:outline-none hx:focus:outline-none hx:block hx:scroll-m-12 hx:px-2.5 hx:py-2; @apply hx:focus-visible:outline-none hx:block hx:scroll-m-12 hx:px-2.5 hx:py-2;
} }
.hextra-search-title { .hextra-search-title {

View File

@@ -1,6 +1,6 @@
@media (max-width: 48rem) { @media (max-width: 48rem) {
.hextra-sidebar-container { .hextra-sidebar-container {
@apply hx:fixed hx:pt-[calc(var(--navbar-height)+var(--hextra-banner-height))] hx:top-0 hx:w-full hx:bottom-0 hx:z-[15] hx:overscroll-contain hx:bg-white hx:dark:bg-dark; @apply hx:fixed hx:pt-[calc(var(--navbar-height)+var(--hextra-banner-height))] hx:top-0 hx:w-full hx:bottom-0 hx:z-15 hx:overscroll-contain hx:bg-white hx:dark:bg-dark;
transition: transform 0.4s cubic-bezier(0.52, 0.16, 0.04, 1); transition: transform 0.4s cubic-bezier(0.52, 0.16, 0.04, 1);
will-change: transform, opacity; will-change: transform, opacity;
contain: layout style; contain: layout style;
@@ -9,13 +9,13 @@
} }
.hextra-sidebar-container { .hextra-sidebar-container {
li > div { li > .hextra-sidebar-children {
@apply hx:h-0; @apply hx:h-0;
} }
li.open > div { li.open > .hextra-sidebar-children {
@apply hx:h-auto hx:pt-1; @apply hx:h-auto hx:pt-1;
} }
li.open > a > span > svg > path { li.open > .hextra-sidebar-item > .hextra-sidebar-collapsible-button > svg > path {
@apply hx:rotate-90; @apply hx:rotate-90;
} }
} }

View File

@@ -10,7 +10,7 @@
} }
.hextra-code-filename { .hextra-code-filename {
@apply hx:absolute hx:top-0 hx:z-[1] hx:w-full hx:truncate hx:rounded-t-xl hx:bg-primary-700/5 hx:py-2 hx:px-4 hx:text-xs hx:text-gray-700 hx:dark:bg-primary-300/10 hx:dark:text-gray-200; @apply hx:absolute hx:top-0 hx:z-1 hx:w-full hx:truncate hx:rounded-t-xl hx:bg-primary-700/5 hx:py-2 hx:px-4 hx:text-xs hx:text-gray-700 hx:dark:bg-primary-300/10 hx:dark:text-gray-200;
} }
.hextra-code-filename + pre:not(.lntable pre) { .hextra-code-filename + pre:not(.lntable pre) {

View File

@@ -43,6 +43,37 @@ body {
@apply hx:outline-none hx:ring-2 hx:ring-primary-200 hx:ring-offset-1 hx:ring-offset-primary-300 hx:dark:ring-primary-800 hx:dark:ring-offset-primary-700; @apply hx:outline-none hx:ring-2 hx:ring-primary-200 hx:ring-offset-1 hx:ring-offset-primary-300 hx:dark:ring-primary-800 hx:dark:ring-offset-primary-700;
} }
@utility hextra-focus-visible {
@apply hx:focus-visible:outline-none hx:focus-visible:ring-2 hx:focus-visible:ring-primary-200 hx:focus-visible:ring-offset-1 hx:focus-visible:ring-offset-primary-300 hx:dark:focus-visible:ring-primary-800 hx:dark:focus-visible:ring-offset-primary-700;
}
@utility hextra-focus-visible-inset {
@apply hx:focus-visible:outline-none hx:focus-visible:ring-inset hx:focus-visible:ring-2 hx:focus-visible:ring-primary-200 hx:dark:focus-visible:ring-primary-800 hx:focus-visible:ring-offset-0;
}
@layer base {
abbr:where([title]) {
cursor: help;
}
}
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
@layer base {
:where(a, button, [role="tab"], [role="menuitem"], [role="menuitemradio"], input, select, textarea, [tabindex="0"]):not(
[class*="hextra-focus-visible"]
):focus-visible {
@apply hx:hextra-focus;
}
}
@import "./typography.css"; @import "./typography.css";
@import "./highlight.css"; @import "./highlight.css";
@import "./components/cards.css"; @import "./components/cards.css";
@@ -57,3 +88,4 @@ body {
@import "./components/jupyter.css"; @import "./components/jupyter.css";
@import "./components/badge.css"; @import "./components/badge.css";
@import "./components/toc.css"; @import "./components/toc.css";
@import "./components/archives.css";

View File

@@ -30,22 +30,22 @@
@apply hx:bg-primary-700/5 hx:mb-4 hx:overflow-x-auto hx:rounded-xl hx:font-medium hx:subpixel-antialiased hx:dark:bg-primary-300/10 hx:text-[.9em] hx:contrast-more:border hx:contrast-more:border-primary-900/20 hx:contrast-more:contrast-150 hx:contrast-more:dark:border-primary-100/40 hx:py-4; @apply hx:bg-primary-700/5 hx:mb-4 hx:overflow-x-auto hx:rounded-xl hx:font-medium hx:subpixel-antialiased hx:dark:bg-primary-300/10 hx:text-[.9em] hx:contrast-more:border hx:contrast-more:border-primary-900/20 hx:contrast-more:contrast-150 hx:contrast-more:dark:border-primary-100/40 hx:py-4;
} }
:where(code):not(:where(.hextra-code-block code, [class~=not-prose],[class~=not-prose] *)) { :where(code):not(:where(.hextra-code-block code, [class~=not-prose],[class~=not-prose] *)) {
@apply hx:border-black/4 hx:bg-black/3 hx:break-words hx:rounded-md hx:border hx:py-0.5 hx:px-[.25em] hx:text-[.9em] hx:dark:border-white/10 hx:dark:bg-white/10; @apply hx:border-black/4 hx:bg-black/3 hx:wrap-break-word hx:rounded-md hx:border hx:py-0.5 hx:px-[.25em] hx:text-[.9em] hx:dark:border-white/10 hx:dark:bg-white/10;
} }
:where(table):not(:where(.hextra-code-block table, [class~=not-prose],[class~=not-prose] *)) { :where(table):not(:where(.hextra-code-block table, [class~=not-prose],[class~=not-prose] *)) {
@apply hx:block hx:overflow-x-auto hx:my-6 hx:p-0 hx:first:mt-0 hx:w-full hx:text-sm hx:leading-5; @apply hx:block hx:overflow-x-auto hx:my-6 hx:p-0 hx:first:mt-0 hx:w-full hx:text-sm hx:leading-5 hx:border-collapse;
thead { thead {
@apply hx:border-b hx:border-gray-200 hx:dark:border-neutral-800; @apply hx:bg-gray-50 hx:dark:bg-gray-600/20;
} }
tbody tr { tr {
@apply hx:m-0 hx:border-b hx:border-gray-100 hx:dark:border-neutral-800/50; @apply hx:m-0 hx:border-t hx:border-gray-300 hx:p-0 hx:dark:border-gray-600;
} }
th { th {
@apply hx:m-0 hx:p-2 hx:font-semibold hx:first:pl-0 hx:last:pr-0; @apply hx:m-0 hx:border hx:border-gray-300 hx:p-2 hx:font-semibold hx:dark:border-gray-600;
} }
td { td {
@apply hx:m-0 hx:p-2 hx:first:pl-0 hx:last:pr-0; @apply hx:m-0 hx:border hx:border-gray-300 hx:p-2 hx:dark:border-gray-600;
} }
} }
:where(ol):not(:where([class~=not-prose],[class~=not-prose] *)) { :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)) {
@@ -71,7 +71,7 @@
@apply hx:mt-0; @apply hx:mt-0;
} }
:where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)) { :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)) {
@apply hx:border-black/4 hx:bg-black/3 hx:break-words hx:rounded-md hx:border hx:py-0.5 hx:px-[.25em] hx:text-[.9em] hx:dark:border-white/10 hx:dark:bg-white/10; @apply hx:border-black/4 hx:bg-black/3 hx:wrap-break-word hx:rounded-md hx:border hx:py-0.5 hx:px-[.25em] hx:text-[.9em] hx:dark:border-white/10 hx:dark:bg-white/10;
} }
:where(pre.mermaid):not(:where(.hextra-code-block pre, [class~=not-prose],[class~=not-prose] *)) { :where(pre.mermaid):not(:where(.hextra-code-block pre, [class~=not-prose],[class~=not-prose] *)) {
@apply hx:bg-transparent hx:rounded-none hx:dark:bg-transparent; @apply hx:bg-transparent hx:rounded-none hx:dark:bg-transparent;
@@ -109,7 +109,7 @@
span:target + &, span:target + &,
:hover > &, :hover > &,
&:focus { &:focus-visible {
@apply hx:opacity-100; @apply hx:opacity-100;
} }

View File

@@ -1,18 +1,19 @@
/* Hugo template to derive CSS variables from site and page parameters */ /* Hugo template to derive CSS variables from site and page parameters */
/* Do not remove the following comment. It is used by Hugo to render CSS variables. /* Do not remove the following comment. It is used by Hugo to render CSS variables.
{{- $pageWidth := site.Params.page.width -}} {{- $layoutWidthValues := dict "normal" "80rem" "wide" "90rem" "full" "100%" -}}
{{- $maxPageWidth := cond (eq $pageWidth "wide") "90rem" (cond (eq $pageWidth "full") "100%" "80rem") -}} {{- $layoutWidthDefault := index $layoutWidthValues "normal" -}}
{{- $navbarWidth := site.Params.navbar.width -}} {{- $maxPageWidth := (index $layoutWidthValues (site.Params.page.width | default "normal")) | default $layoutWidthDefault -}}
{{- $maxNavbarWidth := cond (eq $navbarWidth "wide") "90rem" (cond (eq $navbarWidth "full") "100%" "80rem") -}} {{- $maxNavbarWidth := (index $layoutWidthValues (site.Params.navbar.width | default "normal")) | default $layoutWidthDefault -}}
{{- $maxFooterWidth := (index $layoutWidthValues (site.Params.footer.width | default "normal")) | default $layoutWidthDefault -}}
{{- $footerWidth := site.Params.footer.width -}} {{- $maxContentWidth := "72rem" -}}
{{- $maxFooterWidth := cond (eq $footerWidth "wide") "90rem" (cond (eq $footerWidth "full") "100%" "80rem") -}}
*/ */
:root { :root {
--hextra-max-page-width: {{ $maxPageWidth }}; --hextra-max-page-width: {{ $maxPageWidth }};
--hextra-max-content-width: {{ $maxContentWidth }};
--hextra-max-navbar-width: {{ $maxNavbarWidth }}; --hextra-max-navbar-width: {{ $maxNavbarWidth }};
--hextra-max-footer-width: {{ $maxFooterWidth }}; --hextra-max-footer-width: {{ $maxFooterWidth }};
} }
@@ -21,6 +22,10 @@
max-width: var(--hextra-max-page-width); max-width: var(--hextra-max-page-width);
} }
.hextra-max-content-width {
max-width: var(--hextra-max-content-width);
}
.hextra-max-navbar-width { .hextra-max-navbar-width {
max-width: var(--hextra-max-navbar-width); max-width: var(--hextra-max-navbar-width);
} }

View File

@@ -6,17 +6,20 @@ document.addEventListener("DOMContentLoaded", function () {
document.addEventListener("scroll", (e) => { document.addEventListener("scroll", (e) => {
if (window.scrollY > 300) { if (window.scrollY > 300) {
backToTop.classList.remove("hx:opacity-0"); backToTop.classList.remove("hx:opacity-0");
backToTop.removeAttribute("tabindex");
} else { } else {
backToTop.classList.add("hx:opacity-0"); backToTop.classList.add("hx:opacity-0");
backToTop.setAttribute("tabindex", "-1");
} }
}); });
} }
}); });
function scrollUp() { function scrollUp() {
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
window.scroll({ window.scroll({
top: 0, top: 0,
left: 0, left: 0,
behavior: "smooth", behavior: prefersReducedMotion ? 'auto' : 'smooth',
}); });
} }

View File

@@ -25,6 +25,27 @@ document.addEventListener('DOMContentLoaded', function () {
return svg; return svg;
} }
// Make scrollable code blocks focusable for keyboard users.
const updateScrollableCodeBlocks = () => {
document.querySelectorAll('.hextra-code-block pre, .highlight pre').forEach(function (pre) {
if (pre.scrollWidth > pre.clientWidth) {
pre.setAttribute('tabindex', '0');
} else {
pre.removeAttribute('tabindex');
}
});
};
updateScrollableCodeBlocks();
let resizeRaf;
window.addEventListener('resize', () => {
if (resizeRaf) {
cancelAnimationFrame(resizeRaf);
}
resizeRaf = requestAnimationFrame(updateScrollableCodeBlocks);
});
document.querySelectorAll('.hextra-code-copy-btn').forEach(function (button) { document.querySelectorAll('.hextra-code-copy-btn').forEach(function (button) {
// Add copy and success icons // Add copy and success icons
button.querySelector('.hextra-copy-icon')?.appendChild(getCopyIcon()); button.querySelector('.hextra-copy-icon')?.appendChild(getCopyIcon());
@@ -52,8 +73,12 @@ document.addEventListener('DOMContentLoaded', function () {
} }
navigator.clipboard.writeText(code).then(function () { navigator.clipboard.writeText(code).then(function () {
button.classList.add('copied'); button.classList.add('copied');
var originalLabel = button.getAttribute('aria-label');
var copiedLabel = button.dataset.copiedLabel || 'Copied!';
button.setAttribute('aria-label', copiedLabel);
setTimeout(function () { setTimeout(function () {
button.classList.remove('copied'); button.classList.remove('copied');
button.setAttribute('aria-label', originalLabel);
}, 1000); }, 1000);
}).catch(function (err) { }).catch(function (err) {
console.error('Failed to copy text: ', err); console.error('Failed to copy text: ', err);

View File

@@ -7,7 +7,9 @@ document.addEventListener("DOMContentLoaded", function () {
Array.from(folder.children).forEach(function (el) { Array.from(folder.children).forEach(function (el) {
el.dataset.state = el.dataset.state === "open" ? "closed" : "open"; el.dataset.state = el.dataset.state === "open" ? "closed" : "open";
}); });
folder.nextElementSibling.dataset.state = folder.nextElementSibling.dataset.state === "open" ? "closed" : "open"; var newState = folder.nextElementSibling.dataset.state === "open" ? "closed" : "open";
folder.nextElementSibling.dataset.state = newState;
folder.setAttribute('aria-expanded', newState === 'open' ? 'true' : 'false');
}); });
}); });
}); });

View File

@@ -1,25 +1,102 @@
(function () { (function () {
const languageSwitchers = document.querySelectorAll('.hextra-language-switcher'); const languageSwitchers = document.querySelectorAll('.hextra-language-switcher');
const closeSwitcher = (switcher, focusSwitcher = false) => {
switcher.dataset.state = 'closed';
switcher.setAttribute('aria-expanded', 'false');
const optionsElement = switcher.nextElementSibling;
optionsElement.classList.add('hx:hidden');
if (focusSwitcher) {
switcher.focus();
}
};
const openSwitcher = (switcher, focusTarget = "none") => {
switcher.dataset.state = 'open';
switcher.setAttribute('aria-expanded', 'true');
const optionsElement = switcher.nextElementSibling;
if (optionsElement.classList.contains('hx:hidden')) {
toggleMenu(switcher);
} else {
resizeMenu(switcher);
}
if (focusTarget !== "none") {
const items = Array.from(optionsElement.querySelectorAll('[role="menuitem"]'));
if (items.length > 0) {
const target = focusTarget === "last" ? items[items.length - 1] : items[0];
target.focus();
}
}
};
languageSwitchers.forEach((switcher) => { languageSwitchers.forEach((switcher) => {
switcher.addEventListener('click', (e) => { switcher.addEventListener('click', (e) => {
e.preventDefault(); e.preventDefault();
switcher.dataset.state = switcher.dataset.state === 'open' ? 'closed' : 'open'; if (switcher.dataset.state === 'open') {
closeSwitcher(switcher);
} else {
openSwitcher(switcher);
}
});
toggleMenu(switcher); switcher.addEventListener('keydown', (e) => {
if (e.key === 'ArrowDown') {
e.preventDefault();
openSwitcher(switcher, 'first');
} else if (e.key === 'ArrowUp') {
e.preventDefault();
openSwitcher(switcher, 'last');
}
}); });
}); });
window.addEventListener("resize", () => languageSwitchers.forEach(resizeMenu)) document.querySelectorAll('.hextra-language-options[role=menu]').forEach((menu) => {
menu.addEventListener('keydown', (e) => {
const items = Array.from(menu.querySelectorAll('[role="menuitem"]'));
if (items.length === 0) return;
// Dismiss language switcher when clicking outside const currentIndex = items.indexOf(document.activeElement);
let newIndex;
switch (e.key) {
case 'ArrowDown':
e.preventDefault();
newIndex = (currentIndex + 1) % items.length;
items[newIndex].focus();
break;
case 'ArrowUp':
e.preventDefault();
newIndex = (currentIndex - 1 + items.length) % items.length;
items[newIndex].focus();
break;
case 'Home':
e.preventDefault();
items[0].focus();
break;
case 'End':
e.preventDefault();
items[items.length - 1].focus();
break;
case 'Escape': {
e.preventDefault();
const switcher = menu.previousElementSibling;
if (switcher) {
closeSwitcher(switcher, true);
}
break;
}
}
});
});
window.addEventListener("resize", () => languageSwitchers.forEach(resizeMenu));
// Dismiss language switcher when clicking outside.
document.addEventListener('click', (e) => { document.addEventListener('click', (e) => {
if (e.target.closest('.hextra-language-switcher') === null) { if (!e.target.closest('.hextra-language-switcher') && !e.target.closest('.hextra-language-options')) {
languageSwitchers.forEach((switcher) => { languageSwitchers.forEach((switcher) => {
switcher.dataset.state = 'closed'; closeSwitcher(switcher);
const optionsElement = switcher.nextElementSibling;
optionsElement.classList.add('hx:hidden');
}); });
} }
}); });

View File

@@ -3,8 +3,28 @@
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
const menu = document.querySelector('.hextra-hamburger-menu'); const menu = document.querySelector('.hextra-hamburger-menu');
const sidebarContainer = document.querySelector('.hextra-sidebar-container'); const sidebarContainer = document.querySelector('.hextra-sidebar-container');
const mobileQuery = window.matchMedia('(max-width: 767px)');
function isMenuOpen() {
return menu.querySelector('svg').classList.contains('open');
}
// On mobile, the sidebar is off-screen so hide it from assistive tech
function syncAriaHidden() {
if (mobileQuery.matches) {
sidebarContainer.setAttribute('aria-hidden', isMenuOpen() ? 'false' : 'true');
} else {
sidebarContainer.removeAttribute('aria-hidden');
}
}
// Set initial state
syncAriaHidden();
mobileQuery.addEventListener('change', syncAriaHidden);
function toggleMenu(options = {}) {
const { focusOnOpen = true } = options;
function toggleMenu() {
// Toggle the hamburger menu // Toggle the hamburger menu
menu.querySelector('svg').classList.toggle('open'); menu.querySelector('svg').classList.toggle('open');
@@ -15,11 +35,35 @@ document.addEventListener('DOMContentLoaded', function () {
// When the menu is open, we want to prevent the body from scrolling // When the menu is open, we want to prevent the body from scrolling
document.body.classList.toggle('hx:overflow-hidden'); document.body.classList.toggle('hx:overflow-hidden');
document.body.classList.toggle('hx:md:overflow-auto'); document.body.classList.toggle('hx:md:overflow-auto');
// Sync aria-expanded and aria-hidden
const isOpen = isMenuOpen();
menu.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
syncAriaHidden();
// Move focus into sidebar when opening, restore when closing
if (isOpen) {
if (focusOnOpen) {
const firstFocusable = sidebarContainer.querySelector('a, button, input, [tabindex="0"]');
if (firstFocusable) firstFocusable.focus();
}
} else {
menu.focus();
}
} }
menu.addEventListener('click', (e) => { menu.addEventListener('click', (e) => {
e.preventDefault(); e.preventDefault();
toggleMenu(); // Pointer-initiated clicks on mobile should not force focus into the search input,
// which opens the software keyboard immediately.
toggleMenu({ focusOnOpen: e.detail === 0 });
});
// Close menu on Escape key (mobile only)
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && mobileQuery.matches && isMenuOpen()) {
toggleMenu();
}
}); });
// Select all anchor tags in the sidebar container // Select all anchor tags in the sidebar container

View File

@@ -1,61 +1,125 @@
(function () { (function () {
const hiddenClass = "hx:hidden"; const hiddenClass = "hx:hidden";
const dropdownToggles = document.querySelectorAll(".hextra-nav-menu-toggle"); const dropdownToggles = document.querySelectorAll(".hextra-nav-menu-toggle");
const closeDropdown = (toggle, focusToggle = false) => {
toggle.dataset.state = "closed";
toggle.setAttribute("aria-expanded", "false");
const menuItemsElement = toggle.nextElementSibling;
menuItemsElement.classList.add(hiddenClass);
if (focusToggle) {
toggle.focus();
}
};
const openDropdown = (toggle, focusTarget = "none") => {
// Close all other dropdowns first.
dropdownToggles.forEach((otherToggle) => {
if (otherToggle !== toggle) {
closeDropdown(otherToggle);
}
});
toggle.dataset.state = "open";
toggle.setAttribute("aria-expanded", "true");
const menuItemsElement = toggle.nextElementSibling;
// Position dropdown centered with toggle.
menuItemsElement.style.position = "absolute";
menuItemsElement.style.top = "100%";
menuItemsElement.style.left = "50%";
menuItemsElement.style.transform = "translateX(-50%)";
menuItemsElement.style.zIndex = "1000";
menuItemsElement.classList.remove(hiddenClass);
if (focusTarget !== "none") {
const items = Array.from(menuItemsElement.querySelectorAll('[role="menuitem"]'));
if (items.length > 0) {
const target = focusTarget === "last" ? items[items.length - 1] : items[0];
target.focus();
}
}
};
dropdownToggles.forEach((toggle) => { dropdownToggles.forEach((toggle) => {
toggle.addEventListener("click", (e) => { toggle.addEventListener("click", (e) => {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
// Close all other dropdowns first // Toggle current dropdown.
dropdownToggles.forEach((otherToggle) => {
if (otherToggle !== toggle) {
otherToggle.dataset.state = "closed";
const otherMenuItems = otherToggle.nextElementSibling;
otherMenuItems.classList.add(hiddenClass);
}
});
// Toggle current dropdown
const isOpen = toggle.dataset.state === "open"; const isOpen = toggle.dataset.state === "open";
toggle.dataset.state = isOpen ? "closed" : "open"; if (isOpen) {
const menuItemsElement = toggle.nextElementSibling; closeDropdown(toggle);
if (!isOpen) {
// Position dropdown centered with toggle
menuItemsElement.style.position = "absolute";
menuItemsElement.style.top = "100%";
menuItemsElement.style.left = "50%";
menuItemsElement.style.transform = "translateX(-50%)";
menuItemsElement.style.zIndex = "1000";
// Show dropdown
menuItemsElement.classList.remove(hiddenClass);
} else { } else {
// Hide dropdown openDropdown(toggle);
menuItemsElement.classList.add(hiddenClass); }
});
toggle.addEventListener("keydown", (e) => {
if (e.key === "ArrowDown") {
e.preventDefault();
openDropdown(toggle, "first");
} else if (e.key === "ArrowUp") {
e.preventDefault();
openDropdown(toggle, "last");
} }
}); });
}); });
// Dismiss dropdown when clicking outside document.querySelectorAll(".hextra-nav-menu-items[role=menu]").forEach((menu) => {
menu.addEventListener("keydown", (e) => {
const items = Array.from(menu.querySelectorAll('[role="menuitem"]'));
if (items.length === 0) return;
const currentIndex = items.indexOf(document.activeElement);
let newIndex;
switch (e.key) {
case "ArrowDown":
e.preventDefault();
newIndex = (currentIndex + 1) % items.length;
items[newIndex].focus();
break;
case "ArrowUp":
e.preventDefault();
newIndex = (currentIndex - 1 + items.length) % items.length;
items[newIndex].focus();
break;
case "Home":
e.preventDefault();
items[0].focus();
break;
case "End":
e.preventDefault();
items[items.length - 1].focus();
break;
case "Escape": {
e.preventDefault();
const toggle = menu.previousElementSibling;
if (toggle) {
closeDropdown(toggle, true);
}
break;
}
}
});
});
// Dismiss dropdown when clicking outside.
document.addEventListener("click", (e) => { document.addEventListener("click", (e) => {
if (e.target.closest(".hextra-nav-menu-toggle") === null) { if (!e.target.closest(".hextra-nav-menu-toggle") && !e.target.closest(".hextra-nav-menu-items")) {
dropdownToggles.forEach((toggle) => { dropdownToggles.forEach((toggle) => {
toggle.dataset.state = "closed"; closeDropdown(toggle);
const menuItemsElement = toggle.nextElementSibling;
menuItemsElement.classList.add(hiddenClass);
}); });
} }
}); });
// Close dropdowns on escape key // Close dropdowns on escape key.
document.addEventListener("keydown", (e) => { document.addEventListener("keydown", (e) => {
if (e.key === "Escape") { if (e.key === "Escape") {
dropdownToggles.forEach((toggle) => { dropdownToggles.forEach((toggle) => {
toggle.dataset.state = "closed"; if (toggle.dataset.state === "open") {
const menuItemsElement = toggle.nextElementSibling; closeDropdown(toggle, true);
menuItemsElement.classList.add(hiddenClass); }
}); });
} }
}); });

View File

@@ -0,0 +1,172 @@
document.addEventListener('DOMContentLoaded', () => {
// Pre-fetch markdown content for all copy buttons to avoid Safari NotAllowedError
// Safari requires clipboard writes to happen synchronously within user gesture
const copyButtons = document.querySelectorAll('.hextra-page-context-menu-copy');
const contentCache = new Map();
// Pre-fetch content for each button on page load
copyButtons.forEach(button => {
const url = button.dataset.url;
if (url) {
fetch(url)
.then(response => {
if (response.ok) return response.text();
throw new Error('Failed to fetch');
})
.then(markdown => contentCache.set(url, markdown))
.catch(error => console.error('Failed to pre-fetch markdown:', error));
}
});
// Initialize copy buttons with synchronous clipboard access
copyButtons.forEach(button => {
button.addEventListener('click', () => {
const url = button.dataset.url;
const markdown = contentCache.get(url);
if (markdown) {
// Synchronous clipboard write initiation - works in Safari
navigator.clipboard.writeText(markdown)
.then(() => {
button.classList.add('copied');
setTimeout(() => button.classList.remove('copied'), 1000);
})
.catch(error => console.error('Failed to copy markdown:', error));
} else {
// Fallback: fetch and copy (may fail in Safari if content not pre-fetched)
fetch(url)
.then(response => {
if (!response.ok) throw new Error('Failed to fetch');
return response.text();
})
.then(text => {
contentCache.set(url, text);
return navigator.clipboard.writeText(text);
})
.then(() => {
button.classList.add('copied');
setTimeout(() => button.classList.remove('copied'), 1000);
})
.catch(error => console.error('Failed to copy markdown:', error));
}
});
});
// Initialize dropdown toggles
const dropdownToggles = document.querySelectorAll('.hextra-page-context-menu-toggle');
dropdownToggles.forEach(toggle => {
const container = toggle.closest('.hextra-page-context-menu');
const menu = container.querySelector('.hextra-page-context-menu-dropdown');
const chevron = toggle.querySelector('[data-chevron]');
toggle.addEventListener('click', (e) => {
e.stopPropagation();
const isOpen = toggle.dataset.state === 'open';
// Close all other dropdowns first
dropdownToggles.forEach(t => {
if (t !== toggle) {
t.dataset.state = 'closed';
t.setAttribute('aria-expanded', 'false');
const otherContainer = t.closest('.hextra-page-context-menu');
const otherMenu = otherContainer.querySelector('.hextra-page-context-menu-dropdown');
const otherChevron = t.querySelector('[data-chevron]');
otherMenu.classList.add('hx:hidden');
if (otherChevron) {
otherChevron.style.transform = '';
}
}
});
// Toggle current
toggle.dataset.state = isOpen ? 'closed' : 'open';
toggle.setAttribute('aria-expanded', isOpen ? 'false' : 'true');
menu.classList.toggle('hx:hidden', isOpen);
// Rotate chevron icon
if (chevron) {
chevron.style.transform = isOpen ? '' : 'rotate(180deg)';
}
});
});
// Close dropdown when clicking outside
document.addEventListener('click', (e) => {
// Check if click is outside any dropdown container
const isOutside = !e.target.closest('.hextra-page-context-menu');
if (isOutside) {
dropdownToggles.forEach(toggle => {
toggle.dataset.state = 'closed';
toggle.setAttribute('aria-expanded', 'false');
const container = toggle.closest('.hextra-page-context-menu');
const menu = container.querySelector('.hextra-page-context-menu-dropdown');
const chevron = toggle.querySelector('[data-chevron]');
menu.classList.add('hx:hidden');
if (chevron) {
chevron.style.transform = '';
}
});
}
});
// Close dropdown on Escape key and return focus to toggle
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
dropdownToggles.forEach(toggle => {
if (toggle.dataset.state === 'open') {
const container = toggle.closest('.hextra-page-context-menu');
closeDropdown(container);
toggle.focus();
}
});
}
});
// Helper to close dropdown
const closeDropdown = (container) => {
if (!container) return;
const toggle = container.querySelector('.hextra-page-context-menu-toggle');
const menu = container.querySelector('.hextra-page-context-menu-dropdown');
if (!toggle || !menu) return;
const chevron = toggle.querySelector('[data-chevron]');
toggle.dataset.state = 'closed';
toggle.setAttribute('aria-expanded', 'false');
menu.classList.add('hx:hidden');
if (chevron) {
chevron.style.transform = '';
}
};
// Handle dropdown menu copy action
document.querySelectorAll('.hextra-page-context-menu-dropdown button[data-action="copy"]').forEach(btn => {
btn.addEventListener('click', async (e) => {
e.stopPropagation();
const container = btn.closest('.hextra-page-context-menu');
if (!container) return;
const copyBtn = container.querySelector('.hextra-page-context-menu-copy');
if (!copyBtn) return;
closeDropdown(container);
copyBtn.click();
});
});
// Handle dropdown menu view action
document.querySelectorAll('.hextra-page-context-menu-dropdown button[data-action="view"]').forEach(btn => {
btn.addEventListener('click', (e) => {
e.stopPropagation();
const container = btn.closest('.hextra-page-context-menu');
if (!container) return;
const url = btn.dataset.url;
if (!url) return;
closeDropdown(container);
window.open(url, '_blank', 'noopener,noreferrer');
});
});
});

View File

@@ -8,9 +8,10 @@ function enableCollapsibles() {
buttons.forEach(function (button) { buttons.forEach(function (button) {
button.addEventListener("click", function (e) { button.addEventListener("click", function (e) {
e.preventDefault(); e.preventDefault();
const list = button.parentElement.parentElement; const list = button.closest('li');
if (list) { if (list) {
list.classList.toggle("open") list.classList.toggle("open");
button.setAttribute('aria-expanded', list.classList.contains('open') ? 'true' : 'false');
} }
}); });
}); });

View File

@@ -7,14 +7,15 @@
tab.setAttribute('aria-selected', 'true'); tab.setAttribute('aria-selected', 'true');
tab.tabIndex = 0; tab.tabIndex = 0;
} else { } else {
tab.removeAttribute('aria-selected'); tab.setAttribute('aria-selected', 'false');
tab.removeAttribute('tabindex'); tab.tabIndex = -1;
} }
}); });
const panelsContainer = container.parentElement.nextElementSibling; const panelsContainer = container.parentElement.nextElementSibling;
if (!panelsContainer) return; if (!panelsContainer) return;
Array.from(panelsContainer.children).forEach((panel, i) => { Array.from(panelsContainer.children).forEach((panel, i) => {
panel.dataset.state = i === index ? 'selected' : ''; panel.dataset.state = i === index ? 'selected' : '';
panel.setAttribute('aria-hidden', i === index ? 'false' : 'true');
if (i === index) { if (i === index) {
panel.tabIndex = 0; panel.tabIndex = 0;
} else { } else {
@@ -35,11 +36,12 @@
document.querySelectorAll('.hextra-tabs-toggle').forEach((button) => { document.querySelectorAll('.hextra-tabs-toggle').forEach((button) => {
button.addEventListener('click', function (e) { button.addEventListener('click', function (e) {
const container = e.target.parentElement; const targetButton = e.currentTarget;
const container = targetButton.parentElement;
const index = Array.from(container.querySelectorAll('.hextra-tabs-toggle')).indexOf( const index = Array.from(container.querySelectorAll('.hextra-tabs-toggle')).indexOf(
e.target targetButton
); );
if (container.dataset.tabGroup) { if (container.dataset.tabGroup) {
// Sync behavior: update all tab groups with the same name // Sync behavior: update all tab groups with the same name
const tabGroupValue = container.dataset.tabGroup; const tabGroupValue = container.dataset.tabGroup;
@@ -53,5 +55,48 @@
updateGroup(container, index); updateGroup(container, index);
} }
}); });
// Keyboard navigation for tabs
button.addEventListener('keydown', function (e) {
const container = button.parentElement;
const tabs = Array.from(container.querySelectorAll('.hextra-tabs-toggle'));
const currentIndex = tabs.indexOf(button);
let newIndex;
switch (e.key) {
case 'ArrowRight':
case 'ArrowDown':
e.preventDefault();
newIndex = (currentIndex + 1) % tabs.length;
break;
case 'ArrowLeft':
case 'ArrowUp':
e.preventDefault();
newIndex = (currentIndex - 1 + tabs.length) % tabs.length;
break;
case 'Home':
e.preventDefault();
newIndex = 0;
break;
case 'End':
e.preventDefault();
newIndex = tabs.length - 1;
break;
default:
return;
}
if (container.dataset.tabGroup) {
const tabGroupValue = container.dataset.tabGroup;
const key = encodeURIComponent(tabGroupValue);
document
.querySelectorAll('[data-tab-group="' + tabGroupValue + '"]')
.forEach((grp) => updateGroup(grp, newIndex));
localStorage.setItem('hextra-tab-' + key, newIndex.toString());
} else {
updateGroup(container, newIndex);
}
tabs[newIndex].focus();
});
}); });
})(); })();

View File

@@ -0,0 +1,15 @@
document.addEventListener("DOMContentLoaded", function () {
// Hugo task lists render bare checkboxes; provide an accessible name.
document.querySelectorAll("main#content li > input[type='checkbox']").forEach(function (checkbox) {
if (checkbox.hasAttribute("aria-label") || checkbox.hasAttribute("aria-labelledby")) {
return;
}
var listItem = checkbox.closest("li");
if (!listItem) return;
var labelText = listItem.textContent.replace(/\s+/g, " ").trim();
if (labelText) {
checkbox.setAttribute("aria-label", labelText);
}
});
});

View File

@@ -4,12 +4,15 @@
const themes = ["light", "dark"]; const themes = ["light", "dark"];
const themeToggleButtons = document.querySelectorAll(".hextra-theme-toggle"); const themeToggleButtons = document.querySelectorAll(".hextra-theme-toggle");
const themeToggleOptions = document.querySelectorAll(".hextra-theme-toggle-options p"); const themeToggleOptions = document.querySelectorAll(".hextra-theme-toggle-options button[role=menuitemradio]");
function applyTheme(theme) { function applyTheme(theme) {
theme = themes.includes(theme) ? theme : "system"; theme = themes.includes(theme) ? theme : "system";
themeToggleButtons.forEach((btn) => btn.parentElement.dataset.theme = theme ); themeToggleButtons.forEach((btn) => btn.parentElement.dataset.theme = theme );
themeToggleOptions.forEach((option) => {
option.setAttribute('aria-checked', option.dataset.item === theme ? 'true' : 'false');
});
localStorage.setItem("color-theme", theme); localStorage.setItem("color-theme", theme);
} }
@@ -36,7 +39,16 @@
toggler.addEventListener("click", function (e) { toggler.addEventListener("click", function (e) {
e.preventDefault(); e.preventDefault();
toggler.dataset.state = toggler.dataset.state === 'open' ? 'closed' : 'open';
toggleMenu(toggler); toggleMenu(toggler);
const isOpen = toggler.dataset.state === 'open';
toggler.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
// Focus first menuitem when opening
if (isOpen) {
const firstItem = toggler.nextElementSibling.querySelector('button[role=menuitemradio]');
if (firstItem) firstItem.focus();
}
}); });
}); });
@@ -47,11 +59,50 @@
if (e.target.closest('.hextra-theme-toggle') === null) { if (e.target.closest('.hextra-theme-toggle') === null) {
themeToggleButtons.forEach((toggler) => { themeToggleButtons.forEach((toggler) => {
toggler.dataset.state = 'closed'; toggler.dataset.state = 'closed';
toggler.setAttribute('aria-expanded', 'false');
toggler.nextElementSibling.classList.add('hx:hidden'); toggler.nextElementSibling.classList.add('hx:hidden');
}); });
} }
}); });
// Keyboard navigation for the theme menu
document.querySelectorAll('.hextra-theme-toggle-options[role=menu]').forEach(function (menu) {
menu.addEventListener('keydown', function (e) {
const items = Array.from(menu.querySelectorAll('button[role=menuitemradio]'));
const currentIndex = items.indexOf(document.activeElement);
let newIndex;
switch (e.key) {
case 'ArrowDown':
e.preventDefault();
newIndex = (currentIndex + 1) % items.length;
items[newIndex].focus();
break;
case 'ArrowUp':
e.preventDefault();
newIndex = (currentIndex - 1 + items.length) % items.length;
items[newIndex].focus();
break;
case 'Home':
e.preventDefault();
items[0].focus();
break;
case 'End':
e.preventDefault();
items[items.length - 1].focus();
break;
case 'Escape':
e.preventDefault();
var toggler = menu.previousElementSibling;
toggler.dataset.state = 'closed';
toggler.setAttribute('aria-expanded', 'false');
menu.classList.add('hx:hidden');
toggler.focus();
break;
}
});
});
// Listen for system theme changes // Listen for system theme changes
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", () => { window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", () => {
if (localStorage.getItem("color-theme") === "system") { if (localStorage.getItem("color-theme") === "system") {

View File

@@ -47,10 +47,12 @@ document.addEventListener("DOMContentLoaded", function () {
// Remove active class from previous link // Remove active class from previous link
if (currentActiveLink) { if (currentActiveLink) {
currentActiveLink.classList.remove("hextra-toc-active"); currentActiveLink.classList.remove("hextra-toc-active");
currentActiveLink.removeAttribute("aria-current");
} }
// Add active class to current link // Add active class to current link
targetLink.classList.add("hextra-toc-active"); targetLink.classList.add("hextra-toc-active");
targetLink.setAttribute("aria-current", "location");
currentActiveLink = targetLink; currentActiveLink = targetLink;
} }
}, },
@@ -74,8 +76,10 @@ document.addEventListener("DOMContentLoaded", function () {
if (currentActiveLink) { if (currentActiveLink) {
currentActiveLink.classList.remove("hextra-toc-active"); currentActiveLink.classList.remove("hextra-toc-active");
currentActiveLink.removeAttribute("aria-current");
} }
targetLink.classList.add("hextra-toc-active"); targetLink.classList.add("hextra-toc-active");
targetLink.setAttribute("aria-current", "location");
currentActiveLink = targetLink; currentActiveLink = targetLink;
// Re-enable observer after scroll settles // Re-enable observer after scroll settles

View File

@@ -21,6 +21,7 @@ document.addEventListener("DOMContentLoaded", function () {
(function () { (function () {
const searchDataURL = '{{ $searchData.RelPermalink }}'; const searchDataURL = '{{ $searchData.RelPermalink }}';
const resultsFoundTemplate = '{{ (T "resultsFound") | default "%d results found" }}';
const inputElements = document.querySelectorAll('.hextra-search-input'); const inputElements = document.querySelectorAll('.hextra-search-input');
for (const el of inputElements) { for (const el of inputElements) {
@@ -318,7 +319,10 @@ document.addEventListener("DOMContentLoaded", function () {
} }
resultsElement.classList.remove('hx:hidden'); resultsElement.classList.remove('hx:hidden');
const pageResults = window.pageIndex.search(query, 5, { enrich: true, suggest: true })[0]?.result || []; // Configurable search limits with sensible defaults
const maxPageResults = parseInt('{{- site.Params.search.flexsearch.maxPageResults | default 20 -}}', 10);
const maxSectionResults = parseInt('{{- site.Params.search.flexsearch.maxSectionResults | default 10 -}}', 10);
const pageResults = window.pageIndex.search(query, maxPageResults, { enrich: true, suggest: true })[0]?.result || [];
const results = []; const results = [];
const pageTitleMatches = {}; const pageTitleMatches = {};
@@ -327,12 +331,13 @@ document.addEventListener("DOMContentLoaded", function () {
const result = pageResults[i]; const result = pageResults[i];
pageTitleMatches[i] = 0; pageTitleMatches[i] = 0;
// Show the top 5 results for each page const sectionResults = window.sectionIndex.search(query,
const sectionResults = window.sectionIndex.search(query, 5, { enrich: true, suggest: true, tag: { 'pageId': `page_${result.id}` } })[0]?.result || []; { enrich: true, suggest: true, tag: { 'pageId': `page_${result.id}` } })[0]?.result || [];
let isFirstItemOfPage = true let isFirstItemOfPage = true
const occurred = {} const occurred = {}
for (let j = 0; j < sectionResults.length; j++) { const nResults = Math.min(sectionResults.length, maxSectionResults);
for (let j = 0; j < nResults; j++) {
const { doc } = sectionResults[j] const { doc } = sectionResults[j]
const isMatchingTitle = doc.display !== undefined const isMatchingTitle = doc.display !== undefined
if (isMatchingTitle) { if (isMatchingTitle) {
@@ -385,21 +390,45 @@ document.addEventListener("DOMContentLoaded", function () {
if (!results.length) { if (!results.length) {
resultsElement.innerHTML = `<span class="hextra-search-no-result">{{ $noResultsFound | safeHTML }}</span>`; resultsElement.innerHTML = `<span class="hextra-search-no-result">{{ $noResultsFound | safeHTML }}</span>`;
// Announce no results to screen readers
const wrapper = resultsElement.closest('.hextra-search-wrapper');
const statusEl = wrapper ? wrapper.querySelector('.hextra-search-status') : null;
if (statusEl) {
statusEl.textContent = '{{ $noResultsFound | safeHTML }}';
}
return; return;
} }
// Highlight the query in the result text. // Append text with highlighted matches using safe text nodes.
function highlightMatches(text, query) { function appendHighlightedText(container, text, query) {
const escapedQuery = query.replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&'); if (!text) return;
const regex = new RegExp(escapedQuery, 'gi'); if (!query) {
return text.replace(regex, (match) => `<span class="hextra-search-match">${match}</span>`); container.textContent = text;
} return;
}
// Create a DOM element from the HTML string. const escapedQuery = query.replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&');
function createElement(str) { if (!escapedQuery) {
const div = document.createElement('div'); container.textContent = text;
div.innerHTML = str.trim(); return;
return div.firstChild; }
const regex = new RegExp(escapedQuery, 'gi');
let lastIndex = 0;
let match;
while ((match = regex.exec(text)) !== null) {
if (match.index > lastIndex) {
container.appendChild(document.createTextNode(text.slice(lastIndex, match.index)));
}
const span = document.createElement('span');
span.className = 'hextra-search-match';
span.textContent = match[0];
container.appendChild(span);
lastIndex = match.index + match[0].length;
}
if (lastIndex < text.length) {
container.appendChild(document.createTextNode(text.slice(lastIndex)));
}
} }
function handleMouseMove(e) { function handleMouseMove(e) {
@@ -417,23 +446,47 @@ document.addEventListener("DOMContentLoaded", function () {
for (let i = 0; i < results.length; i++) { for (let i = 0; i < results.length; i++) {
const result = results[i]; const result = results[i];
if (result.prefix) { if (result.prefix) {
fragment.appendChild(createElement(` const prefix = document.createElement('div');
<div class="hextra-search-prefix">${result.prefix}</div>`)); prefix.className = 'hextra-search-prefix';
prefix.textContent = result.prefix;
fragment.appendChild(prefix);
} }
let li = createElement(` const li = document.createElement('li');
<li> const link = document.createElement('a');
<a data-index="${i}" href="${result.route}" class=${i === 0 ? "hextra-search-active" : ""}> link.dataset.index = i;
<div class="hextra-search-title">`+ highlightMatches(result.children.title, query) + `</div>` + link.href = result.route;
(result.children.content ? if (i === 0) {
`<div class="hextra-search-excerpt">` + highlightMatches(result.children.content, query) + `</div>` : '') + ` link.classList.add('hextra-search-active');
</a> }
</li>`);
const title = document.createElement('div');
title.className = 'hextra-search-title';
appendHighlightedText(title, result.children.title, query);
link.appendChild(title);
if (result.children.content) {
const excerpt = document.createElement('div');
excerpt.className = 'hextra-search-excerpt';
appendHighlightedText(excerpt, result.children.content, query);
link.appendChild(excerpt);
}
li.appendChild(link);
li.addEventListener('mousemove', handleMouseMove); li.addEventListener('mousemove', handleMouseMove);
li.addEventListener('keydown', handleKeyDown); li.addEventListener('keydown', handleKeyDown);
li.querySelector('a').addEventListener('click', finishSearch); link.addEventListener('click', finishSearch);
fragment.appendChild(li); fragment.appendChild(li);
} }
resultsElement.appendChild(fragment); resultsElement.appendChild(fragment);
resultsElement.dataset.count = results.length; resultsElement.dataset.count = results.length;
// Announce results count to screen readers
const wrapper = resultsElement.closest('.hextra-search-wrapper');
const statusEl = wrapper ? wrapper.querySelector('.hextra-search-status') : null;
if (statusEl) {
statusEl.textContent = results.length > 0
? resultsFoundTemplate.replace('%d', results.length.toString())
: '{{ $noResultsFound | safeHTML }}';
}
} }
})(); })();

View File

@@ -18,4 +18,20 @@
{{- $output = $output | merge (dict $pageLink (dict "title" $pageTitle "data" $data)) -}} {{- $output = $output | merge (dict $pageLink (dict "title" $pageTitle "data" $data)) -}}
{{- end -}} {{- end -}}
{{/* Extract glossary data entries */}}
{{- $glossaryEntries := dict -}}
{{- with (index .Site.Data .Site.Language.Lang "termbase") -}}
{{- range . -}}
{{- $entry := cond (.abbr) (printf "%s %s %s" .abbr .term .definition) (printf "%s %s" .term .definition) -}}
{{- $glossaryEntries = $glossaryEntries | merge (dict .term $entry) -}}
{{- end -}}
{{- end -}}
{{- $glossary := dict
"title" "Glossary"
"data" $glossaryEntries
-}}
{{- $output = $output | merge (dict (relLangURL "glossary") $glossary )}}
{{- $output | jsonify -}} {{- $output | jsonify -}}

View File

@@ -9,11 +9,11 @@ echo "Using base URL: $BASE_URL"
# Version configuration - modify these arrays to specify versions to build # Version configuration - modify these arrays to specify versions to build
# MAIN_VERSION format: "ref:display_name:source_dir" # MAIN_VERSION format: "ref:display_name:source_dir"
# VERSIONS format: "ref:display_name:source_dir" where source_dir is either "docs" or "exampleSite" # VERSIONS format: "ref:display_name:source_dir" where source_dir is either "docs" or "exampleSite"
MAIN_VERSION="v0.11.1:latest:docs" MAIN_VERSION="v0.12.1:latest:docs"
VERSIONS=( VERSIONS=(
"main:latest:docs" # latest version always builds from main "main:latest:docs" # latest version always builds from main
"v0.10.2:v0.10:exampleSite" "v0.11.3:v0.11:docs"
"v0.9.6:v0.9:exampleSite" "v0.10.3:v0.10:exampleSite"
) )
# Parse main version # Parse main version

View File

@@ -305,3 +305,8 @@ linkedin: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill
slack: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M5.042 15.165a2.528 2.528 0 0 1-2.52 2.523A2.528 2.528 0 0 1 0 15.165a2.527 2.527 0 0 1 2.522-2.52h2.52zm1.271 0a2.527 2.527 0 0 1 2.521-2.52a2.527 2.527 0 0 1 2.521 2.52v6.313A2.528 2.528 0 0 1 8.834 24a2.528 2.528 0 0 1-2.521-2.522zM8.834 5.042a2.528 2.528 0 0 1-2.521-2.52A2.528 2.528 0 0 1 8.834 0a2.528 2.528 0 0 1 2.521 2.522v2.52zm0 1.271a2.528 2.528 0 0 1 2.521 2.521a2.528 2.528 0 0 1-2.521 2.521H2.522A2.528 2.528 0 0 1 0 8.834a2.528 2.528 0 0 1 2.522-2.521zm10.122 2.521a2.528 2.528 0 0 1 2.522-2.521A2.528 2.528 0 0 1 24 8.834a2.528 2.528 0 0 1-2.522 2.521h-2.522zm-1.268 0a2.528 2.528 0 0 1-2.523 2.521a2.527 2.527 0 0 1-2.52-2.521V2.522A2.527 2.527 0 0 1 15.165 0a2.528 2.528 0 0 1 2.523 2.522zm-2.523 10.122a2.528 2.528 0 0 1 2.523 2.522A2.528 2.528 0 0 1 15.165 24a2.527 2.527 0 0 1-2.52-2.522v-2.522zm0-1.268a2.527 2.527 0 0 1-2.52-2.523a2.526 2.526 0 0 1 2.52-2.52h6.313A2.527 2.527 0 0 1 24 15.165a2.528 2.528 0 0 1-2.522 2.523z" /></svg> slack: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M5.042 15.165a2.528 2.528 0 0 1-2.52 2.523A2.528 2.528 0 0 1 0 15.165a2.527 2.527 0 0 1 2.522-2.52h2.52zm1.271 0a2.527 2.527 0 0 1 2.521-2.52a2.527 2.527 0 0 1 2.521 2.52v6.313A2.528 2.528 0 0 1 8.834 24a2.528 2.528 0 0 1-2.521-2.522zM8.834 5.042a2.528 2.528 0 0 1-2.521-2.52A2.528 2.528 0 0 1 8.834 0a2.528 2.528 0 0 1 2.521 2.522v2.52zm0 1.271a2.528 2.528 0 0 1 2.521 2.521a2.528 2.528 0 0 1-2.521 2.521H2.522A2.528 2.528 0 0 1 0 8.834a2.528 2.528 0 0 1 2.522-2.521zm10.122 2.521a2.528 2.528 0 0 1 2.522-2.521A2.528 2.528 0 0 1 24 8.834a2.528 2.528 0 0 1-2.522 2.521h-2.522zm-1.268 0a2.528 2.528 0 0 1-2.523 2.521a2.527 2.527 0 0 1-2.52-2.521V2.522A2.527 2.527 0 0 1 15.165 0a2.528 2.528 0 0 1 2.523 2.522zm-2.523 10.122a2.528 2.528 0 0 1 2.523 2.522A2.528 2.528 0 0 1 15.165 24a2.527 2.527 0 0 1-2.52-2.522v-2.522zm0-1.268a2.527 2.527 0 0 1-2.52-2.523a2.526 2.526 0 0 1 2.52-2.52h6.313A2.527 2.527 0 0 1 24 15.165a2.528 2.528 0 0 1-2.522 2.523z" /></svg>
bluesky: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 530"><path fill="currentColor" d="M136 44c66 50 138 151 164 205 26-54 98-155 164-205 48-36 126-64 126 25 0 18-10 149-16 170-21 74-96 93-163 81 117 20 147 86 82 153-122 125-176-32-189-72-3-8-4-11-4-8 0-3-1 0-4 8-13 40-67 197-189 72-65-67-35-133 82-153-67 12-142-7-163-81-6-21-16-152-16-170 0-89 78-61 126-25z"/></svg> bluesky: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 530"><path fill="currentColor" d="M136 44c66 50 138 151 164 205 26-54 98-155 164-205 48-36 126-64 126 25 0 18-10 149-16 170-21 74-96 93-163 81 117 20 147 86 82 153-122 125-176-32-189-72-3-8-4-11-4-8 0-3-1 0-4 8-13 40-67 197-189 72-65-67-35-133 82-153-67 12-142-7-163-81-6-21-16-152-16-170 0-89 78-61 126-25z"/></svg>
telegram: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path fill="currentColor" d="M248 8C111.033 8 0 119.033 0 256s111.033 248 248 248 248-111.033 248-248S384.967 8 248 8m114.952 168.66c-3.732 39.215-19.881 134.378-28.1 178.3-3.476 18.584-10.322 24.816-16.948 25.425-14.4 1.326-25.338-9.517-39.287-18.661-21.827-14.308-34.158-23.215-55.346-37.177-24.485-16.135-8.612-25 5.342-39.5 3.652-3.793 67.107-61.51 68.335-66.746.153-.655.3-3.1-1.154-4.384s-3.59-.849-5.135-.5q-3.283.746-104.608 69.142-14.845 10.194-26.894 9.934c-8.855-.191-25.888-5.006-38.551-9.123-15.531-5.048-27.875-7.717-26.8-16.291q.84-6.7 18.45-13.7 108.446-47.248 144.628-62.3c68.872-28.647 83.183-33.623 92.511-33.789 2.052-.034 6.639.474 9.61 2.885a10.45 10.45 0 0 1 3.53 6.716 43.8 43.8 0 0 1 .417 9.769"/></svg> telegram: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path fill="currentColor" d="M248 8C111.033 8 0 119.033 0 256s111.033 248 248 248 248-111.033 248-248S384.967 8 248 8m114.952 168.66c-3.732 39.215-19.881 134.378-28.1 178.3-3.476 18.584-10.322 24.816-16.948 25.425-14.4 1.326-25.338-9.517-39.287-18.661-21.827-14.308-34.158-23.215-55.346-37.177-24.485-16.135-8.612-25 5.342-39.5 3.652-3.793 67.107-61.51 68.335-66.746.153-.655.3-3.1-1.154-4.384s-3.59-.849-5.135-.5q-3.283.746-104.608 69.142-14.845 10.194-26.894 9.934c-8.855-.191-25.888-5.006-38.551-9.123-15.531-5.048-27.875-7.717-26.8-16.291q.84-6.7 18.45-13.7 108.446-47.248 144.628-62.3c68.872-28.647 83.183-33.623 92.511-33.789 2.052-.034 6.639.474 9.61 2.885a10.45 10.45 0 0 1 3.53 6.716 43.8 43.8 0 0 1 .417 9.769"/></svg>
# ai
claude: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 257"><path fill="currentColor" d="m50.228 170.321 50.357-28.257.843-2.463-.843-1.361h-2.462l-8.426-.518-28.775-.778-24.952-1.037-24.175-1.296-6.092-1.297L0 125.796l.583-3.759 5.12-3.434 7.324.648 16.202 1.101 24.304 1.685 17.629 1.037 26.118 2.722h4.148l.583-1.685-1.426-1.037-1.101-1.037-25.147-17.045-27.22-18.017-14.258-10.37-7.713-5.25-3.888-4.925-1.685-10.758 7-7.713 9.397.649 2.398.648 9.527 7.323 20.35 15.75L94.817 91.9l3.889 3.24 1.555-1.102.195-.777-1.75-2.917-14.453-26.118-15.425-26.572-6.87-11.018-1.814-6.61c-.648-2.723-1.102-4.991-1.102-7.778l7.972-10.823L71.42 0 82.05 1.426l4.472 3.888 6.61 15.101 10.694 23.786 16.591 32.34 4.861 9.592 2.592 8.879.973 2.722h1.685v-1.556l1.36-18.211 2.528-22.36 2.463-28.776.843-8.1 4.018-9.722 7.971-5.25 6.222 2.981 5.12 7.324-.713 4.73-3.046 19.768-5.962 30.98-3.889 20.739h2.268l2.593-2.593 10.499-13.934 17.628-22.036 7.778-8.749 9.073-9.657 5.833-4.601h11.018l8.1 12.055-3.628 12.443-11.342 14.388-9.398 12.184-13.48 18.147-8.426 14.518.778 1.166 2.01-.194 30.46-6.481 16.462-2.982 19.637-3.37 8.88 4.148.971 4.213-3.5 8.62-20.998 5.184-24.628 4.926-36.682 8.685-.454.324.519.648 16.526 1.555 7.065.389h17.304l32.21 2.398 8.426 5.574 5.055 6.805-.843 5.184-12.962 6.611-17.498-4.148-40.83-9.721-14-3.5h-1.944v1.167l11.666 11.406 21.387 19.314 26.767 24.887 1.36 6.157-3.434 4.86-3.63-.518-23.526-17.693-9.073-7.972-20.545-17.304h-1.36v1.814l4.73 6.935 25.017 37.59 1.296 11.536-1.814 3.76-6.481 2.268-7.13-1.297-14.647-20.544-15.1-23.138-12.185-20.739-1.49.843-7.194 77.448-3.37 3.953-7.778 2.981-6.48-4.925-3.436-7.972 3.435-15.749 4.148-20.544 3.37-16.333 3.046-20.285 1.815-6.74-.13-.454-1.49.194-15.295 20.999-23.267 31.433-18.406 19.702-4.407 1.75-7.648-3.954.713-7.064 4.277-6.286 25.47-32.405 15.36-20.092 9.917-11.6-.065-1.686h-.583L44.07 198.125l-12.055 1.555-5.185-4.86.648-7.972 2.463-2.593 20.35-13.999-.064.065Z"/></svg>
chatgpt: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 260"><path fill="currentColor" d="M239.184 106.203a64.716 64.716 0 0 0-5.576-53.103C219.452 28.459 191 15.784 163.213 21.74A65.586 65.586 0 0 0 52.096 45.22a64.716 64.716 0 0 0-43.23 31.36c-14.31 24.602-11.061 55.634 8.033 76.74a64.665 64.665 0 0 0 5.525 53.102c14.174 24.65 42.644 37.324 70.446 31.36a64.72 64.72 0 0 0 48.754 21.744c28.481.025 53.714-18.361 62.414-45.481a64.767 64.767 0 0 0 43.229-31.36c14.137-24.558 10.875-55.423-8.083-76.483Zm-97.56 136.338a48.397 48.397 0 0 1-31.105-11.255l1.535-.87 51.67-29.825a8.595 8.595 0 0 0 4.247-7.367v-72.85l21.845 12.636c.218.111.37.32.409.563v60.367c-.056 26.818-21.783 48.545-48.601 48.601Zm-104.466-44.61a48.345 48.345 0 0 1-5.781-32.589l1.534.921 51.722 29.826a8.339 8.339 0 0 0 8.441 0l63.181-36.425v25.221a.87.87 0 0 1-.358.665l-52.335 30.184c-23.257 13.398-52.97 5.431-66.404-17.803ZM23.549 85.38a48.499 48.499 0 0 1 25.58-21.333v61.39a8.288 8.288 0 0 0 4.195 7.316l62.874 36.272-21.845 12.636a.819.819 0 0 1-.767 0L41.353 151.53c-23.211-13.454-31.171-43.144-17.804-66.405v.256Zm179.466 41.695-63.08-36.63L161.73 77.86a.819.819 0 0 1 .768 0l52.233 30.184a48.6 48.6 0 0 1-7.316 87.635v-61.391a8.544 8.544 0 0 0-4.4-7.213Zm21.742-32.69-1.535-.922-51.619-30.081a8.39 8.39 0 0 0-8.492 0L99.98 99.808V74.587a.716.716 0 0 1 .307-.665l52.233-30.133a48.652 48.652 0 0 1 72.236 50.391v.205ZM88.061 139.097l-21.845-12.585a.87.87 0 0 1-.41-.614V65.685a48.652 48.652 0 0 1 79.757-37.346l-1.535.87-51.67 29.825a8.595 8.595 0 0 0-4.246 7.367l-.051 72.697Zm11.868-25.58 28.138-16.217 28.188 16.218v32.434l-28.086 16.218-28.188-16.218-.052-32.434Z"/></svg>
gemini: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 192 192"><path fill="currentColor" d="M164.93 86.68c-13.56-5.84-25.42-13.84-35.6-24.01-10.17-10.17-18.18-22.04-24.01-35.6-2.23-5.19-4.04-10.54-5.42-16.02C99.45 9.26 97.85 8 96 8s-3.45 1.26-3.9 3.05c-1.38 5.48-3.18 10.81-5.42 16.02-5.84 13.56-13.84 25.43-24.01 35.6-10.17 10.16-22.04 18.17-35.6 24.01-5.19 2.23-10.54 4.04-16.02 5.42C9.26 92.55 8 94.15 8 96s1.26 3.45 3.05 3.9c5.48 1.38 10.81 3.18 16.02 5.42 13.56 5.84 25.42 13.84 35.6 24.01 10.17 10.17 18.18 22.04 24.01 35.6 2.24 5.2 4.04 10.54 5.42 16.02A4.03 4.03 0 0 0 96 184c1.85 0 3.45-1.26 3.9-3.05 1.38-5.48 3.18-10.81 5.42-16.02 5.84-13.56 13.84-25.42 24.01-35.6 10.17-10.17 22.04-18.18 35.6-24.01 5.2-2.24 10.54-4.04 16.02-5.42A4.03 4.03 0 0 0 184 96c0-1.85-1.26-3.45-3.05-3.9-5.48-1.38-10.81-3.18-16.02-5.42"/></svg>

View File

@@ -0,0 +1,5 @@
---
title: آرشیو
layout: archives
toc: false
---

View File

@@ -0,0 +1,5 @@
---
title: アーカイブ
layout: archives
toc: false
---

View File

@@ -0,0 +1,5 @@
---
title: Archives
layout: archives
toc: false
---

View File

@@ -0,0 +1,5 @@
---
title: 归档
layout: archives
toc: false
---

View File

@@ -0,0 +1,218 @@
---
title: "Hextra v0.12"
date: 2026-02-20
authors:
- name: imfing
link: https://github.com/imfing
image: https://github.com/imfing.png
tags:
- انتشار
---
Hextra v0.12.0 مجموعه‌ای غنی از ویژگی‌های جدید شامل منوی زمینه صفحه، زوم تصویر، تب‌های بازطراحی‌شده و موارد بیشتر، به همراه بهبودهای جامع دسترس‌پذیری WCAG 2.2 AA و رفع اشکالات متعدد ارائه می‌دهد.
<!--more-->
## راهنمای ارتقا
برای بیشتر سایت‌ها تغییر شکست‌آمیزی وجود ندارد. با استفاده از [Hugo Modules](https://gohugo.io/hugo-modules/use-modules/) به‌روزرسانی کنید:
```bash
hugo mod get -u github.com/imfing/hextra
```
## نکات برجسته
- منوی زمینه صفحه برای کپی/مشاهده سورس Markdown
- بازطراحی شورت‌کد تب‌ها با نام‌گذاری هر تب و پشتیبانی از آیکون
- زوم با کلیک برای تصاویر Markdown
- پشتیبانی از تحلیل‌گر GoatCounter
- گزینه مخفی‌کردن نوار کناری اصلی در دسکتاپ
- نمایش آخرین نویسنده ویرایش‌کننده از طریق GitInfo
- گزینه غیرفعال‌سازی ناوبری قبلی/بعدی
- صفحه آرشیو داخلی برای فهرست زمانی نوشته‌های وبلاگ
- شورت‌کد و چیدمان واژه‌نامه
- حذف صفحات/بخش‌ها از llms.txt
- ترتیب و برچسب‌های نوار کناری موبایل هم‌راستا با `menu.main`
- عرض محتوای پایدار با پشتیبانی از بازنویسی متغیر CSS
- بهبودهای جامع دسترس‌پذیری WCAG 2.2 AA
## ویژگی‌های جدید
### منوی زمینه صفحه
![منوی زمینه](https://github.com/user-attachments/assets/0b55bee9-6f4d-4e1d-9461-60c40208cb6c)
منوی زمینه صفحه دکمه‌ای کشویی فراهم می‌کند که با آن می‌توانید محتوای صفحه را به‌صورت Markdown کپی کنید یا سورس خام Markdown را مشاهده نمایید. با افزایش کاربرانی که مستندات را به ابزارهای هوش مصنوعی مولّد می‌دهند، دسترسی سریع به Markdown تمیز بسیار مفید است. پیوندهای سفارشی با متغیرهای قالب (`{url}`، `{title}`، `{markdown_url}`) به شما امکان می‌دهند میان‌برهای «از AI بپرس» یا سایر یکپارچه‌سازی‌ها را مستقیماً در منو ایجاد کنید.
برای استفاده از قابلیت‌های «مشاهده به‌صورت Markdown» و `{markdown_url}`، فرمت خروجی Markdown را در پیکربندی سایت فعال کنید:
```yaml {filename="hugo.yaml"}
outputs:
page: [html, markdown]
section: [html, rss, markdown]
```
سپس منوی زمینه را پیکربندی کنید:
```yaml {filename="hugo.yaml"}
params:
page:
contextMenu:
enable: true
links:
- name: "Ask AI"
url: "https://example.com?content={markdown_url}"
icon: "sparkles"
```
### بازطراحی تب‌ها و پشتیبانی از آیکون
[شورت‌کد تب‌ها]({{% relref "docs/guide/shortcodes/tabs" %}}) بازطراحی شده است. اکنون می‌توان نام تب‌ها را مستقیماً روی هر شورت‌کد `tab` تنظیم کرد و پارامتر اختیاری `icon` یک آیکون قبل از برچسب تب نمایش می‌دهد. نحو قبلی همچنان پشتیبانی می‌شود.
```md
{{</* tabs */>}}
{{</* tab name="Photos" icon="photograph" */>}}مدیریت و سازماندهی کتابخانه عکس‌های شما.{{</* /tab */>}}
{{</* tab name="Music" icon="music-note" */>}}مرور و پخش آهنگ‌های مورد علاقه شما.{{</* /tab */>}}
{{</* tab name="Videos" icon="film" */>}}تماشا و پخش محتوای ویدیویی.{{</* /tab */>}}
{{</* /tabs */>}}
```
![تب‌ها با آیکون](https://github.com/user-attachments/assets/afa4cb8f-615c-4f01-8ae4-81a64c9ce391)
### زوم تصویر
با یک گزینه پیکربندی جدید، زوم با کلیک را روی تصاویر Markdown فعال کنید. این قابلیت از [medium-zoom](https://github.com/francoischalifour/medium-zoom) استفاده می‌کند.
```yaml {filename="hugo.yaml"}
params:
imageZoom:
enable: true
```
### تحلیل‌گر GoatCounter
پشتیبانی داخلی از تحلیل‌گر [GoatCounter](https://www.goatcounter.com/) در کنار یکپارچه‌سازی‌های موجود Google Analytics، Umami و Matomo.
### مخفی‌کردن نوار کناری اصلی
یک پارامتر جدید فرانت‌متر امکان مخفی‌کردن نوار کناری اصلی در دسکتاپ را فراهم می‌کند تا صفحات محتوا عرض کامل داشته باشند.
```yaml {filename="content/my-page.md"}
---
title: My Page
sidebar:
hide: true
---
```
### آخرین نویسنده ویرایش‌کننده
با استفاده از GitInfo هوگو، آخرین نویسنده کامیت را در کنار تاریخ «آخرین به‌روزرسانی» نمایش دهید.
```yaml {filename="hugo.yaml"}
params:
displayUpdatedAuthor: true
```
![آخرین نویسنده ویرایش‌کننده](https://github.com/user-attachments/assets/275b7177-e089-483c-abb6-6d8f16616b9b)
### غیرفعال‌سازی ناوبری قبلی/بعدی
دکمه‌های ناوبری قبلی/بعدی را در سطح سایت غیرفعال کنید:
```yaml {filename="hugo.yaml"}
params:
page:
displayPagination: false
```
### حذف از LLMs.txt
با تنظیم `llms: false` در فرانت‌متر، صفحات یا بخش‌های کامل را از خروجی `llms.txt` حذف کنید.
```yaml {filename="content/private-page.md"}
---
title: "Private Page"
llms: false
---
```
### صفحه آرشیو
چیدمان جدید داخلی `archives` نوشته‌های وبلاگ را در یک خط زمانی گروه‌بندی‌شده بر اساس سال نمایش می‌دهد و برچسب‌ها به‌صورت درون‌خطی پس از عنوان هر نوشته نشان داده می‌شوند.
```yaml {filename="content/archives/_index.md"}
---
title: Archives
layout: archives
---
```
![صفحه آرشیو](https://github.com/user-attachments/assets/262cc0fa-e0af-4a50-8c3d-4465059418b8)
### واژه‌نامه
یک [واژه‌نامه]({{% relref "docs/guide/shortcodes/term" %}}) اصطلاحات سراسری سایت با صفحه فهرست اختصاصی و شورت‌کد `term` برای تعاریف درون‌خطی.
## دسترس‌پذیری
بهبودهای جامع دسترس‌پذیری WCAG 2.2 AA (#924):
- پیوند رفتن به محتوا و نقش‌های نشانه‌ای ARIA در تمام صفحات
- ویژگی‌های ARIA برای تمام ابزارک‌های تعاملی (کلید تغییر تم، تب‌ها، نوار کناری، درخت فایل، منوهای بازشو، جستجو، منوها)
- ناوبری صفحه‌کلیدی برای تب‌ها و کلید تغییر تم (کلیدهای جهتی، Enter، Escape)
- پشتیبانی از `prefers-reduced-motion` و سبک‌های سراسری `focus-visible`
- ۱۵ کلید دسترس‌پذیری i18n جدید با ترجمه کامل در تمام ۲۱ محلی‌سازی
- جایگزینی تمام رشته‌های انگلیسی `aria-label` که به‌صورت هاردکد بودند با جستجوی i18n
## بهبودهای کیفیت زندگی
- بهبود سبک‌های خوانایی جدول
- پشتیبانی از ویژگی‌های Markdown برای سرتیترها
- تشخیص بهتر پیوند فعال برای صفحات فرود بخش چندزبانه
- پشتیبانی شورت‌کد کارت از پارامتر اختیاری `alt` برای تصاویر
- پشتیبانی از تصاویر بسته صفحه در ابرداده OpenGraph
- عرض محتوا اکنون به‌صورت پیش‌فرض ثابت است، با پشتیبانی از بازنویسی متغیر CSS برای چیدمان‌های سفارشی
## رفع اشکالات
- جلوگیری از پیشوند پایه دوگانه `relref` در render-link
- رفع رندر تب‌ها هنگام تودرتوبودن در مراحل
- هم‌راستاسازی ترتیب و برچسب‌های نوار کناری موبایل با `menu.main`
- رعایت `search.enable` در نوار کناری
- رعایت پارامتر صفحه `toc` در منوی بازشو موبایل
- بهبود برجسته‌سازی تطبیق FlexSearch و دستکاری امن DOM
- رفع موقعیت زیرعنوان کارت
- مدیریت اسلش‌های ابتدایی در مسیرهای تصویر OG برای استقرارهای زیرمسیر
- رفع بازگرداندن صفحات نتیجه کمتر از حد انتظار توسط FlexSearch
- تغییر فایل پیش‌فرض Umami analytics به `script.js`
- رفع جستجوی نویسنده RSS برای Hugo v0.156.0+ (`.Site.Params.Author`)
## مستندات و بومی‌سازی
- افزودن بومی‌سازی ایتالیایی
- پیوند مستندات KaTeX
- به‌روزرسانی مستندات شورت‌کد details به نحو angle bracket
## مشارکت‌کنندگان
این انتشار با مشارکت ۱۱ مشارکت‌کننده جدید ممکن شد:
- [@ghac101](https://github.com/ghac101) - رفع Umami analytics، غیرفعال‌سازی ناوبری قبلی/بعدی
- [@pmarrapese](https://github.com/pmarrapese) - پشتیبانی از ویژگی‌های Markdown برای سرتیترها
- [@Bubbler-4](https://github.com/Bubbler-4) - مستندات شورت‌کد details
- [@bloovis](https://github.com/bloovis) - رفع تعداد نتایج FlexSearch
- [@AntoninPvr](https://github.com/AntoninPvr) - رفع موقعیت زیرعنوان کارت
- [@illia-v](https://github.com/illia-v) - رفع TOC موبایل و کلید تغییر جستجو
- [@gallochri](https://github.com/gallochri) - بومی‌سازی ایتالیایی
- [@MatheusFlausino](https://github.com/MatheusFlausino) - حذف از LLMs.txt
- [@daniseijo](https://github.com/daniseijo) - قابلیت آخرین نویسنده ویرایش‌کننده
- [@confusedkernel](https://github.com/confusedkernel) - صفحه آرشیو
- [@Fenyutanchan](https://github.com/Fenyutanchan) - رفع سازگاری نویسنده RSS با Hugo v0.156.0
همچنین از مشارکت‌کنندگان بازگشته [@KStocky](https://github.com/KStocky)، [@ldez](https://github.com/ldez)، [@kowyo](https://github.com/kowyo)، [@torbjornbp](https://github.com/torbjornbp)، [@yuri1969](https://github.com/yuri1969) و [@PrintN](https://github.com/PrintN) بابت مشارکت‌های مداوم‌شان سپاسگزاریم.
---
**تغییرات کامل**: https://github.com/imfing/hextra/compare/v0.11.1...v0.12.0

View File

@@ -0,0 +1,218 @@
---
title: "Hextra v0.12"
date: 2026-02-20
authors:
- name: imfing
link: https://github.com/imfing
image: https://github.com/imfing.png
tags:
- Release
---
Hextra v0.12.0 は、ページコンテキストメニュー、画像ズーム、刷新されたタブ、その他多くの新機能に加え、包括的な WCAG 2.2 AA アクセシビリティ改善と多数のバグ修正を提供します。
<!--more-->
## アップグレードガイド
ほとんどのサイトで破壊的変更はありません。[Hugo Modules](https://gohugo.io/hugo-modules/use-modules/) を使って更新してください:
```bash
hugo mod get -u github.com/imfing/hextra
```
## ハイライト
- Markdown ソースのコピー・表示ができるページコンテキストメニュー
- タブ名指定とアイコンをサポートする刷新されたタブショートコード
- Markdown 画像のクリックズーム
- GoatCounter アナリティクス対応
- デスクトップでメインサイドバーを非表示にするオプション
- GitInfo による最終更新者の表示
- 前へ/次へナビゲーションの無効化オプション
- ブログ記事の年別アーカイブページ
- 用語集ショートコードとレイアウト
- llms.txt からのページ/セクション除外
- モバイルサイドバーの順序とラベルが `menu.main` に準拠
- CSS 変数オーバーライドによる安定したコンテンツ幅
- 包括的な WCAG 2.2 AA アクセシビリティ改善
## 新機能
### ページコンテキストメニュー
![コンテキストメニュー](https://github.com/user-attachments/assets/0b55bee9-6f4d-4e1d-9461-60c40208cb6c)
ページコンテキストメニューはドロップダウンボタンを提供し、ページの内容を Markdown としてコピーしたり、生の Markdown ソースを表示できます。ドキュメントを生成 AI ツールに取り込むユーザーが増える中、クリーンな Markdown への素早いアクセスはますます有用です。テンプレート変数(`{url}``{title}``{markdown_url}`を使ったカスタムリンクにより、「AI に質問」ショートカットなどのインテグレーションをメニューに直接組み込めます。
「Markdown として表示」および `{markdown_url}` 機能を利用するには、サイト設定で Markdown 出力フォーマットを有効にしてください:
```yaml {filename="hugo.yaml"}
outputs:
page: [html, markdown]
section: [html, rss, markdown]
```
次にコンテキストメニューを設定します:
```yaml {filename="hugo.yaml"}
params:
page:
contextMenu:
enable: true
links:
- name: "Ask AI"
url: "https://example.com?content={markdown_url}"
icon: "sparkles"
```
### タブの刷新とアイコン対応
[タブショートコード]({{% relref "docs/guide/shortcodes/tabs" %}})が刷新されました。各 `tab` ショートコードでタブ名を直接設定でき、オプションの `icon` パラメータでラベルの前にアイコンを表示できます。従来の構文も引き続きサポートされています。
```md
{{</* tabs */>}}
{{</* tab name="Photos" icon="photograph" */>}}写真ライブラリを管理・整理します。{{</* /tab */>}}
{{</* tab name="Music" icon="music-note" */>}}お気に入りの曲を閲覧・再生します。{{</* /tab */>}}
{{</* tab name="Videos" icon="film" */>}}動画コンテンツを視聴・ストリーミングします。{{</* /tab */>}}
{{</* /tabs */>}}
```
![アイコン付きタブ](https://github.com/user-attachments/assets/afa4cb8f-615c-4f01-8ae4-81a64c9ce391)
### 画像ズーム
[medium-zoom](https://github.com/francoischalifour/medium-zoom) を利用した新しい設定オプションで、Markdown 画像のクリックズームを有効にできます。
```yaml {filename="hugo.yaml"}
params:
imageZoom:
enable: true
```
### GoatCounter アナリティクス
既存の Google Analytics、Umami、Matomo に加え、[GoatCounter](https://www.goatcounter.com/) アナリティクスの組み込みサポートを追加しました。
### メインサイドバーの非表示
新しいフロントマターパラメータにより、デスクトップでメインサイドバーを非表示にしてコンテンツを全幅表示できます。
```yaml {filename="content/my-page.md"}
---
title: My Page
sidebar:
hide: true
---
```
### 最終更新者の表示
Hugo の GitInfo を使って、「最終更新日」と合わせて最終コミット者を表示します。
```yaml {filename="hugo.yaml"}
params:
displayUpdatedAuthor: true
```
![最終更新者](https://github.com/user-attachments/assets/275b7177-e089-483c-abb6-6d8f16616b9b)
### 前へ/次へナビゲーションの無効化
サイト全体で前へ/次へナビゲーションボタンを無効にできます:
```yaml {filename="hugo.yaml"}
params:
page:
displayPagination: false
```
### LLMs.txt 除外
フロントマターで `llms: false` を設定すると、個別のページやセクション全体を `llms.txt` 出力から除外できます。
```yaml {filename="content/private-page.md"}
---
title: "Private Page"
llms: false
---
```
### アーカイブページ
新しい組み込み `archives` レイアウトは、ブログ記事を年ごとにグループ化した時系列タイムラインで表示し、各タイトルの後にタグをインラインで表示します。
```yaml {filename="content/archives/_index.md"}
---
title: Archives
layout: archives
---
```
![アーカイブページ](https://github.com/user-attachments/assets/262cc0fa-e0af-4a50-8c3d-4465059418b8)
### 用語集
サイト全体の[用語集]({{% relref "docs/guide/shortcodes/term" %}})。専用のリストページとインライン定義用の `term` ショートコードを備えています。
## アクセシビリティ
包括的な WCAG 2.2 AA アクセシビリティ改善 (#924):
- すべてのページに本文へスキップリンクと ARIA ランドマークロール
- すべてのインタラクティブウィジェット(テーマトグル、タブ、サイドバー、ファイルツリー、ドロップダウン、検索、メニュー)に ARIA 属性
- タブとテーマトグルのキーボードナビゲーション矢印キー、Enter、Escape
- `prefers-reduced-motion` サポートとグローバル `focus-visible` スタイル
- 全 21 ロケールに完全翻訳された 15 個の新しい i18n アクセシビリティキー
- ハードコードされた英語 `aria-label` 文字列をすべて i18n ルックアップに置き換え
## 利便性の向上
- テーブルの読みやすさ向上のためのスタイル改善
- ヘッダーでの Markdown 属性サポート
- 多言語セクションランディングページでのアクティブリンク検出の改善
- カードショートコードで画像に `alt` パラメータをオプションでサポート
- ページバンドル画像が OpenGraph メタデータでサポート
- コンテンツ幅がデフォルトで安定し、カスタムレイアウト用の CSS 変数オーバーライドをサポート
## 修正
- render-link での `relref` ベースプレフィックスの二重付与を修正
- ステップ内にネストされたタブの描画を修正
- モバイルサイドバーの順序とラベルを `menu.main` に準拠
- サイドバーでの `search.enable` の尊重
- モバイルドロップダウンでの `toc` ページパラメータの尊重
- FlexSearch のマッチハイライトと安全な DOM 操作の改善
- カードのサブタイトル位置の修正
- サブパスデプロイメントでの OG 画像パスの先頭スラッシュの処理
- FlexSearch が期待より少ない結果ページを返す問題の修正
- Umami アナリティクスのデフォルトファイルを `script.js` に変更
- Hugo v0.156.0+ での RSS author ルックアップの修正 (`.Site.Params.Author`)
## ドキュメントと i18n
- イタリア語ローカリゼーションを追加
- KaTeX ドキュメントへのリンクを追加
- details ショートコードのドキュメントを angle bracket 構文に更新
## コントリビューター
このリリースは 11 名の新しいコントリビューターの貢献により実現しました:
- [@ghac101](https://github.com/ghac101) - Umami アナリティクスの修正、前へ/次へナビゲーションの無効化
- [@pmarrapese](https://github.com/pmarrapese) - ヘッダーの Markdown 属性サポート
- [@Bubbler-4](https://github.com/Bubbler-4) - details ショートコードのドキュメント
- [@bloovis](https://github.com/bloovis) - FlexSearch の結果件数修正
- [@AntoninPvr](https://github.com/AntoninPvr) - カードのサブタイトル位置修正
- [@illia-v](https://github.com/illia-v) - モバイル TOC と検索トグルの修正
- [@gallochri](https://github.com/gallochri) - イタリア語ローカリゼーション
- [@MatheusFlausino](https://github.com/MatheusFlausino) - LLMs.txt 除外
- [@daniseijo](https://github.com/daniseijo) - 最終更新者機能
- [@confusedkernel](https://github.com/confusedkernel) - アーカイブページ
- [@Fenyutanchan](https://github.com/Fenyutanchan) - Hugo v0.156.0 RSS author 互換性修正
さらに、継続的な貢献をいただいている [@KStocky](https://github.com/KStocky)、[@ldez](https://github.com/ldez)、[@kowyo](https://github.com/kowyo)、[@torbjornbp](https://github.com/torbjornbp)、[@yuri1969](https://github.com/yuri1969)、[@PrintN](https://github.com/PrintN) の各コントリビューターに感謝いたします。
---
**完全な変更履歴**: https://github.com/imfing/hextra/compare/v0.11.1...v0.12.0

218
docs/content/blog/v0.12.md Normal file
View File

@@ -0,0 +1,218 @@
---
title: "Hextra v0.12"
date: 2026-02-20
authors:
- name: imfing
link: https://github.com/imfing
image: https://github.com/imfing.png
tags:
- Release
---
Hextra v0.12.0 delivers a rich set of new features including page context menus, image zoom, redesigned tabs, and more, plus comprehensive WCAG 2.2 AA accessibility improvements and numerous bug fixes.
<!--more-->
## Upgrade Guide
No breaking changes are expected for most sites. Update using [Hugo Modules](https://gohugo.io/hugo-modules/use-modules/):
```bash
hugo mod get -u github.com/imfing/hextra
```
## Highlights
- Page context menu for copying/viewing Markdown source
- Redesigned tabs shortcode with per-tab naming and icon support
- Click-to-zoom for Markdown images
- GoatCounter analytics support
- Option to hide the main sidebar on desktop
- Display last modified author via GitInfo
- Option to disable prev/next navigation
- Built-in archives page for chronological blog post listings
- Term glossary shortcode and layout
- Exclude pages/sections from llms.txt
- Mobile sidebar ordering and labels aligned with `menu.main`
- Stable content width with CSS variable override support
- Comprehensive WCAG 2.2 AA accessibility improvements
## New Features
### Page Context Menu
![Context menu](https://github.com/user-attachments/assets/0b55bee9-6f4d-4e1d-9461-60c40208cb6c)
The page context menu provides a dropdown button that lets you copy the page content as Markdown or view the raw Markdown source. As more users feed documentation into generative AI tools, having quick access to clean Markdown is increasingly useful. Custom links with template variables (`{url}`, `{title}`, `{markdown_url}`) let you wire up "Ask AI" shortcuts or other integrations directly in the menu.
To use the "View as Markdown" and `{markdown_url}` features, enable the Markdown output format in your site configuration:
```yaml {filename="hugo.yaml"}
outputs:
page: [html, markdown]
section: [html, rss, markdown]
```
Then configure the context menu:
```yaml {filename="hugo.yaml"}
params:
page:
contextMenu:
enable: true
links:
- name: "Ask AI"
url: "https://example.com?content={markdown_url}"
icon: "sparkles"
```
### Tabs Revamp and Icon Support
The [tabs shortcode]({{% relref "docs/guide/shortcodes/tabs" %}}) has been redesigned. Tab names can now be set directly on each `tab` shortcode, and an optional `icon` parameter displays an icon before the tab label. The previous syntax is still supported.
```md
{{</* tabs */>}}
{{</* tab name="Photos" icon="photograph" */>}}Manage and organize your photo library.{{</* /tab */>}}
{{</* tab name="Music" icon="music-note" */>}}Browse and play your favorite tracks.{{</* /tab */>}}
{{</* tab name="Videos" icon="film" */>}}Watch and stream video content.{{</* /tab */>}}
{{</* /tabs */>}}
```
![Tabs with icons](https://github.com/user-attachments/assets/afa4cb8f-615c-4f01-8ae4-81a64c9ce391)
### Image Zoom
Enable click-to-zoom on Markdown images with a new configuration option, powered by [medium-zoom](https://github.com/francoischalifour/medium-zoom).
```yaml {filename="hugo.yaml"}
params:
imageZoom:
enable: true
```
### GoatCounter Analytics
Built-in support for [GoatCounter](https://www.goatcounter.com/) analytics alongside existing Google Analytics, Umami, and Matomo integrations.
### Hide Main Sidebar
A new front matter parameter allows hiding the main sidebar on desktop to give content pages the full width.
```yaml {filename="content/my-page.md"}
---
title: My Page
sidebar:
hide: true
---
```
### Last Modified Author
Display the last commit author alongside the "last updated" date using Hugo's GitInfo.
```yaml {filename="hugo.yaml"}
params:
displayUpdatedAuthor: true
```
![Last modified author](https://github.com/user-attachments/assets/275b7177-e089-483c-abb6-6d8f16616b9b)
### Disable Prev/Next Navigation
Disable the previous/next navigation buttons site-wide:
```yaml {filename="hugo.yaml"}
params:
page:
displayPagination: false
```
### LLMs.txt Exclusion
Exclude individual pages or entire sections from `llms.txt` output by setting `llms: false` in front matter.
```yaml {filename="content/private-page.md"}
---
title: "Private Page"
llms: false
---
```
### Archives Page
A new built-in `archives` layout displays blog posts in a chronological timeline grouped by year, with tags shown inline after each post title.
```yaml {filename="content/archives/_index.md"}
---
title: Archives
layout: archives
---
```
![Archives page](https://github.com/user-attachments/assets/262cc0fa-e0af-4a50-8c3d-4465059418b8)
### Glossary
A site-wide terminology [glossary]({{% relref "docs/guide/shortcodes/term" %}}) with a dedicated listing page and a `term` shortcode for inline definitions.
## Accessibility
Comprehensive WCAG 2.2 AA accessibility improvements (#924):
- Skip-to-content link and ARIA landmark roles on all pages
- ARIA attributes on all interactive widgets (theme toggle, tabs, sidebar, filetree, dropdowns, search, menus)
- Keyboard navigation for tabs and theme toggle (arrow keys, Enter, Escape)
- `prefers-reduced-motion` support and global `focus-visible` styles
- 15 new i18n accessibility keys with full translations across all 21 locales
- Replaced all hardcoded English `aria-label` strings with i18n lookups
## Quality of Life
- Improved table readability styles
- Markdown attribute support for headers
- Better active link detection for multilingual section landing pages
- Card shortcode supports optional `alt` parameter for images
- Page bundle images supported in OpenGraph metadata
- Content width now stays consistent by default, with CSS variable override support for custom layouts
## Fixes
- Prevent `relref` double base-prefix in render-link
- Fix tabs rendering when nested inside steps
- Align mobile sidebar ordering and labels with `menu.main`
- Respect `search.enable` in the sidebar
- Respect the `toc` page parameter in mobile dropdown
- Enhance FlexSearch match highlighting and safe DOM manipulation
- Fix card subtitle positioning
- Handle leading slashes in OG image paths for subpath deployments
- Fix FlexSearch returning fewer than expected result pages
- Change default Umami analytics file to `script.js`
- Fix RSS author lookup for Hugo v0.156.0+ (`.Site.Params.Author`)
## Documentation & i18n
- Add Italian localization
- Link KaTeX documentation
- Update details shortcode docs to angle bracket syntax
## Contributors
This release was made possible by contributions from 11 new contributors:
- [@ghac101](https://github.com/ghac101) - Umami analytics fix, disable prev/next navigation
- [@pmarrapese](https://github.com/pmarrapese) - Markdown attribute support for headers
- [@Bubbler-4](https://github.com/Bubbler-4) - Details shortcode documentation
- [@bloovis](https://github.com/bloovis) - FlexSearch result count fix
- [@AntoninPvr](https://github.com/AntoninPvr) - Card subtitle positioning fix
- [@illia-v](https://github.com/illia-v) - Mobile TOC and search toggle fixes
- [@gallochri](https://github.com/gallochri) - Italian localization
- [@MatheusFlausino](https://github.com/MatheusFlausino) - LLMs.txt exclusion
- [@daniseijo](https://github.com/daniseijo) - Last modified author feature
- [@confusedkernel](https://github.com/confusedkernel) - Archives page
- [@Fenyutanchan](https://github.com/Fenyutanchan) - Hugo v0.156.0 RSS author compatibility fix
Additional thanks to returning contributors [@KStocky](https://github.com/KStocky), [@ldez](https://github.com/ldez), [@kowyo](https://github.com/kowyo), [@torbjornbp](https://github.com/torbjornbp), [@yuri1969](https://github.com/yuri1969), and [@PrintN](https://github.com/PrintN) for their continued contributions.
---
**Full Changelog**: https://github.com/imfing/hextra/compare/v0.11.1...v0.12.0

View File

@@ -0,0 +1,218 @@
---
title: "Hextra v0.12"
date: 2026-02-20
authors:
- name: imfing
link: https://github.com/imfing
image: https://github.com/imfing.png
tags:
- Release
---
Hextra v0.12.0 带来了丰富的新功能,包括页面上下文菜单、图片缩放、全新设计的标签页等,同时提供全面的 WCAG 2.2 AA 无障碍改进和大量错误修复。
<!--more-->
## 升级指南
对大多数站点而言没有破坏性变更。使用 [Hugo Modules](https://gohugo.io/hugo-modules/use-modules/) 更新:
```bash
hugo mod get -u github.com/imfing/hextra
```
## 亮点
- 页面上下文菜单,可复制/查看 Markdown 源码
- 全新设计的标签页短代码,支持单独命名和图标
- Markdown 图片点击缩放
- GoatCounter 分析支持
- 桌面端隐藏主侧边栏选项
- 通过 GitInfo 显示最后修改作者
- 禁用上一篇/下一篇导航选项
- 内置归档页面,按时间顺序列出博客文章
- 术语表短代码和布局
- 从 llms.txt 中排除页面/章节
- 移动端侧边栏排序和标签与 `menu.main` 对齐
- 通过 CSS 变量覆盖支持稳定的内容宽度
- 全面的 WCAG 2.2 AA 无障碍改进
## 新功能
### 页面上下文菜单
![页面上下文菜单](https://github.com/user-attachments/assets/0b55bee9-6f4d-4e1d-9461-60c40208cb6c)
页面上下文菜单提供下拉按钮,可将页面内容复制为 Markdown 或查看原始 Markdown 源码。随着越来越多用户将文档输入生成式 AI 工具,快速获取干净的 Markdown 变得越来越有用。通过模板变量(`{url}``{title}``{markdown_url}`)添加自定义链接,可以在菜单中直接集成“询问 AI”快捷方式或其他功能。
要使用“以 Markdown 查看”和 `{markdown_url}` 功能,请在站点配置中启用 Markdown 输出格式:
```yaml {filename="hugo.yaml"}
outputs:
page: [html, markdown]
section: [html, rss, markdown]
```
然后配置页面上下文菜单:
```yaml {filename="hugo.yaml"}
params:
page:
contextMenu:
enable: true
links:
- name: "Ask AI"
url: "https://example.com?content={markdown_url}"
icon: "sparkles"
```
### 标签页重设计与图标支持
[标签页短代码]({{% relref "docs/guide/shortcodes/tabs" %}})经过重新设计。现在可以直接在每个 `tab` 短代码上设置标签名称,可选的 `icon` 参数可在标签文字前显示图标。之前的语法仍然支持。
```md
{{</* tabs */>}}
{{</* tab name="Photos" icon="photograph" */>}}管理和整理您的照片库。{{</* /tab */>}}
{{</* tab name="Music" icon="music-note" */>}}浏览和播放您喜爱的曲目。{{</* /tab */>}}
{{</* tab name="Videos" icon="film" */>}}观看和串流视频内容。{{</* /tab */>}}
{{</* /tabs */>}}
```
![带图标的标签页](https://github.com/user-attachments/assets/afa4cb8f-615c-4f01-8ae4-81a64c9ce391)
### 图片缩放
通过新的配置选项,启用 Markdown 图片的点击缩放功能,基于 [medium-zoom](https://github.com/francoischalifour/medium-zoom) 实现。
```yaml {filename="hugo.yaml"}
params:
imageZoom:
enable: true
```
### GoatCounter 分析
在现有的 Google Analytics、Umami 和 Matomo 集成之外,新增 [GoatCounter](https://www.goatcounter.com/) 分析的内置支持。
### 隐藏主侧边栏
新的 Front Matter 参数允许在桌面端隐藏主侧边栏,使内容页面获得全宽显示。
```yaml {filename="content/my-page.md"}
---
title: My Page
sidebar:
hide: true
---
```
### 最后修改作者
使用 Hugo 的 GitInfo 功能,在"最后更新"日期旁显示最后提交的作者。
```yaml {filename="hugo.yaml"}
params:
displayUpdatedAuthor: true
```
![最后修改作者](https://github.com/user-attachments/assets/275b7177-e089-483c-abb6-6d8f16616b9b)
### 禁用上一篇/下一篇导航
在站点范围内禁用上一篇/下一篇导航按钮:
```yaml {filename="hugo.yaml"}
params:
page:
displayPagination: false
```
### LLMs.txt 排除
通过在 Front Matter 中设置 `llms: false`,将单个页面或整个章节从 `llms.txt` 输出中排除。
```yaml {filename="content/private-page.md"}
---
title: "Private Page"
llms: false
---
```
### 归档页面
新的内置 `archives` 布局按年份分组,以时间线形式展示博客文章,每篇文章标题后内联显示标签。
```yaml {filename="content/archives/_index.md"}
---
title: Archives
layout: archives
---
```
![归档页面](https://github.com/user-attachments/assets/262cc0fa-e0af-4a50-8c3d-4465059418b8)
### 术语表
站点级[术语表]({{% relref "docs/guide/shortcodes/term" %}}),提供专用列表页面和用于内联定义的 `term` 短代码。
## 无障碍
全面的 WCAG 2.2 AA 无障碍改进 (#924)
- 所有页面添加跳转到内容链接和 ARIA 地标角色
- 所有交互组件(主题切换、标签页、侧边栏、文件树、下拉菜单、搜索、菜单)添加 ARIA 属性
- 标签页和主题切换的键盘导航方向键、Enter、Escape
- 支持 `prefers-reduced-motion` 和全局 `focus-visible` 样式
- 15 个新的 i18n 无障碍键,在全部 21 个语言环境中提供完整翻译
- 将所有硬编码的英文 `aria-label` 字符串替换为 i18n 查找
## 使用体验优化
- 改进表格可读性样式
- 标题支持 Markdown 属性
- 多语言章节着陆页的活动链接检测改进
- 卡片短代码支持可选的图片 `alt` 参数
- OpenGraph 元数据支持页面资源包图片
- 内容宽度默认保持一致,支持通过 CSS 变量覆盖自定义布局
## 修复
- 修复 render-link 中 `relref` 基础前缀重复问题
- 修复嵌套在步骤中的标签页渲染
- 移动端侧边栏排序和标签与 `menu.main` 对齐
- 侧边栏中遵循 `search.enable` 设置
- 移动端下拉菜单中遵循 `toc` 页面参数
- 增强 FlexSearch 匹配高亮和安全的 DOM 操作
- 修复卡片副标题定位
- 处理子路径部署中 OG 图片路径的前导斜杠
- 修复 FlexSearch 返回结果页数少于预期的问题
- 将 Umami 分析的默认文件改为 `script.js`
- 修复 Hugo v0.156.0+ 的 RSS 作者查找 (`.Site.Params.Author`)
## 文档与 i18n
- 添加意大利语本地化
- 链接 KaTeX 文档
- 将 details 短代码文档更新为尖括号语法
## 贡献者
此版本由 11 位新贡献者共同参与完成:
- [@ghac101](https://github.com/ghac101) - Umami 分析修复、禁用上一篇/下一篇导航
- [@pmarrapese](https://github.com/pmarrapese) - 标题 Markdown 属性支持
- [@Bubbler-4](https://github.com/Bubbler-4) - details 短代码文档
- [@bloovis](https://github.com/bloovis) - FlexSearch 结果计数修复
- [@AntoninPvr](https://github.com/AntoninPvr) - 卡片副标题定位修复
- [@illia-v](https://github.com/illia-v) - 移动端目录和搜索切换修复
- [@gallochri](https://github.com/gallochri) - 意大利语本地化
- [@MatheusFlausino](https://github.com/MatheusFlausino) - LLMs.txt 排除
- [@daniseijo](https://github.com/daniseijo) - 最后修改作者功能
- [@confusedkernel](https://github.com/confusedkernel) - 归档页面
- [@Fenyutanchan](https://github.com/Fenyutanchan) - Hugo v0.156.0 RSS 作者兼容性修复
同时感谢回归贡献者 [@KStocky](https://github.com/KStocky)、[@ldez](https://github.com/ldez)、[@kowyo](https://github.com/kowyo)、[@torbjornbp](https://github.com/torbjornbp)、[@yuri1969](https://github.com/yuri1969) 和 [@PrintN](https://github.com/PrintN) 的持续贡献。
---
**完整变更日志**: https://github.com/imfing/hextra/compare/v0.11.1...v0.12.0

View File

@@ -20,6 +20,7 @@ Hextra یک پوسته مدرن، سریع و کامل برای [Hugo][hugo] ا
- **جستجوی تمام‌متن** - جستجوی تمام‌متن آفلاین داخلی با قدرت FlexSearch، بدون نیاز به پیکربندی اضافی. - **جستجوی تمام‌متن** - جستجوی تمام‌متن آفلاین داخلی با قدرت FlexSearch، بدون نیاز به پیکربندی اضافی.
- **کامل و آماده استفاده** - عناصر Markdown، برجسته‌سازی سینتکس، فرمول‌های ریاضی LaTeX، نمودارها و Shortcodes برای غنی‌تر کردن محتوای شما. فهرست مطالب، مسیرهای ناوبری، صفحه‌بندی، نوار کناری و موارد دیگر همگی به صورت خودکار تولید می‌شوند. - **کامل و آماده استفاده** - عناصر Markdown، برجسته‌سازی سینتکس، فرمول‌های ریاضی LaTeX، نمودارها و Shortcodes برای غنی‌تر کردن محتوای شما. فهرست مطالب، مسیرهای ناوبری، صفحه‌بندی، نوار کناری و موارد دیگر همگی به صورت خودکار تولید می‌شوند.
- **چندزبانه و آماده برای سئو** - ساخت سایت‌های چندزبانه با حالت چندزبانه Hugo آسان شده است. پشتیبانی پیش‌فرض برای تگ‌های سئو، Open Graph و Twitter Cards وجود دارد. - **چندزبانه و آماده برای سئو** - ساخت سایت‌های چندزبانه با حالت چندزبانه Hugo آسان شده است. پشتیبانی پیش‌فرض برای تگ‌های سئو، Open Graph و Twitter Cards وجود دارد.
- **پشتیبانی از دسترس‌پذیری** - اجزای تعاملی از نشانه‌گذاری معنایی، رفتار سازگار با صفحه‌کلید و بررسی‌های خودکار دسترس‌پذیری استفاده می‌کنند تا رابط کاربری در گردش‌کارهای رایج فناوری‌های کمکی قابل استفاده بماند.
## سوال یا بازخورد دارید؟ ## سوال یا بازخورد دارید؟
@@ -38,4 +39,4 @@ Hextra یک پوسته مدرن، سریع و کامل برای [Hugo][hugo] ا
[hugo]: https://gohugo.io/ [hugo]: https://gohugo.io/
[flex-search]: https://github.com/nextapps-de/flexsearch [flex-search]: https://github.com/nextapps-de/flexsearch
[tailwind-css]: https://tailwindcss.com/ [tailwind-css]: https://tailwindcss.com/

View File

@@ -19,6 +19,7 @@ Hextraは、[Tailwind CSS][tailwind-css]を使用して構築された、モダ
- **全文検索** - FlexSearch を利用したオフライン全文検索が組み込まれており、追加の設定は不要です。 - **全文検索** - FlexSearch を利用したオフライン全文検索が組み込まれており、追加の設定は不要です。
- **バッテリーインクルード** - コンテンツを強化するための Markdown、シンタックスハイライト、LaTeX 数式、ダイアグラム、ショートコード要素が利用可能です。目次、パンくずリスト、ページネーション、サイドバーナビゲーションなどはすべて自動生成されます。 - **バッテリーインクルード** - コンテンツを強化するための Markdown、シンタックスハイライト、LaTeX 数式、ダイアグラム、ショートコード要素が利用可能です。目次、パンくずリスト、ページネーション、サイドバーナビゲーションなどはすべて自動生成されます。
- **多言語対応とSEO準備完了** - Hugo の多言語モードを利用して、多言語サイトを簡単に構築できます。SEO タグ、Open Graph、Twitter Cards のサポートも標準で提供されています。 - **多言語対応とSEO準備完了** - Hugo の多言語モードを利用して、多言語サイトを簡単に構築できます。SEO タグ、Open Graph、Twitter Cards のサポートも標準で提供されています。
- **アクセシビリティ対応** - インタラクティブなコンポーネントは、意味論的なマークアップ、キーボードで使いやすい挙動、自動アクセシビリティチェックを備えており、一般的な支援技術の利用環境でも使いやすさを保ちます。
## 質問やフィードバック ## 質問やフィードバック
@@ -37,4 +38,4 @@ Hextraは、[Tailwind CSS][tailwind-css]を使用して構築された、モダ
[hugo]: https://gohugo.io/ [hugo]: https://gohugo.io/
[flex-search]: https://github.com/nextapps-de/flexsearch [flex-search]: https://github.com/nextapps-de/flexsearch
[tailwind-css]: https://tailwindcss.com/ [tailwind-css]: https://tailwindcss.com/

View File

@@ -20,6 +20,7 @@ Designed for building beautiful websites for documentation, blogs, and websites,
- **Full-text Search** - Built-in offline full-text search powered by FlexSearch, no additional configuration required. - **Full-text Search** - Built-in offline full-text search powered by FlexSearch, no additional configuration required.
- **Battery-included** - Markdown, syntax highlighting, LaTeX math formulae, diagrams and Shortcodes elements to enhance your content. Table of contents, breadcrumbs, pagination, sidebar navigation and more are all automatically generated. - **Battery-included** - Markdown, syntax highlighting, LaTeX math formulae, diagrams and Shortcodes elements to enhance your content. Table of contents, breadcrumbs, pagination, sidebar navigation and more are all automatically generated.
- **Multi-language and SEO Ready** - Multi-language sites made easy with Hugo's multilingual mode. Out-of-the-box support is included for SEO tags, Open Graph, and Twitter Cards. - **Multi-language and SEO Ready** - Multi-language sites made easy with Hugo's multilingual mode. Out-of-the-box support is included for SEO tags, Open Graph, and Twitter Cards.
- **Accessibility Support** - Interactive components use semantic markup, keyboard-friendly behavior, and automated accessibility checks to keep the UI usable across common assistive workflows.
## Questions or Feedback? ## Questions or Feedback?

View File

@@ -19,6 +19,7 @@ Hextra 是一个基于 [Tailwind CSS][tailwind-css] 构建的现代化、高性
- **全文搜索** - 内置基于 FlexSearch 的离线全文搜索功能,零配置开箱即用。 - **全文搜索** - 内置基于 FlexSearch 的离线全文搜索功能,零配置开箱即用。
- **功能完备** - 支持 Markdown 语法高亮、LaTeX 数学公式、图表和 Shortcodes 等丰富内容元素。自动生成目录导航、面包屑、分页及侧边栏等组件。 - **功能完备** - 支持 Markdown 语法高亮、LaTeX 数学公式、图表和 Shortcodes 等丰富内容元素。自动生成目录导航、面包屑、分页及侧边栏等组件。
- **多语言与 SEO 友好** - 通过 Hugo 多语言模式轻松构建国际化站点,原生集成 SEO 标签、Open Graph 和 Twitter Cards 支持。 - **多语言与 SEO 友好** - 通过 Hugo 多语言模式轻松构建国际化站点,原生集成 SEO 标签、Open Graph 和 Twitter Cards 支持。
- **无障碍支持** - 交互组件使用语义化标记、友好的键盘交互以及自动化无障碍检查,以便在常见辅助技术工作流中保持良好的可用性。
## 问题或建议? ## 问题或建议?
@@ -37,4 +38,4 @@ Hextra 是一个基于 [Tailwind CSS][tailwind-css] 构建的现代化、高性
[hugo]: https://gohugo.io/ [hugo]: https://gohugo.io/
[flex-search]: https://github.com/nextapps-de/flexsearch [flex-search]: https://github.com/nextapps-de/flexsearch
[tailwind-css]: https://tailwindcss.com/ [tailwind-css]: https://tailwindcss.com/

View File

@@ -13,4 +13,5 @@ next: /docs/advanced/multi-language
{{< card link="multi-language" title="چندزبانه" icon="translate" >}} {{< card link="multi-language" title="چندزبانه" icon="translate" >}}
{{< card link="customization" title="سفارشی‌سازی" icon="pencil" >}} {{< card link="customization" title="سفارشی‌سازی" icon="pencil" >}}
{{< card link="comments" title="سیستم نظرات" icon="chat-alt" >}} {{< card link="comments" title="سیستم نظرات" icon="chat-alt" >}}
{{< /cards >}} {{< card link="additional-pages" title="صفحات اضافی" icon="library" >}}
{{< /cards >}}

View File

@@ -13,4 +13,5 @@ next: /docs/advanced/multi-language
{{< card link="multi-language" title="多言語対応" icon="translate" >}} {{< card link="multi-language" title="多言語対応" icon="translate" >}}
{{< card link="customization" title="カスタマイズ" icon="pencil" >}} {{< card link="customization" title="カスタマイズ" icon="pencil" >}}
{{< card link="comments" title="コメントシステム" icon="chat-alt" >}} {{< card link="comments" title="コメントシステム" icon="chat-alt" >}}
{{< /cards >}} {{< card link="additional-pages" title="追加ページ" icon="library" >}}
{{< /cards >}}

View File

@@ -13,4 +13,5 @@ This section covers some advanced topics of the theme.
{{< card link="multi-language" title="Multi-language" icon="translate" >}} {{< card link="multi-language" title="Multi-language" icon="translate" >}}
{{< card link="customization" title="Customization" icon="pencil" >}} {{< card link="customization" title="Customization" icon="pencil" >}}
{{< card link="comments" title="Comments System" icon="chat-alt" >}} {{< card link="comments" title="Comments System" icon="chat-alt" >}}
{{< card link="additional-pages" title="Additional Pages" icon="library" >}}
{{< /cards >}} {{< /cards >}}

View File

@@ -13,4 +13,5 @@ next: /docs/advanced/multi-language
{{< card link="multi-language" title="多语言支持" icon="translate" >}} {{< card link="multi-language" title="多语言支持" icon="translate" >}}
{{< card link="customization" title="自定义配置" icon="pencil" >}} {{< card link="customization" title="自定义配置" icon="pencil" >}}
{{< card link="comments" title="评论系统" icon="chat-alt" >}} {{< card link="comments" title="评论系统" icon="chat-alt" >}}
{{< /cards >}} {{< card link="additional-pages" title="附加页面" icon="library" >}}
{{< /cards >}}

View File

@@ -0,0 +1,105 @@
---
title: "صفحات اضافی"
weight: 1
prev: /docs/advanced
aliases:
- /docs/advanced/glossary/
---
Hextra چند صفحهٔ اضافی دارد که باید به‌صورت جداگانه فعال شوند: واژه‌نامه و آرشیو.
<!--more-->
## واژه‌نامه
{{< callout type="info" >}}
برای اطلاعات بیشتر دربارهٔ پشتیبانی واژه‌نامهٔ داخلی Hugo، به [مرجع سریع واژه‌نامهٔ Hugo](https://gohugo.io/quick-reference/glossary/) مراجعه کنید.
{{< /callout >}}
### فایل دادهٔ منبع
تعاریف اصطلاحات به‌صورت متمرکز در فایل دادهٔ `termbase.yaml` برای هر [زبان پشتیبانی‌شده](../multi-language/) ذخیره می‌شوند.
{{< filetree/container >}}
{{< filetree/folder name="data" state="open" >}}
{{< filetree/folder name="en" state="open" >}}
{{< filetree/file name="termbase.yaml" >}}
{{< /filetree/folder >}}
{{< filetree/folder name="fr" state="open" >}}
{{< filetree/file name="termbase.yaml" >}}
{{< /filetree/folder >}}
{{< filetree/folder name="ja" state="open" >}}
{{< filetree/file name="termbase.yaml" >}}
{{< /filetree/folder >}}
{{< /filetree/folder >}}
{{< /filetree/container >}}
هر فایل YAML شامل فهرستی از اصطلاحات واژه‌نامه است. هر ورودی شامل موارد زیر است:
- `term`: نام کامل مفهوم یا عبارت.
- `definition`: توضیح یا شرح مختصر اصطلاح.
- `abbr` (اختیاری): مخفف یا سرواژهٔ رایج اصطلاح.
```yaml {filename="data/fa/termbase.yaml"}
- term: seo
abbr: SEO
definition: "بهینه‌سازی موتور جستجو افزایش دیده‌شدن یک صفحهٔ وب در نتایج موتورهای جستجو"
- term: "سازندهٔ سایت ایستا"
definition: "موتورهایی که ورودی متنی را پردازش کرده و صفحات وب ایستا تولید می‌کنند"
```
### صفحهٔ واژه‌نامه
برای رندر شدن صفحهٔ نمایهٔ واژه‌نامه (که شامل فهرست تمام اصطلاحات تعریف‌شده به‌همراه توضیحات و مخفف‌های آن‌هاست)،
باید برای هر زبان پشتیبانی‌شده یک فایل محتوای واژه‌نامهٔ مخصوص همان زبان تعریف شود.
در نام فایل از پسوند کد زبان استفاده کنید؛ برای مثال: `content/glossary/_index.fa.md`.
```markdown {filename="content/glossary/_index.fa.md"}
---
title: واژه‌نامه
layout: glossary
---
```
یک صفحهٔ نمونه از واژه‌نامه در [واژه‌نامه]({{% relref "/glossary" %}}) در دسترس است.
## آرشیو
می‌توانید برای نوشته‌های یک بخش، یک صفحه آرشیو زمانی (گروه‌بندی‌شده بر اساس سال) بسازید.
1. صفحه آرشیو را ایجاد کنید:
```yaml {filename="content/archives/_index.md"}
---
title: Archives
layout: archives
toc: false
---
```
2. (اختیاری) آن را به منوی بالا اضافه کنید:
```yaml {filename="hugo.yaml"}
menu:
main:
- identifier: archives
name: Archives
pageRef: /archives
```
3. (اختیاری، چندزبانه) فایل‌های آرشیو ترجمه‌شده با همان layout اضافه کنید، برای مثال:
- `content/archives/_index.fa.md`
- `content/archives/_index.ja.md`
- `content/archives/_index.zh-cn.md`
4. (اختیاری) بخش مورد استفاده برای آرشیو را تغییر دهید. مقدار پیش‌فرض `blog` است.
```yaml {filename="hugo.yaml"}
params:
archives:
section: blog
```
5. (اختیاری) قالب نمایش تاریخ آیتم‌های آرشیو را تغییر دهید. مقدار پیش‌فرض `Jan 02` است.
```yaml {filename="hugo.yaml"}
params:
archives:
dateFormat: "Jan 02"
```
پیام حالت خالی از کلید ترجمه `noResultsFound` استفاده می‌کند.
یک صفحهٔ نمونه از آرشیو در [آرشیو]({{% relref "/archives" %}}) در دسترس است.

View File

@@ -0,0 +1,105 @@
---
title: "追加ページ"
weight: 1
prev: /docs/advanced
aliases:
- /docs/advanced/glossary/
---
Hextra には明示的に有効化する追加ページがあります。用語集とアーカイブです。
<!--more-->
## 用語集
{{< callout type="info" >}}
Hugo の用語集サポートの詳細については、[Hugo 用語集クイックリファレンス](https://gohugo.io/quick-reference/glossary/)をご覧ください。
{{< /callout >}}
### データソースファイル
用語の定義は、各[対応言語](../multi-language/)ごとに `termbase.yaml` データファイルに一元管理されています。
{{< filetree/container >}}
{{< filetree/folder name="data" state="open" >}}
{{< filetree/folder name="en" state="open" >}}
{{< filetree/file name="termbase.yaml" >}}
{{< /filetree/folder >}}
{{< filetree/folder name="fr" state="open" >}}
{{< filetree/file name="termbase.yaml" >}}
{{< /filetree/folder >}}
{{< filetree/folder name="ja" state="open" >}}
{{< filetree/file name="termbase.yaml" >}}
{{< /filetree/folder >}}
{{< /filetree/folder >}}
{{< /filetree/container >}}
各 YAML データファイルには、用語の一覧が含まれています。各エントリには以下が含まれます:
- `term`:概念やフレーズの正式名称。
- `definition`:用語の簡潔な説明。
- `abbr`(任意):一般的に使用される略語や頭字語。
```yaml {filename="data/ja/termbase.yaml"}
- term: seo
abbr: SEO
definition: "検索エンジン最適化 — ウェブページの検索エンジンでの可視性を向上させる手法"
- term: "静的サイトジェネレーター"
definition: "テキスト入力を処理して静的なウェブページを生成するソフトウェアエンジン"
```
### 用語ページ
定義済みの用語、その説明、および略語を一覧表示するグロッサリーのインデックスページをレンダリングするには、
サポートされている各言語ごとに、言語固有のグロッサリー用コンテンツファイルを定義する必要があります。
ファイル名には言語コードのサフィックスを使用してください。例: `content/glossary/_index.ja.md`。
```markdown {filename="content/glossary/_index.ja.md"}
---
title: 用語集
layout: glossary
---
```
グロッサリーのサンプルページは [用語集]({{% relref "/glossary" %}}) で確認できます。
## アーカイブ
投稿を年ごとにまとめたアーカイブタイムラインページを作成できます。
1. アーカイブページを作成します:
```yaml {filename="content/archives/_index.md"}
---
title: Archives
layout: archives
toc: false
---
```
2. (任意)トップメニューに追加します:
```yaml {filename="hugo.yaml"}
menu:
main:
- identifier: archives
name: Archives
pageRef: /archives
```
3. (任意・多言語)同じ layout を使った翻訳版アーカイブページを追加します。例:
- `content/archives/_index.fa.md`
- `content/archives/_index.ja.md`
- `content/archives/_index.zh-cn.md`
4. (任意)アーカイブ対象のセクションを変更します。デフォルトは `blog` です。
```yaml {filename="hugo.yaml"}
params:
archives:
section: blog
```
5. (任意)アーカイブ項目の日付表示形式を変更します。デフォルトは `Jan 02` です。
```yaml {filename="hugo.yaml"}
params:
archives:
dateFormat: "Jan 02"
```
空状態メッセージは i18n キー `noResultsFound` を使用します。
アーカイブのサンプルページは [アーカイブ]({{% relref "/archives" %}}) で確認できます。

View File

@@ -0,0 +1,105 @@
---
title: "Additional Pages"
weight: 1
prev: /docs/advanced
aliases:
- /docs/advanced/glossary/
---
Hextra includes additional pages that you can enable explicitly: glossary and archives.
<!--more-->
## Glossary
{{< callout type="info" >}}
For more information about Hugo's built-in glossary support, see the [Hugo Glossary Quick Reference](https://gohugo.io/quick-reference/glossary/).
{{< /callout >}}
### Source Data File
Term definitions are centrally stored in a `termbase.yaml` data file for each [supported language](../multi-language/).
{{< filetree/container >}}
{{< filetree/folder name="data" state="open" >}}
{{< filetree/folder name="en" state="open" >}}
{{< filetree/file name="termbase.yaml" >}}
{{< /filetree/folder >}}
{{< filetree/folder name="fr" state="open" >}}
{{< filetree/file name="termbase.yaml" >}}
{{< /filetree/folder >}}
{{< filetree/folder name="ja" state="open" >}}
{{< filetree/file name="termbase.yaml" >}}
{{< /filetree/folder >}}
{{< /filetree/folder >}}
{{< /filetree/container >}}
Each YAML data file contains a list of glossary entries. Every entry includes:
- `term`: The full name of the concept or phrase.
- `definition`: A brief explanation or description of the term.
- `abbr` (optional): A commonly used abbreviation or acronym for the term.
```yaml {filename="data/en/termbase.yaml"}
- term: seo
abbr: SEO
definition: "Search engine optimization improving the visibility of a web page in search engines"
- term: static site generator
definition: "Software engines processing text input to generate static web pages"
```
### Glossary Page
To render the glossary index page (listing all defined terms along with their descriptions and abbreviations),
a language-specific glossary content file must be defined for each supported language. Use the language code suffix
in the filename, for example `content/glossary/_index.en.md`.
```markdown {filename="content/glossary/_index.en.md"}
---
title: Glossary
layout: glossary
---
```
An example glossary page is available at [Glossary]({{% relref "/glossary" %}}).
## Archives
You can create an archive timeline page (grouped by year) for posts in a section.
1. Create the archive page:
```yaml {filename="content/archives/_index.md"}
---
title: Archives
layout: archives
toc: false
---
```
2. (Optional) Add it to the top menu:
```yaml {filename="hugo.yaml"}
menu:
main:
- identifier: archives
name: Archives
pageRef: /archives
```
3. (Optional, multilingual) Add translated archive index pages with the same layout, for example:
- `content/archives/_index.fa.md`
- `content/archives/_index.ja.md`
- `content/archives/_index.zh-cn.md`
4. (Optional) Change the content section used for archives. The default is `blog`.
```yaml {filename="hugo.yaml"}
params:
archives:
section: blog
```
5. (Optional) Change the archive item date format. The default is `Jan 02`.
```yaml {filename="hugo.yaml"}
params:
archives:
dateFormat: "Jan 02"
```
The empty-state message uses the `noResultsFound` i18n key.
An example archive page is available at [Archives]({{% relref "/archives" %}}).

View File

@@ -0,0 +1,105 @@
---
title: "附加页面"
weight: 1
prev: /docs/advanced
aliases:
- /docs/advanced/glossary/
---
Hextra 提供一些需要单独启用的附加页面:术语表与归档页。
<!--more-->
## 术语表
{{< callout type="info" >}}
有关 Hugo 内置术语表支持的更多信息,请参阅 [Hugo 术语表快速参考](https://gohugo.io/quick-reference/glossary/)。
{{< /callout >}}
### 数据源文件
术语定义集中存储在每种[支持语言](../multi-language/)的 `termbase.yaml` 数据文件中。
{{< filetree/container >}}
{{< filetree/folder name="data" state="open" >}}
{{< filetree/folder name="en" state="open" >}}
{{< filetree/file name="termbase.yaml" >}}
{{< /filetree/folder >}}
{{< filetree/folder name="fr" state="open" >}}
{{< filetree/file name="termbase.yaml" >}}
{{< /filetree/folder >}}
{{< filetree/folder name="ja" state="open" >}}
{{< filetree/file name="termbase.yaml" >}}
{{< /filetree/folder >}}
{{< /filetree/folder >}}
{{< /filetree/container >}}
每个 YAML 数据文件包含一组术语条目。每个条目包括:
- `term`:术语或短语的完整名称。
- `definition`:对术语的简要解释或描述。
- `abbr`(可选):术语常用的缩写或首字母缩写。
```yaml {filename="data/zh-cn/termbase.yaml"}
- term: seo
abbr: SEO
definition: "搜索引擎优化——提高网页在搜索引擎中的可见度"
- term: "静态网站生成器"
definition: "将文本输入处理为静态网页的生成引擎"
```
### 术语页面
要渲染词汇表索引页面(列出所有已定义的术语及其说明和缩写),
必须为每种受支持的语言定义一个对应的语言专用词汇表内容文件。
请在文件名中使用语言代码后缀,例如:`content/glossary/_index.zh-cn.md`。
```markdown {filename="content/glossary/_index.zh-cn.md"}
---
title: 术语表
layout: glossary
---
```
示例词汇表页面可在 [术语表]({{% relref "/glossary" %}}) 查看。
## 归档页
你可以为某个内容分区的文章创建按年份分组的归档时间线页面。
1. 创建归档页面:
```yaml {filename="content/archives/_index.md"}
---
title: Archives
layout: archives
toc: false
---
```
2. (可选)将其添加到顶部菜单:
```yaml {filename="hugo.yaml"}
menu:
main:
- identifier: archives
name: Archives
pageRef: /archives
```
3. (可选,多语言)添加使用相同 layout 的多语言归档首页,例如:
- `content/archives/_index.fa.md`
- `content/archives/_index.ja.md`
- `content/archives/_index.zh-cn.md`
4. (可选)修改归档来源分区。默认值为 `blog`。
```yaml {filename="hugo.yaml"}
params:
archives:
section: blog
```
5. (可选)修改归档条目的日期显示格式。默认值是 `Jan 02`。
```yaml {filename="hugo.yaml"}
params:
archives:
dateFormat: "Jan 02"
```
空状态文案使用 i18n 键 `noResultsFound`。
示例归档页面可在 [归档]({{% relref "/archives" %}}) 查看。

View File

@@ -1,7 +1,7 @@
--- ---
title: "Multi-language" title: "Multi-language"
weight: 1 weight: 1
prev: /docs/advanced prev: /docs/advanced/additional-pages
--- ---
Hextra supports creating site with multiple languages using Hugo's [multilingual mode](https://gohugo.io/content-management/multilingual/). Hextra supports creating site with multiple languages using Hugo's [multilingual mode](https://gohugo.io/content-management/multilingual/).

View File

@@ -14,7 +14,7 @@ prev: /docs
می‌توانید با استفاده از مخزن قالب فوق به سرعت شروع به کار کنید. می‌توانید با استفاده از مخزن قالب فوق به سرعت شروع به کار کنید.
<img src="https://docs.github.com/assets/cb-77734/mw-1440/images/help/repository/use-this-template-button.webp" width="500"> <img src="https://docs.github.com/assets/cb-77734/mw-1440/images/help/repository/use-this-template-button.webp" width="500" alt="صفحه مخزن GitHub که دکمه Use this template را نشان می‌دهد">
ما یک [گردش کار GitHub Actions](https://docs.github.com/en/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site#publishing-with-a-custom-github-actions-workflow) ارائه کرده‌ایم که می‌تواند به صورت خودکار سایت شما را ساخته و در GitHub Pages مستقر کند و به صورت رایگان میزبانی کند. ما یک [گردش کار GitHub Actions](https://docs.github.com/en/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site#publishing-with-a-custom-github-actions-workflow) ارائه کرده‌ایم که می‌تواند به صورت خودکار سایت شما را ساخته و در GitHub Pages مستقر کند و به صورت رایگان میزبانی کند.
برای گزینه‌های بیشتر، [استقرار سایت](../guide/deploy-site) را بررسی کنید. برای گزینه‌های بیشتر، [استقرار سایت](../guide/deploy-site) را بررسی کنید.
@@ -201,4 +201,4 @@ git submodule update --remote themes/hextra
{{< card link="../guide/organize-files" title="سازماندهی فایل‌ها" icon="document-duplicate" >}} {{< card link="../guide/organize-files" title="سازماندهی فایل‌ها" icon="document-duplicate" >}}
{{< card link="../guide/configuration" title="پیکربندی" icon="adjustments" >}} {{< card link="../guide/configuration" title="پیکربندی" icon="adjustments" >}}
{{< card link="../guide/markdown" title="Markdown" icon="markdown" >}} {{< card link="../guide/markdown" title="Markdown" icon="markdown" >}}
{{< /cards >}} {{< /cards >}}

View File

@@ -14,7 +14,7 @@ prev: /docs
上記のテンプレートリポジトリを使用して、すぐに始めることができます。 上記のテンプレートリポジトリを使用して、すぐに始めることができます。
<img src="https://docs.github.com/assets/cb-77734/mw-1440/images/help/repository/use-this-template-button.webp" width="500"> <img src="https://docs.github.com/assets/cb-77734/mw-1440/images/help/repository/use-this-template-button.webp" width="500" alt="Use this template ボタンが表示された GitHub リポジトリページ">
[GitHub Actions ワークフロー](https://docs.github.com/ja/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site#publishing-with-a-custom-github-actions-workflow)を提供しており、サイトを自動的にビルドして GitHub Pages にデプロイし、無料でホストすることができます。 [GitHub Actions ワークフロー](https://docs.github.com/ja/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site#publishing-with-a-custom-github-actions-workflow)を提供しており、サイトを自動的にビルドして GitHub Pages にデプロイし、無料でホストすることができます。
その他のオプションについては、[サイトのデプロイ](../guide/deploy-site)を確認してください。 その他のオプションについては、[サイトのデプロイ](../guide/deploy-site)を確認してください。
@@ -201,4 +201,4 @@ git submodule update --remote themes/hextra
{{< card link="../guide/organize-files" title="ファイルの整理" icon="document-duplicate" >}} {{< card link="../guide/organize-files" title="ファイルの整理" icon="document-duplicate" >}}
{{< card link="../guide/configuration" title="設定" icon="adjustments" >}} {{< card link="../guide/configuration" title="設定" icon="adjustments" >}}
{{< card link="../guide/markdown" title="Markdown" icon="markdown" >}} {{< card link="../guide/markdown" title="Markdown" icon="markdown" >}}
{{< /cards >}} {{< /cards >}}

View File

@@ -14,7 +14,7 @@ prev: /docs
You could quickly get started by using the above template repository. You could quickly get started by using the above template repository.
<img src="https://docs.github.com/assets/cb-77734/mw-1440/images/help/repository/use-this-template-button.webp" width="500"> <img src="https://docs.github.com/assets/cb-77734/mw-1440/images/help/repository/use-this-template-button.webp" width="500" alt="GitHub repository page showing the Use this template button">
We have provided a [GitHub Actions workflow](https://docs.github.com/en/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site#publishing-with-a-custom-github-actions-workflow) which can help automatically build and deploy your site to GitHub Pages, and host it for free. We have provided a [GitHub Actions workflow](https://docs.github.com/en/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site#publishing-with-a-custom-github-actions-workflow) which can help automatically build and deploy your site to GitHub Pages, and host it for free.
For more options, check out [Deploy Site](../guide/deploy-site). For more options, check out [Deploy Site](../guide/deploy-site).

View File

@@ -14,7 +14,7 @@ prev: /docs
您可以通过使用上述模板仓库快速开始。 您可以通过使用上述模板仓库快速开始。
<img src="https://docs.github.com/assets/cb-77734/mw-1440/images/help/repository/use-this-template-button.webp" width="500"> <img src="https://docs.github.com/assets/cb-77734/mw-1440/images/help/repository/use-this-template-button.webp" width="500" alt="显示“Use this template”按钮的 GitHub 仓库页面">
我们提供了一个[GitHub Actions工作流](https://docs.github.com/en/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site#publishing-with-a-custom-github-actions-workflow)可以帮助自动构建并将您的站点部署到GitHub Pages并免费托管。 我们提供了一个[GitHub Actions工作流](https://docs.github.com/en/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site#publishing-with-a-custom-github-actions-workflow)可以帮助自动构建并将您的站点部署到GitHub Pages并免费托管。
更多选项,请查看[部署站点](../guide/deploy-site)。 更多选项,请查看[部署站点](../guide/deploy-site)。
@@ -201,4 +201,4 @@ git submodule update --remote themes/hextra
{{< card link="../guide/organize-files" title="组织文件" icon="document-duplicate" >}} {{< card link="../guide/organize-files" title="组织文件" icon="document-duplicate" >}}
{{< card link="../guide/configuration" title="配置" icon="adjustments" >}} {{< card link="../guide/configuration" title="配置" icon="adjustments" >}}
{{< card link="../guide/markdown" title="Markdown" icon="markdown" >}} {{< card link="../guide/markdown" title="Markdown" icon="markdown" >}}
{{< /cards >}} {{< /cards >}}

View File

@@ -121,6 +121,19 @@ params:
height: 20 height: 20
``` ```
### صفحه‌بندی
برای غیرفعال کردن ناوبری قبلی/بعدی در پایین صفحات مستندات یا مقالات وبلاگ:
```yaml {filename="hugo.yaml"}
params:
page:
displayPagination: false # برای صفحات مستندات
blog:
article:
displayPagination: false # برای مقالات وبلاگ
```
## نوار کناری ## نوار کناری
### نوار کناری اصلی ### نوار کناری اصلی
@@ -272,6 +285,8 @@ params:
برای سفارشی کردن فرمت تاریخ، پارامتر `params.dateFormat` را تنظیم کنید. چیدمان آن با [`time.Format`](https://gohugo.io/functions/time/format/) Hugo مطابقت دارد. برای سفارشی کردن فرمت تاریخ، پارامتر `params.dateFormat` را تنظیم کنید. چیدمان آن با [`time.Format`](https://gohugo.io/functions/time/format/) Hugo مطابقت دارد.
علاوه بر این، می‌توانید با فعال کردن پرچم `params.displayUpdatedAuthor` نویسنده آخرین تغییر را نمایش دهید. این نیاز به تنظیم `enableGitInfo: true` دارد.
```yaml {filename="hugo.yaml"} ```yaml {filename="hugo.yaml"}
# تجزیه commit Git # تجزیه commit Git
enableGitInfo: true enableGitInfo: true
@@ -280,6 +295,8 @@ params:
# نمایش تاریخ آخرین تغییر # نمایش تاریخ آخرین تغییر
displayUpdatedDate: true displayUpdatedDate: true
dateFormat: "January 2, 2006" dateFormat: "January 2, 2006"
# نمایش نویسنده آخرین تغییر
displayUpdatedAuthor: true
``` ```
### برچسب‌ها ### برچسب‌ها
@@ -295,9 +312,104 @@ params:
displayTags: true displayTags: true
``` ```
### بزرگنمایی تصویر
بزرگنمایی تصویر به طور پیش‌فرض غیرفعال است. وقتی فعال شود، کلیک روی تصویر Markdown یک نمای بزرگنمایی شده باز می‌کند.
```yaml {filename="hugo.yaml"}
params:
imageZoom:
enable: true
```
برای غیرفعال کردن بزرگنمایی در یک صفحه خاص، این را به front matter صفحه اضافه کنید:
```yaml {filename="content/docs/guide/configuration.md"}
---
imageZoom: false
---
```
اگر می‌خواهید asset Medium Zoom را پین کنید یا از assetهای محلی بارگذاری کنید:
```yaml {filename="hugo.yaml"}
params:
imageZoom:
enable: true
base: "https://cdn.jsdelivr.net/npm/medium-zoom@1.1.0/dist"
# js: "js/medium-zoom.min.js" # اختیاری، نسبت به base یا assetهای محلی
```
### اسکریپت‌های محلی و آینه‌شده
Hextra می‌تواند وابستگی‌های اختیاری فرانت‌اند را از منابع مختلف بارگیری کند:
- تنظیمات پیش‌فرض قالب (CDN)
- URLهای آینه داخلی از طریق `base`
- assetهای محلی Hugo از طریق `js` / `css`
برای assetهای محلی، فایل‌های vendor را در پوشه `assets/` سایت خود قرار دهید و مقادیر پیکربندی را به همان مسیرهای asset اشاره دهید:
```yaml {filename="hugo.yaml"}
params:
imageZoom:
enable: true
js: "js/vendor/medium-zoom.min.js"
mermaid:
js: "js/vendor/mermaid.min.js"
asciinema:
js: "js/vendor/asciinema-player.min.js"
css: "css/vendor/asciinema-player.css"
math:
engine: katex
katex:
css: "css/vendor/katex.min.css"
assets:
- "fonts/KaTeX_Main-Regular.woff2"
- "fonts/KaTeX_Math-Italic.woff2"
search:
type: flexsearch
flexsearch:
js: "js/vendor/flexsearch.bundle.min.js"
```
`imageZoom.enable: true` فقط به این دلیل لازم است که بزرگ‌نمایی تصویر به‌صورت پیش‌فرض غیرفعال است.
برای KaTeX، مطمئن شوید همه فایل‌های فونتی که فایل CSS انتخابی شما به آن‌ها ارجاع می‌دهد منتشر می‌شوند، نه فقط دو موردی که در این مثال آمده‌اند.
برای استفاده از یک آینه داخلی، `base` را تنظیم کنید (و در صورت تفاوت نام فایل، در صورت نیاز `js` / `css` را نیز مشخص کنید):
```yaml {filename="hugo.yaml"}
params:
imageZoom:
base: "https://mirror.example.com/medium-zoom/dist"
mermaid:
base: "https://mirror.example.com/mermaid/dist"
asciinema:
base: "https://mirror.example.com/asciinema-player/dist/bundle"
math:
engine: katex
katex:
base: "https://mirror.example.com/katex/dist"
search:
flexsearch:
base: "https://mirror.example.com/flexsearch/dist"
# js: "flexsearch.bundle.min.js"
```
> [!NOTE]
> برای سفارشی‌سازی منبع بارگذاری MathJax، قالب `layouts/_partials/scripts/mathjax.html` را در پروژه خود بازنویسی کنید.
### عرض صفحه ### عرض صفحه
عرض صفحه را می‌توان با پارامتر `params.page.width` در فایل پیکربندی سفارشی کرد: عرض پوستهٔ صفحه را می‌توان با پارامتر `params.page.width` تنظیم کرد:
```yaml {filename="hugo.yaml"} ```yaml {filename="hugo.yaml"}
params: params:
@@ -306,10 +418,78 @@ params:
width: wide width: wide
``` ```
سه گزینه موجود است: `full`, `wide`, و `normal`. به طور پیش‌فرض، عرض صفحه روی `normal` تنظیم شده است. گزینه‌های `params.page.width`: `full`، `wide`، و `normal`.
عرض محتوای اصلی به صورت پیش‌فرض روی `72rem` ثابت است.
برای سفارشی‌سازی عرض محتوا، متغیر CSS را در فایل استایل سفارشی خود بازنویسی کنید:
```css {filename="assets/css/custom.css"}
:root {
--hextra-max-content-width: 100%;
}
```
به طور مشابه، عرض نوار ناوبری و پاورقی را می‌توان با پارامترهای `params.navbar.width` و `params.footer.width` سفارشی کرد. به طور مشابه، عرض نوار ناوبری و پاورقی را می‌توان با پارامترهای `params.navbar.width` و `params.footer.width` سفارشی کرد.
### منوی زمینه صفحه
منوی زمینه صفحه یک دکمه کشویی ارائه می‌دهد که به کاربران امکان می‌دهد محتوای صفحه را به صورت Markdown کپی کنند یا منبع Markdown خام را مشاهده کنند. این ویژگی برای سایت‌های مستندات که خوانندگان ممکن است بخواهند محتوا را در قالب Markdown به اشتراک بگذارند یا به آن ارجاع دهند، مفید است.
#### فعال‌سازی منوی زمینه
برای فعال‌سازی سراسری منوی زمینه، موارد زیر را به فایل پیکربندی خود اضافه کنید:
```yaml {filename="hugo.yaml"}
params:
page:
contextMenu:
enable: true
```
همچنین باید فرمت خروجی `markdown` را برای صفحات فعال کنید:
```yaml {filename="hugo.yaml"}
outputs:
page: [html, markdown]
section: [html, rss, markdown]
```
#### کنترل هر صفحه
برای فعال یا غیرفعال کردن منوی زمینه برای یک صفحه خاص، از پارامتر `contextMenu` در front matter استفاده کنید:
```yaml {filename="content/docs/example.md"}
---
title: صفحه نمونه
contextMenu: false
---
```
#### لینک‌های سفارشی
می‌توانید لینک‌های سفارشی به منوی کشویی زمینه اضافه کنید. این برای یکپارچه‌سازی با سرویس‌های خارجی مفید است. لینک‌ها از جایگزین‌های زیر پشتیبانی می‌کنند:
- `{url}` - آدرس صفحه (URL-encoded)
- `{title}` - عنوان صفحه (URL-encoded)
- `{markdown_url}` - آدرس محتوای Markdown خام (URL-encoded)
```yaml {filename="hugo.yaml"}
params:
page:
contextMenu:
enable: true
links:
- name: باز کردن در ChatGPT
icon: chatgpt
url: "https://chatgpt.com/?hints=search&q=I%27m+looking+at+this+documentation%3A+{url}%0AHelp+me+understand+how+to+use+it."
```
هر لینک می‌تواند شامل موارد زیر باشد:
- `name` - متن نمایشی لینک
- `icon` - نام آیکون اختیاری (به [آیکون‌ها]({{% relref "docs/guide/shortcodes/icon" %}}) مراجعه کنید)
- `url` - آدرس با جایگزین‌های اختیاری
### نمایه FlexSearch ### نمایه FlexSearch
جستجوی تمام متن با قدرت [FlexSearch](https://github.com/nextapps-de/flexsearch) به طور پیش‌فرض فعال است. جستجوی تمام متن با قدرت [FlexSearch](https://github.com/nextapps-de/flexsearch) به طور پیش‌فرض فعال است.
@@ -327,6 +507,17 @@ params:
index: content index: content
``` ```
همچنین می‌توانید محل بارگیری runtime مربوط به FlexSearch را کنترل کنید:
```yaml {filename="hugo.yaml"}
params:
search:
flexsearch:
version: "0.8.143" # نسخه پیش‌فرض CDN
# base: "https://mirror.example.com/flexsearch/dist" # آدرس پایهٔ remote اختیاری
# js: "js/vendor/flexsearch.bundle.min.js" # مسیر asset محلی یا فایل سفارشی زیر base راه دور
```
گزینه‌های `flexsearch.index`: گزینه‌های `flexsearch.index`:
- `content` - محتوای کامل صفحه (پیش‌فرض) - `content` - محتوای کامل صفحه (پیش‌فرض)
@@ -406,6 +597,15 @@ outputs:
- خلاصه صفحات و تاریخ انتشار - خلاصه صفحات و تاریخ انتشار
- لینک‌های مستقیم به تمام محتوا - لینک‌های مستقیم به تمام محتوا
می‌توانید صفحات یا بخش‌های خاصی را با تنظیم `llms: false` در frontmatter آنها حذف کنید:
```yaml
---
title: "یادداشت‌های داخلی"
llms: false
---
```
فایل llms.txt به طور خودکار از ساختار محتوای شما ایجاد می‌شود و سایت شما را برای ابزارهای هوش مصنوعی و مدل‌های زبانی برای زمینه و مرجع قابل دسترس‌تر می‌کند. فایل llms.txt به طور خودکار از ساختار محتوای شما ایجاد می‌شود و سایت شما را برای ابزارهای هوش مصنوعی و مدل‌های زبانی برای زمینه و مرجع قابل دسترس‌تر می‌کند.
### Open Graph ### Open Graph

View File

@@ -121,6 +121,19 @@ params:
height: 20 height: 20
``` ```
### ページネーション
ドキュメントページやブログ記事の下部にある前へ/次へナビゲーションを無効にするには:
```yaml {filename="hugo.yaml"}
params:
page:
displayPagination: false # ドキュメントページ用
blog:
article:
displayPagination: false # ブログ記事用
```
## サイドバー ## サイドバー
### メインサイドバー ### メインサイドバー
@@ -272,6 +285,8 @@ params:
日付形式をカスタマイズするには、`params.dateFormat` パラメータを設定します。そのレイアウトは Hugo の [`time.Format`](https://gohugo.io/functions/time/format/) に準拠します。 日付形式をカスタマイズするには、`params.dateFormat` パラメータを設定します。そのレイアウトは Hugo の [`time.Format`](https://gohugo.io/functions/time/format/) に準拠します。
さらに、`params.displayUpdatedAuthor` フラグを有効にすると、最終更新の作者を表示できます。これには `enableGitInfo: true` の設定が必要です。
```yaml {filename="hugo.yaml"} ```yaml {filename="hugo.yaml"}
# Git コミットを解析 # Git コミットを解析
enableGitInfo: true enableGitInfo: true
@@ -280,6 +295,8 @@ params:
# 最終更新日を表示 # 最終更新日を表示
displayUpdatedDate: true displayUpdatedDate: true
dateFormat: "2006年1月2日" dateFormat: "2006年1月2日"
# 最終更新の作者を表示
displayUpdatedAuthor: true
``` ```
### タグ ### タグ
@@ -295,9 +312,104 @@ params:
displayTags: true displayTags: true
``` ```
### 画像ズーム
画像ズームはデフォルトで無効です。有効にすると、Markdown 画像をクリックするとズームビューが開きます。
```yaml {filename="hugo.yaml"}
params:
imageZoom:
enable: true
```
特定のページでズームを無効にするには、ページのフロントマターに以下を追加します:
```yaml {filename="content/docs/guide/configuration.md"}
---
imageZoom: false
---
```
Medium Zoom アセットを固定するか、ローカルアセットから読み込む場合:
```yaml {filename="hugo.yaml"}
params:
imageZoom:
enable: true
base: "https://cdn.jsdelivr.net/npm/medium-zoom@1.1.0/dist"
# js: "js/medium-zoom.min.js" # オプション、base またはローカルアセットからの相対パス
```
### ローカルおよびミラー済みスクリプトアセット
Hextra はオプションのフロントエンド依存ファイルを複数のソースから読み込めます:
- テーマのデフォルト設定CDN
- `base` を使った社内ミラー URL
- `js` / `css` を使った Hugo のローカルアセット
ローカルアセットを使う場合は、vendor ファイルをサイトの `assets/` ディレクトリに配置し、そのアセットパスを設定値に指定します:
```yaml {filename="hugo.yaml"}
params:
imageZoom:
enable: true
js: "js/vendor/medium-zoom.min.js"
mermaid:
js: "js/vendor/mermaid.min.js"
asciinema:
js: "js/vendor/asciinema-player.min.js"
css: "css/vendor/asciinema-player.css"
math:
engine: katex
katex:
css: "css/vendor/katex.min.css"
assets:
- "fonts/KaTeX_Main-Regular.woff2"
- "fonts/KaTeX_Math-Italic.woff2"
search:
type: flexsearch
flexsearch:
js: "js/vendor/flexsearch.bundle.min.js"
```
`imageZoom.enable: true` が必要なのは、画像ズームがデフォルトで無効になっているためです。
KaTeX については、この例の 2 つだけでなく、選択した CSS が参照するすべてのフォントファイルを公開してください。
社内ミラーを使う場合は `base` を設定し、ファイル名が異なる場合のみ `js` / `css` を追加してください:
```yaml {filename="hugo.yaml"}
params:
imageZoom:
base: "https://mirror.example.com/medium-zoom/dist"
mermaid:
base: "https://mirror.example.com/mermaid/dist"
asciinema:
base: "https://mirror.example.com/asciinema-player/dist/bundle"
math:
engine: katex
katex:
base: "https://mirror.example.com/katex/dist"
search:
flexsearch:
base: "https://mirror.example.com/flexsearch/dist"
# js: "flexsearch.bundle.min.js"
```
> [!NOTE]
> MathJax の読み込み元をカスタマイズするには、プロジェクト内で `layouts/_partials/scripts/mathjax.html` を上書きしてください。
### ページ幅 ### ページ幅
ページの幅は設定ファイルの `params.page.width` パラメータでカスタマイズできます: レイアウト全体の幅は `params.page.width` で設定できます:
```yaml {filename="hugo.yaml"} ```yaml {filename="hugo.yaml"}
params: params:
@@ -306,10 +418,78 @@ params:
width: wide width: wide
``` ```
利用可能なオプションは `full`、`wide`、`normal` の3つです。デフォルトではページ幅は `normal` に設定されています。 `params.page.width` の選択肢は `full`、`wide`、`normal` す。
本文コンテンツ幅はデフォルトで `72rem` に固定されています。
コンテンツ幅を変更したい場合は、カスタムスタイルシートで CSS 変数を上書きしてください:
```css {filename="assets/css/custom.css"}
:root {
--hextra-max-content-width: 100%;
}
```
同様に、ナビゲーションバーとフッターの幅は `params.navbar.width` と `params.footer.width` パラメータでカスタマイズできます。 同様に、ナビゲーションバーとフッターの幅は `params.navbar.width` と `params.footer.width` パラメータでカスタマイズできます。
### ページコンテキストメニュー
ページコンテキストメニューは、ページの内容を Markdown としてコピーしたり、生の Markdown ソースを表示したりできるドロップダウンボタンを提供します。この機能は、読者が Markdown 形式でコンテンツを共有または参照したいドキュメントサイトに便利です。
#### コンテキストメニューの有効化
コンテキストメニューをグローバルに有効にするには、設定ファイルに以下を追加します:
```yaml {filename="hugo.yaml"}
params:
page:
contextMenu:
enable: true
```
また、ページの `markdown` 出力形式を有効にする必要があります:
```yaml {filename="hugo.yaml"}
outputs:
page: [html, markdown]
section: [html, rss, markdown]
```
#### ページごとの制御
特定のページでコンテキストメニューを有効または無効にするには、フロントマターで `contextMenu` パラメータを使用します:
```yaml {filename="content/docs/example.md"}
---
title: サンプルページ
contextMenu: false
---
```
#### カスタムリンク
コンテキストメニューのドロップダウンにカスタムリンクを追加できます。これは外部サービスとの統合に便利です。リンクは以下のプレースホルダーをサポートしています:
- `{url}` - ページの URLURL エンコード済み)
- `{title}` - ページのタイトルURL エンコード済み)
- `{markdown_url}` - 生の Markdown コンテンツの URLURL エンコード済み)
```yaml {filename="hugo.yaml"}
params:
page:
contextMenu:
enable: true
links:
- name: ChatGPT で開く
icon: chatgpt
url: "https://chatgpt.com/?hints=search&q=I%27m+looking+at+this+documentation%3A+{url}%0AHelp+me+understand+how+to+use+it."
```
各リンクには以下を設定できます:
- `name` - リンクの表示テキスト
- `icon` - オプションのアイコン名([アイコン]({{% relref "docs/guide/shortcodes/icon" %}})を参照)
- `url` - オプションのプレースホルダーを含む URL
### FlexSearch インデックス ### FlexSearch インデックス
[FlexSearch](https://github.com/nextapps-de/flexsearch) を利用した全文検索はデフォルトで有効です。 [FlexSearch](https://github.com/nextapps-de/flexsearch) を利用した全文検索はデフォルトで有効です。
@@ -327,6 +507,17 @@ params:
index: content index: content
``` ```
FlexSearch ランタイムの読み込み元も制御できます:
```yaml {filename="hugo.yaml"}
params:
search:
flexsearch:
version: "0.8.143" # デフォルトの CDN バージョン
# base: "https://mirror.example.com/flexsearch/dist" # オプションのリモート base URL
# js: "js/vendor/flexsearch.bundle.min.js" # ローカルアセットのパス、またはリモート base 配下のカスタムファイル
```
`flexsearch.index` のオプション: `flexsearch.index` のオプション:
- `content` - ページの全文(デフォルト) - `content` - ページの全文(デフォルト)
@@ -406,6 +597,15 @@ outputs:
- ページの要約と公開日 - ページの要約と公開日
- すべてのコンテンツへの直接リンク - すべてのコンテンツへの直接リンク
フロントマターで `llms: false` を設定することで、特定のページやセクションを除外できます:
```yaml
---
title: "内部メモ"
llms: false
---
```
llms.txt ファイルはコンテンツ構造から自動生成され、AI ツールや言語モデルがコンテキストや参照のためにあなたのサイトにアクセスしやすくします。 llms.txt ファイルはコンテンツ構造から自動生成され、AI ツールや言語モデルがコンテキストや参照のためにあなたのサイトにアクセスしやすくします。
### Open Graph ### Open Graph
@@ -420,6 +620,6 @@ llms.txt ファイルはコンテンツ構造から自動生成され、AI ツ
title: "設定" title: "設定"
params: params:
images: images:
- "/img/config-image.jpg" - "img/config-image.jpg"
audio: "config-talk.mp3" audio: "config-talk.mp3"
``` ```

View File

@@ -128,6 +128,19 @@ params:
height: 20 height: 20
``` ```
### Pagination
To disable the previous/next navigation at the bottom of docs pages or blog articles:
```yaml {filename="hugo.yaml"}
params:
page:
displayPagination: false # for docs pages
blog:
article:
displayPagination: false # for blog articles
```
## Sidebar ## Sidebar
### Main Sidebar ### Main Sidebar
@@ -294,6 +307,8 @@ The date of the page's last modification can be displayed by enabling the `param
To customize the date format, set the `params.dateFormat` parameter. Its layout matches Hugo's [`time.Format`](https://gohugo.io/functions/time/format/). To customize the date format, set the `params.dateFormat` parameter. Its layout matches Hugo's [`time.Format`](https://gohugo.io/functions/time/format/).
Additionally, the author of the last modification can be displayed by enabling the `params.displayUpdatedAuthor` flag. This requires `enableGitInfo: true` to be set.
```yaml {filename="hugo.yaml"} ```yaml {filename="hugo.yaml"}
# Parse Git commit # Parse Git commit
enableGitInfo: true enableGitInfo: true
@@ -302,6 +317,8 @@ params:
# Display the last modification date # Display the last modification date
displayUpdatedDate: true displayUpdatedDate: true
dateFormat: "January 2, 2006" dateFormat: "January 2, 2006"
# Display the author of the last modification
displayUpdatedAuthor: true
``` ```
### Tags ### Tags
@@ -317,9 +334,104 @@ params:
displayTags: true displayTags: true
``` ```
### Image Zoom
Image zoom is disabled by default. When enabled, clicking a Markdown image opens a zoomed view.
```yaml {filename="hugo.yaml"}
params:
imageZoom:
enable: true
```
To disable zoom on a specific page, add this to the page front matter:
```yaml {filename="content/docs/guide/configuration.md"}
---
imageZoom: false
---
```
If you want to pin the Medium Zoom asset or load it from local assets:
```yaml {filename="hugo.yaml"}
params:
imageZoom:
enable: true
base: "https://cdn.jsdelivr.net/npm/medium-zoom@1.1.0/dist"
# js: "js/medium-zoom.min.js" # optional, relative to the base or local assets
```
### Local and Mirrored Script Assets
Hextra can load optional frontend dependencies from different sources:
- Theme defaults (CDN)
- Internal mirror URLs via `base`
- Local Hugo assets via `js` / `css`
For local assets, place vendor files under your site's `assets/` directory and point config values to those asset paths:
```yaml {filename="hugo.yaml"}
params:
imageZoom:
enable: true
js: "js/vendor/medium-zoom.min.js"
mermaid:
js: "js/vendor/mermaid.min.js"
asciinema:
js: "js/vendor/asciinema-player.min.js"
css: "css/vendor/asciinema-player.css"
math:
engine: katex
katex:
css: "css/vendor/katex.min.css"
assets:
- "fonts/KaTeX_Main-Regular.woff2"
- "fonts/KaTeX_Math-Italic.woff2"
search:
type: flexsearch
flexsearch:
js: "js/vendor/flexsearch.bundle.min.js"
```
`imageZoom.enable: true` is only needed here because image zoom is disabled by default.
For KaTeX, make sure to publish all font files referenced by your chosen CSS file, not just the two shown in this example.
To use an internal mirror instead, set `base` (and optionally `js` / `css` when the filename differs):
```yaml {filename="hugo.yaml"}
params:
imageZoom:
base: "https://mirror.example.com/medium-zoom/dist"
mermaid:
base: "https://mirror.example.com/mermaid/dist"
asciinema:
base: "https://mirror.example.com/asciinema-player/dist/bundle"
math:
engine: katex
katex:
base: "https://mirror.example.com/katex/dist"
search:
flexsearch:
base: "https://mirror.example.com/flexsearch/dist"
# js: "flexsearch.bundle.min.js"
```
> [!NOTE]
> To customize MathJax source loading, override `layouts/_partials/scripts/mathjax.html` in your site.
### Page Width ### Page Width
The width of the page can be customized by the `params.page.width` parameter in the config file: The layout shell width can be customized by the `params.page.width` parameter in the config file:
```yaml {filename="hugo.yaml"} ```yaml {filename="hugo.yaml"}
params: params:
@@ -328,10 +440,78 @@ params:
width: wide width: wide
``` ```
There are three available options: `full`, `wide`, and `normal`. By default, the page width is set to `normal`. Available options for `params.page.width`: `full`, `wide`, `normal`.
The main reading content width remains fixed at `72rem` by default.
To customize content width, override the CSS variable in your custom stylesheet:
```css {filename="assets/css/custom.css"}
:root {
--hextra-max-content-width: 100%;
}
```
Similarly, the width of the navbar and footer can be customized by the `params.navbar.width` and `params.footer.width` parameters. Similarly, the width of the navbar and footer can be customized by the `params.navbar.width` and `params.footer.width` parameters.
### Page Context Menu
The page context menu provides a dropdown button that allows users to copy the page content as Markdown or view the raw Markdown source. This feature is useful for documentation sites where readers may want to share or reference the content in Markdown format.
#### Enabling the Context Menu
To enable the context menu globally, add the following to your config file:
```yaml {filename="hugo.yaml"}
params:
page:
contextMenu:
enable: true
```
You also need to enable the `markdown` output format for pages:
```yaml {filename="hugo.yaml"}
outputs:
page: [html, markdown]
section: [html, rss, markdown]
```
#### Per-Page Control
To enable or disable the context menu for a specific page, use the `contextMenu` parameter in the front matter:
```yaml {filename="content/docs/example.md"}
---
title: Example Page
contextMenu: false
---
```
#### Custom Links
You can add custom links to the context menu dropdown. This is useful for integrating with external services. The links support the following placeholders:
- `{url}` - The page URL (URL-encoded)
- `{title}` - The page title (URL-encoded)
- `{markdown_url}` - The URL to the raw Markdown content (URL-encoded)
```yaml {filename="hugo.yaml"}
params:
page:
contextMenu:
enable: true
links:
- name: Open in ChatGPT
icon: chatgpt
url: "https://chatgpt.com/?hints=search&q=I%27m+looking+at+this+documentation%3A+{url}%0AHelp+me+understand+how+to+use+it."
```
Each link can have:
- `name` - The display text for the link
- `icon` - An optional icon name (see [Icons]({{% relref "docs/guide/shortcodes/icon" %}}))
- `url` - The URL with optional placeholders
### FlexSearch Index ### FlexSearch Index
Full-text search powered by [FlexSearch](https://github.com/nextapps-de/flexsearch) is enabled by default. Full-text search powered by [FlexSearch](https://github.com/nextapps-de/flexsearch) is enabled by default.
@@ -349,6 +529,17 @@ params:
index: content index: content
``` ```
You can also control where the FlexSearch runtime is loaded from:
```yaml {filename="hugo.yaml"}
params:
search:
flexsearch:
version: "0.8.143" # default CDN version
# base: "https://mirror.example.com/flexsearch/dist" # optional remote base URL
# js: "js/vendor/flexsearch.bundle.min.js" # local asset path, or custom file under remote base
```
Options for `flexsearch.index`: Options for `flexsearch.index`:
- `content` - full content of the page (default) - `content` - full content of the page (default)
@@ -383,16 +574,6 @@ excludeSearch: true
--- ---
``` ```
### Google Analytics
To enable [Google Analytics](https://marketingplatform.google.com/about/analytics/), set `services.googleAnalytics.ID` flag in `hugo.yaml`:
```yaml {filename="hugo.yaml"}
services:
googleAnalytics:
ID: G-MEASUREMENT_ID
```
### Google Search Index ### Google Search Index
To [block Google Search](https://developers.google.com/search/docs/crawling-indexing/block-indexing) from indexing a page, set `noindex` to true in your page frontmatter: To [block Google Search](https://developers.google.com/search/docs/crawling-indexing/block-indexing) from indexing a page, set `noindex` to true in your page frontmatter:
@@ -409,7 +590,25 @@ To exclude an entire directory, use the [`cascade`](https://gohugo.io/configurat
> To block search crawlers, you can make a [`robots.txt` template](https://gohugo.io/templates/robots/). > To block search crawlers, you can make a [`robots.txt` template](https://gohugo.io/templates/robots/).
> However, `robots.txt` instructions do not necessarily keep a page out of Google search results. > However, `robots.txt` instructions do not necessarily keep a page out of Google search results.
### Umami Analytics ### Analytics
Hextra has support for several different analytics solutions. Hextra only supports analytics in production environments. This is to ensure that you do not accidentally send analytic events when working locally. If, however, you do want to test analytics locally, you can run a production server using:
```
hugo server --environment production
```
#### Google Analytics
To enable [Google Analytics](https://marketingplatform.google.com/about/analytics/), set `services.googleAnalytics.ID` flag in `hugo.yaml`:
```yaml {filename="hugo.yaml"}
services:
googleAnalytics:
ID: G-MEASUREMENT_ID
```
#### Umami Analytics
To enable [Umami](https://umami.is/docs/), set `params.analytics.umami.serverURL` and `params.analytics.umami.websiteID` flag in `hugo.yaml`: To enable [Umami](https://umami.is/docs/), set `params.analytics.umami.serverURL` and `params.analytics.umami.websiteID` flag in `hugo.yaml`:
@@ -419,7 +618,7 @@ params:
umami: umami:
serverURL: "https://example.com" serverURL: "https://example.com"
websiteID: "94db1cb1-74f4-4a40-ad6c-962362670409" websiteID: "94db1cb1-74f4-4a40-ad6c-962362670409"
# scriptName: "umami.js" # optional (default: umami.js) # scriptName: "script.js" # optional (default: script.js)
# https://umami.is/docs/tracker-configuration#data-host-url # https://umami.is/docs/tracker-configuration#data-host-url
# hostURL: "http://stats.example.org" # optional # hostURL: "http://stats.example.org" # optional
# https://umami.is/docs/tracker-configuration#data-auto-track # https://umami.is/docs/tracker-configuration#data-auto-track
@@ -436,7 +635,7 @@ params:
# doNotTrack: "true" # optional # doNotTrack: "true" # optional
``` ```
### Matomo Analytics #### Matomo Analytics
To enable [Matomo](https://matomo.org/), set `params.analytics.matomo.URL` and `params.analytics.matomo.ID` flag in `hugo.yaml`: To enable [Matomo](https://matomo.org/), set `params.analytics.matomo.URL` and `params.analytics.matomo.ID` flag in `hugo.yaml`:
@@ -448,6 +647,32 @@ params:
websiteID: "94db1cb1-74f4-4a40-ad6c-962362670409" websiteID: "94db1cb1-74f4-4a40-ad6c-962362670409"
``` ```
#### GoatCounter Analytics
To enable [GoatCounter](https://www.goatcounter.com/), set `params.analytics.goatCounter.code` in `hugo.yaml`
All settings available here are mirrors of the settings described in GoatCounter [settings](https://www.goatcounter.com/help/js#settings-44186)
```yaml {filename="hugo.yaml"}
params:
analytics:
goatCounter:
code: "ABCDE"
# Optional Settings
#------------------
# disables automatic collection of data
# noOnload: true
# disables event binding. See more here https://www.goatcounter.com/help/events
# noEvents: true
# allows data collection from local addresses. Use this with a production environment to test locally
# allowLocal: true
# Allow data collection when a page is loaded in a frame or iframe
# allowFrame: true
```
### LLMS.txt Support ### LLMS.txt Support
To enable [llms.txt](https://llmstxt.org/) output format for your site, which provides a structured text outline for [large language models](https://en.wikipedia.org/wiki/Large_language_model) and AI agents, add the `llms` output format to your site's `hugo.yaml`: To enable [llms.txt](https://llmstxt.org/) output format for your site, which provides a structured text outline for [large language models](https://en.wikipedia.org/wiki/Large_language_model) and AI agents, add the `llms` output format to your site's `hugo.yaml`:
@@ -467,6 +692,15 @@ This will generate an `llms.txt` file at your site's root containing:
- Page summaries and publication dates - Page summaries and publication dates
- Direct links to all content - Direct links to all content
You can exclude specific pages or sections by setting `llms: false` in their front matter:
```yaml
---
title: "Internal Notes"
llms: false
---
```
The llms.txt file is automatically generated from your content structure and makes your site more accessible to AI tools and language models for context and reference. The llms.txt file is automatically generated from your content structure and makes your site more accessible to AI tools and language models for context and reference.
### Open Graph ### Open Graph
@@ -478,15 +712,15 @@ To add [Open Graph](https://ogp.me/) metadata, you can:
As a page can have multiple `image` and `video` tags, place their values in an array. As a page can have multiple `image` and `video` tags, place their values in an array.
Other Open Graph properties can have only one value. Other Open Graph properties can have only one value.
{{< tabs items="Page Level, Global Level" >}} {{< tabs >}}
{{< tab >}} {{< tab name="Page Level" >}}
```md {filename="mypage.md"} ```md {filename="mypage.md"}
--- ---
title: "My Page" title: "My Page"
params: params:
images: images:
- "/images/image01.jpg" - "images/image01.jpg"
audio: "podcast02.mp3" audio: "podcast02.mp3"
videos: videos:
- "video01.mp4" - "video01.mp4"
@@ -495,11 +729,11 @@ params:
Page content. Page content.
``` ```
{{< /tab >}} {{< /tab >}}
{{< tab >}} {{< tab name="Global Level" >}}
```yaml {filename="hugo.yaml"} ```yaml {filename="hugo.yaml"}
params: params:
images: images:
- "/images/image01.jpg" - "images/image01.jpg"
audio: "podcast02.mp3" audio: "podcast02.mp3"
videos: videos:
- "video01.mp4" - "video01.mp4"

View File

@@ -121,6 +121,19 @@ params:
height: 20 height: 20
``` ```
### 分页导航
禁用文档页面或博客文章底部的上一篇/下一篇导航:
```yaml {filename="hugo.yaml"}
params:
page:
displayPagination: false # 文档页面
blog:
article:
displayPagination: false # 博客文章
```
## 侧边栏 ## 侧边栏
### 主侧边栏 ### 主侧边栏
@@ -272,6 +285,8 @@ params:
要自定义日期格式,设置 `params.dateFormat` 参数。其布局与 Hugo 的 [`time.Format`](https://gohugo.io/functions/time/format/) 匹配。 要自定义日期格式,设置 `params.dateFormat` 参数。其布局与 Hugo 的 [`time.Format`](https://gohugo.io/functions/time/format/) 匹配。
此外,可以通过启用 `params.displayUpdatedAuthor` 标志来显示最后修改的作者。这需要设置 `enableGitInfo: true`。
```yaml {filename="hugo.yaml"} ```yaml {filename="hugo.yaml"}
# 解析 Git 提交 # 解析 Git 提交
enableGitInfo: true enableGitInfo: true
@@ -280,6 +295,8 @@ params:
# 显示最后修改日期 # 显示最后修改日期
displayUpdatedDate: true displayUpdatedDate: true
dateFormat: "2006年1月2日" dateFormat: "2006年1月2日"
# 显示最后修改的作者
displayUpdatedAuthor: true
``` ```
### 标签 ### 标签
@@ -295,9 +312,104 @@ params:
displayTags: true displayTags: true
``` ```
### 图片缩放
图片缩放默认禁用。启用后,点击 Markdown 图片会打开放大视图。
```yaml {filename="hugo.yaml"}
params:
imageZoom:
enable: true
```
要在特定页面禁用缩放,在页面的 front matter 中添加:
```yaml {filename="content/docs/guide/configuration.md"}
---
imageZoom: false
---
```
如果想固定 Medium Zoom 资源或从本地资源加载:
```yaml {filename="hugo.yaml"}
params:
imageZoom:
enable: true
base: "https://cdn.jsdelivr.net/npm/medium-zoom@1.1.0/dist"
# js: "js/medium-zoom.min.js" # 可选,相对于 base 或本地资源
```
### 本地与镜像脚本资源
Hextra 可以从多种来源加载可选的前端依赖:
- 主题默认配置CDN
- 通过 `base` 指定的内部镜像 URL
- 通过 `js` / `css` 指定的 Hugo 本地资源
对于本地资源,请将 vendor 文件放在站点的 `assets/` 目录下,并在配置中引用这些资源路径:
```yaml {filename="hugo.yaml"}
params:
imageZoom:
enable: true
js: "js/vendor/medium-zoom.min.js"
mermaid:
js: "js/vendor/mermaid.min.js"
asciinema:
js: "js/vendor/asciinema-player.min.js"
css: "css/vendor/asciinema-player.css"
math:
engine: katex
katex:
css: "css/vendor/katex.min.css"
assets:
- "fonts/KaTeX_Main-Regular.woff2"
- "fonts/KaTeX_Math-Italic.woff2"
search:
type: flexsearch
flexsearch:
js: "js/vendor/flexsearch.bundle.min.js"
```
这里只有因为图片缩放默认关闭,才需要设置 `imageZoom.enable: true`。
对于 KaTeX请确保发布你所选 CSS 文件引用的全部字体文件,而不仅仅是此示例中的两个。
如果要使用内部镜像,请设置 `base`;只有当文件名不同时,才需要额外设置 `js` / `css`
```yaml {filename="hugo.yaml"}
params:
imageZoom:
base: "https://mirror.example.com/medium-zoom/dist"
mermaid:
base: "https://mirror.example.com/mermaid/dist"
asciinema:
base: "https://mirror.example.com/asciinema-player/dist/bundle"
math:
engine: katex
katex:
base: "https://mirror.example.com/katex/dist"
search:
flexsearch:
base: "https://mirror.example.com/flexsearch/dist"
# js: "flexsearch.bundle.min.js"
```
> [!NOTE]
> 如需自定义 MathJax 的加载来源,请在项目中覆盖 `layouts/_partials/scripts/mathjax.html`。
### 页面宽度 ### 页面宽度
页面宽度可通过配置文件中的 `params.page.width` 参数自定义 页面整体布局宽度可通过 `params.page.width` 配置
```yaml {filename="hugo.yaml"} ```yaml {filename="hugo.yaml"}
params: params:
@@ -306,10 +418,78 @@ params:
width: wide width: wide
``` ```
有三个可用选项:`full`、`wide` 和 `normal`。默认页面宽度为 `normal`。 `params.page.width` 可用选项:`full`、`wide`、`normal`。
正文内容宽度默认固定为 `72rem`。
如需自定义内容宽度,请在自定义样式表中覆盖 CSS 变量:
```css {filename="assets/css/custom.css"}
:root {
--hextra-max-content-width: 100%;
}
```
类似地,导航栏和页脚的宽度可以通过 `params.navbar.width` 和 `params.footer.width` 参数自定义。 类似地,导航栏和页脚的宽度可以通过 `params.navbar.width` 和 `params.footer.width` 参数自定义。
### 页面上下文菜单
页面上下文菜单提供一个下拉按钮,允许用户将页面内容复制为 Markdown 或查看原始 Markdown 源码。此功能对于读者可能希望以 Markdown 格式共享或引用内容的文档站点非常有用。
#### 启用上下文菜单
要全局启用上下文菜单,请在配置文件中添加以下内容:
```yaml {filename="hugo.yaml"}
params:
page:
contextMenu:
enable: true
```
您还需要为页面启用 `markdown` 输出格式:
```yaml {filename="hugo.yaml"}
outputs:
page: [html, markdown]
section: [html, rss, markdown]
```
#### 单页控制
要为特定页面启用或禁用上下文菜单,请在 front matter 中使用 `contextMenu` 参数:
```yaml {filename="content/docs/example.md"}
---
title: 示例页面
contextMenu: false
---
```
#### 自定义链接
您可以向上下文菜单下拉列表添加自定义链接。这对于与外部服务集成非常有用。链接支持以下占位符:
- `{url}` - 页面 URLURL 编码)
- `{title}` - 页面标题URL 编码)
- `{markdown_url}` - 原始 Markdown 内容的 URLURL 编码)
```yaml {filename="hugo.yaml"}
params:
page:
contextMenu:
enable: true
links:
- name: 在 ChatGPT 中打开
icon: chatgpt
url: "https://chatgpt.com/?hints=search&q=I%27m+looking+at+this+documentation%3A+{url}%0AHelp+me+understand+how+to+use+it."
```
每个链接可以包含:
- `name` - 链接的显示文本
- `icon` - 可选的图标名称(参见[图标]({{% relref "docs/guide/shortcodes/icon" %}})
- `url` - 包含可选占位符的 URL
### FlexSearch 索引 ### FlexSearch 索引
默认启用由 [FlexSearch](https://github.com/nextapps-de/flexsearch) 提供的全文搜索。 默认启用由 [FlexSearch](https://github.com/nextapps-de/flexsearch) 提供的全文搜索。
@@ -327,6 +507,17 @@ params:
index: content index: content
``` ```
你也可以控制 FlexSearch runtime 的加载来源:
```yaml {filename="hugo.yaml"}
params:
search:
flexsearch:
version: "0.8.143" # 默认 CDN 版本
# base: "https://mirror.example.com/flexsearch/dist" # 可选的远程 base URL
# js: "js/vendor/flexsearch.bundle.min.js" # 本地资源路径,或远程 base 下的自定义文件
```
`flexsearch.index` 的选项: `flexsearch.index` 的选项:
- `content` - 页面的完整内容(默认) - `content` - 页面的完整内容(默认)
@@ -406,6 +597,15 @@ outputs:
- 页面摘要和发布日期 - 页面摘要和发布日期
- 所有内容的直接链接 - 所有内容的直接链接
您可以通过在 front matter 中设置 `llms: false` 来排除特定页面或章节:
```yaml
---
title: "内部笔记"
llms: false
---
```
llms.txt 文件根据内容结构自动生成,使 AI 工具和语言模型更容易获取上下文和参考。 llms.txt 文件根据内容结构自动生成,使 AI 工具和语言模型更容易获取上下文和参考。
### Open Graph ### Open Graph
@@ -420,6 +620,6 @@ llms.txt 文件根据内容结构自动生成,使 AI 工具和语言模型更
title: "配置" title: "配置"
params: params:
images: images:
- "/img/config-image.jpg" - "img/config-image.jpg"
audio: "config-talk.mp3" audio: "config-talk.mp3"
``` ```

View File

@@ -3,7 +3,7 @@ title: "LaTeX"
weight: 4 weight: 4
--- ---
عبارات ریاضی LaTeX به طور پیش‌فرض با استفاده از \(\KaTeX\) نمایش داده می‌شوند. کافی است آن‌ها را در محتوای Markdown خود قرار دهید بدون نیاز به هیچ پیکربندی دستی. عبارات ریاضی LaTeX به طور پیش‌فرض با استفاده از \(\KaTeX\) ([katex.org](https://katex.org/)) نمایش داده می‌شوند. کافی است آن‌ها را در محتوای Markdown خود قرار دهید بدون نیاز به هیچ پیکربندی دستی.
## نحوه استفاده ## نحوه استفاده
@@ -143,4 +143,4 @@ params:
[katex]: https://katex.org/ [katex]: https://katex.org/
[mathjax]: https://www.mathjax.org/ [mathjax]: https://www.mathjax.org/
[mhchem]: https://mhchem.github.io/MathJax-mhchem/ [mhchem]: https://mhchem.github.io/MathJax-mhchem/
[hugo-transform-tomath]: https://gohugo.io/functions/transform/tomath/ [hugo-transform-tomath]: https://gohugo.io/functions/transform/tomath/

View File

@@ -3,7 +3,7 @@ title: "LaTeX"
weight: 4 weight: 4
--- ---
LaTeX の数式表現はデフォルトで \(\KaTeX\) を使用してレンダリングされます。特別な設定なしで、Markdown コンテンツ内に直接記述できます。 LaTeX の数式表現はデフォルトで \(\KaTeX\) ([katex.org](https://katex.org/)) を使用してレンダリングされます。特別な設定なしで、Markdown コンテンツ内に直接記述できます。
## 使用方法 ## 使用方法
@@ -143,4 +143,4 @@ params:
[katex]: https://katex.org/ [katex]: https://katex.org/
[mathjax]: https://www.mathjax.org/ [mathjax]: https://www.mathjax.org/
[mhchem]: https://mhchem.github.io/MathJax-mhchem/ [mhchem]: https://mhchem.github.io/MathJax-mhchem/
[hugo-transform-tomath]: https://gohugo.io/functions/transform/tomath/ [hugo-transform-tomath]: https://gohugo.io/functions/transform/tomath/

View File

@@ -3,7 +3,7 @@ title: "LaTeX"
weight: 4 weight: 4
--- ---
LaTeX math expressions are rendered using \(\KaTeX\) by default. Simply start including them in your Markdown content without any manual configurations. LaTeX math expressions are rendered using \(\KaTeX\) ([katex.org](https://katex.org/)) by default. Simply start including them in your Markdown content without any manual configurations.
## Usage ## Usage

View File

@@ -14,6 +14,7 @@ Hextra provides a collection of beautiful shortcodes to enhance your content.
{{< card link="cards" title="Cards" icon="card" >}} {{< card link="cards" title="Cards" icon="card" >}}
{{< card link="details" title="Details" icon="chevron-right" >}} {{< card link="details" title="Details" icon="chevron-right" >}}
{{< card link="filetree" title="FileTree" icon="folder-tree" >}} {{< card link="filetree" title="FileTree" icon="folder-tree" >}}
{{< card link="term" title="Term" icon="question-mark-circle" >}}
{{< card link="icon" title="Icon" icon="badge-check" >}} {{< card link="icon" title="Icon" icon="badge-check" >}}
{{< card link="steps" title="Steps" icon="one" >}} {{< card link="steps" title="Steps" icon="one" >}}
{{< card link="tabs" title="Tabs" icon="collection" >}} {{< card link="tabs" title="Tabs" icon="collection" >}}

View File

@@ -6,15 +6,15 @@ linkTitle: Cards
## Example ## Example
{{< cards >}} {{< cards >}}
{{< card link="../callout" title="Callout" icon="warning" >}} {{< card link="../callout" title="Callout" icon="warning" >}}
{{< card link="../callout" title="Card with tag" icon="tag" tag="custom tag">}} {{< card link="../callout" title="Card with tag" icon="tag" tag="custom tag">}}
{{< card link="/" title="No Icon" >}} {{< card link="/" title="No Icon" >}}
{{< /cards >}} {{< /cards >}}
{{< cards >}} {{< cards >}}
{{< card link="/" title="Image Card" image="https://github.com/user-attachments/assets/71b7e3ec-1a8d-4582-b600-5425c6cc0407" subtitle="Internet Image" >}} {{< card link="/" title="Image Card" image="https://github.com/user-attachments/assets/71b7e3ec-1a8d-4582-b600-5425c6cc0407" subtitle="Internet Image" >}}
{{< card link="/" title="Local Image" image="/images/card-image-unprocessed.jpg" subtitle="Raw image under static directory." >}} {{< card link="/" title="Local Image" image="/images/card-image-unprocessed.jpg" subtitle="Raw image under static directory." >}}
{{< card link="/" title="Local Image" image="images/space.jpg" subtitle="Image under assets directory, processed by Hugo." method="Resize" options="600x q80 webp" >}} {{< card link="/" title="Local Image" image="images/space.jpg" subtitle="Image under assets directory, processed by Hugo." method="Resize" options="600x q80 webp" >}}
{{< /cards >}} {{< /cards >}}
## Usage ## Usage
@@ -32,28 +32,30 @@ linkTitle: Cards
{{</* card link="/" title="Image Card" image="https://source.unsplash.com/featured/800x600?landscape" subtitle="Unsplash Landscape" */>}} {{</* card link="/" title="Image Card" image="https://source.unsplash.com/featured/800x600?landscape" subtitle="Unsplash Landscape" */>}}
{{</* card link="/" title="Local Image" image="/images/card-image-unprocessed.jpg" subtitle="Raw image under static directory." */>}} {{</* card link="/" title="Local Image" image="/images/card-image-unprocessed.jpg" subtitle="Raw image under static directory." */>}}
{{</* card link="/" title="Local Image" image="images/space.jpg" subtitle="Image under assets directory, processed by Hugo." method="Resize" options="600x q80 webp" */>}} {{</* card link="/" title="Local Image" image="images/space.jpg" subtitle="Image under assets directory, processed by Hugo." method="Resize" options="600x q80 webp" */>}}
{{</* card link="/" title="Custom Alt Text" image="images/space.jpg" alt="A beautiful view of space with stars and galaxies" subtitle="Image with custom alt text for accessibility." */>}}
{{</* /cards */>}} {{</* /cards */>}}
``` ```
## Card Parameters ## Card Parameters
| Parameter | Description | | Parameter | Description |
|-------------|----------------------------------------------------------------------------------------| | ---------- | -------------------------------------------------------------------------- |
| `link` | URL (internal or external). | | `link` | URL (internal or external). |
| `title` | Title heading for the card. | | `title` | Title heading for the card. |
| `subtitle` | Subtitle heading (supports Markdown). | | `subtitle` | Subtitle heading (supports Markdown). |
| `icon` | Name of the icon. See [icons]({{% relRef "icon" %}}) for more information. | | `icon` | Name of the icon. See [icons]({{% relRef "icon" %}}) for more information. |
## Image Card ## Image Card
Additionally, the card supports adding image and processing through these parameters: Additionally, the card supports adding image and processing through these parameters:
| Parameter | Description | | Parameter | Description |
|--------------|----------------------------------------------------| | ------------ | ------------------------------------------------------------------- |
| `image` | Specifies the image URL for the card. | | `image` | Specifies the image URL for the card. |
| `method` | Sets Hugo's image processing method. | | `alt` | Alternative text for the image (defaults to title if not provided). |
| `options` | Configures Hugo's image processing options. | | `method` | Sets Hugo's image processing method. |
| `imageStyle` | Used to fill the style attribute of the image tag. | | `options` | Configures Hugo's image processing options. |
| `imageStyle` | Used to fill the style attribute of the image tag. |
Card supports three kinds of images: Card supports three kinds of images:
@@ -71,19 +73,19 @@ For more on Hugo's built in image processing commands, methods, and options see
Card supports adding tags which could be useful to show extra status information. Card supports adding tags which could be useful to show extra status information.
| Parameter | Description | | Parameter | Description |
|-------------|----------------------------------------------------------------------------------------| | ----------- | -------------------------------------------------------------------------------------- |
| `tag` | Text in tag. | | `tag` | Text in tag. |
| `tagColor` | Color of the tag. See [badges]({{% relRef "others/#badges" %}}) for more information. | | `tagColor` | Color of the tag. See [badges]({{% relRef "others/#badges" %}}) for more information. |
| `tagIcon` | Icon of the tag. See [badges]({{% relRef "others/#badges" %}}) for more information. | | `tagIcon` | Icon of the tag. See [badges]({{% relRef "others/#badges" %}}) for more information. |
| `tagBorder` | Border of the tag. See [badges]({{% relRef "others/#badges" %}}) for more information. | | `tagBorder` | Border of the tag. See [badges]({{% relRef "others/#badges" %}}) for more information. |
{{< cards >}} {{< cards >}}
{{< card link="../callout" title="Card with default tag" tag="tag text" >}} {{< card link="../callout" title="Card with default tag" tag="tag text" >}}
{{< card link="../callout" title="Card with red tag" tag="tag text" tagColor="red" >}} {{< card link="../callout" title="Card with red tag" tag="tag text" tagColor="red" >}}
{{< card link="../callout" title="Card with blue tag" tag="tag text" tagColor="blue" >}} {{< card link="../callout" title="Card with blue tag" tag="tag text" tagColor="blue" >}}
{{< card link="../callout" title="Card with yellow tag" tag="tag text" tagColor="yellow" tagIcon="sparkles" tagBorder=false >}} {{< card link="../callout" title="Card with yellow tag" tag="tag text" tagColor="yellow" tagIcon="sparkles" tagBorder=false >}}
{{< card link="/" title="Image Card" image="/images/card-image-unprocessed.jpg" subtitle="Image" tag="tag text" tagColor="green" >}} {{< card link="/" title="Image Card" image="/images/card-image-unprocessed.jpg" subtitle="Image" tag="tag text" tagColor="green" >}}
{{< card link="/" title="Image Card" image="images/space.jpg" subtitle="Image" tag="tag text" tagColor="purple" tagIcon="sparkles" tagBorder=false >}} {{< card link="/" title="Image Card" image="images/space.jpg" subtitle="Image" tag="tag text" tagColor="purple" tagIcon="sparkles" tagBorder=false >}}
{{< /cards >}} {{< /cards >}}
``` ```
@@ -102,13 +104,13 @@ Card supports adding tags which could be useful to show extra status information
You can specify the maximum number of columns for cards to span by passing the `cols` parameter to the `cards` shortcode. Note that columns will still be collapsed on smaller screens. You can specify the maximum number of columns for cards to span by passing the `cols` parameter to the `cards` shortcode. Note that columns will still be collapsed on smaller screens.
{{< cards cols="1" >}} {{< cards cols="1" >}}
{{< card link="/" title="Top Card" >}} {{< card link="/" title="Top Card" >}}
{{< card link="/" title="Bottom Card" >}} {{< card link="/" title="Bottom Card" >}}
{{< /cards >}} {{< /cards >}}
{{< cards cols="2" >}} {{< cards cols="2" >}}
{{< card link="/" title="Left Card" >}} {{< card link="/" title="Left Card" >}}
{{< card link="/" title="Right Card" >}} {{< card link="/" title="Right Card" >}}
{{< /cards >}} {{< /cards >}}
``` ```
@@ -122,4 +124,3 @@ You can specify the maximum number of columns for cards to span by passing the `
{{</* card link="/" title="Right Card" */>}} {{</* card link="/" title="Right Card" */>}}
{{</* /cards */>}} {{</* /cards */>}}
``` ```

View File

@@ -8,36 +8,36 @@ title: جزئیات
## مثال ## مثال
{{% details title="جزئیات" %}} {{< details title="جزئیات" >}}
این محتوای جزئیات است. این محتوای جزئیات است.
مارک‌داون **پشتیبانی می‌شود**. مارک‌داون **پشتیبانی می‌شود**.
{{% /details %}} {{< /details >}}
{{% details title="برای نمایش کلیک کنید" closed="true" %}} {{< details title="برای نمایش کلیک کنید" closed="true" >}}
این به‌صورت پیش‌فرض مخفی خواهد بود. این به‌صورت پیش‌فرض مخفی خواهد بود.
{{% /details %}} {{< /details >}}
## نحوه استفاده ## نحوه استفاده
````markdown ````markdown
{{%/* details title="جزئیات" */%}} {{</* details title="جزئیات" */>}}
این محتوای جزئیات است. این محتوای جزئیات است.
مارک‌داون **پشتیبانی می‌شود**. مارک‌داون **پشتیبانی می‌شود**.
{{%/* /details */%}} {{</* /details */>}}
```` ````
````markdown ````markdown
{{%/* details title="برای نمایش کلیک کنید" closed="true" */%}} {{</* details title="برای نمایش کلیک کنید" closed="true" */>}}
این به‌صورت پیش‌فرض مخفی خواهد بود. این به‌صورت پیش‌فرض مخفی خواهد بود.
{{%/* /details */%}} {{</* /details */>}}
```` ````

View File

@@ -8,36 +8,36 @@ title: 詳細
## 例 ## 例
{{% details title="詳細" %}} {{< details title="詳細" >}}
これは詳細のコンテンツです。 これは詳細のコンテンツです。
Markdown は **サポートされています** Markdown は **サポートされています**
{{% /details %}} {{< /details >}}
{{% details title="クリックして表示" closed="true" %}} {{< details title="クリックして表示" closed="true" >}}
これはデフォルトで非表示になります。 これはデフォルトで非表示になります。
{{% /details %}} {{< /details >}}
## 使用方法 ## 使用方法
````markdown ````markdown
{{%/* details title="詳細" */%}} {{</* details title="詳細" */>}}
これは詳細のコンテンツです。 これは詳細のコンテンツです。
Markdown は **サポートされています**。 Markdown は **サポートされています**。
{{%/* /details */%}} {{</* /details */>}}
```` ````
````markdown ````markdown
{{%/* details title="クリックして表示" closed="true" */%}} {{</* details title="クリックして表示" closed="true" */>}}
これはデフォルトで非表示になります。 これはデフォルトで非表示になります。
{{%/* /details */%}} {{</* /details */>}}
```` ````

View File

@@ -8,36 +8,36 @@ A built-in component to display a collapsible content.
## Example ## Example
{{% details title="Details" %}} {{< details title="Details" >}}
This is the content of the details. This is the content of the details.
Markdown is **supported**. Markdown is **supported**.
{{% /details %}} {{< /details >}}
{{% 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.
{{% /details %}} {{< /details >}}
## Usage ## Usage
````markdown ````markdown
{{%/* details title="Details" */%}} {{</* details title="Details" */>}}
This is the content of the details. This is the content of the details.
Markdown is **supported**. Markdown is **supported**.
{{%/* /details */%}} {{</* /details */>}}
```` ````
````markdown ````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.
{{%/* /details */%}} {{</* /details */>}}
```` ````

View File

@@ -8,36 +8,36 @@ title: 详情
## 示例 ## 示例
{{% details title="详情" %}} {{< details title="详情" >}}
这是详情的内容。 这是详情的内容。
支持 **Markdown** 格式。 支持 **Markdown** 格式。
{{% /details %}} {{< /details >}}
{{% details title="点击我展开" closed="true" %}} {{< details title="点击我展开" closed="true" >}}
默认情况下,这部分内容会被隐藏。 默认情况下,这部分内容会被隐藏。
{{% /details %}} {{< /details >}}
## 使用方法 ## 使用方法
````markdown ````markdown
{{%/* details title="详情" */%}} {{</* details title="详情" */>}}
这是详情的内容。 这是详情的内容。
支持 **Markdown** 格式。 支持 **Markdown** 格式。
{{%/* /details */%}} {{</* /details */>}}
```` ````
````markdown ````markdown
{{%/* details title="点击我展开" closed="true" */%}} {{</* details title="点击我展开" closed="true" */>}}
默认情况下,这部分内容会被隐藏。 默认情况下,这部分内容会被隐藏。
{{%/* /details */%}} {{</* /details */>}}
```` ````

View File

@@ -9,6 +9,8 @@ next: /docs/guide/deploy-site
این شورتکدها کمتر پایدار در نظر گرفته می‌شوند و ممکن است هر زمان تغییر کنند. این شورتکدها کمتر پایدار در نظر گرفته می‌شوند و ممکن است هر زمان تغییر کنند.
{{< /callout >}} {{< /callout >}}
## نشان
### أمثلة ### أمثلة
{{< badge "default" >}}&nbsp; {{< badge "default" >}}&nbsp;
@@ -124,4 +126,4 @@ next: /docs/guide/deploy-site
مثال: مثال:
{{< pdf "https://upload.wikimedia.org/wikipedia/commons/1/13/Example.pdf" >}} {{< pdf "https://upload.wikimedia.org/wikipedia/commons/1/13/Example.pdf" >}}

View File

@@ -9,6 +9,8 @@ next: /docs/guide/deploy-site
これらのショートコードは安定性が低く、いつでも変更される可能性があります。 これらのショートコードは安定性が低く、いつでも変更される可能性があります。
{{< /callout >}} {{< /callout >}}
## バッジ
### 例 ### 例
{{< badge "default" >}}&nbsp; {{< badge "default" >}}&nbsp;
@@ -124,4 +126,4 @@ PDF ショートコードを使用すると、コンテンツ内に PDF ファ
例: 例:
{{< pdf "https://upload.wikimedia.org/wikipedia/commons/1/13/Example.pdf" >}} {{< pdf "https://upload.wikimedia.org/wikipedia/commons/1/13/Example.pdf" >}}

View File

@@ -9,6 +9,8 @@ next: /docs/guide/deploy-site
这些短代码稳定性较低,可能随时变更。 这些短代码稳定性较低,可能随时变更。
{{< /callout >}} {{< /callout >}}
## 徽章
### 示例 ### 示例
{{< badge "default" >}}&nbsp; {{< badge "default" >}}&nbsp;
@@ -124,4 +126,4 @@ next: /docs/guide/deploy-site
示例: 示例:
{{< pdf "https://upload.wikimedia.org/wikipedia/commons/1/13/Example.pdf" >}} {{< pdf "https://upload.wikimedia.org/wikipedia/commons/1/13/Example.pdf" >}}

View File

@@ -4,6 +4,8 @@ title: Steps
A built-in component to display a series of steps. A built-in component to display a series of steps.
You can use the Markdown attribute `{class="no-step-marker"}` to prevent a heading from being counted as a step.
## Example ## Example
{{% steps %}} {{% steps %}}
@@ -16,6 +18,10 @@ This is the first step.
This is the second step. This is the second step.
#### Step subheading {class="no-step-marker"}
This will not be counted as a step.
### Step 3 ### Step 3
This is the third step. This is the third step.
@@ -43,5 +49,9 @@ This is the first step.
This is the second step. This is the second step.
#### Step subheading {class="no-step-marker"}
This will not be counted as a step.
{{%/* /steps */%}} {{%/* /steps */%}}
``` ```

View File

@@ -5,11 +5,11 @@ next: /docs/guide/deploy-site
## مثال ## مثال
{{< tabs items="macOS,Linux,Windows" >}} {{< tabs >}}
{{< tab >}}**macOS**: یک سیستم عامل دسکتاپ توسط اپل.{{< /tab >}} {{< tab name="macOS" >}}**macOS**: یک سیستم عامل دسکتاپ توسط اپل.{{< /tab >}}
{{< tab >}}**Linux**: یک سیستم عامل متن‌باز.{{< /tab >}} {{< tab name="Linux" >}}**Linux**: یک سیستم عامل متن‌باز.{{< /tab >}}
{{< tab >}}**Windows**: یک سیستم عامل دسکتاپ توسط مایکروسافت.{{< /tab >}} {{< tab name="Windows" >}}**Windows**: یک سیستم عامل دسکتاپ توسط مایکروسافت.{{< /tab >}}
{{< /tabs >}} {{< /tabs >}}
@@ -18,36 +18,60 @@ next: /docs/guide/deploy-site
### پیش‌فرض ### پیش‌فرض
``` ```
{{</* tabs items="JSON,YAML,TOML" */>}} {{</* tabs */>}}
{{</* tab */>}}**JSON**: JavaScript Object Notation (JSON) یک فرمت متنی استاندارد برای نمایش داده‌های ساختاریافته بر اساس نحو شیء جاوااسکریپت است.{{</* /tab */>}} {{</* tab name="JSON" */>}}**JSON**: JavaScript Object Notation (JSON) یک فرمت متنی استاندارد برای نمایش داده‌های ساختاریافته بر اساس نحو شیء جاوااسکریپت است.{{</* /tab */>}}
{{</* tab */>}}**YAML**: YAML یک زبان سریال‌سازی داده‌های قابل خواندن توسط انسان است.{{</* /tab */>}} {{</* tab name="YAML" */>}}**YAML**: YAML یک زبان سریال‌سازی داده‌های قابل خواندن توسط انسان است.{{</* /tab */>}}
{{</* tab */>}}**TOML**: TOML هدفش این است که یک فرمت فایل پیکربندی حداقلی باشد که به دلیل معناشناسی واضح، خواندنش آسان باشد.{{</* /tab */>}} {{</* tab name="TOML" */>}}**TOML**: TOML هدفش این است که یک فرمت فایل پیکربندی حداقلی باشد که به دلیل معناشناسی واضح، خواندنش آسان باشد.{{</* /tab */>}}
{{</* /tabs */>}} {{</* /tabs */>}}
``` ```
### مشخص کردن ایندکس انتخاب شده ### مشخص کردن ایندکس انتخاب شده
از ویژگی `defaultIndex` برای مشخص کردن تب انتخاب شده استفاده کنید. ایندکس از 0 شروع می‌شود. از ویژگی `selected` برای مشخص کردن تب انتخاب شده استفاده کنید.
``` ```
{{</* tabs items="JSON,YAML,TOML" defaultIndex="1" */>}} {{</* tabs */>}}
{{</* tab */>}}**JSON**: JavaScript Object Notation (JSON) یک فرمت متنی استاندارد برای نمایش داده‌های ساختاریافته بر اساس نحو شیء جاوااسکریپت است.{{</* /tab */>}} {{</* tab name="JSON" */>}}**JSON**: JavaScript Object Notation (JSON) یک فرمت متنی استاندارد برای نمایش داده‌های ساختاریافته بر اساس نحو شیء جاوااسکریپت است.{{</* /tab */>}}
{{</* tab */>}}**YAML**: YAML یک زبان سریال‌سازی داده‌های قابل خواندن توسط انسان است.{{</* /tab */>}} {{</* tab name="YAML" selected=true */>}}**YAML**: YAML یک زبان سریال‌سازی داده‌های قابل خواندن توسط انسان است.{{</* /tab */>}}
{{</* tab */>}}**TOML**: TOML هدفش این است که یک فرمت فایل پیکربندی حداقلی باشد که به دلیل معناشناسی واضح، خواندنش آسان باشد.{{</* /tab */>}} {{</* tab name="TOML" */>}}**TOML**: TOML هدفش این است که یک فرمت فایل پیکربندی حداقلی باشد که به دلیل معناشناسی واضح، خواندنش آسان باشد.{{</* /tab */>}}
{{</* /tabs */>}} {{</* /tabs */>}}
``` ```
تب `YAML` به طور پیش‌فرض انتخاب خواهد شد. تب `YAML` به طور پیش‌فرض انتخاب خواهد شد.
{{< tabs items="JSON,YAML,TOML" defaultIndex="1" >}} {{< tabs >}}
{{< tab >}}**JSON**: JavaScript Object Notation (JSON) یک فرمت متنی استاندارد برای نمایش داده‌های ساختاریافته بر اساس نحو شیء جاوااسکریپت است.{{< /tab >}} {{< tab name="JSON" >}}**JSON**: JavaScript Object Notation (JSON) یک فرمت متنی استاندارد برای نمایش داده‌های ساختاریافته بر اساس نحو شیء جاوااسکریپت است.{{< /tab >}}
{{< tab >}}**YAML**: YAML یک زبان سریال‌سازی داده‌های قابل خواندن توسط انسان است.{{< /tab >}} {{< tab name="YAML" selected=true >}}**YAML**: YAML یک زبان سریال‌سازی داده‌های قابل خواندن توسط انسان است.{{< /tab >}}
{{< tab >}}**TOML**: TOML هدفش این است که یک فرمت فایل پیکربندی حداقلی باشد که به دلیل معناشناسی واضح، خواندنش آسان باشد.{{< /tab >}} {{< tab name="TOML" >}}**TOML**: TOML هدفش این است که یک فرمت فایل پیکربندی حداقلی باشد که به دلیل معناشناسی واضح، خواندنش آسان باشد.{{< /tab >}}
{{< /tabs >}}
### افزودن آیکون
با استفاده از پارامتر `icon` برای هر `tab` می‌توانید قبل از عنوان تب آیکون نمایش دهید.
برای مشاهده لیست آیکون‌های موجود، صفحه [شورت‌کد آیکون](../icon) را ببینید.
```
{{</* tabs */>}}
{{</* tab name="Photos" icon="photograph" */>}}مدیریت و سازماندهی کتابخانه عکس‌های شما.{{</* /tab */>}}
{{</* tab name="Music" icon="music-note" */>}}مرور و پخش آهنگ‌های مورد علاقه شما.{{</* /tab */>}}
{{</* tab name="Videos" icon="film" */>}}تماشا و پخش محتوای ویدیویی.{{</* /tab */>}}
{{</* /tabs */>}}
```
{{< tabs >}}
{{< tab name="Photos" icon="photograph" >}}مدیریت و سازماندهی کتابخانه عکس‌های شما.{{< /tab >}}
{{< tab name="Music" icon="music-note" >}}مرور و پخش آهنگ‌های مورد علاقه شما.{{< /tab >}}
{{< tab name="Videos" icon="film" >}}تماشا و پخش محتوای ویدیویی.{{< /tab >}}
{{< /tabs >}} {{< /tabs >}}
@@ -57,9 +81,9 @@ next: /docs/guide/deploy-site
نحو Markdown شامل بلوک کد نیز پشتیبانی می‌شود: نحو Markdown شامل بلوک کد نیز پشتیبانی می‌شود:
```` ````
{{</* tabs items="JSON,YAML,TOML" */>}} {{</* tabs */>}}
{{</* tab */>}} {{</* tab name="JSON" */>}}
```json ```json
{ "hello": "world" } { "hello": "world" }
``` ```
@@ -70,21 +94,21 @@ next: /docs/guide/deploy-site
{{</* /tabs */>}} {{</* /tabs */>}}
```` ````
{{< tabs items="JSON,YAML,TOML" >}} {{< tabs >}}
{{< tab >}} {{< tab name="JSON" >}}
```json ```json
{ "hello": "world" } { "hello": "world" }
``` ```
{{< /tab >}} {{< /tab >}}
{{< tab >}} {{< tab name="YAML" >}}
```yaml ```yaml
hello: world hello: world
``` ```
{{< /tab >}} {{< /tab >}}
{{< tab >}} {{< tab name="TOML" >}}
```toml ```toml
hello = "world" hello = "world"
``` ```
@@ -95,7 +119,7 @@ next: /docs/guide/deploy-site
### همگام‌سازی تب‌ها ### همگام‌سازی تب‌ها
تب‌هایی که لیست `items` یکسانی دارند می‌توانند همگام‌سازی شوند. وقتی فعال باشد، انتخاب یک تب تمام تب‌های دیگر با `items` یکسان را به‌روز می‌کند و انتخاب را در بین صفحات به خاطر می‌سپارد. تب‌هایی که لیست `name` یکسانی دارند می‌توانند همگام‌سازی شوند. وقتی فعال باشد، انتخاب یک تب تمام تب‌های دیگر با `name` یکسان را به‌روز می‌کند و انتخاب را در بین صفحات به خاطر می‌سپارد.
به صورت جهانی در فایل `hugo.yaml` در بخش `page` فعال کنید: به صورت جهانی در فایل `hugo.yaml` در بخش `page` فعال کنید:
@@ -109,17 +133,17 @@ params:
با فعال کردن این گزینه، دو بلوک تب زیر همیشه آیتم انتخاب شده یکسانی را نمایش خواهند داد: با فعال کردن این گزینه، دو بلوک تب زیر همیشه آیتم انتخاب شده یکسانی را نمایش خواهند داد:
```markdown ```markdown
{{</* tabs items="A,B" */>}} {{</* tabs */>}}
{{</* tab */>}}محتوای A{{</* /tab */>}} {{</* tab name="A" */>}}محتوای A{{</* /tab */>}}
{{</* tab */>}}محتوای B{{</* /tab */>}} {{</* tab name="B" */>}}محتوای B{{</* /tab */>}}
{{</* /tabs */>}} {{</* /tabs */>}}
{{</* tabs items="A,B" */>}} {{</* tabs */>}}
{{</* tab */>}}محتوای دوم A{{</* /tab */>}} {{</* tab name="A" */>}}محتوای دوم A{{</* /tab */>}}
{{</* tab */>}}محتوای دوم B{{</* /tab */>}} {{</* tab name="B" */>}}محتوای دوم B{{</* /tab */>}}
{{</* /tabs */>}} {{</* /tabs */>}}
``` ```

View File

@@ -5,11 +5,11 @@ next: /docs/guide/deploy-site
## 例 ## 例
{{< tabs items="macOS,Linux,Windows" >}} {{< tabs >}}
{{< tab >}}**macOS**: Apple が提供するデスクトップオペレーティングシステム。{{< /tab >}} {{< tab name="macOS" >}}**macOS**: Apple が提供するデスクトップオペレーティングシステム。{{< /tab >}}
{{< tab >}}**Linux**: オープンソースのオペレーティングシステム。{{< /tab >}} {{< tab name="Linux" >}}**Linux**: オープンソースのオペレーティングシステム。{{< /tab >}}
{{< tab >}}**Windows**: Microsoft が提供するデスクトップオペレーティングシステム。{{< /tab >}} {{< tab name="Windows" >}}**Windows**: Microsoft が提供するデスクトップオペレーティングシステム。{{< /tab >}}
{{< /tabs >}} {{< /tabs >}}
@@ -18,36 +18,60 @@ next: /docs/guide/deploy-site
### デフォルト ### デフォルト
``` ```
{{</* tabs items="JSON,YAML,TOML" */>}} {{</* tabs */>}}
{{</* tab */>}}**JSON**: JavaScript Object Notation (JSON) は、JavaScript オブジェクト構文に基づいた構造化データを表現する標準のテキストベースフォーマットです。{{</* /tab */>}} {{</* tab name="JSON" */>}}**JSON**: JavaScript Object Notation (JSON) は、JavaScript オブジェクト構文に基づいた構造化データを表現する標準のテキストベースフォーマットです。{{</* /tab */>}}
{{</* tab */>}}**YAML**: YAML は人間が読みやすいデータシリアライゼーション言語です。{{</* /tab */>}} {{</* tab name="YAML" */>}}**YAML**: YAML は人間が読みやすいデータシリアライゼーション言語です。{{</* /tab */>}}
{{</* tab */>}}**TOML**: TOML は、明確なセマンティクスにより読みやすい最小限の設定ファイルフォーマットを目指しています。{{</* /tab */>}} {{</* tab name="TOML" */>}}**TOML**: TOML は、明確なセマンティクスにより読みやすい最小限の設定ファイルフォーマットを目指しています。{{</* /tab */>}}
{{</* /tabs */>}} {{</* /tabs */>}}
``` ```
### 選択インデックスの指定 ### 選択インデックスの指定
`defaultIndex` プロパティを使用して選択するタブを指定します。インデックスは 0 から始まります。 `selected` プロパティを使用して選択するタブを指定します。
``` ```
{{</* tabs items="JSON,YAML,TOML" defaultIndex="1" */>}} {{</* tabs */>}}
{{</* tab */>}}**JSON**: JavaScript Object Notation (JSON) は、JavaScript オブジェクト構文に基づいた構造化データを表現する標準のテキストベースフォーマットです。{{</* /tab */>}} {{</* tab name="JSON" */>}}**JSON**: JavaScript Object Notation (JSON) は、JavaScript オブジェクト構文に基づいた構造化データを表現する標準のテキストベースフォーマットです。{{</* /tab */>}}
{{</* tab */>}}**YAML**: YAML は人間が読みやすいデータシリアライゼーション言語です。{{</* /tab */>}} {{</* tab name="YAML" selected=true */>}}**YAML**: YAML は人間が読みやすいデータシリアライゼーション言語です。{{</* /tab */>}}
{{</* tab */>}}**TOML**: TOML は、明確なセマンティクスにより読みやすい最小限の設定ファイルフォーマットを目指しています。{{</* /tab */>}} {{</* tab name="TOML" */>}}**TOML**: TOML は、明確なセマンティクスにより読みやすい最小限の設定ファイルフォーマットを目指しています。{{</* /tab */>}}
{{</* /tabs */>}} {{</* /tabs */>}}
``` ```
`YAML` タブがデフォルトで選択されます。 `YAML` タブがデフォルトで選択されます。
{{< tabs items="JSON,YAML,TOML" defaultIndex="1" >}} {{< tabs >}}
{{< tab >}}**JSON**: JavaScript Object Notation (JSON) は、JavaScript オブジェクト構文に基づいた構造化データを表現する標準のテキストベースフォーマットです。{{< /tab >}} {{< tab name="JSON" >}}**JSON**: JavaScript Object Notation (JSON) は、JavaScript オブジェクト構文に基づいた構造化データを表現する標準のテキストベースフォーマットです。{{< /tab >}}
{{< tab >}}**YAML**: YAML は人間が読みやすいデータシリアライゼーション言語です。{{< /tab >}} {{< tab name="YAML" selected=true >}}**YAML**: YAML は人間が読みやすいデータシリアライゼーション言語です。{{< /tab >}}
{{< tab >}}**TOML**: TOML は、明確なセマンティクスにより読みやすい最小限の設定ファイルフォーマットを目指しています。{{< /tab >}} {{< tab name="TOML" >}}**TOML**: TOML は、明確なセマンティクスにより読みやすい最小限の設定ファイルフォーマットを目指しています。{{< /tab >}}
{{< /tabs >}}
### アイコンを追加する
各タブに `icon` を指定すると、ラベルの前にアイコンを表示できます。
利用可能なアイコンの一覧は [Icon ショートコード](../icon) ページを参照してください。
```
{{</* tabs */>}}
{{</* tab name="Photos" icon="photograph" */>}}写真ライブラリを管理・整理します。{{</* /tab */>}}
{{</* tab name="Music" icon="music-note" */>}}お気に入りの曲を閲覧・再生します。{{</* /tab */>}}
{{</* tab name="Videos" icon="film" */>}}動画コンテンツを視聴・ストリーミングします。{{</* /tab */>}}
{{</* /tabs */>}}
```
{{< tabs >}}
{{< tab name="Photos" icon="photograph" >}}写真ライブラリを管理・整理します。{{< /tab >}}
{{< tab name="Music" icon="music-note" >}}お気に入りの曲を閲覧・再生します。{{< /tab >}}
{{< tab name="Videos" icon="film" >}}動画コンテンツを視聴・ストリーミングします。{{< /tab >}}
{{< /tabs >}} {{< /tabs >}}
@@ -57,9 +81,9 @@ next: /docs/guide/deploy-site
コードブロックを含む Markdown 構文もサポートされています: コードブロックを含む Markdown 構文もサポートされています:
```` ````
{{</* tabs items="JSON,YAML,TOML" */>}} {{</* tabs */>}}
{{</* tab */>}} {{</* tab name="JSON" */>}}
```json ```json
{ "hello": "world" } { "hello": "world" }
``` ```
@@ -70,21 +94,21 @@ next: /docs/guide/deploy-site
{{</* /tabs */>}} {{</* /tabs */>}}
```` ````
{{< tabs items="JSON,YAML,TOML" >}} {{< tabs >}}
{{< tab >}} {{< tab name="JSON" >}}
```json ```json
{ "hello": "world" } { "hello": "world" }
``` ```
{{< /tab >}} {{< /tab >}}
{{< tab >}} {{< tab name="YAML" >}}
```yaml ```yaml
hello: world hello: world
``` ```
{{< /tab >}} {{< /tab >}}
{{< tab >}} {{< tab name="TOML" >}}
```toml ```toml
hello = "world" hello = "world"
``` ```
@@ -95,7 +119,7 @@ next: /docs/guide/deploy-site
### タブの同期 ### タブの同期
同じ `items` リストを持つタブは同期できます。有効にすると、タブを選択すると同じ `items` を持つ他のタブも更新され、ページ間で選択が記憶されます。 同じ `name` リストを持つタブは同期できます。有効にすると、タブを選択すると同じ `name` を持つ他のタブも更新され、ページ間で選択が記憶されます。
`hugo.yaml` の `page` セクションでグローバルに有効にします: `hugo.yaml` の `page` セクションでグローバルに有効にします:
@@ -109,17 +133,17 @@ params:
これを有効にすると、以下の 2 つのタブブロックは常に同じ選択項目を表示します: これを有効にすると、以下の 2 つのタブブロックは常に同じ選択項目を表示します:
```markdown ```markdown
{{</* tabs items="A,B" */>}} {{</* tabs */>}}
{{</* tab */>}}A の内容{{</* /tab */>}} {{</* tab name="A" */>}}A の内容{{</* /tab */>}}
{{</* tab */>}}B の内容{{</* /tab */>}} {{</* tab name="B" */>}}B の内容{{</* /tab */>}}
{{</* /tabs */>}} {{</* /tabs */>}}
{{</* tabs items="A,B" */>}} {{</* tabs */>}}
{{</* tab */>}}2 番目の A の内容{{</* /tab */>}} {{</* tab name="A" */>}}2 番目の A の内容{{</* /tab */>}}
{{</* tab */>}}2 番目の B の内容{{</* /tab */>}} {{</* tab name="B" */>}}2 番目の B の内容{{</* /tab */>}}
{{</* /tabs */>}} {{</* /tabs */>}}
``` ```

View File

@@ -1,6 +1,6 @@
--- ---
title: Tabs title: Tabs
next: /docs/guide/deploy-site next: /docs/guide/term
--- ---
## Example ## Example
@@ -47,6 +47,27 @@ The `YAML` tab will be selected by default.
{{< tab name="TOML" >}}**TOML**: TOML aims to be a minimal configuration file format that's easy to read due to obvious semantics.{{< /tab >}} {{< tab name="TOML" >}}**TOML**: TOML aims to be a minimal configuration file format that's easy to read due to obvious semantics.{{< /tab >}}
{{< /tabs >}} {{< /tabs >}}
### Add Icons
Use the `icon` property on each `tab` to display an icon before the label.
See the [Icon shortcode](../icon) page for the list of available icons.
```
{{</* tabs */>}}
{{</* tab name="Photos" icon="photograph" */>}}Manage and organize your photo library.{{</* /tab */>}}
{{</* tab name="Music" icon="music-note" */>}}Browse and play your favorite tracks.{{</* /tab */>}}
{{</* tab name="Videos" icon="film" */>}}Watch and stream video content.{{</* /tab */>}}
{{</* /tabs */>}}
```
{{< tabs >}}
{{< tab name="Photos" icon="photograph" >}}Manage and organize your photo library.{{< /tab >}}
{{< tab name="Music" icon="music-note" >}}Browse and play your favorite tracks.{{< /tab >}}
{{< tab name="Videos" icon="film" >}}Watch and stream video content.{{< /tab >}}
{{< /tabs >}}
### Use Markdown ### Use Markdown

View File

@@ -5,11 +5,11 @@ next: /docs/guide/deploy-site
## 示例 ## 示例
{{< tabs items="macOS,Linux,Windows" >}} {{< tabs >}}
{{< tab >}}**macOS**: 苹果公司开发的桌面操作系统。{{< /tab >}} {{< tab name="macOS" >}}**macOS**: 苹果公司开发的桌面操作系统。{{< /tab >}}
{{< tab >}}**Linux**: 一款开源操作系统。{{< /tab >}} {{< tab name="Linux" >}}**Linux**: 一款开源操作系统。{{< /tab >}}
{{< tab >}}**Windows**: 微软公司开发的桌面操作系统。{{< /tab >}} {{< tab name="Windows" >}}**Windows**: 微软公司开发的桌面操作系统。{{< /tab >}}
{{< /tabs >}} {{< /tabs >}}
@@ -18,36 +18,60 @@ next: /docs/guide/deploy-site
### 默认 ### 默认
``` ```
{{</* tabs items="JSON,YAML,TOML" */>}} {{</* tabs */>}}
{{</* tab */>}}**JSON**: JavaScript对象表示法JSON是一种基于JavaScript对象语法的标准文本格式用于表示结构化数据。{{</* /tab */>}} {{</* tab name="JSON" */>}}**JSON**: JavaScript对象表示法JSON是一种基于JavaScript对象语法的标准文本格式用于表示结构化数据。{{</* /tab */>}}
{{</* tab */>}}**YAML**: YAML是一种人类可读的数据序列化语言。{{</* /tab */>}} {{</* tab name="YAML" */>}}**YAML**: YAML是一种人类可读的数据序列化语言。{{</* /tab */>}}
{{</* tab */>}}**TOML**: TOML旨在成为一种易于阅读的最小化配置文件格式因其明显的语义而易于理解。{{</* /tab */>}} {{</* tab name="TOML" */>}}**TOML**: TOML旨在成为一种易于阅读的最小化配置文件格式因其明显的语义而易于理解。{{</* /tab */>}}
{{</* /tabs */>}} {{</* /tabs */>}}
``` ```
### 指定默认选中项 ### 指定默认选中项
使用 `defaultIndex` 属性指定默认选中的标签页索引从0开始 使用 `selected` 属性指定默认选中的标签页。
``` ```
{{</* tabs items="JSON,YAML,TOML" defaultIndex="1" */>}} {{</* tabs */>}}
{{</* tab */>}}**JSON**: JavaScript对象表示法JSON是一种基于JavaScript对象语法的标准文本格式用于表示结构化数据。{{</* /tab */>}} {{</* tab name="JSON" */>}}**JSON**: JavaScript对象表示法JSON是一种基于JavaScript对象语法的标准文本格式用于表示结构化数据。{{</* /tab */>}}
{{</* tab */>}}**YAML**: YAML是一种人类可读的数据序列化语言。{{</* /tab */>}} {{</* tab name="YAML" selected=true */>}}**YAML**: YAML是一种人类可读的数据序列化语言。{{</* /tab */>}}
{{</* tab */>}}**TOML**: TOML旨在成为一种易于阅读的最小化配置文件格式因其明显的语义而易于理解。{{</* /tab */>}} {{</* tab name="TOML" */>}}**TOML**: TOML旨在成为一种易于阅读的最小化配置文件格式因其明显的语义而易于理解。{{</* /tab */>}}
{{</* /tabs */>}} {{</* /tabs */>}}
``` ```
默认会选中 `YAML` 标签页。 默认会选中 `YAML` 标签页。
{{< tabs items="JSON,YAML,TOML" defaultIndex="1" >}} {{< tabs >}}
{{< tab >}}**JSON**: JavaScript对象表示法JSON是一种基于JavaScript对象语法的标准文本格式用于表示结构化数据。{{< /tab >}} {{< tab name="JSON" >}}**JSON**: JavaScript对象表示法JSON是一种基于JavaScript对象语法的标准文本格式用于表示结构化数据。{{< /tab >}}
{{< tab >}}**YAML**: YAML是一种人类可读的数据序列化语言。{{< /tab >}} {{< tab name="YAML" selected=true >}}**YAML**: YAML是一种人类可读的数据序列化语言。{{< /tab >}}
{{< tab >}}**TOML**: TOML旨在成为一种易于阅读的最小化配置文件格式因其明显的语义而易于理解。{{< /tab >}} {{< tab name="TOML" >}}**TOML**: TOML旨在成为一种易于阅读的最小化配置文件格式因其明显的语义而易于理解。{{< /tab >}}
{{< /tabs >}}
### 添加图标
在每个 `tab` 上使用 `icon` 参数,可以在标签文本前显示图标。
可用图标列表请参阅 [Icon 短代码](../icon) 页面。
```
{{</* tabs */>}}
{{</* tab name="Photos" icon="photograph" */>}}管理和整理您的照片库。{{</* /tab */>}}
{{</* tab name="Music" icon="music-note" */>}}浏览和播放您喜爱的曲目。{{</* /tab */>}}
{{</* tab name="Videos" icon="film" */>}}观看和串流视频内容。{{</* /tab */>}}
{{</* /tabs */>}}
```
{{< tabs >}}
{{< tab name="Photos" icon="photograph" >}}管理和整理您的照片库。{{< /tab >}}
{{< tab name="Music" icon="music-note" >}}浏览和播放您喜爱的曲目。{{< /tab >}}
{{< tab name="Videos" icon="film" >}}观看和串流视频内容。{{< /tab >}}
{{< /tabs >}} {{< /tabs >}}
@@ -57,9 +81,9 @@ next: /docs/guide/deploy-site
支持包括代码块在内的Markdown语法 支持包括代码块在内的Markdown语法
```` ````
{{</* tabs items="JSON,YAML,TOML" */>}} {{</* tabs */>}}
{{</* tab */>}} {{</* tab name="JSON" */>}}
```json ```json
{ "hello": "world" } { "hello": "world" }
``` ```
@@ -70,21 +94,21 @@ next: /docs/guide/deploy-site
{{</* /tabs */>}} {{</* /tabs */>}}
```` ````
{{< tabs items="JSON,YAML,TOML" >}} {{< tabs >}}
{{< tab >}} {{< tab name="JSON" >}}
```json ```json
{ "hello": "world" } { "hello": "world" }
``` ```
{{< /tab >}} {{< /tab >}}
{{< tab >}} {{< tab name="YAML" >}}
```yaml ```yaml
hello: world hello: world
``` ```
{{< /tab >}} {{< /tab >}}
{{< tab >}} {{< tab name="TOML" >}}
```toml ```toml
hello = "world" hello = "world"
``` ```
@@ -95,7 +119,7 @@ next: /docs/guide/deploy-site
### 同步标签页 ### 同步标签页
具有相同 `items` 列表的标签页可以同步。启用后,选择一个标签页会更新所有具有相同 `items` 的其他标签页,并在页面间记住选择。 具有相同 `name` 列表的标签页可以同步。启用后,选择一个标签页会更新所有具有相同 `name` 的其他标签页,并在页面间记住选择。
在 `hugo.yaml` 的 `page` 部分全局启用: 在 `hugo.yaml` 的 `page` 部分全局启用:
@@ -109,17 +133,17 @@ params:
启用后,以下两个标签页块将始终显示相同的选中项: 启用后,以下两个标签页块将始终显示相同的选中项:
```markdown ```markdown
{{</* tabs items="A,B" */>}} {{</* tabs */>}}
{{</* tab */>}}A内容{{</* /tab */>}} {{</* tab name="A" */>}}A内容{{</* /tab */>}}
{{</* tab */>}}B内容{{</* /tab */>}} {{</* tab name="B" */>}}B内容{{</* /tab */>}}
{{</* /tabs */>}} {{</* /tabs */>}}
{{</* tabs items="A,B" */>}} {{</* tabs */>}}
{{</* tab */>}}第二个A内容{{</* /tab */>}} {{</* tab name="A" */>}}第二个A内容{{</* /tab */>}}
{{</* tab */>}}第二个B内容{{</* /tab */>}} {{</* tab name="B" */>}}第二个B内容{{</* /tab */>}}
{{</* /tabs */>}} {{</* /tabs */>}}
``` ```

View File

@@ -0,0 +1,28 @@
---
title: اصطلاح
next: /docs/guide/deploy-site
---
یک مؤلفهٔ داخلی برای نمایش تعریف اصطلاحات.
تعاریف اصطلاحات در یک [فایل دادهٔ YAML](/docs/advanced/additional-pages/#glossary) ساختاریافته نگهداری می‌شوند،
و برای هر زبان پشتیبانی‌شده یک فایل جداگانه تعریف می‌گردد.
## مثال
* {{< term "سازندهٔ سایت ایستا" >}}
* {{< term "SEO" >}}
## نحوهٔ استفاده
```
{{</* term "SEO" */>}}
```
اگر اصطلاحی در واژه‌نامه یافت نشود، همان‌طور که وارد شده نمایش داده می‌شود.
## گزینه‌ها
| نام | توضیح |
|---------------|----------------------------|
| `entry` | اصطلاح واژه‌نامه |

View File

@@ -0,0 +1,28 @@
---
title: 用語
next: /docs/guide/deploy-site
---
用語の定義を表示するための組み込みコンポーネントです。
用語の定義は、構造化された YAML [データファイル](/docs/advanced/additional-pages/#glossary)で管理されており、
対応する言語ごとに1つのファイルが定義されています。
## 例
* {{< term "静的サイトジェネレーター" >}}
* {{< term "SEO" >}}
## 使用方法
```
{{</* term "SEO" */>}}
```
用語が用語集に存在しない場合は、そのまま表示されます。
## オプション
| 名前 | 説明 |
|--------------|--------------------------|
| `entry` | 用語名 |

View File

@@ -0,0 +1,29 @@
---
title: Term
next: /docs/guide/deploy-site
---
A built-in component to display a terminology definition.
Glossary definition is maintained in a structured YAML [data file](/docs/advanced/additional-pages/#glossary),
with one file defined per supported language.
## Example
* {{< term "static site generator" >}}
* {{< term "SEO" >}}
## Usage
```
{{</* term "SEO" */>}}
```
If a term is not found in the glossary, it is returned as-is.
## Options
| Name | Description |
|--------------|-----------------------------|
| `entry` | Glossary term |

View File

@@ -0,0 +1,28 @@
---
title: 术语
next: /docs/guide/deploy-site
---
一个用于显示术语定义的内置组件。
术语定义保存在结构化的 YAML [数据文件](/docs/advanced/additional-pages/#glossary)中,
每种支持的语言对应一个文件。
## 示例
* {{< term "静态网站生成器" >}}
* {{< term "SEO" >}}
## 用法
```
{{</* term "SEO" */>}}
```
如果术语在词汇表中未找到,则会原样返回该术语。
## 选项
| 名称 | 描述 |
|--------------|------------------|
| `entry` | 术语名称 |

View File

@@ -0,0 +1,4 @@
---
title: Glossary
layout: glossary
---

View File

@@ -0,0 +1,4 @@
---
title: واژه‌نامه
layout: glossary
---

View File

@@ -0,0 +1,4 @@
---
title: 用語集
layout: glossary
---

View File

@@ -0,0 +1,4 @@
---
title: 术语表
layout: glossary
---

View File

@@ -12,10 +12,17 @@ layout: wide
</p> </p>
{{< cards >}} {{< cards >}}
{{< card
link="https://printn.dev"
title="PrintN"
image="https://raw.githubusercontent.com/printn/printn.github.io/refs/heads/main/static/images/screenshot.png"
imageStyle="object-fit:cover; aspect-ratio:16/9;"
>}}
{{< card {{< card
link="https://beginnerprivacy.com" link="https://beginnerprivacy.com"
title="Beginner Privacy" title="Beginner Privacy"
image="https://github.com/user-attachments/assets/a72582a8-7c54-40cd-b8e3-8fd77164687c" image="https://raw.githubusercontent.com/beginnerprivacy/beginnerprivacy.com/refs/heads/main/static/images/screenshot.png"
imageStyle="object-fit:cover; aspect-ratio:16/9;" imageStyle="object-fit:cover; aspect-ratio:16/9;"
>}} >}}

View File

@@ -12,10 +12,17 @@ Hextra で構築されたオープンソースプロジェクト
</p> </p>
{{< cards >}} {{< cards >}}
{{< card
link="https://printn.dev"
title="PrintN"
image="https://raw.githubusercontent.com/printn/printn.github.io/refs/heads/main/static/images/screenshot.png"
imageStyle="object-fit:cover; aspect-ratio:16/9;"
>}}
{{< card {{< card
link="https://beginnerprivacy.com" link="https://beginnerprivacy.com"
title="Beginner Privacy" title="Beginner Privacy"
image="https://github.com/user-attachments/assets/a72582a8-7c54-40cd-b8e3-8fd77164687c" image="https://raw.githubusercontent.com/beginnerprivacy/beginnerprivacy.com/refs/heads/main/static/images/screenshot.png"
imageStyle="object-fit:cover; aspect-ratio:16/9;" imageStyle="object-fit:cover; aspect-ratio:16/9;"
>}} >}}

View File

@@ -12,10 +12,17 @@ Open source projects powered by Hextra
</p> </p>
{{< cards >}} {{< cards >}}
{{< card
link="https://printn.dev"
title="PrintN"
image="https://raw.githubusercontent.com/printn/printn.github.io/refs/heads/main/static/images/screenshot.png"
imageStyle="object-fit:cover; aspect-ratio:16/9;"
>}}
{{< card {{< card
link="https://beginnerprivacy.com" link="https://beginnerprivacy.com"
title="Beginner Privacy" title="Beginner Privacy"
image="https://github.com/user-attachments/assets/a72582a8-7c54-40cd-b8e3-8fd77164687c" image="https://raw.githubusercontent.com/beginnerprivacy/beginnerprivacy.com/refs/heads/main/static/images/screenshot.png"
imageStyle="object-fit:cover; aspect-ratio:16/9;" imageStyle="object-fit:cover; aspect-ratio:16/9;"
>}} >}}

View File

@@ -12,10 +12,17 @@ layout: wide
</p> </p>
{{< cards >}} {{< cards >}}
{{< card
link="https://printn.dev"
title="PrintN"
image="https://raw.githubusercontent.com/printn/printn.github.io/refs/heads/main/static/images/screenshot.png"
imageStyle="object-fit:cover; aspect-ratio:16/9;"
>}}
{{< card {{< card
link="https://beginnerprivacy.com" link="https://beginnerprivacy.com"
title="Beginner Privacy" title="Beginner Privacy"
image="https://github.com/user-attachments/assets/a72582a8-7c54-40cd-b8e3-8fd77164687c" image="https://raw.githubusercontent.com/beginnerprivacy/beginnerprivacy.com/refs/heads/main/static/images/screenshot.png"
imageStyle="object-fit:cover; aspect-ratio:16/9;" imageStyle="object-fit:cover; aspect-ratio:16/9;"
>}} >}}

View File

@@ -0,0 +1,12 @@
---
# Terminology glossary
#
# Example usage of term.html shortcode:
#
# {{< term "SEO" >}}
- term: seo
abbr: SEO
definition: "Search engine optimization improving the visibility of a web page in search engines"
- term: static site generator
definition: "Software engines processing text input to generate static web pages"

View File

@@ -0,0 +1,12 @@
---
# واژه‌نامه اصطلاحات
#
# نمونه‌ای از استفاده از term.html:
#
# {{< term "SEO" >}}
- term: seo
abbr: SEO
definition: "بهینه‌سازی موتور جستجو افزایش دیده‌شدن یک صفحهٔ وب در نتایج موتورهای جستجو"
- term: "سازندهٔ سایت ایستا"
definition: "موتورهایی که ورودی متنی را پردازش کرده و صفحات وب ایستا تولید می‌کنند"

View File

@@ -0,0 +1,12 @@
---
# 用語集
#
# term.html ショートコードの使用例:
#
# {{< term "SEO" >}}
- term: seo
abbr: SEO
definition: "検索エンジン最適化 — ウェブページの検索エンジンでの可視性を向上させる手法"
- term: "静的サイトジェネレーター"
definition: "テキスト入力を処理して静的なウェブページを生成するソフトウェアエンジン"

View File

@@ -0,0 +1,12 @@
---
# 术语词汇表
#
# term.html shortcode 的使用示例:
#
# {{< term "SEO" >}}
- term: seo
abbr: SEO
definition: "搜索引擎优化——提高网页在搜索引擎中的可见度"
- term: "静态网站生成器"
definition: "将文本输入处理为静态网页的生成引擎"

View File

@@ -1,5 +1,5 @@
module github.com/imfing/hextra/docs module github.com/imfing/hextra/docs
go 1.20 go 1.21
replace github.com/imfing/hextra => ../ replace github.com/imfing/hextra => ../

View File

@@ -1,3 +1,3 @@
go 1.20 go 1.26
use ../ use ../

Some files were not shown because too many files have changed in this diff Show More