mirror of
https://github.com/gcushen/hugo-academic.git
synced 2025-07-26 19:15:16 +02:00
feat: rewritten Figure shortcode supporting multi-resolutions
New shortcode supports - enable re-usable *optimized* image assets from new primary media library location at `assets/images/` - new behavior: load image from page dir falling back to media library at `assets/images/` and then to remote URI. - multi-res support. leading to increased perf. - custom ID for cross-refs - efficient, vanilla (non-jQuery), MIT licensed image zooming - FancyBox now only loaded for Gallery shortcode - themeable SVG support - native lazy loading Experimental, may change. BREAKING CHANGE: Move any figure images (i.e. not the `sharing.*` image) from `static/media/` to `assets/images/` See #2164
This commit is contained in:
parent
b811f9a1bb
commit
7b235ea453
8 changed files with 696 additions and 54 deletions
|
@ -15,7 +15,8 @@
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bootstrap": "^4.4.1",
|
"bootstrap": "^4.4.1",
|
||||||
"instant.page": "^5.1.0"
|
"instant.page": "^5.1.0",
|
||||||
|
"medium-zoom": "^1.0.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint": "^7.17.0",
|
"eslint": "^7.17.0",
|
||||||
|
|
622
wowchemy/assets/js/_vendor/medium-zoom.esm.js
Normal file
622
wowchemy/assets/js/_vendor/medium-zoom.esm.js
Normal file
|
@ -0,0 +1,622 @@
|
||||||
|
/*! medium-zoom 1.0.6 | MIT License | https://github.com/francoischalifour/medium-zoom */
|
||||||
|
var _extends = Object.assign || function (target) {
|
||||||
|
for (var i = 1; i < arguments.length; i++) {
|
||||||
|
var source = arguments[i];
|
||||||
|
|
||||||
|
for (var key in source) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
||||||
|
target[key] = source[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return target;
|
||||||
|
};
|
||||||
|
|
||||||
|
var isSupported = function isSupported(node) {
|
||||||
|
return node.tagName === 'IMG';
|
||||||
|
};
|
||||||
|
|
||||||
|
/* eslint-disable-next-line no-prototype-builtins */
|
||||||
|
var isNodeList = function isNodeList(selector) {
|
||||||
|
return NodeList.prototype.isPrototypeOf(selector);
|
||||||
|
};
|
||||||
|
|
||||||
|
var isNode = function isNode(selector) {
|
||||||
|
return selector && selector.nodeType === 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
var isSvg = function isSvg(image) {
|
||||||
|
var source = image.currentSrc || image.src;
|
||||||
|
return source.substr(-4).toLowerCase() === '.svg';
|
||||||
|
};
|
||||||
|
|
||||||
|
var getImagesFromSelector = function getImagesFromSelector(selector) {
|
||||||
|
try {
|
||||||
|
if (Array.isArray(selector)) {
|
||||||
|
return selector.filter(isSupported);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNodeList(selector)) {
|
||||||
|
// Do not use spread operator or Array.from() for IE support
|
||||||
|
return [].slice.call(selector).filter(isSupported);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNode(selector)) {
|
||||||
|
return [selector].filter(isSupported);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof selector === 'string') {
|
||||||
|
// Do not use spread operator or Array.from() for IE support
|
||||||
|
return [].slice.call(document.querySelectorAll(selector)).filter(isSupported);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
} catch (err) {
|
||||||
|
throw new TypeError('The provided selector is invalid.\n' + 'Expects a CSS selector, a Node element, a NodeList or an array.\n' + 'See: https://github.com/francoischalifour/medium-zoom');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var createOverlay = function createOverlay(background) {
|
||||||
|
var overlay = document.createElement('div');
|
||||||
|
overlay.classList.add('medium-zoom-overlay');
|
||||||
|
overlay.style.background = background;
|
||||||
|
|
||||||
|
return overlay;
|
||||||
|
};
|
||||||
|
|
||||||
|
var cloneTarget = function cloneTarget(template) {
|
||||||
|
var _template$getBounding = template.getBoundingClientRect(),
|
||||||
|
top = _template$getBounding.top,
|
||||||
|
left = _template$getBounding.left,
|
||||||
|
width = _template$getBounding.width,
|
||||||
|
height = _template$getBounding.height;
|
||||||
|
|
||||||
|
var clone = template.cloneNode();
|
||||||
|
var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
|
||||||
|
var scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0;
|
||||||
|
|
||||||
|
clone.removeAttribute('id');
|
||||||
|
clone.style.position = 'absolute';
|
||||||
|
clone.style.top = top + scrollTop + 'px';
|
||||||
|
clone.style.left = left + scrollLeft + 'px';
|
||||||
|
clone.style.width = width + 'px';
|
||||||
|
clone.style.height = height + 'px';
|
||||||
|
clone.style.transform = '';
|
||||||
|
|
||||||
|
return clone;
|
||||||
|
};
|
||||||
|
|
||||||
|
var createCustomEvent = function createCustomEvent(type, params) {
|
||||||
|
var eventParams = _extends({
|
||||||
|
bubbles: false,
|
||||||
|
cancelable: false,
|
||||||
|
detail: undefined
|
||||||
|
}, params);
|
||||||
|
|
||||||
|
if (typeof window.CustomEvent === 'function') {
|
||||||
|
return new CustomEvent(type, eventParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
var customEvent = document.createEvent('CustomEvent');
|
||||||
|
customEvent.initCustomEvent(type, eventParams.bubbles, eventParams.cancelable, eventParams.detail);
|
||||||
|
|
||||||
|
return customEvent;
|
||||||
|
};
|
||||||
|
|
||||||
|
var mediumZoomEsm = function mediumZoom(selector) {
|
||||||
|
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure the compatibility with IE11 if no Promise polyfill are used.
|
||||||
|
*/
|
||||||
|
var Promise = window.Promise || function Promise(fn) {
|
||||||
|
function noop() {}
|
||||||
|
fn(noop, noop);
|
||||||
|
};
|
||||||
|
|
||||||
|
var _handleClick = function _handleClick(event) {
|
||||||
|
var target = event.target;
|
||||||
|
|
||||||
|
|
||||||
|
if (target === overlay) {
|
||||||
|
close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (images.indexOf(target) === -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
toggle({ target: target });
|
||||||
|
};
|
||||||
|
|
||||||
|
var _handleScroll = function _handleScroll() {
|
||||||
|
if (isAnimating || !active.original) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentScroll = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
|
||||||
|
|
||||||
|
if (Math.abs(scrollTop - currentScroll) > zoomOptions.scrollOffset) {
|
||||||
|
setTimeout(close, 150);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var _handleKeyUp = function _handleKeyUp(event) {
|
||||||
|
var key = event.key || event.keyCode;
|
||||||
|
|
||||||
|
// Close if escape key is pressed
|
||||||
|
if (key === 'Escape' || key === 'Esc' || key === 27) {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var update = function update() {
|
||||||
|
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
||||||
|
|
||||||
|
var newOptions = options;
|
||||||
|
|
||||||
|
if (options.background) {
|
||||||
|
overlay.style.background = options.background;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.container && options.container instanceof Object) {
|
||||||
|
newOptions.container = _extends({}, zoomOptions.container, options.container);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.template) {
|
||||||
|
var template = isNode(options.template) ? options.template : document.querySelector(options.template);
|
||||||
|
|
||||||
|
newOptions.template = template;
|
||||||
|
}
|
||||||
|
|
||||||
|
zoomOptions = _extends({}, zoomOptions, newOptions);
|
||||||
|
|
||||||
|
images.forEach(function (image) {
|
||||||
|
image.dispatchEvent(createCustomEvent('medium-zoom:update', {
|
||||||
|
detail: { zoom: zoom }
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
return zoom;
|
||||||
|
};
|
||||||
|
|
||||||
|
var clone = function clone() {
|
||||||
|
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
||||||
|
return mediumZoomEsm(_extends({}, zoomOptions, options));
|
||||||
|
};
|
||||||
|
|
||||||
|
var attach = function attach() {
|
||||||
|
for (var _len = arguments.length, selectors = Array(_len), _key = 0; _key < _len; _key++) {
|
||||||
|
selectors[_key] = arguments[_key];
|
||||||
|
}
|
||||||
|
|
||||||
|
var newImages = selectors.reduce(function (imagesAccumulator, currentSelector) {
|
||||||
|
return [].concat(imagesAccumulator, getImagesFromSelector(currentSelector));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
newImages.filter(function (newImage) {
|
||||||
|
return images.indexOf(newImage) === -1;
|
||||||
|
}).forEach(function (newImage) {
|
||||||
|
images.push(newImage);
|
||||||
|
newImage.classList.add('medium-zoom-image');
|
||||||
|
});
|
||||||
|
|
||||||
|
eventListeners.forEach(function (_ref) {
|
||||||
|
var type = _ref.type,
|
||||||
|
listener = _ref.listener,
|
||||||
|
options = _ref.options;
|
||||||
|
|
||||||
|
newImages.forEach(function (image) {
|
||||||
|
image.addEventListener(type, listener, options);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return zoom;
|
||||||
|
};
|
||||||
|
|
||||||
|
var detach = function detach() {
|
||||||
|
for (var _len2 = arguments.length, selectors = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
||||||
|
selectors[_key2] = arguments[_key2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (active.zoomed) {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
var imagesToDetach = selectors.length > 0 ? selectors.reduce(function (imagesAccumulator, currentSelector) {
|
||||||
|
return [].concat(imagesAccumulator, getImagesFromSelector(currentSelector));
|
||||||
|
}, []) : images;
|
||||||
|
|
||||||
|
imagesToDetach.forEach(function (image) {
|
||||||
|
image.classList.remove('medium-zoom-image');
|
||||||
|
image.dispatchEvent(createCustomEvent('medium-zoom:detach', {
|
||||||
|
detail: { zoom: zoom }
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
images = images.filter(function (image) {
|
||||||
|
return imagesToDetach.indexOf(image) === -1;
|
||||||
|
});
|
||||||
|
|
||||||
|
return zoom;
|
||||||
|
};
|
||||||
|
|
||||||
|
var on = function on(type, listener) {
|
||||||
|
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
||||||
|
|
||||||
|
images.forEach(function (image) {
|
||||||
|
image.addEventListener('medium-zoom:' + type, listener, options);
|
||||||
|
});
|
||||||
|
|
||||||
|
eventListeners.push({ type: 'medium-zoom:' + type, listener: listener, options: options });
|
||||||
|
|
||||||
|
return zoom;
|
||||||
|
};
|
||||||
|
|
||||||
|
var off = function off(type, listener) {
|
||||||
|
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
||||||
|
|
||||||
|
images.forEach(function (image) {
|
||||||
|
image.removeEventListener('medium-zoom:' + type, listener, options);
|
||||||
|
});
|
||||||
|
|
||||||
|
eventListeners = eventListeners.filter(function (eventListener) {
|
||||||
|
return !(eventListener.type === 'medium-zoom:' + type && eventListener.listener.toString() === listener.toString());
|
||||||
|
});
|
||||||
|
|
||||||
|
return zoom;
|
||||||
|
};
|
||||||
|
|
||||||
|
var open = function open() {
|
||||||
|
var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
|
||||||
|
target = _ref2.target;
|
||||||
|
|
||||||
|
var _animate = function _animate() {
|
||||||
|
var container = {
|
||||||
|
width: document.documentElement.clientWidth,
|
||||||
|
height: document.documentElement.clientHeight,
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0
|
||||||
|
};
|
||||||
|
var viewportWidth = void 0;
|
||||||
|
var viewportHeight = void 0;
|
||||||
|
|
||||||
|
if (zoomOptions.container) {
|
||||||
|
if (zoomOptions.container instanceof Object) {
|
||||||
|
// The container is given as an object with properties like width, height, left, top
|
||||||
|
container = _extends({}, container, zoomOptions.container);
|
||||||
|
|
||||||
|
// We need to adjust custom options like container.right or container.bottom
|
||||||
|
viewportWidth = container.width - container.left - container.right - zoomOptions.margin * 2;
|
||||||
|
viewportHeight = container.height - container.top - container.bottom - zoomOptions.margin * 2;
|
||||||
|
} else {
|
||||||
|
// The container is given as an element
|
||||||
|
var zoomContainer = isNode(zoomOptions.container) ? zoomOptions.container : document.querySelector(zoomOptions.container);
|
||||||
|
|
||||||
|
var _zoomContainer$getBou = zoomContainer.getBoundingClientRect(),
|
||||||
|
_width = _zoomContainer$getBou.width,
|
||||||
|
_height = _zoomContainer$getBou.height,
|
||||||
|
_left = _zoomContainer$getBou.left,
|
||||||
|
_top = _zoomContainer$getBou.top;
|
||||||
|
|
||||||
|
container = _extends({}, container, {
|
||||||
|
width: _width,
|
||||||
|
height: _height,
|
||||||
|
left: _left,
|
||||||
|
top: _top
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
viewportWidth = viewportWidth || container.width - zoomOptions.margin * 2;
|
||||||
|
viewportHeight = viewportHeight || container.height - zoomOptions.margin * 2;
|
||||||
|
|
||||||
|
var zoomTarget = active.zoomedHd || active.original;
|
||||||
|
var naturalWidth = isSvg(zoomTarget) ? viewportWidth : zoomTarget.naturalWidth || viewportWidth;
|
||||||
|
var naturalHeight = isSvg(zoomTarget) ? viewportHeight : zoomTarget.naturalHeight || viewportHeight;
|
||||||
|
|
||||||
|
var _zoomTarget$getBoundi = zoomTarget.getBoundingClientRect(),
|
||||||
|
top = _zoomTarget$getBoundi.top,
|
||||||
|
left = _zoomTarget$getBoundi.left,
|
||||||
|
width = _zoomTarget$getBoundi.width,
|
||||||
|
height = _zoomTarget$getBoundi.height;
|
||||||
|
|
||||||
|
var scaleX = Math.min(naturalWidth, viewportWidth) / width;
|
||||||
|
var scaleY = Math.min(naturalHeight, viewportHeight) / height;
|
||||||
|
var scale = Math.min(scaleX, scaleY);
|
||||||
|
var translateX = (-left + (viewportWidth - width) / 2 + zoomOptions.margin + container.left) / scale;
|
||||||
|
var translateY = (-top + (viewportHeight - height) / 2 + zoomOptions.margin + container.top) / scale;
|
||||||
|
var transform = 'scale(' + scale + ') translate3d(' + translateX + 'px, ' + translateY + 'px, 0)';
|
||||||
|
|
||||||
|
active.zoomed.style.transform = transform;
|
||||||
|
|
||||||
|
if (active.zoomedHd) {
|
||||||
|
active.zoomedHd.style.transform = transform;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return new Promise(function (resolve) {
|
||||||
|
if (target && images.indexOf(target) === -1) {
|
||||||
|
resolve(zoom);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var _handleOpenEnd = function _handleOpenEnd() {
|
||||||
|
isAnimating = false;
|
||||||
|
active.zoomed.removeEventListener('transitionend', _handleOpenEnd);
|
||||||
|
active.original.dispatchEvent(createCustomEvent('medium-zoom:opened', {
|
||||||
|
detail: { zoom: zoom }
|
||||||
|
}));
|
||||||
|
|
||||||
|
resolve(zoom);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (active.zoomed) {
|
||||||
|
resolve(zoom);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target) {
|
||||||
|
// The zoom was triggered manually via a click
|
||||||
|
active.original = target;
|
||||||
|
} else if (images.length > 0) {
|
||||||
|
var _images = images;
|
||||||
|
active.original = _images[0];
|
||||||
|
} else {
|
||||||
|
resolve(zoom);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
active.original.dispatchEvent(createCustomEvent('medium-zoom:open', {
|
||||||
|
detail: { zoom: zoom }
|
||||||
|
}));
|
||||||
|
|
||||||
|
scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
|
||||||
|
isAnimating = true;
|
||||||
|
active.zoomed = cloneTarget(active.original);
|
||||||
|
|
||||||
|
document.body.appendChild(overlay);
|
||||||
|
|
||||||
|
if (zoomOptions.template) {
|
||||||
|
var template = isNode(zoomOptions.template) ? zoomOptions.template : document.querySelector(zoomOptions.template);
|
||||||
|
active.template = document.createElement('div');
|
||||||
|
active.template.appendChild(template.content.cloneNode(true));
|
||||||
|
|
||||||
|
document.body.appendChild(active.template);
|
||||||
|
}
|
||||||
|
|
||||||
|
document.body.appendChild(active.zoomed);
|
||||||
|
|
||||||
|
window.requestAnimationFrame(function () {
|
||||||
|
document.body.classList.add('medium-zoom--opened');
|
||||||
|
});
|
||||||
|
|
||||||
|
active.original.classList.add('medium-zoom-image--hidden');
|
||||||
|
active.zoomed.classList.add('medium-zoom-image--opened');
|
||||||
|
|
||||||
|
active.zoomed.addEventListener('click', close);
|
||||||
|
active.zoomed.addEventListener('transitionend', _handleOpenEnd);
|
||||||
|
|
||||||
|
if (active.original.getAttribute('data-zoom-src')) {
|
||||||
|
active.zoomedHd = active.zoomed.cloneNode();
|
||||||
|
|
||||||
|
// Reset the `scrset` property or the HD image won't load.
|
||||||
|
active.zoomedHd.removeAttribute('srcset');
|
||||||
|
active.zoomedHd.removeAttribute('sizes');
|
||||||
|
|
||||||
|
active.zoomedHd.src = active.zoomed.getAttribute('data-zoom-src');
|
||||||
|
|
||||||
|
active.zoomedHd.onerror = function () {
|
||||||
|
clearInterval(getZoomTargetSize);
|
||||||
|
console.warn('Unable to reach the zoom image target ' + active.zoomedHd.src);
|
||||||
|
active.zoomedHd = null;
|
||||||
|
_animate();
|
||||||
|
};
|
||||||
|
|
||||||
|
// We need to access the natural size of the full HD
|
||||||
|
// target as fast as possible to compute the animation.
|
||||||
|
var getZoomTargetSize = setInterval(function () {
|
||||||
|
if ( active.zoomedHd.complete) {
|
||||||
|
clearInterval(getZoomTargetSize);
|
||||||
|
active.zoomedHd.classList.add('medium-zoom-image--opened');
|
||||||
|
active.zoomedHd.addEventListener('click', close);
|
||||||
|
document.body.appendChild(active.zoomedHd);
|
||||||
|
_animate();
|
||||||
|
}
|
||||||
|
}, 10);
|
||||||
|
} else if (active.original.hasAttribute('srcset')) {
|
||||||
|
// If an image has a `srcset` attribuet, we don't know the dimensions of the
|
||||||
|
// zoomed (HD) image (like when `data-zoom-src` is specified).
|
||||||
|
// Therefore the approach is quite similar.
|
||||||
|
active.zoomedHd = active.zoomed.cloneNode();
|
||||||
|
|
||||||
|
// Resetting the sizes attribute tells the browser to load the
|
||||||
|
// image best fitting the current viewport size, respecting the `srcset`.
|
||||||
|
active.zoomedHd.removeAttribute('sizes');
|
||||||
|
|
||||||
|
// In Firefox, the `loading` attribute needs to be set to `eager` (default
|
||||||
|
// value) for the load event to be fired.
|
||||||
|
active.zoomedHd.removeAttribute('loading');
|
||||||
|
|
||||||
|
// Wait for the load event of the hd image. This will fire if the image
|
||||||
|
// is already cached.
|
||||||
|
var loadEventListener = active.zoomedHd.addEventListener('load', function () {
|
||||||
|
active.zoomedHd.removeEventListener('load', loadEventListener);
|
||||||
|
active.zoomedHd.classList.add('medium-zoom-image--opened');
|
||||||
|
active.zoomedHd.addEventListener('click', close);
|
||||||
|
document.body.appendChild(active.zoomedHd);
|
||||||
|
_animate();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
_animate();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var close = function close() {
|
||||||
|
return new Promise(function (resolve) {
|
||||||
|
if (isAnimating || !active.original) {
|
||||||
|
resolve(zoom);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var _handleCloseEnd = function _handleCloseEnd() {
|
||||||
|
active.original.classList.remove('medium-zoom-image--hidden');
|
||||||
|
document.body.removeChild(active.zoomed);
|
||||||
|
if (active.zoomedHd) {
|
||||||
|
document.body.removeChild(active.zoomedHd);
|
||||||
|
}
|
||||||
|
document.body.removeChild(overlay);
|
||||||
|
active.zoomed.classList.remove('medium-zoom-image--opened');
|
||||||
|
if (active.template) {
|
||||||
|
document.body.removeChild(active.template);
|
||||||
|
}
|
||||||
|
|
||||||
|
isAnimating = false;
|
||||||
|
active.zoomed.removeEventListener('transitionend', _handleCloseEnd);
|
||||||
|
|
||||||
|
active.original.dispatchEvent(createCustomEvent('medium-zoom:closed', {
|
||||||
|
detail: { zoom: zoom }
|
||||||
|
}));
|
||||||
|
|
||||||
|
active.original = null;
|
||||||
|
active.zoomed = null;
|
||||||
|
active.zoomedHd = null;
|
||||||
|
active.template = null;
|
||||||
|
|
||||||
|
resolve(zoom);
|
||||||
|
};
|
||||||
|
|
||||||
|
isAnimating = true;
|
||||||
|
document.body.classList.remove('medium-zoom--opened');
|
||||||
|
active.zoomed.style.transform = '';
|
||||||
|
|
||||||
|
if (active.zoomedHd) {
|
||||||
|
active.zoomedHd.style.transform = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fade out the template so it's not too abrupt
|
||||||
|
if (active.template) {
|
||||||
|
active.template.style.transition = 'opacity 150ms';
|
||||||
|
active.template.style.opacity = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
active.original.dispatchEvent(createCustomEvent('medium-zoom:close', {
|
||||||
|
detail: { zoom: zoom }
|
||||||
|
}));
|
||||||
|
|
||||||
|
active.zoomed.addEventListener('transitionend', _handleCloseEnd);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var toggle = function toggle() {
|
||||||
|
var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
|
||||||
|
target = _ref3.target;
|
||||||
|
|
||||||
|
if (active.original) {
|
||||||
|
return close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return open({ target: target });
|
||||||
|
};
|
||||||
|
|
||||||
|
var getOptions = function getOptions() {
|
||||||
|
return zoomOptions;
|
||||||
|
};
|
||||||
|
|
||||||
|
var getImages = function getImages() {
|
||||||
|
return images;
|
||||||
|
};
|
||||||
|
|
||||||
|
var getZoomedImage = function getZoomedImage() {
|
||||||
|
return active.original;
|
||||||
|
};
|
||||||
|
|
||||||
|
var images = [];
|
||||||
|
var eventListeners = [];
|
||||||
|
var isAnimating = false;
|
||||||
|
var scrollTop = 0;
|
||||||
|
var zoomOptions = options;
|
||||||
|
var active = {
|
||||||
|
original: null,
|
||||||
|
zoomed: null,
|
||||||
|
zoomedHd: null,
|
||||||
|
template: null
|
||||||
|
|
||||||
|
// If the selector is omitted, it's replaced by the options
|
||||||
|
};if (Object.prototype.toString.call(selector) === '[object Object]') {
|
||||||
|
zoomOptions = selector;
|
||||||
|
} else if (selector || typeof selector === 'string' // to process empty string as a selector
|
||||||
|
) {
|
||||||
|
attach(selector);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply the default option values
|
||||||
|
zoomOptions = _extends({
|
||||||
|
margin: 0,
|
||||||
|
background: '#fff',
|
||||||
|
scrollOffset: 40,
|
||||||
|
container: null,
|
||||||
|
template: null
|
||||||
|
}, zoomOptions);
|
||||||
|
|
||||||
|
var overlay = createOverlay(zoomOptions.background);
|
||||||
|
|
||||||
|
document.addEventListener('click', _handleClick);
|
||||||
|
document.addEventListener('keyup', _handleKeyUp);
|
||||||
|
document.addEventListener('scroll', _handleScroll);
|
||||||
|
window.addEventListener('resize', close);
|
||||||
|
|
||||||
|
var zoom = {
|
||||||
|
open: open,
|
||||||
|
close: close,
|
||||||
|
toggle: toggle,
|
||||||
|
update: update,
|
||||||
|
clone: clone,
|
||||||
|
attach: attach,
|
||||||
|
detach: detach,
|
||||||
|
on: on,
|
||||||
|
off: off,
|
||||||
|
getOptions: getOptions,
|
||||||
|
getImages: getImages,
|
||||||
|
getZoomedImage: getZoomedImage
|
||||||
|
};
|
||||||
|
|
||||||
|
return zoom;
|
||||||
|
};
|
||||||
|
|
||||||
|
function styleInject(css, ref) {
|
||||||
|
if ( ref === void 0 ) ref = {};
|
||||||
|
var insertAt = ref.insertAt;
|
||||||
|
|
||||||
|
if (!css || typeof document === 'undefined') { return; }
|
||||||
|
|
||||||
|
var head = document.head || document.getElementsByTagName('head')[0];
|
||||||
|
var style = document.createElement('style');
|
||||||
|
style.type = 'text/css';
|
||||||
|
|
||||||
|
if (insertAt === 'top') {
|
||||||
|
if (head.firstChild) {
|
||||||
|
head.insertBefore(style, head.firstChild);
|
||||||
|
} else {
|
||||||
|
head.appendChild(style);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
head.appendChild(style);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (style.styleSheet) {
|
||||||
|
style.styleSheet.cssText = css;
|
||||||
|
} else {
|
||||||
|
style.appendChild(document.createTextNode(css));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var css = ".medium-zoom-overlay{position:fixed;top:0;right:0;bottom:0;left:0;opacity:0;transition:opacity .3s;will-change:opacity}.medium-zoom--opened .medium-zoom-overlay{cursor:pointer;cursor:zoom-out;opacity:1}.medium-zoom-image{cursor:pointer;cursor:zoom-in;transition:transform .3s cubic-bezier(.2,0,.2,1)!important}.medium-zoom-image--hidden{visibility:hidden}.medium-zoom-image--opened{position:relative;cursor:pointer;cursor:zoom-out;will-change:transform}";
|
||||||
|
styleInject(css);
|
||||||
|
|
||||||
|
export default mediumZoomEsm;
|
|
@ -5,10 +5,9 @@
|
||||||
* Core JS functions and initialization.
|
* Core JS functions and initialization.
|
||||||
**************************************************/
|
**************************************************/
|
||||||
|
|
||||||
|
import mediumZoom from './_vendor/medium-zoom.esm';
|
||||||
import {hugoEnvironment, codeHighlighting, searchEnabled} from '@params';
|
import {hugoEnvironment, codeHighlighting, searchEnabled} from '@params';
|
||||||
|
|
||||||
import {fixMermaid, scrollParentToChild} from './wowchemy-utils';
|
import {fixMermaid, scrollParentToChild} from './wowchemy-utils';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
changeThemeModeClick,
|
changeThemeModeClick,
|
||||||
initThemeVariation,
|
initThemeVariation,
|
||||||
|
@ -470,6 +469,15 @@ $(window).on('load', function () {
|
||||||
scrollParentToChild(parent, child);
|
scrollParentToChild(parent, child);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enable images to be zoomed.
|
||||||
|
let zoomOptions = {};
|
||||||
|
if (document.body.classList.contains('dark')) {
|
||||||
|
zoomOptions.background = 'rgba(0,0,0,0.9)';
|
||||||
|
} else {
|
||||||
|
zoomOptions.background = 'rgba(255,255,255,0.9)';
|
||||||
|
}
|
||||||
|
mediumZoom('[data-zoomable]', zoomOptions);
|
||||||
|
|
||||||
// Init Isotope Layout Engine for instances of the Portfolio widget.
|
// Init Isotope Layout Engine for instances of the Portfolio widget.
|
||||||
let isotopeCounter = 0;
|
let isotopeCounter = 0;
|
||||||
isotopeInstances.forEach(function (isotopeInstance, index) {
|
isotopeInstances.forEach(function (isotopeInstance, index) {
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
|
/*************************************************
|
||||||
|
* Image zooming.
|
||||||
|
**************************************************/
|
||||||
|
|
||||||
|
.medium-zoom-overlay,
|
||||||
|
.medium-zoom-image--opened {
|
||||||
|
z-index: 1031; // Nav bar index +1.
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************
|
/*************************************************
|
||||||
* Gallery.
|
* Gallery.
|
||||||
**************************************************/
|
**************************************************/
|
||||||
|
|
|
@ -85,7 +85,10 @@
|
||||||
{{ printf "<link rel=\"stylesheet\" href=\"%s\" integrity=\"%s\" crossorigin=\"anonymous\">" (printf $css.academicons.url $css.academicons.version) $css.academicons.sri | safeHTML }}
|
{{ printf "<link rel=\"stylesheet\" href=\"%s\" integrity=\"%s\" crossorigin=\"anonymous\">" (printf $css.academicons.url $css.academicons.version) $css.academicons.sri | safeHTML }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ printf "<link rel=\"stylesheet\" href=\"%s\" integrity=\"%s\" crossorigin=\"anonymous\">" (printf $css.fontAwesome.url $css.fontAwesome.version) $css.fontAwesome.sri | safeHTML }}
|
{{ printf "<link rel=\"stylesheet\" href=\"%s\" integrity=\"%s\" crossorigin=\"anonymous\">" (printf $css.fontAwesome.url $css.fontAwesome.version) $css.fontAwesome.sri | safeHTML }}
|
||||||
{{ printf "<link rel=\"stylesheet\" href=\"%s\" integrity=\"%s\" crossorigin=\"anonymous\" media=\"print\" onload=\"this.media='all'\">" (printf $css.fancybox.url $css.fancybox.version) $css.fancybox.sri | safeHTML }}
|
|
||||||
|
{{ if .HasShortcode "gallery" }}
|
||||||
|
{{ printf "<link rel=\"stylesheet\" href=\"%s\" integrity=\"%s\" crossorigin=\"anonymous\" media=\"print\" onload=\"this.media='all'\">" (printf $css.fancybox.url $css.fancybox.version) $css.fancybox.sri | safeHTML }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
{{/* Default to disabling highlighting, but allow the user to override it in .Params or site.Params.
|
{{/* Default to disabling highlighting, but allow the user to override it in .Params or site.Params.
|
||||||
Use $scr to store "highlight_enabled", so that we can read it again in footer.html. */}}
|
Use $scr to store "highlight_enabled", so that we can read it again in footer.html. */}}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
<script src="{{ printf "/js/vendor/%s" ($scr.Get "vendor_js_filename") | relURL }}"></script>
|
<script src="{{ printf "/js/vendor/%s" ($scr.Get "vendor_js_filename") | relURL }}"></script>
|
||||||
{{ else }}
|
{{ else }}
|
||||||
{{ printf "<script src=\"%s\" integrity=\"%s\" crossorigin=\"anonymous\"></script>" (printf $js.jQuery.url $js.jQuery.version) $js.jQuery.sri | safeHTML }}
|
{{ printf "<script src=\"%s\" integrity=\"%s\" crossorigin=\"anonymous\"></script>" (printf $js.jQuery.url $js.jQuery.version) $js.jQuery.sri | safeHTML }}
|
||||||
|
{{ printf "<script src=\"%s\" integrity=\"%s\" crossorigin=\"anonymous\"></script>" (printf $js.instantpage.url $js.instantpage.version) $js.instantpage.sri | safeHTML }}
|
||||||
|
|
||||||
{{ $require_isotope := site.Params.require_isotope | default true }}
|
{{ $require_isotope := site.Params.require_isotope | default true }}
|
||||||
{{ if $require_isotope }}
|
{{ if $require_isotope }}
|
||||||
|
@ -13,8 +14,9 @@
|
||||||
{{ printf "<script src=\"%s\" integrity=\"%s\" crossorigin=\"anonymous\"></script>" (printf $js.isotope.url $js.isotope.version) $js.isotope.sri | safeHTML }}
|
{{ printf "<script src=\"%s\" integrity=\"%s\" crossorigin=\"anonymous\"></script>" (printf $js.isotope.url $js.isotope.version) $js.isotope.sri | safeHTML }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
{{ printf "<script src=\"%s\" integrity=\"%s\" crossorigin=\"anonymous\"></script>" (printf $js.fancybox.url $js.fancybox.version) $js.fancybox.sri | safeHTML }}
|
{{ if .HasShortcode "gallery" }}
|
||||||
{{ printf "<script src=\"%s\" integrity=\"%s\" crossorigin=\"anonymous\"></script>" (printf $js.instantpage.url $js.instantpage.version) $js.instantpage.sri | safeHTML }}
|
{{ printf "<script src=\"%s\" integrity=\"%s\" crossorigin=\"anonymous\"></script>" (printf $js.fancybox.url $js.fancybox.version) $js.fancybox.sri | safeHTML }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
{{ if or .Params.diagram site.Params.diagram }}
|
{{ if or .Params.diagram site.Params.diagram }}
|
||||||
{{ printf "<script src=\"%s\" integrity=\"%s\" crossorigin=\"anonymous\" title=\"mermaid\"></script>" (printf $js.mermaid.url $js.mermaid.version) $js.mermaid.sri | safeHTML }}
|
{{ printf "<script src=\"%s\" integrity=\"%s\" crossorigin=\"anonymous\" title=\"mermaid\"></script>" (printf $js.mermaid.url $js.mermaid.version) $js.mermaid.sri | safeHTML }}
|
||||||
|
|
|
@ -1,55 +1,47 @@
|
||||||
{{/* Enable image to be loaded from local page dir or media library at `static/media/`. */}}
|
{{/* Figure Shortcode for Wowchemy. */}}
|
||||||
|
{{/* Load image from page dir falling back to media library at `assets/images/` and then to remote URI. */}}
|
||||||
|
|
||||||
{{ $media_dir := site.Params.media_dir | default "media" }}
|
{{ $destination := .Get "src" }}
|
||||||
{{ $asset := (.Page.Resources.ByType "image").GetMatch (.Get "src") }}
|
|
||||||
{{ $is_svg := false }}
|
|
||||||
{{ if $asset }}
|
|
||||||
{{ if eq $asset.MediaType.SubType "svg"}}
|
|
||||||
{{ $is_svg = true }}
|
|
||||||
{{ end }}
|
|
||||||
{{ end }}
|
|
||||||
{{ $image_src := (.Get "src") }}
|
|
||||||
{{ if and $asset (not $is_svg) }}
|
|
||||||
{{ $asset2 := $asset.Fit "2000x2000" }}
|
|
||||||
{{ $image_src = $asset2.RelPermalink }}
|
|
||||||
{{ else if .Get "library" }}
|
|
||||||
{{ $image_src = printf "%s/%s" $media_dir $image_src | relURL }}
|
|
||||||
{{ end }}
|
|
||||||
|
|
||||||
{{/* Disallow user from opening image in the lightbox? */}}
|
|
||||||
{{ $lightbox := eq (.Get "lightbox" | default "true") "true" }}
|
|
||||||
|
|
||||||
{{/* Get lightbox group for showing multiple images in a lightbox. */}}
|
|
||||||
{{ $group := .Get "lightbox-group" | default "" }}
|
|
||||||
|
|
||||||
{{/* Get caption. Support legacy `title` option. */}}
|
|
||||||
{{ $caption := .Get "title" | default (.Get "caption") | default "" }}
|
{{ $caption := .Get "title" | default (.Get "caption") | default "" }}
|
||||||
|
{{ $id := .Get "id" | default $caption }}
|
||||||
|
{{ $alt := .Get "alt" | default ($caption | plainify) }}
|
||||||
|
|
||||||
<figure{{ with .Get "class" }} class="{{.}}"{{ end }} {{ with $caption }}id="figure-{{ anchorize . }}"{{ end }}>
|
{{- $img := (.Page.Resources.ByType "image").GetMatch $destination -}}
|
||||||
|
{{- if and (not $img) .Page.File -}}
|
||||||
|
{{ $path := $destination }}
|
||||||
|
{{- $img = resources.Get (path.Join "images" $path) -}}
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
{{ if $lightbox }}
|
<figure {{ with .Get "class" }}class="{{.}}"{{ end }} {{ with $id }}id="figure-{{ anchorize . }}"{{ end }}>
|
||||||
<a data-fancybox="{{$group}}" href="{{$image_src}}" {{ with $caption }}data-caption="{{ .|markdownify|emojify|safeHTMLAttr }}"{{ end }}>
|
|
||||||
{{ else if .Get "link"}}
|
|
||||||
<a href="{{ .Get "link" }}"{{ with .Get "target" }} target="{{.}}"{{ end }}{{ with .Get "rel" }} rel="{{.}}"{{ end }}>
|
|
||||||
{{ end -}}
|
|
||||||
|
|
||||||
{{/* Lazy load only when we know image dimensions in order to preserve anchor linking. */}}
|
{{- if $img -}}
|
||||||
{{ if and $asset (not $is_svg) }}
|
{{ $isSVG := eq $img.MediaType.SubType "svg" }}
|
||||||
<img data-src="{{$image_src}}" class="lazyload" alt="{{ with .Get "alt" }}{{.}}{{end}}" width="{{ (.Get "width") | default $asset.Width }}" height="{{ (.Get "height") | default $asset.Height }}">
|
{{ if $isSVG }}
|
||||||
{{ else if and (.Get "width") (.Get "height") }}
|
{{ $img.Content | safeHTML }}
|
||||||
<img data-src="{{$image_src}}" class="lazyload" alt="{{ with .Get "alt" }}{{.}}{{end}}" {{ with .Get "width" }}width="{{.}}"{{end}} {{ with .Get "height" }}height="{{.}}"{{end}}>
|
{{ else }}
|
||||||
{{ else }}
|
{{- $img_lg := $img.Fit "1200x1200" -}}
|
||||||
<img src="{{$image_src}}" alt="{{ with .Get "alt" }}{{.}}{{end}}" {{ with .Get "width" }}width="{{.}}"{{end}} {{ with .Get "height" }}height="{{.}}"{{end}}>
|
{{- $img_md := $img_lg.Fit "760x760" -}}{{/* Match `.docs-article-container` max-width */}}
|
||||||
{{ end }}
|
{{- $img_sm := $img_md.Fit "400x400" -}}
|
||||||
|
<img alt="{{ $alt }}" srcset="
|
||||||
{{- if or $lightbox (.Get "link") }}</a>{{ end }}
|
{{ $img_sm.RelPermalink }} 400w,
|
||||||
|
{{ $img_md.RelPermalink }} 760w,
|
||||||
{{ if $caption }}
|
{{ $img_lg.RelPermalink }} 1200w"
|
||||||
{{/* Localize the figure numbering (if enabled). */}}
|
src="{{ $img_sm.RelPermalink }}"
|
||||||
{{ $figure := split (i18n "figure" | default "Figure %d:") "%d" }}
|
width="{{ (.Get "width") | default $img_md.Width }}"
|
||||||
<figcaption{{ if eq (.Get "numbered") "true" }} data-pre="{{- trim (index $figure 0) " " -}} " data-post="{{ index $figure 1 }} " class="numbered"{{ end }}>
|
height="{{ (.Get "height") | default $img_md.Height }}"
|
||||||
{{ $caption | markdownify | emojify }}
|
loading="lazy"
|
||||||
</figcaption>
|
data-zoomable />
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
{{- else -}}
|
||||||
|
<img src="{{ $destination | safeURL }}" alt="{{ $alt }}" loading="lazy" data-zoomable
|
||||||
|
{{ with .Get "width" }}width="{{.}}"{{end}} {{ with .Get "height" }}height="{{.}}"{{end}} />
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
{{ if $caption }}
|
||||||
|
{{/* Localize the figure numbering (if enabled). */}}
|
||||||
|
{{ $figure := split (i18n "figure" | default "Figure %d:") "%d" }}
|
||||||
|
<figcaption{{ if eq (.Get "numbered") "true" }} data-pre="{{- trim (index $figure 0) " " -}} " data-post="{{ index $figure 1 }} " class="numbered"{{ end }}>
|
||||||
|
{{ $caption | markdownify | emojify }}
|
||||||
|
</figcaption>
|
||||||
|
{{ end }}
|
||||||
</figure>
|
</figure>
|
||||||
|
|
|
@ -1269,6 +1269,11 @@ mdast-util-to-string@^2.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz#b8cfe6a713e1091cb5b728fc48885a4767f8b97b"
|
resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz#b8cfe6a713e1091cb5b728fc48885a4767f8b97b"
|
||||||
integrity sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==
|
integrity sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==
|
||||||
|
|
||||||
|
medium-zoom@^1.0.6:
|
||||||
|
version "1.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/medium-zoom/-/medium-zoom-1.0.6.tgz#9247f21ca9313d8bbe9420aca153a410df08d027"
|
||||||
|
integrity sha512-UdiUWfvz9fZMg1pzf4dcuqA0W079o0mpqbTnOz5ip4VGYX96QjmbM+OgOU/0uOzAytxC0Ny4z+VcYQnhdifimg==
|
||||||
|
|
||||||
meow@^8.0.0:
|
meow@^8.0.0:
|
||||||
version "8.1.2"
|
version "8.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/meow/-/meow-8.1.2.tgz#bcbe45bda0ee1729d350c03cffc8395a36c4e897"
|
resolved "https://registry.yarnpkg.com/meow/-/meow-8.1.2.tgz#bcbe45bda0ee1729d350c03cffc8395a36c4e897"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue