hexo-theme-linen 1.0.32 → 1.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/layout/layout.ejs +3 -3
- package/package.json +1 -1
- package/scripts/lazyload/client.js +126 -65
- package/scripts/lazyload/inject.js +2 -1
- package/source/linen-theme/css/lazyload.css +2 -2
- package/source/linen-theme/css/leaflet.css +661 -661
- package/source/linen-theme/js/hdr.js +28 -1
- package/source/linen-theme/js/lazyload.js +126 -65
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
var hdrSupport = false;
|
|
2
2
|
var hdrEnabled = false;
|
|
3
3
|
var lang = document.documentElement.getAttribute("lang") || "en";
|
|
4
|
+
var hdrAutoEnableMinWidth = 500;
|
|
4
5
|
|
|
5
6
|
function testHDRSupport() {
|
|
6
7
|
// `dynamic-range: high` describes the combination of the user agent and the
|
|
@@ -89,14 +90,40 @@ function switchHDR() {
|
|
|
89
90
|
);
|
|
90
91
|
}
|
|
91
92
|
}
|
|
93
|
+
var encodedHDRPath = encodeURIComponent(HDRPath);
|
|
94
|
+
var encodedSDRPath = encodeURIComponent(SDRPath);
|
|
95
|
+
var isHDRAsset =
|
|
96
|
+
dcontent.includes(encodedHDRPath) ||
|
|
97
|
+
dcontent.includes(encodedSDRPath);
|
|
98
|
+
if (isHDRAsset) {
|
|
99
|
+
lazyloadItem.setAttribute("data-hdr-active", targetState ? "true" : "false");
|
|
100
|
+
} else {
|
|
101
|
+
lazyloadItem.removeAttribute("data-hdr-active");
|
|
102
|
+
}
|
|
103
|
+
var innerWrap = lazyloadItem.querySelector(".inner-wrap");
|
|
104
|
+
var placeholder = lazyloadItem.querySelector(".placeholder");
|
|
92
105
|
var InnerImgs = lazyloadItem.querySelectorAll("img");
|
|
93
106
|
InnerImgs.forEach((img) => {
|
|
94
107
|
if (targetState) {
|
|
95
108
|
if (img.src && img.src.includes(SDRPath)) {
|
|
109
|
+
// Re-enter the lazyload visual state while the replacement image
|
|
110
|
+
// is loading. The placeholder remains underneath the image.
|
|
111
|
+
lazyloadItem.classList.remove("loaded");
|
|
112
|
+
if (innerWrap) {
|
|
113
|
+
innerWrap.classList.remove("loaded");
|
|
114
|
+
innerWrap.style.opacity = "0";
|
|
115
|
+
}
|
|
116
|
+
if (placeholder) placeholder.classList.remove("loaded");
|
|
96
117
|
img.src = img.src.replace(SDRPath, HDRPath);
|
|
97
118
|
}
|
|
98
119
|
} else {
|
|
99
120
|
if (img.src && img.src.includes(HDRPath)) {
|
|
121
|
+
lazyloadItem.classList.remove("loaded");
|
|
122
|
+
if (innerWrap) {
|
|
123
|
+
innerWrap.classList.remove("loaded");
|
|
124
|
+
innerWrap.style.opacity = "0";
|
|
125
|
+
}
|
|
126
|
+
if (placeholder) placeholder.classList.remove("loaded");
|
|
100
127
|
img.src = img.src.replace(HDRPath, SDRPath);
|
|
101
128
|
}
|
|
102
129
|
}
|
|
@@ -113,7 +140,7 @@ function switchHDR() {
|
|
|
113
140
|
}
|
|
114
141
|
}
|
|
115
142
|
|
|
116
|
-
if (hdrSupport) {
|
|
143
|
+
if (hdrSupport && window.innerWidth >= hdrAutoEnableMinWidth) {
|
|
117
144
|
switchHDR();
|
|
118
145
|
}
|
|
119
146
|
|
|
@@ -94,26 +94,34 @@
|
|
|
94
94
|
if (typeof window === "undefined") {
|
|
95
95
|
return;
|
|
96
96
|
}
|
|
97
|
-
function get(object, path, defaultValue) {
|
|
98
|
-
if (object == null) return defaultValue;
|
|
99
|
-
|
|
100
|
-
// 把 a[0].b 转成 a.0.b
|
|
101
|
-
var pathArray =
|
|
102
|
-
typeof path === "string"
|
|
103
|
-
? path.replace(/\[(\w+)\]/g, ".$1").split(".")
|
|
104
|
-
: path;
|
|
105
|
-
|
|
106
|
-
var result = object;
|
|
107
|
-
|
|
108
|
-
for (var i = 0; i < pathArray.length; i++) {
|
|
109
|
-
if (result == null) return defaultValue;
|
|
110
|
-
result = result[pathArray[i]];
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return result === undefined ? defaultValue : result;
|
|
114
|
-
}
|
|
115
97
|
var lazyloadItems = document.querySelectorAll(".lazyload-wrap");
|
|
116
98
|
var loadingQueue = [];
|
|
99
|
+
var scheduleFrame = window.requestAnimationFrame || function (callback) {
|
|
100
|
+
return window.setTimeout(callback, 16);
|
|
101
|
+
};
|
|
102
|
+
var revealQueue = [];
|
|
103
|
+
var revealScheduled = false;
|
|
104
|
+
var flushRevealQueue = function flushRevealQueue() {
|
|
105
|
+
var callbacks = revealQueue.splice(0);
|
|
106
|
+
revealScheduled = false;
|
|
107
|
+
callbacks.forEach(function (callback) {
|
|
108
|
+
if (callback) callback();
|
|
109
|
+
});
|
|
110
|
+
if (revealQueue.length) {
|
|
111
|
+
scheduleReveal();
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
var scheduleReveal = function scheduleReveal(callback) {
|
|
115
|
+
if (callback) revealQueue.push(callback);
|
|
116
|
+
if (revealScheduled) return;
|
|
117
|
+
revealScheduled = true;
|
|
118
|
+
// Wait for one paint opportunity before revealing. The second frame is
|
|
119
|
+
// shared by all images that become ready together, avoiding per-image
|
|
120
|
+
// frame callbacks and preserving the transition for cached HDR images.
|
|
121
|
+
scheduleFrame(function () {
|
|
122
|
+
scheduleFrame(flushRevealQueue);
|
|
123
|
+
});
|
|
124
|
+
};
|
|
117
125
|
var appendStyles = function appendStyles(element, styles) {
|
|
118
126
|
var currentStyle = element.getAttribute("style");
|
|
119
127
|
var newStyles = "";
|
|
@@ -128,6 +136,10 @@
|
|
|
128
136
|
var nElement = document.createElement("div");
|
|
129
137
|
nElement.innerHTML = contentStr;
|
|
130
138
|
nElement.classList.add("inner-wrap");
|
|
139
|
+
nElement.style.opacity = "0";
|
|
140
|
+
if (!window.$lazyload || window.$lazyload.showTransition !== false) {
|
|
141
|
+
nElement.style.transition = "opacity ease-in-out 0.3s";
|
|
142
|
+
}
|
|
131
143
|
return nElement;
|
|
132
144
|
};
|
|
133
145
|
var restore_fallback = function restore_fallback(element) {
|
|
@@ -151,6 +163,28 @@
|
|
|
151
163
|
}
|
|
152
164
|
return obj;
|
|
153
165
|
};
|
|
166
|
+
var renderBlurHashPlaceholder = function renderBlurHashPlaceholder(element) {
|
|
167
|
+
var placeholderImage = element.dataset.blurhash;
|
|
168
|
+
if (!placeholderImage || element.dataset.blurhashRendered === "true") {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
var width = 32;
|
|
172
|
+
var height = 32;
|
|
173
|
+
var pixels = blurhash.decodeBlurHash(
|
|
174
|
+
placeholderImage.replace("blurhash:", ""),
|
|
175
|
+
width,
|
|
176
|
+
height,
|
|
177
|
+
);
|
|
178
|
+
var canvas = document.createElement("canvas");
|
|
179
|
+
var ctx = canvas.getContext("2d");
|
|
180
|
+
canvas.width = width;
|
|
181
|
+
canvas.height = height;
|
|
182
|
+
var imageData = ctx.createImageData(width, height);
|
|
183
|
+
imageData.data.set(pixels);
|
|
184
|
+
ctx.putImageData(imageData, 0, 0);
|
|
185
|
+
element.children[0].appendChild(canvas);
|
|
186
|
+
element.dataset.blurhashRendered = "true";
|
|
187
|
+
};
|
|
154
188
|
var initPlaceholder = function initPlaceholder(element) {
|
|
155
189
|
var wrap = document.createElement("div");
|
|
156
190
|
// prevent triggering load event
|
|
@@ -166,25 +200,9 @@
|
|
|
166
200
|
var placeholderImage =
|
|
167
201
|
resourceElement.dataset.placeholderimg || altAttributes.placeholderImage;
|
|
168
202
|
if (placeholderImage && /blurhash:/.test(placeholderImage)) {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
var height = 32;
|
|
173
|
-
var pixels = blurhash.decodeBlurHash(
|
|
174
|
-
placeholderImage.replace("blurhash:", ""),
|
|
175
|
-
width,
|
|
176
|
-
height,
|
|
177
|
-
);
|
|
178
|
-
var ctx = canvas.getContext("2d");
|
|
179
|
-
canvas.width = width;
|
|
180
|
-
canvas.height = height;
|
|
181
|
-
var imageData = ctx.createImageData(width, height);
|
|
182
|
-
imageData.data.set(pixels);
|
|
183
|
-
ctx.putImageData(imageData, 0, 0);
|
|
184
|
-
return canvas;
|
|
185
|
-
};
|
|
186
|
-
var cv = createCanvas();
|
|
187
|
-
element.children[0].appendChild(cv);
|
|
203
|
+
// Decode only when this item is actually restored. Doing this for
|
|
204
|
+
// every image during page initialization can block the main thread.
|
|
205
|
+
element.dataset.blurhash = placeholderImage;
|
|
188
206
|
}
|
|
189
207
|
element.dataset.content = element.dataset.content
|
|
190
208
|
.replace(/%24placeholder%3D(\S+)%3Dplaceholder/gi, "")
|
|
@@ -196,34 +214,70 @@
|
|
|
196
214
|
loadingQueue.push(element);
|
|
197
215
|
}
|
|
198
216
|
if (element.classList && element.classList.contains("loaded")) return;
|
|
217
|
+
renderBlurHashPlaceholder(element);
|
|
199
218
|
var contentStr = decodeURIComponent(element.dataset.content);
|
|
200
219
|
var newElement = createResourceElement(contentStr);
|
|
201
220
|
var initOnLoadEvent = function initOnLoadEvent(resourceElement) {
|
|
202
|
-
resourceElement.children[0]
|
|
221
|
+
var imageElement = resourceElement.children[0];
|
|
222
|
+
var revealedSource = "";
|
|
223
|
+
var revealToken = 0;
|
|
224
|
+
var showTransition =
|
|
225
|
+
!window.$lazyload || window.$lazyload.showTransition !== false;
|
|
226
|
+
var clearPlaceholder = function clearPlaceholder() {
|
|
227
|
+
var keepPlaceholder =
|
|
228
|
+
element.getAttribute("data-hdr-active") === "true" ||
|
|
229
|
+
(window.$lazyload && window.$lazyload.keepPlaceholder === true);
|
|
230
|
+
if (!keepPlaceholder) {
|
|
231
|
+
element.children[0].classList.add("loaded");
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
var revealResource = function revealResource() {
|
|
235
|
+
var source = imageElement.currentSrc || imageElement.src || "";
|
|
236
|
+
if (revealedSource === source && element.classList.contains("loaded")) {
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
var token = ++revealToken;
|
|
240
|
+
// `load` means the resource is available, but the browser may still
|
|
241
|
+
// need a paint opportunity before the image becomes visible. Do not
|
|
242
|
+
// call HTMLImageElement.decode() here: some HDR decoders crash the
|
|
243
|
+
// renderer before JavaScript can handle the resulting exception.
|
|
244
|
+
scheduleReveal(function () {
|
|
245
|
+
if (token !== revealToken) return;
|
|
246
|
+
if ((imageElement.currentSrc || imageElement.src || "") !== source) {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
revealedSource = source;
|
|
250
|
+
// The inline opacity is already 0 and the inline transition is set
|
|
251
|
+
// before insertion, so the next frame can reveal without forcing a
|
|
252
|
+
// synchronous layout for every image.
|
|
253
|
+
resourceElement.style.opacity = "1";
|
|
254
|
+
resourceElement.classList.add("loaded");
|
|
255
|
+
element.classList.add("loaded");
|
|
256
|
+
if (!showTransition) {
|
|
257
|
+
clearPlaceholder();
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
};
|
|
261
|
+
imageElement.onload = function () {
|
|
203
262
|
try {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
wrapElement.setAttribute("data-pswp-width", width);
|
|
223
|
-
wrapElement.setAttribute("data-pswp-height", height);
|
|
224
|
-
wrapElement.setAttribute("data-cropped", true);
|
|
225
|
-
}
|
|
226
|
-
}, 100);
|
|
263
|
+
revealResource();
|
|
264
|
+
var isImage = imageElement && imageElement.tagName === "IMG";
|
|
265
|
+
var wrapElement = element.parentElement;
|
|
266
|
+
var width = imageElement.naturalWidth;
|
|
267
|
+
if (
|
|
268
|
+
isImage &&
|
|
269
|
+
wrapElement &&
|
|
270
|
+
wrapElement.tagName === "A" &&
|
|
271
|
+
wrapElement.getAttribute("data-pswp-hassize") !== "true"
|
|
272
|
+
) {
|
|
273
|
+
var height = imageElement.naturalHeight;
|
|
274
|
+
element.children[0].style.paddingBottom = `${
|
|
275
|
+
(height / width) * 100
|
|
276
|
+
}%`;
|
|
277
|
+
wrapElement.setAttribute("data-pswp-width", width);
|
|
278
|
+
wrapElement.setAttribute("data-pswp-height", height);
|
|
279
|
+
wrapElement.setAttribute("data-cropped", true);
|
|
280
|
+
}
|
|
227
281
|
var errorElement = element.querySelectorAll(".error-wrap")[0];
|
|
228
282
|
if (errorElement) {
|
|
229
283
|
element.removeChild(errorElement);
|
|
@@ -232,10 +286,17 @@
|
|
|
232
286
|
console.log(e);
|
|
233
287
|
}
|
|
234
288
|
};
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
289
|
+
// Cached images can already be complete before the load listener is
|
|
290
|
+
// observed. Use the same paint-safe path for that case.
|
|
291
|
+
if (imageElement.complete && imageElement.naturalWidth) {
|
|
292
|
+
revealResource();
|
|
293
|
+
}
|
|
294
|
+
resourceElement.ontransitionend = function (event) {
|
|
295
|
+
if (event.propertyName && event.propertyName !== "opacity") return;
|
|
296
|
+
// HDR gain-map composition can finish after the normal image
|
|
297
|
+
// load/opacity transition. Keep its placeholder, but clear it for
|
|
298
|
+
// normal images so transparent PNG/WebP images are not covered by it.
|
|
299
|
+
clearPlaceholder();
|
|
239
300
|
};
|
|
240
301
|
if (/<video/.test(contentStr)) {
|
|
241
302
|
setTimeout(function () {
|