Skip to content

Commit 0602137

Browse files
committed
feat: use calculated integrity hashes for local vendor plugins
When `vendors.plugins` is set to `local`, integrity hashes are now computed from the actual local files via `@next-theme/plugins` `getLocalIntegrity()` rather than using the hardcoded CDN hashes from `_vendors.yml`. This fixes SRI (Subresource Integrity) validation failures that caused browsers to block all vendor assets when self-hosting, resulting in blank pages. CDN mode is unaffected: hardcoded hashes from `_vendors.yml` are still used when `plugins` is not `local`. Depends on: next-theme/plugins#347
1 parent b90614f commit 0602137

1 file changed

Lines changed: 42 additions & 26 deletions

File tree

scripts/events/lib/vendors.js

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,71 @@
1-
'use strict';
1+
"use strict";
22

3-
const fs = require('fs');
4-
const path = require('path');
5-
const yaml = require('js-yaml');
6-
const { url_for } = require('hexo-util');
7-
const { getVendors } = require('./utils');
3+
const fs = require("fs");
4+
const path = require("path");
5+
const yaml = require("js-yaml");
6+
const { url_for } = require("hexo-util");
7+
const { getVendors } = require("./utils");
88

99
let internal;
1010
try {
11-
internal = require('@next-theme/plugins');
12-
} catch {
13-
}
14-
const vendorsFile = fs.readFileSync(path.join(__dirname, '../../../_vendors.yml'));
11+
internal = require("@next-theme/plugins");
12+
} catch {}
13+
const vendorsFile = fs.readFileSync(
14+
path.join(__dirname, "../../../_vendors.yml"),
15+
);
1516
const dependencies = yaml.load(vendorsFile);
1617

17-
module.exports = hexo => {
18+
module.exports = (hexo) => {
1819
const { vendors, creative_commons, pace } = hexo.theme.config;
19-
if (typeof internal === 'function') {
20+
if (typeof internal === "function") {
2021
internal(hexo, dependencies);
2122
}
22-
let { plugins = 'cdnjs' } = vendors;
23-
if (plugins === 'local' && typeof internal === 'undefined') {
24-
hexo.log.warn('Dependencies for `plugins: local` not found. The default CDN provider CDNJS is used instead.');
25-
hexo.log.warn('Run `npm install @next-theme/plugins` in Hexo site root directory to install the plugin.');
26-
plugins = 'cdnjs';
23+
let { plugins = "cdnjs" } = vendors;
24+
if (plugins === "local" && typeof internal === "undefined") {
25+
hexo.log.warn(
26+
"Dependencies for `plugins: local` not found. The default CDN provider CDNJS is used instead.",
27+
);
28+
hexo.log.warn(
29+
"Run `npm install @next-theme/plugins` in Hexo site root directory to install the plugin.",
30+
);
31+
plugins = "cdnjs";
2732
}
2833
for (const [key, value] of Object.entries(dependencies)) {
2934
// This script will be executed repeatedly when Hexo listens file changes
3035
// But the variable vendors[key] only needs to be modified once
31-
if (vendors[key] && typeof vendors[key] === 'string') {
36+
if (vendors[key] && typeof vendors[key] === "string") {
3237
vendors[key] = {
33-
url: url_for.call(hexo, vendors[key])
38+
url: url_for.call(hexo, vendors[key]),
3439
};
3540
continue;
3641
}
37-
if (key === 'creative_commons') {
38-
value.file = `${value.dir}/${creative_commons.size}/${creative_commons.license.replace(/-/g, '_')}.svg`;
42+
if (key === "creative_commons") {
43+
value.file = `${value.dir}/${creative_commons.size}/${creative_commons.license.replace(/-/g, "_")}.svg`;
3944
}
40-
if (key === 'pace_css') {
45+
if (key === "pace_css") {
4146
value.file = `${value.dir}/${pace.color}/pace-theme-${pace.theme}.css`;
4247
}
4348
const { name, file } = value;
4449
const links = getVendors({
4550
...value,
4651
minified: file,
47-
local : url_for.call(hexo, `lib/${name}/${file}`),
48-
custom : vendors.custom_cdn_url
52+
local: url_for.call(hexo, `lib/${name}/${file}`),
53+
custom: vendors.custom_cdn_url,
4954
});
55+
56+
// For local plugins, use calculated integrity hash from the plugin
57+
// For CDN, use the hardcoded hash from _vendors.yml
58+
let integrityHash = value.integrity;
59+
if (plugins === "local" && typeof internal === "function") {
60+
const localHash = internal.getLocalIntegrity(`lib/${name}/${file}`);
61+
if (localHash) {
62+
integrityHash = localHash;
63+
}
64+
}
65+
5066
vendors[key] = {
51-
url : links[plugins] || links.cdnjs,
52-
integrity: value.integrity
67+
url: links[plugins] || links.cdnjs,
68+
integrity: integrityHash,
5369
};
5470
}
5571
};

0 commit comments

Comments
 (0)