feat(config): new config checking for Hexo 5.0
parent
03567e402b
commit
83043f4c84
|
@ -4,71 +4,104 @@ const path = require('path');
|
||||||
const util = require('util');
|
const util = require('util');
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
const logger = require('hexo-log')();
|
const logger = require('hexo-log')();
|
||||||
const { Migrator } = require('hexo-component-inferno/lib/core/migrate');
|
|
||||||
|
|
||||||
module.exports = hexo => {
|
|
||||||
if (!process.argv.includes('--icarus-dont-check-config')) {
|
|
||||||
const SCHEMA_ROOT = path.join(hexo.theme_dir, 'include/schema/');
|
|
||||||
const CONFIG_PATH = path.join(hexo.theme_dir, '_config.yml');
|
|
||||||
|
|
||||||
const yaml = require('hexo-component-inferno/lib/util/yaml');
|
const yaml = require('hexo-component-inferno/lib/util/yaml');
|
||||||
|
const { Migrator } = require('hexo-component-inferno/lib/core/migrate');
|
||||||
const { SchemaLoader } = require('hexo-component-inferno/lib/core/schema');
|
const { SchemaLoader } = require('hexo-component-inferno/lib/core/schema');
|
||||||
const loader = SchemaLoader.load(require(path.join(SCHEMA_ROOT, 'config.json')), SCHEMA_ROOT);
|
const { yellow } = require('./util/console');
|
||||||
|
|
||||||
|
function loadThemeConfig(hexo, cfgPaths) {
|
||||||
|
const configs = cfgPaths.map(cfgPath => fs.readFileSync(cfgPath))
|
||||||
|
.map(cfgPath => yaml.parse(cfgPath));
|
||||||
|
return Object.assign({}, ...configs, hexo.config.theme_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateThemeConfigFile(schema, cfgPath) {
|
||||||
|
const defaultValue = schema.getDefaultValue();
|
||||||
|
fs.writeFileSync(cfgPath, defaultValue.toYaml());
|
||||||
|
}
|
||||||
|
|
||||||
|
function hashConfigFile(cfgPath) {
|
||||||
|
const content = fs.readFileSync(cfgPath);
|
||||||
|
return crypto.createHash('md5').update(content).digest('hex');
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkConfig(hexo) {
|
||||||
|
if (!process.argv.includes('--icarus-dont-check-config')) {
|
||||||
|
logger.info('=== Checking theme configurations ===');
|
||||||
|
|
||||||
|
const siteCfgFile = path.join(hexo.base_dir, '_config.yml');
|
||||||
|
const themeSiteCfg = path.join(hexo.base_dir, '_config.icarus.yml');
|
||||||
|
const themeDirCfg = path.join(hexo.theme_dir, '_config.yml');
|
||||||
|
const themeCfgPaths = [themeDirCfg, themeSiteCfg].filter(cfgPath => fs.existsSync(cfgPath));
|
||||||
|
const themeSiteCfgExample = themeSiteCfg + '.example';
|
||||||
|
|
||||||
|
const schemaDir = path.join(hexo.theme_dir, 'include/schema/');
|
||||||
|
const loader = SchemaLoader.load(require(path.join(schemaDir, 'config.json')), schemaDir);
|
||||||
const schema = loader.getSchema('/config.json');
|
const schema = loader.getSchema('/config.json');
|
||||||
logger.info('=== Checking the configuration file ===');
|
|
||||||
|
|
||||||
// Generate config file if not exist
|
|
||||||
if (!process.argv.includes('--icarus-dont-generate-config')) {
|
if (!process.argv.includes('--icarus-dont-generate-config')) {
|
||||||
if (!fs.existsSync(CONFIG_PATH)) {
|
if (!themeCfgPaths.length) {
|
||||||
logger.warn(`${CONFIG_PATH} is not found. We are creating one for you...`);
|
logger.warn('None of the following configuration files is found:');
|
||||||
logger.info('You may add \'--icarus-dont-generate-config\' to prevent creating the configuration file.');
|
logger.warn(`- ${yellow(themeSiteCfg)}`);
|
||||||
const defaultValue = schema.getDefaultValue();
|
logger.warn(`- ${yellow(themeDirCfg)}`);
|
||||||
fs.writeFileSync(CONFIG_PATH, defaultValue.toYaml());
|
logger.info('Generating theme configuration file...');
|
||||||
logger.info(`${CONFIG_PATH} created successfully.`);
|
generateThemeConfigFile(schema, themeSiteCfg);
|
||||||
|
themeCfgPaths.push(themeSiteCfg);
|
||||||
|
logger.info(`${yellow(themeSiteCfg)} created successfully.`);
|
||||||
|
logger.info('To skip configuration generation, use "--icarus-dont-generate-config".');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
let cfg = loadThemeConfig(hexo, themeCfgPaths);
|
||||||
const cfgStr = fs.readFileSync(CONFIG_PATH);
|
|
||||||
let cfg = yaml.parse(cfgStr);
|
|
||||||
// Check config version
|
|
||||||
if (!process.argv.includes('--icarus-dont-upgrade-config')) {
|
if (!process.argv.includes('--icarus-dont-upgrade-config')) {
|
||||||
const head = require(path.join(hexo.theme_dir, 'include/migration/head'));
|
const migrator = new Migrator(require(path.join(hexo.theme_dir, 'include/migration/head')));
|
||||||
const migrator = new Migrator(head);
|
if (cfg.version && migrator.isOudated(cfg.version)) {
|
||||||
// Upgrade config
|
logger.warn(`Your theme configuration is outdated (${cfg.version} < ${migrator.getLatestVersion()}).`);
|
||||||
if (migrator.isOudated(cfg.version)) {
|
logger.info('To skip the configuration upgrade, use "--icarus-dont-upgrade-config".');
|
||||||
logger.info(`Your configuration file is outdated (${cfg.version} < ${migrator.getLatestVersion()}). `
|
|
||||||
+ 'Trying to upgrade it...');
|
logger.info('Backing up theme configuration files...');
|
||||||
// Backup old config
|
for (const cfgPath of themeCfgPaths) {
|
||||||
const hash = crypto.createHash('sha256').update(cfgStr).digest('hex');
|
const backupPath = cfgPath + '.' + hashConfigFile(cfgPath);
|
||||||
const backupPath = CONFIG_PATH + '.' + hash.substring(0, 16);
|
const relCfgPath = path.relative(hexo.base_dir, cfgPath);
|
||||||
fs.writeFileSync(backupPath, cfgStr);
|
const relBackupPath = path.relative(hexo.base_dir, backupPath);
|
||||||
logger.info(`Current configurations are written up to ${backupPath}`);
|
fs.renameSync(cfgPath, backupPath);
|
||||||
// Migrate config
|
logger.info(`${yellow(relCfgPath)} => ${yellow(relBackupPath)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info('Upgrading theme configurations...');
|
||||||
cfg = migrator.migrate(cfg);
|
cfg = migrator.migrate(cfg);
|
||||||
// Save config
|
fs.writeFileSync(themeSiteCfg, yaml.stringify(cfg));
|
||||||
fs.writeFileSync(CONFIG_PATH, yaml.stringify(cfg));
|
logger.info(`Theme configurations are written to ${yellow(themeSiteCfg)}.`);
|
||||||
logger.info(`${CONFIG_PATH} upgraded successfully.`);
|
|
||||||
const defaultValue = schema.getDefaultValue();
|
generateThemeConfigFile(schema, themeSiteCfgExample);
|
||||||
fs.writeFileSync(CONFIG_PATH + '.example', defaultValue.toYaml());
|
logger.info(`Example configurations is at ${yellow(themeSiteCfgExample)}.`);
|
||||||
logger.info(`We also created an example at ${CONFIG_PATH + '.example'} for your reference.`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check config file against schemas
|
const validation = schema.validate(cfg);
|
||||||
const result = schema.validate(cfg);
|
if (validation !== true) {
|
||||||
if (result !== true) {
|
logger.warn('Theme configurations failed one or more checks.');
|
||||||
logger.warn('Configuration file failed one or more checks.');
|
|
||||||
logger.warn('Icarus may still run, but you will encounter unexcepted results.');
|
logger.warn('Icarus may still run, but you will encounter unexcepted results.');
|
||||||
logger.warn('Here is some information for you to correct the configuration file.');
|
logger.warn('Here is some information for you to correct the configuration file.');
|
||||||
logger.warn(util.inspect(result));
|
logger.warn(util.inspect(validation));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const rootCfg = yaml.parse(fs.readFileSync(siteCfgFile));
|
||||||
|
if (rootCfg.theme_config) {
|
||||||
|
logger.warn(`"theme_config" found in ${yellow(siteCfgFile)}.`);
|
||||||
|
logger.warn(`Please remove theme configurations from ${yellow(siteCfgFile)}.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = hexo => {
|
||||||
|
try {
|
||||||
|
checkConfig(hexo);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error(e);
|
logger.error(e);
|
||||||
logger.error(`Failed to load the configuration file ${CONFIG_PATH}.`);
|
logger.error('Theme configuration checking failed.');
|
||||||
logger.error('Please add \'--icarus-dont-check-config\' to your Hexo command if you');
|
logger.info('You may use \'--icarus-dont-check-config\' to skip configuration checking.');
|
||||||
logger.error('wish to skip the config file checking.');
|
|
||||||
process.exit(-1);
|
process.exit(-1);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8.3.0"
|
"node": ">=10.13.0"
|
||||||
},
|
},
|
||||||
"description": "A simple, delicate, and modern theme for Hexo",
|
"description": "A simple, delicate, and modern theme for Hexo",
|
||||||
"repository": "https://github.com/ppoffice/hexo-theme-icarus.git",
|
"repository": "https://github.com/ppoffice/hexo-theme-icarus.git",
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
"hexo-pagination": "^1.0.0",
|
"hexo-pagination": "^1.0.0",
|
||||||
"hexo-renderer-inferno": "^0.1.3",
|
"hexo-renderer-inferno": "^0.1.3",
|
||||||
"hexo-renderer-stylus": "^1.1.0",
|
"hexo-renderer-stylus": "^1.1.0",
|
||||||
"hexo-util": "^2.3.0",
|
"hexo-util": "^2.2.0",
|
||||||
"inferno": "^7.3.3",
|
"inferno": "^7.3.3",
|
||||||
"inferno-create-element": "^7.3.3",
|
"inferno-create-element": "^7.3.3",
|
||||||
"moment": "^2.22.2",
|
"moment": "^2.22.2",
|
||||||
|
|
Loading…
Reference in New Issue