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.
This commit is contained in:
Xin
2026-01-20 22:55:41 +00:00
committed by GitHub
parent 6a13f17326
commit e81447e7ae
8 changed files with 215 additions and 2 deletions

View File

@@ -1,5 +1,9 @@
{{- $alt := .PlainText | safeHTML -}}
{{- $lazyLoading := .Page.Site.Params.enableImageLazyLoading | default true -}}
{{- $enableImageZoom := .Page.Site.Params.imageZoom.enable | default false -}}
{{- if not (eq .Page.Params.imageZoom nil) -}}
{{- $enableImageZoom = .Page.Params.imageZoom -}}
{{- end -}}
{{- $dest := .Destination -}}
{{- $url := urls.Parse $dest -}}
@@ -33,11 +37,15 @@
{{- end -}}
{{- end -}}
{{- if $enableImageZoom -}}
{{- .Page.Store.Set "hasImageZoom" true -}}
{{- end -}}
{{- with .Title -}}
<figure>
<img src="{{ $dest | safeURL }}" title="{{ . }}" alt="{{ $alt }}" {{ $attributes | safeHTMLAttr }} {{ if $lazyLoading }}loading="lazy"{{ end }} />
<img src="{{ $dest | safeURL }}" title="{{ . }}" alt="{{ $alt }}" {{ $attributes | safeHTMLAttr }}{{ if $enableImageZoom }} data-zoomable{{ end }}{{ if $lazyLoading }} loading="lazy"{{ end }} />
<figcaption>{{ . }}</figcaption>
</figure>
{{- else -}}
<img src="{{ $dest | safeURL }}" alt="{{ $alt }}" {{ $attributes | safeHTMLAttr }} {{ if $lazyLoading }}loading="lazy"{{ end }} />
<img src="{{ $dest | safeURL }}" alt="{{ $alt }}" {{ $attributes | safeHTMLAttr }}{{ if $enableImageZoom }} data-zoomable{{ end }}{{ if $lazyLoading }} loading="lazy"{{ end }} />
{{- end -}}

View File

@@ -13,3 +13,8 @@
{{- if (.Store.Get "hasAsciinema") -}}
{{- partial "scripts/asciinema.html" . -}}
{{- end -}}
{{/* Medium Zoom */}}
{{- if (.Store.Get "hasImageZoom") -}}
{{- partial "scripts/medium-zoom.html" . -}}
{{- end -}}

View File

@@ -0,0 +1,85 @@
{{- /* Medium Zoom */ -}}
{{- $zoomBase := "" -}}
{{- $useDefaultCdn := true -}}
{{- with site.Params.imageZoom.base -}}
{{- $zoomBase = . -}}
{{- $useDefaultCdn = false -}}
{{- end -}}
{{- $zoomJsAsset := "" -}}
{{- with site.Params.imageZoom.js -}}
{{- $zoomJsAsset = . -}}
{{- end -}}
{{- /* If only js is set without base, use local asset loading */ -}}
{{- if and $useDefaultCdn (ne $zoomJsAsset "") -}}
{{- $useDefaultCdn = false -}}
{{- end -}}
{{- /* Set default CDN base if needed */ -}}
{{- if $useDefaultCdn -}}
{{- $zoomBase = "https://cdn.jsdelivr.net/npm/medium-zoom@latest/dist" -}}
{{- end -}}
{{- $isRemoteBase := or (strings.HasPrefix $zoomBase "http://") (strings.HasPrefix $zoomBase "https://") -}}
{{- $minSuffix := cond hugo.IsProduction ".min" "" -}}
{{- /* 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 -}}
{{- with try (resources.GetRemote $zoomJsUrl) -}}
{{- with .Err -}}
{{- errorf "Could not retrieve Medium Zoom js file from %s. Reason: %s." $zoomJsUrl . -}}
{{- else with .Value -}}
{{- with resources.Copy (printf "js/medium-zoom%s.js" $minSuffix) . -}}
{{- $zoomJs := . | fingerprint -}}
<script defer src="{{ $zoomJs.RelPermalink }}" integrity="{{ $zoomJs.Data.Integrity }}" crossorigin="anonymous"></script>
{{- end -}}
{{- end -}}
{{- end -}}
{{- else if $zoomJsAsset -}}
{{- with resources.Get $zoomJsAsset -}}
{{- $zoomJs := . | fingerprint -}}
<script defer src="{{ $zoomJs.RelPermalink }}" integrity="{{ $zoomJs.Data.Integrity }}" crossorigin="anonymous"></script>
{{- else -}}
{{- errorf "Medium Zoom js asset not found at %q" $zoomJsAsset -}}
{{- end -}}
{{- end -}}
<script>
document.addEventListener("DOMContentLoaded", () => {
if (!window.mediumZoom) {
return;
}
const getOverlay = () => {
return document.documentElement.classList.contains("dark")
? "rgba(17, 17, 17, 0.98)"
: "rgba(255, 255, 255, 0.98)";
};
const zoom = window.mediumZoom("[data-zoomable]", {
background: getOverlay(),
});
const style = document.createElement("style");
style.textContent = `
.medium-zoom-overlay {
z-index: 1000;
}
.medium-zoom-image--opened {
z-index: 1001;
}
`;
document.head.appendChild(style);
new MutationObserver(() => {
zoom.update({ background: getOverlay() });
}).observe(document.documentElement, {
attributes: true,
attributeFilter: ["class"],
});
});
</script>