diff --git a/docs/content/docs/guide/configuration.fa.md b/docs/content/docs/guide/configuration.fa.md index d8264bb..3ceae51 100644 --- a/docs/content/docs/guide/configuration.fa.md +++ b/docs/content/docs/guide/configuration.fa.md @@ -340,6 +340,73 @@ params: # 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` تنظیم کرد: @@ -440,6 +507,17 @@ params: 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`: - `content` - محتوای کامل صفحه (پیش‌فرض) diff --git a/docs/content/docs/guide/configuration.ja.md b/docs/content/docs/guide/configuration.ja.md index 9175796..b273944 100644 --- a/docs/content/docs/guide/configuration.ja.md +++ b/docs/content/docs/guide/configuration.ja.md @@ -340,6 +340,73 @@ params: # 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` で設定できます: @@ -440,6 +507,17 @@ params: 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` のオプション: - `content` - ページの全文(デフォルト) diff --git a/docs/content/docs/guide/configuration.md b/docs/content/docs/guide/configuration.md index 8d74d9d..0be8fc0 100644 --- a/docs/content/docs/guide/configuration.md +++ b/docs/content/docs/guide/configuration.md @@ -362,6 +362,73 @@ params: # 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 The layout shell width can be customized by the `params.page.width` parameter in the config file: @@ -462,6 +529,17 @@ params: 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`: - `content` - full content of the page (default) diff --git a/docs/content/docs/guide/configuration.zh-cn.md b/docs/content/docs/guide/configuration.zh-cn.md index e936b29..f689e89 100644 --- a/docs/content/docs/guide/configuration.zh-cn.md +++ b/docs/content/docs/guide/configuration.zh-cn.md @@ -340,6 +340,73 @@ params: # 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` 配置: @@ -440,6 +507,17 @@ params: 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` 的选项: - `content` - 页面的完整内容(默认) diff --git a/layouts/_partials/scripts/asciinema.html b/layouts/_partials/scripts/asciinema.html index f982699..6db5a8b 100644 --- a/layouts/_partials/scripts/asciinema.html +++ b/layouts/_partials/scripts/asciinema.html @@ -33,7 +33,7 @@ {{- /* CSS retrieval: get raw CSS from either local asset or remote, then process */ -}} {{- if $isRemoteBase -}} {{- $cssPath := cond (ne $asciinemaCssAsset "") $asciinemaCssAsset "asciinema-player.css" -}} - {{- $asciinemaCssUrl := printf "%s/%s" $asciinemaBase $cssPath -}} + {{- $asciinemaCssUrl := urls.JoinPath $asciinemaBase $cssPath -}} {{- with try (resources.GetRemote $asciinemaCssUrl) -}} {{- with .Err -}} {{- errorf "Could not retrieve Asciinema css file from %s. Reason: %s." $asciinemaCssUrl . -}} @@ -56,7 +56,7 @@ {{- /* JS retrieval: get raw JS from either local asset or remote, then process */ -}} {{- if $isRemoteBase -}} {{- $jsPath := cond (ne $asciinemaJsAsset "") $asciinemaJsAsset (printf "asciinema-player%s.js" $minSuffix) -}} - {{- $asciinemaJsUrl := printf "%s/%s" $asciinemaBase $jsPath -}} + {{- $asciinemaJsUrl := urls.JoinPath $asciinemaBase $jsPath -}} {{- with try (resources.GetRemote $asciinemaJsUrl) -}} {{- with .Err -}} {{- errorf "Could not retrieve Asciinema js file from %s. Reason: %s." $asciinemaJsUrl . -}} diff --git a/layouts/_partials/scripts/katex.html b/layouts/_partials/scripts/katex.html index 2cd24fc..add36c0 100644 --- a/layouts/_partials/scripts/katex.html +++ b/layouts/_partials/scripts/katex.html @@ -39,7 +39,7 @@ {{- $minSuffix := cond hugo.IsProduction ".min" "" -}} {{- if $isRemoteBase -}} {{- $cssPath := cond (ne $katexCssAsset "") $katexCssAsset (printf "katex%s.css" $minSuffix) -}} - {{- $katexCssUrl := printf "%s/%s" $katexBase $cssPath -}} + {{- $katexCssUrl := urls.JoinPath $katexBase $cssPath -}} {{- with try (resources.GetRemote $katexCssUrl) -}} {{- with .Err -}} {{- errorf "Could not retrieve KaTeX css file from %s. Reason: %s." $katexCssUrl . -}} @@ -59,7 +59,7 @@ {{- $cssContent := . -}} {{- if $isRemoteBase -}} {{- $fontPattern := "url(fonts/" -}} - {{- $fontSub := printf "url(%s/fonts/" $katexBase -}} + {{- $fontSub := printf "url(%s/" (urls.JoinPath $katexBase "fonts") -}} {{- $cssContent = strings.Replace $cssContent $fontPattern $fontSub -}} {{- end -}} {{- with resources.FromString (printf "css/katex%s.css" $minSuffix) $cssContent -}} @@ -69,7 +69,7 @@ {{- else -}} {{- if not $isRemoteBase -}} {{- $cssPath := cond (ne $katexCssAsset "") $katexCssAsset (printf "katex%s.css" $minSuffix) -}} - + {{- end -}} {{- end -}} diff --git a/layouts/_partials/scripts/medium-zoom.html b/layouts/_partials/scripts/medium-zoom.html index 6203442..c11925c 100644 --- a/layouts/_partials/scripts/medium-zoom.html +++ b/layouts/_partials/scripts/medium-zoom.html @@ -28,7 +28,7 @@ {{- /* JS retrieval: get raw JS from either local asset or remote, then process */ -}} {{- if $isRemoteBase -}} {{- $jsPath := cond (ne $zoomJsAsset "") $zoomJsAsset (printf "medium-zoom%s.js" $minSuffix) -}} - {{- $zoomJsUrl := printf "%s/%s" $zoomBase $jsPath -}} + {{- $zoomJsUrl := urls.JoinPath $zoomBase $jsPath -}} {{- with try (resources.GetRemote $zoomJsUrl) -}} {{- with .Err -}} {{- errorf "Could not retrieve Medium Zoom js file from %s. Reason: %s." $zoomJsUrl . -}} diff --git a/layouts/_partials/scripts/mermaid.html b/layouts/_partials/scripts/mermaid.html index b4f957b..60bc230 100644 --- a/layouts/_partials/scripts/mermaid.html +++ b/layouts/_partials/scripts/mermaid.html @@ -28,7 +28,7 @@ {{- /* JS retrieval: get raw JS from either local asset or remote, then process */ -}} {{- if $isRemoteBase -}} {{- $jsPath := cond (ne $mermaidJsAsset "") $mermaidJsAsset (printf "mermaid%s.js" $minSuffix) -}} - {{- $mermaidJsUrl := printf "%s/%s" $mermaidBase $jsPath -}} + {{- $mermaidJsUrl := urls.JoinPath $mermaidBase $jsPath -}} {{- with try (resources.GetRemote $mermaidJsUrl) -}} {{- with .Err -}} {{- errorf "Could not retrieve Mermaid js file from %s. Reason: %s." $mermaidJsUrl . -}} diff --git a/layouts/_partials/scripts/search.html b/layouts/_partials/scripts/search.html index 15ec9a0..363b3bc 100644 --- a/layouts/_partials/scripts/search.html +++ b/layouts/_partials/scripts/search.html @@ -7,18 +7,55 @@ {{- if hugo.IsProduction -}} {{- $jsSearch = $jsSearch | minify | fingerprint -}} {{- end -}} - {{- $flexSearchVersion := site.Params.search.flexsearch.version | default "0.8.143" -}} - {{- $flexSearchJsUrl := printf "https://cdn.jsdelivr.net/npm/flexsearch@%s/dist/flexsearch.bundle%s.js" $flexSearchVersion (cond hugo.IsProduction ".min" ".debug") -}} - {{ with try (resources.GetRemote $flexSearchJsUrl) -}} - {{ with .Err -}} - {{ errorf "Could not retrieve FlexSearch js file from %s. Reason: %s." $flexSearchJsUrl . -}} - {{ else with.Value -}} - {{ with resources.Copy (printf "js/flexsearch.js") . -}} - {{ $flexSearchJs := . | fingerprint -}} - - {{ end -}} - {{ end -}} - {{ end -}} + + {{- $flexSearchBase := "" -}} + {{- $useDefaultCdn := true -}} + {{- with site.Params.search.flexsearch.base -}} + {{- $flexSearchBase = . -}} + {{- $useDefaultCdn = false -}} + {{- end -}} + + {{- $flexSearchJsAsset := "" -}} + {{- with site.Params.search.flexsearch.js -}} + {{- $flexSearchJsAsset = . -}} + {{- end -}} + + {{- /* If only js is set without base, use local asset loading. */ -}} + {{- if and $useDefaultCdn (ne $flexSearchJsAsset "") -}} + {{- $useDefaultCdn = false -}} + {{- end -}} + + {{- $bundleSuffix := cond hugo.IsProduction ".min" ".debug" -}} + {{- if $useDefaultCdn -}} + {{- $flexSearchVersion := site.Params.search.flexsearch.version | default "0.8.143" -}} + {{- $flexSearchBase = printf "https://cdn.jsdelivr.net/npm/flexsearch@%s/dist" $flexSearchVersion -}} + {{- end -}} + + {{- $isRemoteBase := or (strings.HasPrefix $flexSearchBase "http://") (strings.HasPrefix $flexSearchBase "https://") -}} + {{- if $isRemoteBase -}} + {{- $jsPath := cond (ne $flexSearchJsAsset "") $flexSearchJsAsset (printf "flexsearch.bundle%s.js" $bundleSuffix) -}} + {{- $flexSearchJsUrl := urls.JoinPath $flexSearchBase $jsPath -}} + {{- with try (resources.GetRemote $flexSearchJsUrl) -}} + {{- with .Err -}} + {{- errorf "Could not retrieve FlexSearch js file from %s. Reason: %s." $flexSearchJsUrl . -}} + {{- else with .Value -}} + {{- with resources.Copy "js/flexsearch.js" . -}} + {{- $flexSearchJs := . | fingerprint -}} + + {{- end -}} + {{- end -}} + {{- end -}} + {{- else if $flexSearchJsAsset -}} + {{- with resources.Get $flexSearchJsAsset -}} + {{- $flexSearchJs := . | fingerprint -}} + + {{- else -}} + {{- errorf "FlexSearch js asset not found at %q" $flexSearchJsAsset -}} + {{- end -}} + {{- else if not $useDefaultCdn -}} + {{- errorf "FlexSearch local loading requires params.search.flexsearch.js when using non-remote base %q" $flexSearchBase -}} + {{- end -}} + {{- else -}} {{- warnf `search type "%s" is not supported` $searchType -}}