Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(load_theme_config): support alternate theme config #4120

Merged
merged 1 commit into from
Feb 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/hexo/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ class Hexo {
return Promise.each([
'update_package', // Update package.json
'load_config', // Load config
'load_theme_config', // Load alternate theme config
'load_plugins' // Load external plugins & scripts
], name => require(`./${name}`)(this)).then(() => this.execFilter('after_init', null, {context: this})).then(() => {
// Ready to go!
Expand Down Expand Up @@ -357,6 +358,7 @@ class Hexo {
const ctx = { config: { url: this.config.url } };
const localsObj = this.locals.toObject();

// config.theme_config has "_config.[theme].yml" merged in load_theme_config.js
if (config.theme_config) {
theme.config = deepMerge(theme.config, config.theme_config);
}
Expand Down
42 changes: 42 additions & 0 deletions lib/hexo/load_theme_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
'use strict';

const { join, parse } = require('path');
const tildify = require('tildify');
const { exists, readdir } = require('hexo-fs');
const { magenta } = require('chalk');
const { deepMerge } = require('hexo-util');

module.exports = ctx => {
if (!ctx.env.init) return;
if (!ctx.config.theme) return;

let configPath = join(ctx.base_dir, `_config.${String(ctx.config.theme)}.yml`);

return exists(configPath).then(exist => {
return exist ? configPath : findConfigPath(configPath);
}).then(path => {
if (!path) return;

configPath = path;
return ctx.render.render({ path });
}).then(config => {
if (!config || typeof config !== 'object') return;

ctx.log.debug('Second Theme Config loaded: %s', magenta(tildify(configPath)));

// ctx.config.theme_config should have highest piority
// If ctx.config.theme_config exists, then merge it with _config.[theme].yml
// If ctx.config.theme_config doesn't exist, set it to _config.[theme].yml
ctx.config.theme_config = ctx.config.theme_config
? deepMerge(config, ctx.config.theme_config) : config;
});
};

function findConfigPath(path) {
const { dir, name } = parse(path);

return readdir(dir).then(files => {
const item = files.find(item => item.startsWith(name));
if (item != null) return join(dir, item);
});
}
1 change: 1 addition & 0 deletions test/scripts/hexo/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ describe('Core', () => {
require('./load_config');
require('./load_database');
require('./load_plugins');
require('./load_theme_config');
require('./locals');
require('./multi_config_path');
require('./post');
Expand Down
65 changes: 65 additions & 0 deletions test/scripts/hexo/load_theme_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
'use strict';

const { join } = require('path');
const { mkdirs, unlink, writeFile, rmdir } = require('hexo-fs');

describe('Load alternate theme config', () => {
const Hexo = require('../../../lib/hexo');
const hexo = new Hexo(join(__dirname, 'config_test'), {silent: true});
const loadThemeConfig = require('../../../lib/hexo/load_theme_config');

hexo.env.init = true;

before(() => mkdirs(hexo.base_dir).then(() => hexo.init()));

after(() => rmdir(hexo.base_dir));

beforeEach(() => {
hexo.config.theme_config = { foo: { bar: 'ahhhhhh' } };
hexo.config.theme = 'test_theme';
});

it('_config.[theme].yml does not exist', () => loadThemeConfig(hexo).then(() => {
hexo.config.theme_config = {};
}));

it('_config.[theme].yml exists', () => {
const configPath = join(hexo.base_dir, '_config.test_theme.yml');

return writeFile(configPath, 'bar: 1').then(() => loadThemeConfig(hexo)).then(() => {
hexo.config.theme_config.bar.should.eql(1);
}).finally(() => unlink(configPath));
});

it('_config.[theme].json exists', () => {
const configPath = join(hexo.base_dir, '_config.test_theme.json');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this feature will allow other than YAML format?

Copy link
Member Author

@SukkaW SukkaW Feb 16, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since I just port the feature from load_config, if Hexo support _config.json, then _config.test_theme.json should be supported as well (That's why I include this in test cases)


return writeFile(configPath, '{"baz": 3}').then(() => loadThemeConfig(hexo)).then(() => {
hexo.config.theme_config.baz.should.eql(3);
}).finally(() => unlink(configPath));
});

it('_config.[theme].txt exists', () => {
const configPath = join(hexo.base_dir, '_config.test_theme.txt');

return writeFile(configPath, 'qux: 1').then(() => loadThemeConfig(hexo)).then(() => {
should.not.exist(hexo.config.theme_config.qux);
}).finally(() => unlink(configPath));
});

it('merge config', () => {
const configPath = join(hexo.base_dir, '_config.test_theme.yml');

const content = [
'foo:',
' bar: yoooo',
' baz: true'
].join('\n');

return writeFile(configPath, content).then(() => loadThemeConfig(hexo)).then(() => {
hexo.config.theme_config.foo.baz.should.eql(true);
hexo.config.theme_config.foo.bar.should.eql('ahhhhhh');
hexo.config.theme_config.foo.bar.should.not.eql('yoooo');
}).finally(() => unlink(configPath));
});
});