refactor(*): use hexo-component-inferno
This commit is contained in:
parent
e3737f5488
commit
fe70756366
|
@ -10,8 +10,8 @@ module.exports = hexo => {
|
||||||
const SCHEMA_ROOT = path.join(hexo.theme_dir, 'include/schema/');
|
const SCHEMA_ROOT = path.join(hexo.theme_dir, 'include/schema/');
|
||||||
const CONFIG_PATH = path.join(hexo.theme_dir, '_config.yml');
|
const CONFIG_PATH = path.join(hexo.theme_dir, '_config.yml');
|
||||||
|
|
||||||
const yaml = require('../include/util/yaml');
|
const yaml = require('hexo-component-inferno/lib/util/yaml');
|
||||||
const { SchemaLoader } = require('../include/util/schema');
|
const { SchemaLoader } = require('hexo-component-inferno/lib/core/schema');
|
||||||
const loader = SchemaLoader.load(require(path.join(SCHEMA_ROOT, 'config.json')), SCHEMA_ROOT);
|
const loader = SchemaLoader.load(require(path.join(SCHEMA_ROOT, 'config.json')), SCHEMA_ROOT);
|
||||||
const schema = loader.getSchema('/config.json');
|
const schema = loader.getSchema('/config.json');
|
||||||
logger.info('=== Checking the configuration file ===');
|
logger.info('=== Checking the configuration file ===');
|
||||||
|
@ -32,7 +32,7 @@ module.exports = hexo => {
|
||||||
let cfg = yaml.parse(cfgStr);
|
let cfg = yaml.parse(cfgStr);
|
||||||
// Check config version
|
// Check config version
|
||||||
if (!process.argv.includes('--icarus-dont-upgrade-config')) {
|
if (!process.argv.includes('--icarus-dont-upgrade-config')) {
|
||||||
const migrator = new(require('../include/util/migrate'))(path.join(hexo.theme_dir, 'include/migration'));
|
const migrator = new(require('hexo-component-inferno/lib/core/migrate'))(path.join(hexo.theme_dir, 'include/migration'));
|
||||||
// Upgrade config
|
// Upgrade config
|
||||||
if (migrator.isOudated(cfg.version)) {
|
if (migrator.isOudated(cfg.version)) {
|
||||||
logger.info(`Your configuration file is outdated (${cfg.version} < ${migrator.getLatestVersion()}). `
|
logger.info(`Your configuration file is outdated (${cfg.version} < ${migrator.getLatestVersion()}). `
|
||||||
|
|
|
@ -1,66 +0,0 @@
|
||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
const yaml = require('js-yaml');
|
|
||||||
|
|
||||||
module.exports = hexo => {
|
|
||||||
const RESERVED_KEYS = {
|
|
||||||
post: Object.keys(require('hexo/lib/models/post')(hexo).paths),
|
|
||||||
page: Object.keys(require('hexo/lib/models/page')(hexo).paths)
|
|
||||||
};
|
|
||||||
|
|
||||||
function getThemeConfig(extension) {
|
|
||||||
if (fs.existsSync(path.join(hexo.theme_dir, '_config' + extension + '.yml'))) {
|
|
||||||
return yaml.safeLoad(fs.readFileSync(path.join(hexo.theme_dir, '_config' + extension + '.yml')));
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ALTERNATIVE_CONFIG = {
|
|
||||||
post: getThemeConfig('.post'),
|
|
||||||
page: getThemeConfig('.page')
|
|
||||||
};
|
|
||||||
|
|
||||||
function getExtraConfig(source, reservedKeys) {
|
|
||||||
const result = {};
|
|
||||||
for (const key in source) {
|
|
||||||
if (!key.startsWith('_') && !reservedKeys.includes(key) && typeof source[key] !== 'function') {
|
|
||||||
result[key] = source[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
hexo.extend.filter.register('template_locals', locals => {
|
|
||||||
// inject helper functions
|
|
||||||
locals.helper = {};
|
|
||||||
const helpers = hexo.extend.helper.list();
|
|
||||||
for (const name in helpers) {
|
|
||||||
locals.helper[name] = helpers[name].bind(locals);
|
|
||||||
}
|
|
||||||
if (typeof locals.__ === 'function') {
|
|
||||||
locals.helper.__ = locals.__;
|
|
||||||
}
|
|
||||||
if (typeof locals._p === 'function') {
|
|
||||||
locals.helper._p = locals._p;
|
|
||||||
}
|
|
||||||
|
|
||||||
const page = locals.page;
|
|
||||||
if (page) {
|
|
||||||
if ((page.layout !== 'page' || page.layout !== 'post') && ALTERNATIVE_CONFIG[page.layout]) {
|
|
||||||
// load alternative config if exists
|
|
||||||
locals.config = Object.assign({}, Object.getPrototypeOf(locals).theme || locals.theme, ALTERNATIVE_CONFIG[page.layout]);
|
|
||||||
} else {
|
|
||||||
// site config already merged into theme config in hexo/lib/hexo/index.js#Hexo.prototype._generateLocals()
|
|
||||||
locals.config = Object.assign({}, Object.getPrototypeOf(locals).theme || locals.theme);
|
|
||||||
}
|
|
||||||
// merge page configs
|
|
||||||
if (page.__post === true) {
|
|
||||||
Object.assign(locals.config, getExtraConfig(page, RESERVED_KEYS.page));
|
|
||||||
} else if (page.__page === true) {
|
|
||||||
Object.assign(locals.config, getExtraConfig(page, RESERVED_KEYS.page));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return locals;
|
|
||||||
});
|
|
||||||
};
|
|
|
@ -1,14 +0,0 @@
|
||||||
/**
|
|
||||||
* Category list page generator
|
|
||||||
*/
|
|
||||||
module.exports = function(hexo) {
|
|
||||||
hexo.extend.generator.register('categories', locals => {
|
|
||||||
return {
|
|
||||||
path: 'categories/',
|
|
||||||
layout: ['categories'],
|
|
||||||
data: Object.assign({}, locals, {
|
|
||||||
__categories: true
|
|
||||||
})
|
|
||||||
};
|
|
||||||
});
|
|
||||||
};
|
|
|
@ -1,14 +0,0 @@
|
||||||
/**
|
|
||||||
* Tag list page generator
|
|
||||||
*/
|
|
||||||
module.exports = function(hexo) {
|
|
||||||
hexo.extend.generator.register('tags', locals => {
|
|
||||||
return {
|
|
||||||
path: 'tags/',
|
|
||||||
layout: ['tags'],
|
|
||||||
data: Object.assign({}, locals, {
|
|
||||||
__tags: true
|
|
||||||
})
|
|
||||||
};
|
|
||||||
});
|
|
||||||
};
|
|
|
@ -1,99 +0,0 @@
|
||||||
/**
|
|
||||||
* CDN static file resolvers.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* <%- cdn(package, version, filename) %>
|
|
||||||
* <%- fontcdn(fontName) %>
|
|
||||||
* <%- iconcdn() %>
|
|
||||||
*/
|
|
||||||
|
|
||||||
const PROVIDERS = {
|
|
||||||
LIBRARY: {
|
|
||||||
cdnjs: '[cdnjs]https://cdnjs.cloudflare.com/ajax/libs/${ package }/${ version }/${ filename }',
|
|
||||||
loli: '[cdnjs]https://cdnjs.loli.net/ajax/libs/${ package }/${ version }/${ filename }',
|
|
||||||
jsdelivr: 'https://cdn.jsdelivr.net/npm/${ package }@${ version }/${ filename }',
|
|
||||||
unpkg: 'https://unpkg.com/${ package }@${ version }/${ filename }'
|
|
||||||
},
|
|
||||||
FONT: {
|
|
||||||
google: 'https://fonts.googleapis.com/${ type }?family=${ fontname }',
|
|
||||||
loli: 'https://fonts.loli.net/${ type }?family=${ fontname }'
|
|
||||||
},
|
|
||||||
ICON: {
|
|
||||||
fontawesome: 'https://use.fontawesome.com/releases/v5.12.0/css/all.css'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert npm library path to CDN.js path
|
|
||||||
*/
|
|
||||||
const CDNJS_FIXTURES = {
|
|
||||||
'moment': (ver, fname) => [
|
|
||||||
'moment.js', ver, fname.startsWith('min/') ? fname.substr(4) : fname
|
|
||||||
],
|
|
||||||
'outdatedbrowser': (ver, fname) => [
|
|
||||||
'outdated-browser', ver, fname.startsWith('outdatedbrowser/') ? fname.substr(16) : fname
|
|
||||||
],
|
|
||||||
'highlight.js': (ver, fname) => [
|
|
||||||
'highlight.js', ver, fname.endsWith('.css') && fname.indexOf('.min.') === -1
|
|
||||||
? fname.substr(0, fname.length - 4) + '.min.css' : fname
|
|
||||||
],
|
|
||||||
'mathjax': (ver, fname) => [
|
|
||||||
'mathjax', ver, fname.startsWith('unpacked/') ? fname.substr(9) : fname
|
|
||||||
],
|
|
||||||
'katex': (ver, fname) => [
|
|
||||||
'KaTeX', ver, fname
|
|
||||||
],
|
|
||||||
'pace-js': (ver, fname) => [
|
|
||||||
'pace', ver, fname
|
|
||||||
],
|
|
||||||
'clipboard': (ver, fname) => [
|
|
||||||
'clipboard.js', ver, fname
|
|
||||||
],
|
|
||||||
// disqusjs is not hosted on CDN.js
|
|
||||||
'disqusjs': (ver, fname) => []
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = function(hexo) {
|
|
||||||
hexo.extend.helper.register('cdn', function(_package, version, filename) {
|
|
||||||
let { cdn = 'jsdelivr' } = typeof this.config.providers === 'object' ? this.config.providers : {};
|
|
||||||
if (cdn in PROVIDERS.LIBRARY) {
|
|
||||||
cdn = PROVIDERS.LIBRARY[cdn];
|
|
||||||
}
|
|
||||||
// cdn.js does not follow a GitHub npm style like jsdeliver and unpkg do. Patch it!
|
|
||||||
if (cdn === 'cdnjs' || cdn.startsWith('[cdnjs]')) {
|
|
||||||
if (cdn.startsWith('[cdnjs]')) {
|
|
||||||
cdn = cdn.substr(7);
|
|
||||||
}
|
|
||||||
if (filename.startsWith('dist/')) {
|
|
||||||
filename = filename.substr(5);
|
|
||||||
}
|
|
||||||
if (Object.prototype.hasOwnProperty.call(CDNJS_FIXTURES, _package)) {
|
|
||||||
[_package, version, filename] = CDNJS_FIXTURES[_package](version, filename);
|
|
||||||
// package is not hosted on CDN.js
|
|
||||||
if (!_package) {
|
|
||||||
cdn = 'jsdelivr';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cdn.replace(/\${\s*package\s*}/gi, _package)
|
|
||||||
.replace(/\${\s*version\s*}/gi, version)
|
|
||||||
.replace(/\${\s*filename\s*}/gi, filename);
|
|
||||||
});
|
|
||||||
|
|
||||||
hexo.extend.helper.register('fontcdn', function(fontName, type = 'css') {
|
|
||||||
let { fontcdn = 'google' } = typeof this.config.providers === 'object' ? this.config.providers : {};
|
|
||||||
if (fontcdn in PROVIDERS.FONT) {
|
|
||||||
fontcdn = PROVIDERS.FONT[fontcdn];
|
|
||||||
}
|
|
||||||
return fontcdn.replace(/\${\s*fontname\s*}/gi, fontName)
|
|
||||||
.replace(/\${\s*type\s*}/gi, type);
|
|
||||||
});
|
|
||||||
|
|
||||||
hexo.extend.helper.register('iconcdn', function() {
|
|
||||||
let { iconfont = 'fontawesome' } = typeof this.config.providers === 'object' ? this.config.providers : {};
|
|
||||||
if (iconfont in PROVIDERS.ICON) {
|
|
||||||
iconfont = PROVIDERS.ICON[iconfont];
|
|
||||||
}
|
|
||||||
return iconfont;
|
|
||||||
});
|
|
||||||
};
|
|
|
@ -1,16 +0,0 @@
|
||||||
/**
|
|
||||||
* Helper functions for page/post.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* <%- is_categories(page) %>
|
|
||||||
* <%- is_tags(page) %>
|
|
||||||
*/
|
|
||||||
module.exports = function(hexo) {
|
|
||||||
hexo.extend.helper.register('is_categories', function(page = null) {
|
|
||||||
return (page === null ? this.page : page).__categories === true;
|
|
||||||
});
|
|
||||||
|
|
||||||
hexo.extend.helper.register('is_tags', function(page = null) {
|
|
||||||
return (page === null ? this.page : page).__tags === true;
|
|
||||||
});
|
|
||||||
};
|
|
|
@ -1,24 +0,0 @@
|
||||||
/**
|
|
||||||
* Helper functions for post thumbnail.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* <%- has_thumbnail(post) %>
|
|
||||||
* <%- get_thumbnail(post) %>
|
|
||||||
*/
|
|
||||||
module.exports = function(hexo) {
|
|
||||||
hexo.extend.helper.register('has_thumbnail', function(post) {
|
|
||||||
const { article } = this.config;
|
|
||||||
if (typeof post !== 'object') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (article && article.thumbnail === false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return 'thumbnail' in post && post.thumbnail;
|
|
||||||
});
|
|
||||||
|
|
||||||
hexo.extend.helper.register('get_thumbnail', function(post) {
|
|
||||||
const { url_for, has_thumbnail } = this.helper;
|
|
||||||
return url_for(has_thumbnail.call(this, post) ? post.thumbnail : '/img/thumbnail.svg');
|
|
||||||
});
|
|
||||||
};
|
|
|
@ -1,13 +1,13 @@
|
||||||
const logger = require('hexo-log')();
|
const logger = require('hexo-log')();
|
||||||
const deepmerge = require('deepmerge');
|
const deepmerge = require('deepmerge');
|
||||||
const Migration = require('../util/migrate').Migration;
|
const Migration = require('hexo-component-inferno/lib/core/migrate').Migration;
|
||||||
|
|
||||||
module.exports = class extends Migration {
|
module.exports = class extends Migration {
|
||||||
constructor() {
|
constructor() {
|
||||||
super('3.0.0', null);
|
super('3.0.0', null);
|
||||||
}
|
}
|
||||||
|
|
||||||
doMigrate(config) {
|
upgrade(config) {
|
||||||
const result = deepmerge({}, config);
|
const result = deepmerge({}, config);
|
||||||
result.head = {
|
result.head = {
|
||||||
favicon: config.favicon || null,
|
favicon: config.favicon || null,
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
const logger = require('hexo-log')();
|
const logger = require('hexo-log')();
|
||||||
|
|
||||||
module.exports = hexo => {
|
module.exports = hexo => {
|
||||||
logger.info('=== Patching Hexo ===');
|
logger.info('=== Registering Hexo extensions ===');
|
||||||
require('../include/generator/categories')(hexo);
|
require('hexo-component-inferno/lib/hexo/filter/locals')(hexo);
|
||||||
require('../include/generator/category')(hexo);
|
require('./generator/category')(hexo);
|
||||||
require('../include/generator/tags')(hexo);
|
require('./generator/insight')(hexo);
|
||||||
require('../include/generator/insight')(hexo);
|
require('hexo-component-inferno/lib/hexo/generator/categories')(hexo);
|
||||||
require('../include/filter/locals')(hexo);
|
require('hexo-component-inferno/lib/hexo/generator/tags')(hexo);
|
||||||
require('../include/helper/cdn')(hexo);
|
require('hexo-component-inferno/lib/hexo/helper/cdn')(hexo);
|
||||||
require('../include/helper/page')(hexo);
|
require('hexo-component-inferno/lib/hexo/helper/page')(hexo);
|
||||||
require('../include/helper/thumbnail')(hexo);
|
require('hexo-component-inferno/lib/hexo/helper/thumbnail')(hexo);
|
||||||
|
require('hexo-component-inferno/lib/core/view').init(hexo);
|
||||||
|
|
||||||
const hooks = [
|
const hooks = [
|
||||||
'after_render:html',
|
'after_render:html',
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/comment/changyan.json",
|
|
||||||
"description": "Changyan comment plugin configurations",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "changyan"
|
|
||||||
},
|
|
||||||
"app_id": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Changyan app ID"
|
|
||||||
},
|
|
||||||
"conf": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Changyan configuration ID"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type",
|
|
||||||
"app_id",
|
|
||||||
"conf"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/comment/disqus.json",
|
|
||||||
"description": "Disqus comment plugin configurations",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "disqus"
|
|
||||||
},
|
|
||||||
"shortname": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Disqus shortname"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type",
|
|
||||||
"shortname"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,58 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/comment/disqusjs.json",
|
|
||||||
"description": "DisqusJS comment plugin configurations",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "disqusjs"
|
|
||||||
},
|
|
||||||
"shortname": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Disqus shortname"
|
|
||||||
},
|
|
||||||
"api_key": {
|
|
||||||
"description": "Disqus application API key",
|
|
||||||
"anyOf": [
|
|
||||||
{
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "array",
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"api": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Disqus API endpoint"
|
|
||||||
},
|
|
||||||
"admin": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Disqus moderator username",
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"admin_label": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Disqus moderator badge text",
|
|
||||||
"default": false,
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"nesting": {
|
|
||||||
"type": "integer",
|
|
||||||
"description": "Maximum number of comment nesting level",
|
|
||||||
"default": 4,
|
|
||||||
"nullable": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type",
|
|
||||||
"shortname",
|
|
||||||
"api_key"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/comment/facebook.json",
|
|
||||||
"description": "Facebook comment plugin configurations",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "facebook"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,83 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/comment/gitalk.json",
|
|
||||||
"description": "Gitalk comment plugin configurations",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "gitalk"
|
|
||||||
},
|
|
||||||
"client_id": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "GitHub application client ID"
|
|
||||||
},
|
|
||||||
"client_secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "GitHub application client secret"
|
|
||||||
},
|
|
||||||
"repo": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "GitHub repository"
|
|
||||||
},
|
|
||||||
"owner": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "GitHub repository owner. Can be personal user or organization"
|
|
||||||
},
|
|
||||||
"admin": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "GitHub repository owner and collaborators. (Users who having write access to this repository)",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"per_page": {
|
|
||||||
"type": "number",
|
|
||||||
"description": "Pagination size, with maximum 100",
|
|
||||||
"default": 10,
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"distraction_free_mode": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Facebook-like distraction free mode",
|
|
||||||
"default": false,
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"pager_direction": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Comment sorting direction, available values are `last` and `first`",
|
|
||||||
"default": "last",
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"create_issue_manually": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Create GitHub issues manually for each page",
|
|
||||||
"default": false,
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"proxy": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "GitHub oauth request reverse proxy for CORS",
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"flip_move_options": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "Comment list animation",
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"enable_hotkey": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Enable hot key (cmd|ctrl + enter) submit comment",
|
|
||||||
"default": true,
|
|
||||||
"nullable": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type",
|
|
||||||
"client_id",
|
|
||||||
"client_secret",
|
|
||||||
"repo",
|
|
||||||
"owner",
|
|
||||||
"admin"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,53 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/comment/gitment.json",
|
|
||||||
"description": "Gitment comment plugin configurations",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "gitment"
|
|
||||||
},
|
|
||||||
"owner": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Your GitHub ID"
|
|
||||||
},
|
|
||||||
"repo": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The repository to store your comments. Make sure you're repo's owner"
|
|
||||||
},
|
|
||||||
"client_id": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "GitHub client ID"
|
|
||||||
},
|
|
||||||
"client_secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "GitHub client secret"
|
|
||||||
},
|
|
||||||
"theme": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "An optional Gitment theme object",
|
|
||||||
"default": "gitment.defaultTheme",
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"per_page": {
|
|
||||||
"type": "number",
|
|
||||||
"description": "An optional number to which comments will be paginated",
|
|
||||||
"default": 20,
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"max_comment_height": {
|
|
||||||
"type": "number",
|
|
||||||
"description": "An optional number to limit comments' max height, over which comments will be folded",
|
|
||||||
"default": 250,
|
|
||||||
"nullable": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type",
|
|
||||||
"owner",
|
|
||||||
"repo",
|
|
||||||
"client_id",
|
|
||||||
"client_secret"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/comment/isso.json",
|
|
||||||
"description": "Isso comment plugin configurations",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "isso"
|
|
||||||
},
|
|
||||||
"url": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "URL to your Isso comment service"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type",
|
|
||||||
"url"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/comment/livere.json",
|
|
||||||
"description": "Livere comment plugin configurations",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "livere"
|
|
||||||
},
|
|
||||||
"uid": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "LiveRe comment service UID"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type",
|
|
||||||
"uid"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,102 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/comment/valine.json",
|
|
||||||
"description": "Valine comment plugin configurations",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "valine"
|
|
||||||
},
|
|
||||||
"app_id": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Application <APP_ID> from Leancloud"
|
|
||||||
},
|
|
||||||
"app_key": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Application <APP_KEY> from Leancloud"
|
|
||||||
},
|
|
||||||
"placeholder": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Comment box placeholders",
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"notify": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Enable email notification when someone comments",
|
|
||||||
"default": false,
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"verify": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Enable verification code service",
|
|
||||||
"default": false,
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"avatar": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Gravatar type",
|
|
||||||
"enum": [
|
|
||||||
"",
|
|
||||||
"mp",
|
|
||||||
"identicon",
|
|
||||||
"monsterid",
|
|
||||||
"wavatar",
|
|
||||||
"robohash",
|
|
||||||
"retro",
|
|
||||||
"hide",
|
|
||||||
"mm"
|
|
||||||
],
|
|
||||||
"default": "mm",
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"avatar_force": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Pull the latest avatar upon page visit",
|
|
||||||
"default": false,
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"meta": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "Reviewer attributes",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"default": [
|
|
||||||
"nick",
|
|
||||||
"mail",
|
|
||||||
"link"
|
|
||||||
],
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"page_size": {
|
|
||||||
"type": "integer",
|
|
||||||
"description": "Number of comments per page",
|
|
||||||
"default": 10,
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"visitor": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Show visitor count",
|
|
||||||
"default": false,
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"highlight": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Enable code highlighting",
|
|
||||||
"default": true,
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"record_ip": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Record reviewer IP address",
|
|
||||||
"default": false,
|
|
||||||
"nullable": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type",
|
|
||||||
"app_id",
|
|
||||||
"app_key"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/donate/alipay.json",
|
|
||||||
"description": "Alipay donate button configurations",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "alipay"
|
|
||||||
},
|
|
||||||
"qrcode": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Alipay qrcode image URL"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type",
|
|
||||||
"qrcode"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/donate/buymeacoffee.json",
|
|
||||||
"description": "\"Buy me a coffee\" donate button configurations",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "buymeacoffee"
|
|
||||||
},
|
|
||||||
"url": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "URL to the \"Buy me a coffee\" page"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type",
|
|
||||||
"url"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/donate/patreon.json",
|
|
||||||
"description": "Patreon donate button configurations",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "patreon"
|
|
||||||
},
|
|
||||||
"url": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "URL to the Patreon page"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type",
|
|
||||||
"url"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/donate/paypal.json",
|
|
||||||
"description": "Paypal donate button configurations",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "paypal"
|
|
||||||
},
|
|
||||||
"business": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Paypal business ID or email address"
|
|
||||||
},
|
|
||||||
"currency_code": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Currency code",
|
|
||||||
"examples": [
|
|
||||||
"USD"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type",
|
|
||||||
"business",
|
|
||||||
"currency_code"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/donate/wechat.json",
|
|
||||||
"description": "Wechat donate button configurations",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "wechat"
|
|
||||||
},
|
|
||||||
"qrcode": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Wechat qrcode image URL"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type",
|
|
||||||
"qrcode"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/misc/meta.json",
|
|
||||||
"description": "Additional HTML meta tags in an array",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Meta tag specified in <attribute>=<value> style\nE.g., name=theme-color;content=#123456 => <meta name=\"theme-color\" content=\"#123456\">"
|
|
||||||
},
|
|
||||||
"nullable": true
|
|
||||||
}
|
|
|
@ -1,81 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/misc/open_graph.json",
|
|
||||||
"description": "Open Graph metadata\nhttps://hexo.io/docs/helpers.html#open-graph",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"title": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Page title (og:title) (optional)\nYou should leave this blank for most of the time",
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Page type (og:type) (optional)\nYou should leave this blank for most of the time",
|
|
||||||
"default": "blog",
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"url": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Page URL (og:url) (optional)\nYou should leave this blank for most of the time",
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"image": {
|
|
||||||
"type": [
|
|
||||||
"string",
|
|
||||||
"array"
|
|
||||||
],
|
|
||||||
"description": "Page cover (og:image) (optional) Default to the Open Graph image or thumbnail of the page\nYou should leave this blank for most of the time",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"site_name": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Site name (og:site_name) (optional)\nYou should leave this blank for most of the time",
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"author": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Page author (article:author) (optional)\nYou should leave this blank for most of the time",
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"description": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Page description (og:description) (optional)\nYou should leave this blank for most of the time",
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"twitter_card": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Twitter card type (twitter:card)",
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"twitter_id": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Twitter ID (twitter:creator)",
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"twitter_site": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Twitter ID (twitter:creator)",
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"google_plus": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Google+ profile link (deprecated)",
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"fb_admins": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Facebook admin ID",
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"fb_app_id": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Facebook App ID",
|
|
||||||
"nullable": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nullable": true
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/misc/poly_links.json",
|
|
||||||
"description": "A polymorphic link",
|
|
||||||
"type": "object",
|
|
||||||
"patternProperties": {
|
|
||||||
".+": {
|
|
||||||
"type": [
|
|
||||||
"string",
|
|
||||||
"object"
|
|
||||||
],
|
|
||||||
"description": "URL or path of the link, with/without the icon element class name",
|
|
||||||
"properties": {
|
|
||||||
"url": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "URL or path of the link"
|
|
||||||
},
|
|
||||||
"icon": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Icon element class name"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"url",
|
|
||||||
"icon"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"examples": [
|
|
||||||
{
|
|
||||||
"My GitHub Page": "https://github.com/ppoffice"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"My GitHub Page": {
|
|
||||||
"url": "https://github.com/ppoffice",
|
|
||||||
"icon": "fab fa-github"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nullable": true
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/misc/structured_data.json",
|
|
||||||
"description": "Structured data of the page\nhttps://developers.google.com/search/docs/guides/intro-structured-data",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"title": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Page title (optional)\nYou should leave this blank for most of the time",
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"description": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Page description (optional)\nYou should leave this blank for most of the time",
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"url": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Page URL (optional)\nYou should leave this blank for most of the time",
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"author": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Page author (article:author) (optional)\nYou should leave this blank for most of the time",
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"image": {
|
|
||||||
"type": [
|
|
||||||
"string",
|
|
||||||
"array"
|
|
||||||
],
|
|
||||||
"description": "Page images (optional) Default to the Open Graph image or thumbnail of the page\nYou should leave this blank for most of the time",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"nullable": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nullable": true
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/plugin/baidu_analytics.json",
|
|
||||||
"description": "Baidu Analytics plugin settings\nhttps://tongji.baidu.com",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"tracking_id": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Baidu Analytics tracking ID",
|
|
||||||
"nullable": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"tracking_id"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/plugin/busuanzi.json",
|
|
||||||
"description": "BuSuanZi site/page view counter\nhttps://busuanzi.ibruce.info",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/plugin/gallery.json",
|
|
||||||
"description": "Enable the lightGallery and Justified Gallery plugins\nhttps://ppoffice.github.io/hexo-theme-icarus/Plugins/General/gallery-plugin/",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": true
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/plugin/google_analytics.json",
|
|
||||||
"description": "Google Analytics plugin settings\nhttps://analytics.google.com",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"tracking_id": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Google Analytics tracking ID",
|
|
||||||
"nullable": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"tracking_id"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/plugin/hotjar.json",
|
|
||||||
"description": "Hotjar user feedback plugin\nhttps://www.hotjar.com/",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"site_id": {
|
|
||||||
"type": [
|
|
||||||
"string",
|
|
||||||
"number"
|
|
||||||
],
|
|
||||||
"description": "Hotjar site id",
|
|
||||||
"nullable": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"site_id"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/plugin/katex.json",
|
|
||||||
"description": "Enable the KaTeX math typesetting supprot\nhttps://katex.org/",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/plugin/mathjax.json",
|
|
||||||
"description": "Enable the MathJax math typesetting support\nhttps://www.mathjax.org/",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/plugin/outdated_browser.json",
|
|
||||||
"description": "Enable the Outdated Browser plugin\nhttp://outdatedbrowser.com/",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/plugin/progressbar.json",
|
|
||||||
"description": "Show a progress bar at top of the page on page loading",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": true
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/search/baidu.json",
|
|
||||||
"description": "Enable Baidu search",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "baidu"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/search/google_cse.json",
|
|
||||||
"description": "Enable Google CSE\nhttps://cse.google.com/cse/create/new",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "google_cse"
|
|
||||||
},
|
|
||||||
"cx": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Google CSE cx value"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type",
|
|
||||||
"cx"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/share/addthis.json",
|
|
||||||
"description": "Enable AddThis share buttons\nhttps://www.addthis.com/",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "addthis"
|
|
||||||
},
|
|
||||||
"install_url": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "URL to the AddThis share plugin script"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type",
|
|
||||||
"install_url"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/share/addtoany.json",
|
|
||||||
"description": "Enable AddToAny share buttons\nhttps://www.addtoany.com/",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "addtoany"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/share/bdshare.json",
|
|
||||||
"description": "Enable Baidu share buttons",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "bdshare"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/share/sharejs.json",
|
|
||||||
"description": "Enable Share.js share buttons\nhttps://github.com/overtrue/share.js/",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "sharejs"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/share/sharethis.json",
|
|
||||||
"description": "Enable ShareThis share buttons\nhttps://sharethis.com/",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "sharethis"
|
|
||||||
},
|
|
||||||
"install_url": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "URL to the ShareThis share plugin script"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type",
|
|
||||||
"install_url"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/widget/adsense.json",
|
|
||||||
"description": "Google AdSense unit configurations",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "adsense"
|
|
||||||
},
|
|
||||||
"client_id": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "AdSense client ID"
|
|
||||||
},
|
|
||||||
"slot_id": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "AdSense AD unit ID"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type",
|
|
||||||
"client_id",
|
|
||||||
"slot_id"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/widget/archives.json",
|
|
||||||
"description": "Archives widget configurations",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "archives"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/widget/categories.json",
|
|
||||||
"description": "Categories widget configurations",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "categories"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/widget/links.json",
|
|
||||||
"description": "Recommendation links widget configurations",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "links"
|
|
||||||
},
|
|
||||||
"links": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "Names and URLs of the sites",
|
|
||||||
"patternProperties": {
|
|
||||||
".+": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "URL of the site"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"examples": [
|
|
||||||
{
|
|
||||||
"Hexo": "https://hexo.io",
|
|
||||||
"Bulma": "https://bulma.io"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nullable": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/widget/recent_posts.json",
|
|
||||||
"description": "Recent posts widget configurations",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "recent_posts"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/widget/subscribe_email.json",
|
|
||||||
"description": "Google FeedBurner email subscription widget configurations",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "subscribe_email"
|
|
||||||
},
|
|
||||||
"description": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Hint text under the email input",
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"feedburner_id": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Feedburner ID"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type",
|
|
||||||
"feedburner_id"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/widget/tags.json",
|
|
||||||
"description": "Tags widget configurations",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "tags"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": "/widget/toc.json",
|
|
||||||
"description": "Table of contents widget configurations",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "toc"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,110 +0,0 @@
|
||||||
const path = require('path');
|
|
||||||
const logger = require('hexo-log')();
|
|
||||||
|
|
||||||
class Version {
|
|
||||||
constructor(version) {
|
|
||||||
const ver = version.split('.').map(i => parseInt(i, 10));
|
|
||||||
if (ver.length !== 3) {
|
|
||||||
throw new Error('Malformed version number ' + version);
|
|
||||||
}
|
|
||||||
this.major = ver[0];
|
|
||||||
this.minor = ver[1];
|
|
||||||
this.patch = ver[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
toString() {
|
|
||||||
return `${this.major}.${this.minor}.${this.patch}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Version.compare = function(a, b) {
|
|
||||||
if (!(a instanceof Version) || !(b instanceof Version)) {
|
|
||||||
throw new Error('Cannot compare non-Versions');
|
|
||||||
}
|
|
||||||
if (a.major !== b.major) {
|
|
||||||
return a.major - b.major;
|
|
||||||
}
|
|
||||||
if (a.minor !== b.minor) {
|
|
||||||
return a.minor - b.minor;
|
|
||||||
}
|
|
||||||
if (a.patch !== b.patch) {
|
|
||||||
return a.patch - b.patch;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Migration {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} version Target version
|
|
||||||
* @param {string} head File name of the previous migration
|
|
||||||
*/
|
|
||||||
constructor(version, head) {
|
|
||||||
this.version = new Version(version);
|
|
||||||
this.head = head;
|
|
||||||
}
|
|
||||||
|
|
||||||
doMigrate(config) {
|
|
||||||
throw new Error('Not implemented!');
|
|
||||||
}
|
|
||||||
|
|
||||||
migrate(config) {
|
|
||||||
logger.info(`Updating configurations from ${config.version} to ${this.version.toString()}...`);
|
|
||||||
const result = this.doMigrate(config);
|
|
||||||
result.version = this.version.toString();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class Migrator {
|
|
||||||
constructor(root) {
|
|
||||||
this.versions = [];
|
|
||||||
this.migrations = {};
|
|
||||||
|
|
||||||
let head = 'head';
|
|
||||||
while (head) {
|
|
||||||
const migration = new(require(path.join(root, head)))();
|
|
||||||
if (!(migration instanceof Migration)) {
|
|
||||||
throw new Error(`Migration ${head} is not a Migration class.`);
|
|
||||||
}
|
|
||||||
this.versions.push(migration.version);
|
|
||||||
this.migrations[migration.version.toString()] = migration;
|
|
||||||
head = migration.head;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.versions.sort(Version.compare);
|
|
||||||
}
|
|
||||||
|
|
||||||
isOudated(version) {
|
|
||||||
if (!this.versions.length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return Version.compare(new Version(version), this.getLatestVersion()) < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
getLatestVersion() {
|
|
||||||
if (!this.versions.length) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return this.versions[this.versions.length - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
migrate(config, toVersion = null) {
|
|
||||||
const fVer = new Version(config.version);
|
|
||||||
const tVer = toVersion ? new Version(toVersion) : this.getLatestVersion();
|
|
||||||
// find all migrations whose version is larger than fromVer, smaller or equal to toVer
|
|
||||||
// and run migrations on the config one by one
|
|
||||||
return this.versions.filter(ver => Version.compare(ver, fVer) > 0 && Version.compare(ver, tVer) <= 0)
|
|
||||||
.sort(Version.compare)
|
|
||||||
.reduce((cfg, ver) => {
|
|
||||||
const migration = this.migrations[ver.toString()];
|
|
||||||
return migration.migrate(cfg);
|
|
||||||
}, config);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Migrator.Version = Version;
|
|
||||||
Migrator.Migration = Migration;
|
|
||||||
|
|
||||||
module.exports = Migrator;
|
|
|
@ -1,305 +0,0 @@
|
||||||
const Ajv = require('ajv');
|
|
||||||
const path = require('path');
|
|
||||||
const deepmerge = require('deepmerge');
|
|
||||||
const yaml = require('./yaml');
|
|
||||||
|
|
||||||
const MAGIC = 'c823d4d4';
|
|
||||||
|
|
||||||
const PRIMITIVE_DEFAULTS = {
|
|
||||||
'null': null,
|
|
||||||
'boolean': false,
|
|
||||||
'number': 0,
|
|
||||||
'integer': 0,
|
|
||||||
'string': '',
|
|
||||||
'array': [],
|
|
||||||
'object': {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class DefaultValue {
|
|
||||||
constructor(value, description) {
|
|
||||||
this.value = value;
|
|
||||||
this.description = description;
|
|
||||||
}
|
|
||||||
|
|
||||||
merge(source) {
|
|
||||||
if ('description' in source && source.description) {
|
|
||||||
this.description = source.description;
|
|
||||||
}
|
|
||||||
if ('value' in source && source.value) {
|
|
||||||
if (this.value instanceof DefaultValue) {
|
|
||||||
this.value.merge(source.value);
|
|
||||||
} else if (Array.isArray(this.value) && Array.isArray(source.value)) {
|
|
||||||
this.value.concat(...source.value);
|
|
||||||
} else if (typeof this.value === 'object' && typeof source.value === 'object') {
|
|
||||||
for (const key in source.value) {
|
|
||||||
this.value[key] = source.value[key];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.value = deepmerge(this.value, source.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
clone() {
|
|
||||||
const result = new DefaultValue(this.value, this.description);
|
|
||||||
if (result.value instanceof DefaultValue) {
|
|
||||||
result.value = result.value.clone();
|
|
||||||
} else if (Array.isArray(result.value)) {
|
|
||||||
result.value = [].concat(...result.value);
|
|
||||||
} else if (typeof result.value === 'object') {
|
|
||||||
result.value = Object.assign({}, result.value);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
toCommentedArray() {
|
|
||||||
return [].concat(...this.value.map(item => {
|
|
||||||
if (item instanceof DefaultValue) {
|
|
||||||
if (typeof item.description !== 'string' || !item.description.trim()) {
|
|
||||||
return [item.toCommented()];
|
|
||||||
}
|
|
||||||
return item.description.split('\n').map((line, i) => {
|
|
||||||
return MAGIC + i + ': ' + line;
|
|
||||||
}).concat(item.toCommented());
|
|
||||||
}
|
|
||||||
return [item];
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
toCommentedObject() {
|
|
||||||
if (this.value instanceof DefaultValue) {
|
|
||||||
return this.value.toCommented();
|
|
||||||
}
|
|
||||||
const result = {};
|
|
||||||
for (const key in this.value) {
|
|
||||||
const item = this.value[key];
|
|
||||||
if (item instanceof DefaultValue) {
|
|
||||||
if (typeof item.description === 'string' && item.description.trim()) {
|
|
||||||
item.description.split('\n').forEach((line, i) => {
|
|
||||||
result[MAGIC + key + i] = line;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
result[key] = item.toCommented();
|
|
||||||
} else {
|
|
||||||
result[key] = item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
toCommented() {
|
|
||||||
if (Array.isArray(this.value)) {
|
|
||||||
return this.toCommentedArray();
|
|
||||||
} else if (typeof this.value === 'object' && this.value !== null) {
|
|
||||||
return this.toCommentedObject();
|
|
||||||
}
|
|
||||||
return this.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
toYaml() {
|
|
||||||
const regex = new RegExp('^(\\s*)(?:-\\s*\\\')?' + MAGIC + '.*?:\\s*\\\'?(.*?)\\\'*$', 'mg');
|
|
||||||
return yaml.stringify(this.toCommented()).replace(regex, '$1# $2');// restore comments
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* eslint-disable no-use-before-define */
|
|
||||||
class Schema {
|
|
||||||
constructor(loader, def) {
|
|
||||||
if (!(loader instanceof SchemaLoader)) {
|
|
||||||
throw new Error('loader must be an instance of SchemaLoader');
|
|
||||||
}
|
|
||||||
if (typeof def !== 'object') {
|
|
||||||
throw new Error('schema definition must be an object');
|
|
||||||
}
|
|
||||||
this.loader = loader;
|
|
||||||
this.def = def;
|
|
||||||
this.compiledSchema = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
validate(obj) {
|
|
||||||
if (!this.compiledSchema) {
|
|
||||||
this.compiledSchema = this.loader.compileValidator(this.def.$id);
|
|
||||||
}
|
|
||||||
return this.compiledSchema(obj) ? true : this.compiledSchema.errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
getArrayDefaultValue(def) {
|
|
||||||
let value;
|
|
||||||
const defaultValue = new DefaultValue(null, def.description);
|
|
||||||
if ('items' in def && typeof def.items === 'object') {
|
|
||||||
const items = Object.assign({}, def.items);
|
|
||||||
delete items.oneOf;
|
|
||||||
value = this.getDefaultValue(items);
|
|
||||||
}
|
|
||||||
if ('oneOf' in def.items && Array.isArray(def.items.oneOf)) {
|
|
||||||
defaultValue.value = def.items.oneOf.map(one => {
|
|
||||||
if (!(value instanceof DefaultValue)) {
|
|
||||||
return this.getDefaultValue(one);
|
|
||||||
}
|
|
||||||
return value.clone().merge(this.getDefaultValue(one));
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (!Array.isArray(value)) {
|
|
||||||
value = [value];
|
|
||||||
}
|
|
||||||
defaultValue.value = value;
|
|
||||||
}
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
getObjectDefaultValue(def) {
|
|
||||||
const value = {};
|
|
||||||
if ('properties' in def && typeof def.properties === 'object') {
|
|
||||||
for (const property in def.properties) {
|
|
||||||
value[property] = this.getDefaultValue(def.properties[property]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const defaultValue = new DefaultValue(value, def.description);
|
|
||||||
if ('oneOf' in def && Array.isArray(def.oneOf) && def.oneOf.length) {
|
|
||||||
defaultValue.merge(this.getDefaultValue(def.oneOf[0]));
|
|
||||||
defaultValue.description = def.description;
|
|
||||||
}
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
getTypedDefaultValue(def) {
|
|
||||||
let defaultValue;
|
|
||||||
const type = Array.isArray(def.type) ? def.type[0] : def.type;
|
|
||||||
if (type === 'array') {
|
|
||||||
defaultValue = this.getArrayDefaultValue(def);
|
|
||||||
} else if (type === 'object') {
|
|
||||||
defaultValue = this.getObjectDefaultValue(def);
|
|
||||||
} else if (type in PRIMITIVE_DEFAULTS) {
|
|
||||||
if ('nullable' in def && def.nullable) {
|
|
||||||
defaultValue = new DefaultValue(null, def.description);
|
|
||||||
} else {
|
|
||||||
defaultValue = new DefaultValue(PRIMITIVE_DEFAULTS[type], def.description);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new Error(`Cannot get default value for type ${type}`);
|
|
||||||
}
|
|
||||||
// referred default value always get overwritten by its parent default value
|
|
||||||
if ('$ref' in def && def.$ref) {
|
|
||||||
defaultValue = this.getReferredDefaultValue(def).merge(defaultValue);
|
|
||||||
}
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
getReferredDefaultValue(def) {
|
|
||||||
const schema = this.loader.getSchema(def.$ref);
|
|
||||||
if (!schema) {
|
|
||||||
throw new Error(`Schema ${def.$ref} is not loaded`);
|
|
||||||
}
|
|
||||||
return this.getDefaultValue(schema.def).merge({ description: def.description });
|
|
||||||
}
|
|
||||||
|
|
||||||
getDefaultValue(def = null) {
|
|
||||||
if (!def) {
|
|
||||||
def = this.def;
|
|
||||||
}
|
|
||||||
if ('const' in def) {
|
|
||||||
return new DefaultValue(def.const, def.description);
|
|
||||||
}
|
|
||||||
if ('default' in def) {
|
|
||||||
return new DefaultValue(def.default, def.description);
|
|
||||||
}
|
|
||||||
if ('examples' in def && Array.isArray(def.examples) && def.examples.length) {
|
|
||||||
return new DefaultValue(def.examples[0], def.description);
|
|
||||||
}
|
|
||||||
if ('type' in def && def.type) {
|
|
||||||
return this.getTypedDefaultValue(def);
|
|
||||||
}
|
|
||||||
// $ref only schemas
|
|
||||||
if ('$ref' in def && def.$ref) {
|
|
||||||
return this.getReferredDefaultValue(def);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SchemaLoader {
|
|
||||||
constructor() {
|
|
||||||
this.schemas = {};
|
|
||||||
this.ajv = new Ajv({ nullable: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
getSchema($id) {
|
|
||||||
return this.schemas[$id];
|
|
||||||
}
|
|
||||||
|
|
||||||
addSchema(def) {
|
|
||||||
if (!Object.prototype.hasOwnProperty.call(def, '$id')) {
|
|
||||||
throw new Error('The schema definition does not have an $id field');
|
|
||||||
}
|
|
||||||
this.ajv.addSchema(def);
|
|
||||||
this.schemas[def.$id] = new Schema(this, def);
|
|
||||||
}
|
|
||||||
|
|
||||||
removeSchema($id) {
|
|
||||||
this.ajv.removeSchema($id);
|
|
||||||
delete this.schemas[$id];
|
|
||||||
}
|
|
||||||
|
|
||||||
compileValidator($id) {
|
|
||||||
return this.ajv.compile(this.schemas[$id].def);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function traverseObj(obj, targetKey, handler) {
|
|
||||||
if (Array.isArray(obj)) {
|
|
||||||
for (const child of obj) {
|
|
||||||
traverseObj(child, targetKey, handler);
|
|
||||||
}
|
|
||||||
} else if (typeof obj === 'object') {
|
|
||||||
for (const key in obj) {
|
|
||||||
if (key === targetKey) {
|
|
||||||
handler(obj[key]);
|
|
||||||
} else {
|
|
||||||
traverseObj(obj[key], targetKey, handler);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SchemaLoader.load = (rootSchemaDef, resolveDirs = []) => {
|
|
||||||
if (!Array.isArray(resolveDirs)) {
|
|
||||||
resolveDirs = [resolveDirs];
|
|
||||||
}
|
|
||||||
|
|
||||||
const loader = new SchemaLoader();
|
|
||||||
loader.addSchema(rootSchemaDef);
|
|
||||||
|
|
||||||
function handler($ref) {
|
|
||||||
if (typeof $ref !== 'string') {
|
|
||||||
throw new Error('Invalid schema reference id: ' + JSON.stringify($ref));
|
|
||||||
}
|
|
||||||
if (loader.getSchema($ref)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (const dir of resolveDirs) {
|
|
||||||
let def;
|
|
||||||
try {
|
|
||||||
def = require(path.join(dir, $ref));
|
|
||||||
} catch (e) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (typeof def !== 'object' || def.$id !== $ref) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
loader.addSchema(def);
|
|
||||||
traverseObj(def, '$ref', handler);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw new Error('Cannot find schema definition ' + $ref + '.\n'
|
|
||||||
+ 'Please check if the file exists and its $id is correct');
|
|
||||||
}
|
|
||||||
|
|
||||||
traverseObj(rootSchemaDef, '$ref', handler);
|
|
||||||
return loader;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
Schema,
|
|
||||||
SchemaLoader,
|
|
||||||
DefaultValue
|
|
||||||
};
|
|
|
@ -1,43 +0,0 @@
|
||||||
const yaml = require('js-yaml');
|
|
||||||
const YamlType = require('js-yaml/lib/js-yaml/type');
|
|
||||||
const YamlSchema = require('js-yaml/lib/js-yaml/schema');
|
|
||||||
|
|
||||||
// output null as empty in yaml
|
|
||||||
const YAML_SCHEMA = new YamlSchema({
|
|
||||||
include: [
|
|
||||||
require('js-yaml/lib/js-yaml/schema/default_full')
|
|
||||||
],
|
|
||||||
implicit: [
|
|
||||||
new YamlType('tag:yaml.org,2002:null', {
|
|
||||||
kind: 'scalar',
|
|
||||||
resolve(data) {
|
|
||||||
if (data === null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
const max = data.length;
|
|
||||||
return (max === 1 && data === '~')
|
|
||||||
|| (max === 4 && (data === 'null' || data === 'Null' || data === 'NULL'));
|
|
||||||
},
|
|
||||||
construct: () => null,
|
|
||||||
predicate: object => object === null,
|
|
||||||
represent: {
|
|
||||||
empty: () => ''
|
|
||||||
},
|
|
||||||
defaultStyle: 'empty'
|
|
||||||
})
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
parse(str) {
|
|
||||||
return yaml.safeLoad(str);
|
|
||||||
},
|
|
||||||
|
|
||||||
stringify(object) {
|
|
||||||
return yaml.safeDump(object, {
|
|
||||||
indent: 4,
|
|
||||||
lineWidth: 1024,
|
|
||||||
schema: YAML_SCHEMA
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,7 +1,7 @@
|
||||||
const moment = require('moment');
|
const moment = require('moment');
|
||||||
const { Component, Fragment } = require('inferno');
|
const { Component, Fragment } = require('inferno');
|
||||||
const Paginator = require('./misc/paginator');
|
const Paginator = require('hexo-component-inferno/lib/view/misc/paginator');
|
||||||
const ArticleMedia = require('./common/article-media');
|
const ArticleMedia = require('hexo-component-inferno/lib/view/common/article-media');
|
||||||
|
|
||||||
module.exports = class extends Component {
|
module.exports = class extends Component {
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const { Component } = require('inferno');
|
const { Component } = require('inferno');
|
||||||
const Categories = require('./widget/categories');
|
const Categories = require('hexo-component-inferno/lib/view/widget/categories');
|
||||||
|
|
||||||
module.exports = class extends Component {
|
module.exports = class extends Component {
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
const { Component, Fragment } = require('inferno');
|
|
||||||
const { cacheComponent } = require('../util/cache');
|
|
||||||
|
|
||||||
class ChangeYan extends Component {
|
|
||||||
render() {
|
|
||||||
const { appId, conf, path } = this.props;
|
|
||||||
if (!appId || !conf) {
|
|
||||||
return <div class="notification is-danger">
|
|
||||||
You forgot to set the <code>app_id</code> or <code>conf</code> for Changyan.
|
|
||||||
Please set it in <code>_config.yml</code>.
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
const js = `window.changyan.api.config({appid: '${appId}',conf: '${conf}'});`;
|
|
||||||
return <Fragment>
|
|
||||||
<div id="SOHUCS" sid={path}></div>
|
|
||||||
<script charset="utf-8" src="https://changyan.sohu.com/upload/changyan.js"></script>
|
|
||||||
<script dangerouslySetInnerHTML={{ __html: js }}></script>
|
|
||||||
</Fragment>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = cacheComponent(ChangeYan, 'comment.changyan', props => {
|
|
||||||
const { comment, page } = props;
|
|
||||||
|
|
||||||
return {
|
|
||||||
appId: comment.app_id,
|
|
||||||
conf: comment.conf,
|
|
||||||
path: page.path
|
|
||||||
};
|
|
||||||
});
|
|
|
@ -1,41 +0,0 @@
|
||||||
const { Component, Fragment } = require('inferno');
|
|
||||||
const { cacheComponent } = require('../util/cache');
|
|
||||||
|
|
||||||
class Disqus extends Component {
|
|
||||||
render() {
|
|
||||||
const { shortname, disqusId, path, permalink } = this.props;
|
|
||||||
if (!shortname) {
|
|
||||||
return <div class="notification is-danger">
|
|
||||||
You forgot to set the <code>shortname</code> for Disqus.
|
|
||||||
Please set it in <code>_config.yml</code>.
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
const js = `var disqus_config = function () {
|
|
||||||
this.page.url = '${permalink}';
|
|
||||||
this.page.identifier = '${disqusId || path}';
|
|
||||||
};
|
|
||||||
(function() {
|
|
||||||
var d = document, s = d.createElement('script');
|
|
||||||
s.src = '//' + '${shortname}' + '.disqus.com/embed.js';
|
|
||||||
s.setAttribute('data-timestamp', +new Date());
|
|
||||||
(d.head || d.body).appendChild(s);
|
|
||||||
})();`;
|
|
||||||
return <Fragment>
|
|
||||||
<div id="disqus_thread">
|
|
||||||
<noscript>Please enable JavaScript to view the <a href="//disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
|
|
||||||
</div>
|
|
||||||
<script dangerouslySetInnerHTML={{ __html: js }}></script>
|
|
||||||
</Fragment>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = cacheComponent(Disqus, 'comment.disqus', props => {
|
|
||||||
const { comment, page } = props;
|
|
||||||
|
|
||||||
return {
|
|
||||||
path: page.path,
|
|
||||||
shortname: comment.shortname,
|
|
||||||
disqusId: page.disqusId,
|
|
||||||
permalink: page.permalink
|
|
||||||
};
|
|
||||||
});
|
|
|
@ -1,68 +0,0 @@
|
||||||
const { Component, Fragment } = require('inferno');
|
|
||||||
const { cacheComponent } = require('../util/cache');
|
|
||||||
|
|
||||||
class DisqusJs extends Component {
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
shortname,
|
|
||||||
apiKey,
|
|
||||||
api,
|
|
||||||
admin,
|
|
||||||
adminLabel = false,
|
|
||||||
nesting = 4,
|
|
||||||
disqusId,
|
|
||||||
path,
|
|
||||||
permalink,
|
|
||||||
pageTitle,
|
|
||||||
siteTitle,
|
|
||||||
jsUrl,
|
|
||||||
cssUrl
|
|
||||||
} = this.props;
|
|
||||||
if (!shortname) {
|
|
||||||
return <div class="notification is-danger">
|
|
||||||
You forgot to set the <code>shortname</code> or <code>api_key</code> for Disqus.
|
|
||||||
Please set it in <code>_config.yml</code>.
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
const js = `new DisqusJS({
|
|
||||||
shortname: '${shortname}',
|
|
||||||
apikey: '${JSON.stringify(apiKey)}',
|
|
||||||
siteName: '${siteTitle}',
|
|
||||||
identifier: '${disqusId || path}',
|
|
||||||
url: '${permalink || path}',
|
|
||||||
title: '${pageTitle}',
|
|
||||||
api: '${api}',
|
|
||||||
admin: '${admin}',
|
|
||||||
adminLabel: '${adminLabel}',
|
|
||||||
nesting: ${nesting}
|
|
||||||
});`;
|
|
||||||
return <Fragment>
|
|
||||||
<link rel="stylesheet" href={cssUrl} />
|
|
||||||
<div id="disqus_thread">
|
|
||||||
<noscript>Please enable JavaScript to view the <a href="//disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
|
|
||||||
</div>
|
|
||||||
<script src={jsUrl}></script>
|
|
||||||
<script dangerouslySetInnerHTML={{ __html: js }}></script>
|
|
||||||
</Fragment>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = cacheComponent(DisqusJs, 'comment.disqusjs', props => {
|
|
||||||
const { config, page, helper, comment } = props;
|
|
||||||
|
|
||||||
return {
|
|
||||||
path: page.path,
|
|
||||||
shortname: comment.shortname,
|
|
||||||
apiKey: comment.api_key,
|
|
||||||
api: comment.api,
|
|
||||||
admin: comment.admin,
|
|
||||||
adminLabel: comment.admin_label,
|
|
||||||
nesting: comment.nesting,
|
|
||||||
disqusId: page.disqusId,
|
|
||||||
permalink: page.permalink,
|
|
||||||
pageTitle: page.title,
|
|
||||||
siteTitle: config.title,
|
|
||||||
jsUrl: helper.cdn('disqusjs', '1.2.5', 'dist/disqus.js'),
|
|
||||||
cssUrl: helper.cdn('disqusjs', '1.2.5', 'dist/disqusjs.css')
|
|
||||||
};
|
|
||||||
});
|
|
|
@ -1,28 +0,0 @@
|
||||||
const { Component, Fragment } = require('inferno');
|
|
||||||
const { cacheComponent } = require('../util/cache');
|
|
||||||
|
|
||||||
class Facebook extends Component {
|
|
||||||
render() {
|
|
||||||
const { language, permalink } = this.props;
|
|
||||||
const js = `(function(d, s, id) {
|
|
||||||
var js, fjs = d.getElementsByTagName(s)[0];
|
|
||||||
if (d.getElementById(id)) return;
|
|
||||||
js = d.createElement(s); js.id = id;
|
|
||||||
js.src = "//connect.facebook.net/${language.split('-').join('_')}/sdk.js#xfbml=1&version=v2.8";
|
|
||||||
fjs.parentNode.insertBefore(js, fjs);
|
|
||||||
}(document, 'script', 'facebook-jssdk'));`;
|
|
||||||
return <Fragment>
|
|
||||||
<div class="fb-comments" data-width="100%" data-href={permalink} data-num-posts="5"></div>
|
|
||||||
<script dangerouslySetInnerHTML={{ __html: js }}></script>
|
|
||||||
</Fragment>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = cacheComponent(Facebook, 'comment.facebook', props => {
|
|
||||||
const { config, page } = props;
|
|
||||||
|
|
||||||
return {
|
|
||||||
language: page.lang || page.language || config.language || 'en',
|
|
||||||
permalink: page.permalink
|
|
||||||
};
|
|
||||||
});
|
|
|
@ -1,79 +0,0 @@
|
||||||
const crypto = require('crypto');
|
|
||||||
const { Component, Fragment } = require('inferno');
|
|
||||||
const { cacheComponent } = require('../util/cache');
|
|
||||||
|
|
||||||
class Gitalk extends Component {
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
id,
|
|
||||||
repo,
|
|
||||||
owner,
|
|
||||||
admin,
|
|
||||||
clientId,
|
|
||||||
clientSecret,
|
|
||||||
createIssueManually = false,
|
|
||||||
distractionFreeMode = false,
|
|
||||||
pagerDirection = 'last',
|
|
||||||
perPage = 10,
|
|
||||||
proxy,
|
|
||||||
flipMoveOptions,
|
|
||||||
enableHotKey,
|
|
||||||
jsUrl,
|
|
||||||
cssUrl
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
if (!id || !repo || !owner || !admin || !clientId || !clientSecret) {
|
|
||||||
return <div class="notification is-danger">
|
|
||||||
You forgot to set the <code>owner</code>, <code>admin</code>, <code>repo</code>,
|
|
||||||
<code>client_id</code>, or <code>client_secret</code> for Gitalk.
|
|
||||||
Please set it in <code>_config.yml</code>.
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
const js = `var gitalk = new Gitalk({
|
|
||||||
id: '${id}',
|
|
||||||
repo: '${repo}',
|
|
||||||
owner: '${owner}',
|
|
||||||
clientID: '${clientId}',
|
|
||||||
clientSecret: '${clientSecret}',
|
|
||||||
admin: ${JSON.stringify(admin)},
|
|
||||||
createIssueManually: ${createIssueManually},
|
|
||||||
distractionFreeMode: ${distractionFreeMode},
|
|
||||||
perPage: ${perPage},
|
|
||||||
pagerDirection: '${pagerDirection}',
|
|
||||||
${proxy ? `proxy: '${proxy}',` : ''}
|
|
||||||
${flipMoveOptions ? `flipMoveOptions: ${JSON.stringify(flipMoveOptions)},` : ''}
|
|
||||||
enableHotKey: ${enableHotKey ? !!enableHotKey : true}
|
|
||||||
})
|
|
||||||
gitalk.render('comment-container')`;
|
|
||||||
return <Fragment>
|
|
||||||
<div id="comment-container"></div>
|
|
||||||
<link rel="stylesheet" href={cssUrl} />
|
|
||||||
<script src={jsUrl}></script>
|
|
||||||
<script dangerouslySetInnerHTML={{ __html: js }}></script>
|
|
||||||
</Fragment>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = cacheComponent(Gitalk, 'comment.gitalk', props => {
|
|
||||||
const { helper, comment } = props;
|
|
||||||
|
|
||||||
// FIXME: config name change
|
|
||||||
const id = crypto.createHash('md5').update(props.page.path).digest('hex');
|
|
||||||
return {
|
|
||||||
id,
|
|
||||||
repo: comment.repo,
|
|
||||||
owner: comment.owner,
|
|
||||||
admin: comment.admin,
|
|
||||||
clientId: comment.client_id,
|
|
||||||
clientSecret: comment.client_secret,
|
|
||||||
createIssueManually: comment.create_issue_manually,
|
|
||||||
distractionFreeMode: comment.distraction_free_mode,
|
|
||||||
pagerDirection: comment.pager_direction,
|
|
||||||
perPage: comment.per_page,
|
|
||||||
proxy: comment.proxy,
|
|
||||||
flipMoveOptions: comment.flip_move_options,
|
|
||||||
enableHotKey: comment.enable_hotkey,
|
|
||||||
cssUrl: helper.cdn('gitalk', '1.4.1', 'dist/gitalk.css'),
|
|
||||||
jsUrl: helper.cdn('gitalk', '1.4.1', 'dist/gitalk.min.js')
|
|
||||||
};
|
|
||||||
});
|
|
|
@ -1,58 +0,0 @@
|
||||||
const crypto = require('crypto');
|
|
||||||
const { Component, Fragment } = require('inferno');
|
|
||||||
const { cacheComponent } = require('../util/cache');
|
|
||||||
|
|
||||||
class Gitment extends Component {
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
id,
|
|
||||||
repo,
|
|
||||||
owner,
|
|
||||||
clientId,
|
|
||||||
clientSecret,
|
|
||||||
perPage = 20,
|
|
||||||
maxCommentHeight = 250
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
if (!id || !repo || !owner || !clientId || !clientSecret) {
|
|
||||||
return <div class="notification is-danger">
|
|
||||||
You forgot to set the <code>owner</code>, <code>repo</code>, <code>clientId</code>,
|
|
||||||
or <code>clientSecret</code> for Gitment.
|
|
||||||
Please set it in <code>_config.yml</code>.
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
const js = `var gitment = new Gitment({
|
|
||||||
id: '${id}',
|
|
||||||
repo: '${repo}',
|
|
||||||
owner: '${owner}',
|
|
||||||
oauth: {
|
|
||||||
client_id: '${clientId}',
|
|
||||||
client_secret: '${clientSecret}',
|
|
||||||
},
|
|
||||||
perPage: ${perPage},
|
|
||||||
maxCommentHeight: ${maxCommentHeight}
|
|
||||||
})
|
|
||||||
gitment.render('comment-container')`;
|
|
||||||
return <Fragment>
|
|
||||||
<div id="comment-container"></div>
|
|
||||||
<link rel="stylesheet" href="https://imsun.github.io/gitment/style/default.css" />
|
|
||||||
<script src="https://imsun.github.io/gitment/dist/gitment.browser.js"></script>
|
|
||||||
<script dangerouslySetInnerHTML={{ __html: js }}></script>
|
|
||||||
</Fragment>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = cacheComponent(Gitment, 'comment.gitment', props => {
|
|
||||||
const { comment } = props;
|
|
||||||
|
|
||||||
const id = crypto.createHash('md5').update(props.page.path).digest('hex');
|
|
||||||
return {
|
|
||||||
id,
|
|
||||||
repo: comment.repo,
|
|
||||||
owner: comment.owner,
|
|
||||||
clientId: comment.client_id,
|
|
||||||
clientSecret: comment.client_secret,
|
|
||||||
perPage: comment.per_page,
|
|
||||||
maxCommentHeight: comment.max_comment_height
|
|
||||||
};
|
|
||||||
});
|
|
|
@ -1,26 +0,0 @@
|
||||||
const { Component, Fragment } = require('inferno');
|
|
||||||
const { cacheComponent } = require('../util/cache');
|
|
||||||
|
|
||||||
class Isso extends Component {
|
|
||||||
render() {
|
|
||||||
const { url } = this.props;
|
|
||||||
if (!url) {
|
|
||||||
return <div class="notification is-danger">
|
|
||||||
You forgot to set the <code>url</code> for Isso.
|
|
||||||
Please set it in <code>_config.yml</code>.
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
return <Fragment>
|
|
||||||
<div id="isso-thread"></div>
|
|
||||||
<script data-isso={'//' + url} src={`//${url}/js/embed.min.js`}></script>
|
|
||||||
</Fragment>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = cacheComponent(Isso, 'comment.isso', props => {
|
|
||||||
const { comment } = props;
|
|
||||||
|
|
||||||
return {
|
|
||||||
url: comment.url
|
|
||||||
};
|
|
||||||
});
|
|
|
@ -1,37 +0,0 @@
|
||||||
const { Component } = require('inferno');
|
|
||||||
const { cacheComponent } = require('../util/cache');
|
|
||||||
|
|
||||||
class LiveRe extends Component {
|
|
||||||
render() {
|
|
||||||
const { uid } = this.props;
|
|
||||||
if (!uid) {
|
|
||||||
return <div class="notification is-danger">
|
|
||||||
You forgot to set the <code>uid</code> for LiveRe.
|
|
||||||
Please set it in <code>_config.yml</code>.
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
const js = `(function(d, s) {
|
|
||||||
var j, e = d.getElementsByTagName(s)[0];
|
|
||||||
|
|
||||||
if (typeof LivereTower === 'function') { return; }
|
|
||||||
|
|
||||||
j = d.createElement(s);
|
|
||||||
j.src = 'https://cdn-city.livere.com/js/embed.dist.js';
|
|
||||||
j.async = true;
|
|
||||||
|
|
||||||
e.parentNode.insertBefore(j, e);
|
|
||||||
})(document, 'script');`;
|
|
||||||
return <div id="lv-container" data-id="city" data-uid={uid}>
|
|
||||||
<script dangerouslySetInnerHTML={{ __html: js }}></script>
|
|
||||||
<noscript>Please activate JavaScript for write a comment in LiveRe</noscript>
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = cacheComponent(LiveRe, 'comment.livere', props => {
|
|
||||||
const { comment } = props;
|
|
||||||
|
|
||||||
return {
|
|
||||||
uid: comment.uid
|
|
||||||
};
|
|
||||||
});
|
|
|
@ -1,69 +0,0 @@
|
||||||
const { Component, Fragment } = require('inferno');
|
|
||||||
const { cacheComponent } = require('../util/cache');
|
|
||||||
|
|
||||||
class Valine extends Component {
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
appId,
|
|
||||||
appKey,
|
|
||||||
notify,
|
|
||||||
verify,
|
|
||||||
placeholder,
|
|
||||||
avatar = 'mm',
|
|
||||||
avatarForce = false,
|
|
||||||
meta = ['nick', 'mail', 'link'],
|
|
||||||
pageSize = 10,
|
|
||||||
visitor = false,
|
|
||||||
highlight = true,
|
|
||||||
recordIp = false,
|
|
||||||
jsUrl
|
|
||||||
} = this.props;
|
|
||||||
if (!appId || !appKey) {
|
|
||||||
return <div class="notification is-danger">
|
|
||||||
You forgot to set the <code>app_id</code> or <code>app_key</code> for Valine.
|
|
||||||
Please set it in <code>_config.yml</code>.
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
const js = `new Valine({
|
|
||||||
el: '#valine-thread' ,
|
|
||||||
notify: ${notify},
|
|
||||||
verify: ${verify},
|
|
||||||
appId: '${appId}',
|
|
||||||
appKey: '${appKey}',
|
|
||||||
placeholder: '${placeholder}',
|
|
||||||
avatar: '${avatar}',
|
|
||||||
avatarForce: ${avatarForce},
|
|
||||||
meta: ${JSON.stringify(meta)},
|
|
||||||
pageSize: ${pageSize},
|
|
||||||
visitor: ${visitor},
|
|
||||||
highlight: ${highlight},
|
|
||||||
recordIP: ${recordIp}
|
|
||||||
});`;
|
|
||||||
return <Fragment>
|
|
||||||
<div id="valine-thread" class="content"></div>
|
|
||||||
<script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
|
|
||||||
<script src={jsUrl}></script>
|
|
||||||
<script dangerouslySetInnerHTML={{ __html: js }}></script>
|
|
||||||
</Fragment>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = cacheComponent(Valine, 'comment.valine', props => {
|
|
||||||
const { comment, helper } = props;
|
|
||||||
|
|
||||||
return {
|
|
||||||
appId: comment.app_id,
|
|
||||||
appKey: comment.app_key,
|
|
||||||
notify: comment.notify,
|
|
||||||
verify: comment.verify,
|
|
||||||
placeholder: comment.placeholder,
|
|
||||||
avatar: comment.avatar,
|
|
||||||
avatarForce: comment.avatar_force,
|
|
||||||
meta: comment.meta,
|
|
||||||
pageSize: comment.page_size,
|
|
||||||
visitor: comment.visitor,
|
|
||||||
highlight: comment.highlight,
|
|
||||||
recordIp: comment.record_ip,
|
|
||||||
jsUrl: helper.cdn('valine', '1.3.10', 'dist/Valine.min.js')
|
|
||||||
};
|
|
||||||
});
|
|
|
@ -1,28 +0,0 @@
|
||||||
const { Component } = require('inferno');
|
|
||||||
|
|
||||||
module.exports = class extends Component {
|
|
||||||
render() {
|
|
||||||
const { thumbnail, url, title, date, dateXml, categories } = this.props;
|
|
||||||
|
|
||||||
const categoryTags = [];
|
|
||||||
categories.forEach((category, i) => {
|
|
||||||
categoryTags.push(<a class="link-muted" href={category.url}>{category.name}</a>);
|
|
||||||
if (i < categories.length - 1) {
|
|
||||||
categoryTags.push(' / ');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return <article class="media">
|
|
||||||
{thumbnail ? <a href={url} class="media-left">
|
|
||||||
<p class="image is-64x64">
|
|
||||||
<img class="thumbnail" src={thumbnail} alt={title} />
|
|
||||||
</p>
|
|
||||||
</a> : null}
|
|
||||||
<div class="media-content size-small">
|
|
||||||
<p><time dateTime={dateXml}>{date}</time></p>
|
|
||||||
<p class="title is-6"><a href={url} class="link-muted">{title}</a></p>
|
|
||||||
<p class="is-uppercase">{categoryTags.length ? categoryTags : null}</p>
|
|
||||||
</div>
|
|
||||||
</article>;
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,5 +1,6 @@
|
||||||
const logger = require('hexo-log')();
|
const logger = require('hexo-log')();
|
||||||
const { Component } = require('inferno');
|
const { Component } = require('inferno');
|
||||||
|
const view = require('hexo-component-inferno/lib/core/view');
|
||||||
|
|
||||||
module.exports = class extends Component {
|
module.exports = class extends Component {
|
||||||
render() {
|
render() {
|
||||||
|
@ -15,7 +16,7 @@ module.exports = class extends Component {
|
||||||
<h3 class="title is-5">{__('article.comments')}</h3>
|
<h3 class="title is-5">{__('article.comments')}</h3>
|
||||||
{(() => {
|
{(() => {
|
||||||
try {
|
try {
|
||||||
const Comment = require('../comment/' + comment.type);
|
const Comment = view.require('comment/' + comment.type);
|
||||||
return <Comment config={config} page={page} helper={helper} comment={comment} />;
|
return <Comment config={config} page={page} helper={helper} comment={comment} />;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.w(`Icarus cannot load comment "${comment.type}"`);
|
logger.w(`Icarus cannot load comment "${comment.type}"`);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
const logger = require('hexo-log')();
|
const logger = require('hexo-log')();
|
||||||
const { Component } = require('inferno');
|
const { Component } = require('inferno');
|
||||||
|
const view = require('hexo-component-inferno/lib/core/view');
|
||||||
|
|
||||||
module.exports = class extends Component {
|
module.exports = class extends Component {
|
||||||
render() {
|
render() {
|
||||||
|
@ -17,7 +18,7 @@ module.exports = class extends Component {
|
||||||
const type = service.type;
|
const type = service.type;
|
||||||
if (typeof type === 'string') {
|
if (typeof type === 'string') {
|
||||||
try {
|
try {
|
||||||
const Donate = require('../donate/' + type);
|
const Donate = view.require('donate/' + type);
|
||||||
return <Donate helper={helper} donate={service} />;
|
return <Donate helper={helper} donate={service} />;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.w(`Icarus cannot load donate button "${type}"`);
|
logger.w(`Icarus cannot load donate button "${type}"`);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const { Component } = require('inferno');
|
const { Component } = require('inferno');
|
||||||
const { cacheComponent } = require('../util/cache');
|
const { cacheComponent } = require('hexo-component-inferno/lib/util/cache');
|
||||||
|
|
||||||
class Footer extends Component {
|
class Footer extends Component {
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
const { Component } = require('inferno');
|
const { Component } = require('inferno');
|
||||||
const MetaTags = require('../misc/meta');
|
const MetaTags = require('hexo-component-inferno/lib/view/misc/meta');
|
||||||
const OpenGraph = require('../misc/open_graph');
|
const OpenGraph = require('hexo-component-inferno/lib/view/misc/open_graph');
|
||||||
const StructuredData = require('../misc/structured_data');
|
const StructuredData = require('hexo-component-inferno/lib/view/misc/structured_data');
|
||||||
const Plugins = require('./plugins');
|
const Plugins = require('./plugins');
|
||||||
|
|
||||||
function getPageTitle(page, siteTitle, helper) {
|
function getPageTitle(page, siteTitle, helper) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
const { Component, Fragment } = require('inferno');
|
const { Component, Fragment } = require('inferno');
|
||||||
const { cacheComponent } = require('../util/cache');
|
const { cacheComponent } = require('hexo-component-inferno/lib/util/cache');
|
||||||
const classname = require('../util/classname');
|
const classname = require('hexo-component-inferno/lib/util/classname');
|
||||||
|
|
||||||
function isSameLink(a, b) {
|
function isSameLink(a, b) {
|
||||||
function santize(url) {
|
function santize(url) {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
const logger = require('hexo-log')();
|
const logger = require('hexo-log')();
|
||||||
const { Component, Fragment } = require('inferno');
|
const { Component, Fragment } = require('inferno');
|
||||||
|
const view = require('hexo-component-inferno/lib/core/view');
|
||||||
|
|
||||||
module.exports = class extends Component {
|
module.exports = class extends Component {
|
||||||
render() {
|
render() {
|
||||||
|
@ -13,7 +14,7 @@ module.exports = class extends Component {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const Plugin = require('../plugin/' + name);
|
const Plugin = view.require('plugin/' + name);
|
||||||
return <Plugin site={site} config={config} page={page} helper={helper} plugin={plugins[name]} head={head} />;
|
return <Plugin site={site} config={config} page={page} helper={helper} plugin={plugins[name]} head={head} />;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.w(`Icarus cannot load plugin "${name}"`);
|
logger.w(`Icarus cannot load plugin "${name}"`);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
const logger = require('hexo-log')();
|
const logger = require('hexo-log')();
|
||||||
const { Component } = require('inferno');
|
const { Component } = require('inferno');
|
||||||
|
const view = require('hexo-component-inferno/lib/core/view');
|
||||||
|
|
||||||
module.exports = class extends Component {
|
module.exports = class extends Component {
|
||||||
render() {
|
render() {
|
||||||
|
@ -10,7 +11,7 @@ module.exports = class extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const Search = require('../search/' + search.type);
|
const Search = view.require('search/' + search.type);
|
||||||
return <Search config={config} helper={helper} search={search} />;
|
return <Search config={config} helper={helper} search={search} />;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.w(`Icarus cannot load search "${search.type}"`);
|
logger.w(`Icarus cannot load search "${search.type}"`);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
const logger = require('hexo-log')();
|
const logger = require('hexo-log')();
|
||||||
const { Component } = require('inferno');
|
const { Component } = require('inferno');
|
||||||
|
const view = require('hexo-component-inferno/lib/core/view');
|
||||||
|
|
||||||
module.exports = class extends Component {
|
module.exports = class extends Component {
|
||||||
render() {
|
render() {
|
||||||
|
@ -10,7 +11,7 @@ module.exports = class extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const Share = require('../share/' + share.type);
|
const Share = view.require('share/' + share.type);
|
||||||
return <Share config={config} page={page} helper={helper} share={share} />;
|
return <Share config={config} page={page} helper={helper} share={share} />;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.w(`Icarus cannot load share button "${share.type}"`);
|
logger.w(`Icarus cannot load share button "${share.type}"`);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
const logger = require('hexo-log')();
|
const logger = require('hexo-log')();
|
||||||
const { Component } = require('inferno');
|
const { Component } = require('inferno');
|
||||||
const classname = require('../util/classname');
|
const view = require('hexo-component-inferno/lib/core/view');
|
||||||
|
const classname = require('hexo-component-inferno/lib/util/classname');
|
||||||
|
|
||||||
function formatWidgets(widgets) {
|
function formatWidgets(widgets) {
|
||||||
const result = {};
|
const result = {};
|
||||||
|
@ -80,7 +81,7 @@ class Widgets extends Component {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const Widget = require('../widget/' + widget.type);
|
const Widget = view.require('widget/' + widget.type);
|
||||||
return <Widget site={site} helper={helper} config={config} page={page} widget={widget} />;
|
return <Widget site={site} helper={helper} config={config} page={page} widget={widget} />;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.w(`Icarus cannot load widget "${widget.type}"`);
|
logger.w(`Icarus cannot load widget "${widget.type}"`);
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
const { Component } = require('inferno');
|
|
||||||
const { cacheComponent } = require('../util/cache');
|
|
||||||
|
|
||||||
class Alipay extends Component {
|
|
||||||
render() {
|
|
||||||
const { title, qrcode } = this.props;
|
|
||||||
if (!qrcode) {
|
|
||||||
return <div class="notification is-danger">
|
|
||||||
You forgot to set the <code>qrcode</code> for Alipay.
|
|
||||||
Please set it in <code>_config.yml</code>.
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
return <a class="button is-info donate">
|
|
||||||
<span class="icon is-small">
|
|
||||||
<i class="fab fa-alipay"></i>
|
|
||||||
</span>
|
|
||||||
<span>{title}</span>
|
|
||||||
<span class="qrcode"><img src={qrcode} alt={title} /></span>
|
|
||||||
</a>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = cacheComponent(Alipay, 'donate.alipay', props => {
|
|
||||||
const { donate, helper } = props;
|
|
||||||
|
|
||||||
return {
|
|
||||||
title: helper.__('donate.' + donate.type),
|
|
||||||
qrcode: helper.url_for(donate.qrcode)
|
|
||||||
};
|
|
||||||
});
|
|
|
@ -1,33 +0,0 @@
|
||||||
const { Component } = require('inferno');
|
|
||||||
const { cacheComponent } = require('../util/cache');
|
|
||||||
|
|
||||||
class BuyMeACoffee extends Component {
|
|
||||||
render() {
|
|
||||||
const { title, url } = this.props;
|
|
||||||
if (!url) {
|
|
||||||
return <div class="notification is-danger">
|
|
||||||
You forgot to set the <code>url</code> for "Buy me a coffee".
|
|
||||||
Please set it in <code>_config.yml</code>.
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
return <a class="button donate" href={url} style={{
|
|
||||||
'background-color': 'rgba(255,128,62,.87)',
|
|
||||||
'border-color': 'transparent',
|
|
||||||
'color': 'white'
|
|
||||||
}} target="_blank" rel="noopener">
|
|
||||||
<span class="icon is-small">
|
|
||||||
<i class="fas fa-coffee"></i>
|
|
||||||
</span>
|
|
||||||
<span>{title}</span>
|
|
||||||
</a>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = cacheComponent(BuyMeACoffee, 'donate.buymeacoffee', props => {
|
|
||||||
const { donate, helper } = props;
|
|
||||||
|
|
||||||
return {
|
|
||||||
url: helper.url_for(donate.url),
|
|
||||||
title: helper.__('donate.' + donate.type)
|
|
||||||
};
|
|
||||||
});
|
|
|
@ -1,29 +0,0 @@
|
||||||
const { Component } = require('inferno');
|
|
||||||
const { cacheComponent } = require('../util/cache');
|
|
||||||
|
|
||||||
class Patreon extends Component {
|
|
||||||
render() {
|
|
||||||
const { title, url } = this.props;
|
|
||||||
if (!url) {
|
|
||||||
return <div class="notification is-danger">
|
|
||||||
You forgot to set the <code>url</code> for Patreon.
|
|
||||||
Please set it in <code>_config.yml</code>.
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
return <a class="button is-danger donate" href={url} target="_blank" rel="noopener">
|
|
||||||
<span class="icon is-small">
|
|
||||||
<i class="fab fa-patreon"></i>
|
|
||||||
</span>
|
|
||||||
<span>{title}</span>
|
|
||||||
</a>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = cacheComponent(Patreon, 'donate.petreon', props => {
|
|
||||||
const { donate, helper } = props;
|
|
||||||
|
|
||||||
return {
|
|
||||||
url: helper.url_for(donate.url),
|
|
||||||
title: helper.__('donate.' + donate.type)
|
|
||||||
};
|
|
||||||
});
|
|
|
@ -1,37 +0,0 @@
|
||||||
const { Component, Fragment } = require('inferno');
|
|
||||||
const { cacheComponent } = require('../util/cache');
|
|
||||||
|
|
||||||
class Paypal extends Component {
|
|
||||||
render() {
|
|
||||||
const { title, business, currencyCode } = this.props;
|
|
||||||
if (!business || !currencyCode) {
|
|
||||||
return <div class="notification is-danger">
|
|
||||||
You forgot to set the <code>business</code> or <code>currency_code</code> for Paypal.
|
|
||||||
Please set it in <code>_config.yml</code>.
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
return <Fragment>
|
|
||||||
<a class="button is-warning donate" onclick="document.getElementById('paypal-donate-form').submit()">
|
|
||||||
<span class="icon is-small">
|
|
||||||
<i class="fab fa-paypal"></i>
|
|
||||||
</span>
|
|
||||||
<span>{title}</span>
|
|
||||||
</a>
|
|
||||||
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank" rel="noopener" id="paypal-donate-form">
|
|
||||||
<input type="hidden" name="cmd" value="_donations" />
|
|
||||||
<input type="hidden" name="business" value={business} />
|
|
||||||
<input type="hidden" name="currency_code" value={currencyCode} />
|
|
||||||
</form>
|
|
||||||
</Fragment>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = cacheComponent(Paypal, 'donate.paypal', props => {
|
|
||||||
const { donate, helper } = props;
|
|
||||||
|
|
||||||
return {
|
|
||||||
business: donate.business,
|
|
||||||
currencyCode: donate.currency_code,
|
|
||||||
title: helper.__('donate.' + donate.type)
|
|
||||||
};
|
|
||||||
});
|
|
|
@ -1,30 +0,0 @@
|
||||||
const { Component } = require('inferno');
|
|
||||||
const { cacheComponent } = require('../util/cache');
|
|
||||||
|
|
||||||
class Wechat extends Component {
|
|
||||||
render() {
|
|
||||||
const { title, qrcode } = this.props;
|
|
||||||
if (!qrcode) {
|
|
||||||
return <div class="notification is-danger">
|
|
||||||
You forgot to set the <code>qrcode</code> for Wechat.
|
|
||||||
Please set it in <code>_config.yml</code>.
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
return <a class="button is-success donate">
|
|
||||||
<span class="icon is-small">
|
|
||||||
<i class="fab fa-weixin"></i>
|
|
||||||
</span>
|
|
||||||
<span>{title}</span>
|
|
||||||
<span class="qrcode"><img src={qrcode} alt={title} /></span>
|
|
||||||
</a>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = cacheComponent(Wechat, 'donate.wechat', props => {
|
|
||||||
const { donate, helper } = props;
|
|
||||||
|
|
||||||
return {
|
|
||||||
qrcode: helper.url_for(donate.qrcode),
|
|
||||||
title: helper.__('donate.' + donate.type)
|
|
||||||
};
|
|
||||||
});
|
|
|
@ -1,6 +1,6 @@
|
||||||
const { Component, Fragment } = require('inferno');
|
const { Component, Fragment } = require('inferno');
|
||||||
|
const Paginator = require('hexo-component-inferno/lib/view/misc/paginator');
|
||||||
const Article = require('./common/article');
|
const Article = require('./common/article');
|
||||||
const Paginator = require('./misc/paginator');
|
|
||||||
|
|
||||||
module.exports = class extends Component {
|
module.exports = class extends Component {
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
const { Component } = require('inferno');
|
const { Component } = require('inferno');
|
||||||
|
const classname = require('hexo-component-inferno/lib/util/classname');
|
||||||
const Head = require('./common/head');
|
const Head = require('./common/head');
|
||||||
const Navbar = require('./common/navbar');
|
const Navbar = require('./common/navbar');
|
||||||
const Widgets = require('./common/widgets');
|
const Widgets = require('./common/widgets');
|
||||||
const Footer = require('./common/footer');
|
const Footer = require('./common/footer');
|
||||||
const Scripts = require('./common/scripts');
|
const Scripts = require('./common/scripts');
|
||||||
const Search = require('./common/search');
|
const Search = require('./common/search');
|
||||||
const classname = require('./util/classname');
|
|
||||||
|
|
||||||
module.exports = class extends Component {
|
module.exports = class extends Component {
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
const { Component, Fragment } = require('inferno');
|
|
||||||
|
|
||||||
function trim(str) {
|
|
||||||
return str.trim().replace(/^"(.*)"$/, '$1').replace(/^'(.*)'$/, '$1');
|
|
||||||
}
|
|
||||||
|
|
||||||
function split(str, sep) {
|
|
||||||
const result = [];
|
|
||||||
let matched = null;
|
|
||||||
while ((matched = sep.exec(str)) !== null) {
|
|
||||||
result.push(matched[0]);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = class extends Component {
|
|
||||||
render() {
|
|
||||||
let { meta = [] } = this.props;
|
|
||||||
if (!Array.isArray(meta)) {
|
|
||||||
meta = [meta];
|
|
||||||
}
|
|
||||||
const tags = meta.filter(entry => typeof entry === 'string')
|
|
||||||
.map(entry => {
|
|
||||||
const props = split(entry, /(?:[^\\;]+|\\.)+/g)
|
|
||||||
.map(property => {
|
|
||||||
const entry = split(property, /(?:[^\\=]+|\\.)+/g);
|
|
||||||
if (entry.length < 2) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return { [trim(entry[0])]: trim(entry[1]) };
|
|
||||||
}).filter(property => {
|
|
||||||
return property !== null;
|
|
||||||
}).reduce((prev, current) => {
|
|
||||||
return Object.assign(prev, current);
|
|
||||||
}, {});
|
|
||||||
return <meta {...props} />;
|
|
||||||
});
|
|
||||||
|
|
||||||
return <Fragment>{tags}</Fragment>;
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,145 +0,0 @@
|
||||||
// adapted from hexo/lib/plugins/helper/open_graph.js
|
|
||||||
const urlFn = require('url');
|
|
||||||
const moment = require('moment');
|
|
||||||
const { Component, Fragment } = require('inferno');
|
|
||||||
const { encodeURL, stripHTML, escapeHTML } = require('hexo-util');
|
|
||||||
const localeMap = {
|
|
||||||
'en': 'en_US',
|
|
||||||
'de': 'de_DE',
|
|
||||||
'es': 'es_ES',
|
|
||||||
'fr': 'fr_FR',
|
|
||||||
'hu': 'hu_HU',
|
|
||||||
'id': 'id_ID',
|
|
||||||
'it': 'it_IT',
|
|
||||||
'ja': 'ja_JP',
|
|
||||||
'ko': 'ko_KR',
|
|
||||||
'nl': 'nl_NL',
|
|
||||||
'ru': 'ru_RU',
|
|
||||||
'th': 'th_TH',
|
|
||||||
'tr': 'tr_TR',
|
|
||||||
'vi': 'vi_VN'
|
|
||||||
};
|
|
||||||
const localeRegex = new RegExp(Object.keys(localeMap).join('|'), 'i');
|
|
||||||
|
|
||||||
module.exports = class extends Component {
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
type,
|
|
||||||
title,
|
|
||||||
date,
|
|
||||||
updated,
|
|
||||||
author,
|
|
||||||
url,
|
|
||||||
siteName,
|
|
||||||
twitterCard,
|
|
||||||
twitterSite,
|
|
||||||
googlePlus,
|
|
||||||
facebookAdmins,
|
|
||||||
facebookAppId
|
|
||||||
} = this.props;
|
|
||||||
let {
|
|
||||||
description,
|
|
||||||
language,
|
|
||||||
images,
|
|
||||||
keywords,
|
|
||||||
twitterId
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
const htmlTags = [];
|
|
||||||
|
|
||||||
if (description) {
|
|
||||||
description = escapeHTML(stripHTML(description).substring(0, 200).trim())
|
|
||||||
.replace(/\n/g, ' ');
|
|
||||||
htmlTags.push(<meta description={description} />);
|
|
||||||
}
|
|
||||||
|
|
||||||
htmlTags.push(<meta property='og:type' content={type || 'website'} />);
|
|
||||||
htmlTags.push(<meta property='og:title' content={title} />);
|
|
||||||
htmlTags.push(<meta property='og:url' content={encodeURL(url)} />);
|
|
||||||
htmlTags.push(<meta property='og:site_name' content={siteName} />);
|
|
||||||
|
|
||||||
if (description) {
|
|
||||||
htmlTags.push(<meta property='og:description' content={description} />);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (language) {
|
|
||||||
if (language.length === 2) {
|
|
||||||
language = language.replace(localeRegex, str => localeMap[str]);
|
|
||||||
htmlTags.push(<meta property='og:locale' content={language} />);
|
|
||||||
} else if (language.length === 5) {
|
|
||||||
const territory = language.slice(-2);
|
|
||||||
const territoryRegex = new RegExp(territory.concat('$'));
|
|
||||||
language = language.replace('-', '_').replace(territoryRegex, territory.toUpperCase());
|
|
||||||
htmlTags.push(<meta property='og:locale' content={language} />);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Array.isArray(images)) {
|
|
||||||
images = [images];
|
|
||||||
}
|
|
||||||
images = images.map(path => {
|
|
||||||
if (!urlFn.parse(path).host) {
|
|
||||||
// resolve `path`'s absolute path relative to current page's url
|
|
||||||
// `path` can be both absolute (starts with `/`) or relative.
|
|
||||||
return urlFn.resolve(url, path);
|
|
||||||
}
|
|
||||||
htmlTags.push(<meta property='og:image' content={path} />);
|
|
||||||
return path;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (date && (moment.isMoment(date) || moment.isDate(date)) && !isNaN(date.valueOf())) {
|
|
||||||
htmlTags.push(<meta property='article:published_time' content={date.toISOString()} />);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (updated && (moment.isMoment(updated) || moment.isDate(updated)) && !isNaN(updated.valueOf())) {
|
|
||||||
htmlTags.push(<meta property='article:modified_time' content={updated.toISOString()} />);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (author) {
|
|
||||||
htmlTags.push(<meta property='article:author' content={author} />);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keywords) {
|
|
||||||
if (typeof keywords === 'string') {
|
|
||||||
keywords = keywords.split(',');
|
|
||||||
}
|
|
||||||
|
|
||||||
keywords.map(tag => {
|
|
||||||
return tag.name ? tag.name : tag;
|
|
||||||
}).filter(Boolean).forEach(keyword => {
|
|
||||||
htmlTags.push(<meta property='article:tag' content={keyword} />);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
htmlTags.push(<meta property='twitter:card' content={twitterCard || 'summary'} />);
|
|
||||||
|
|
||||||
if (images.length) {
|
|
||||||
htmlTags.push(<meta property='twitter:image' content={images[0]} />);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (twitterId) {
|
|
||||||
if (twitterId[0] !== '@') {
|
|
||||||
twitterId = `@${twitterId}`;
|
|
||||||
}
|
|
||||||
htmlTags.push(<meta property='twitter:creator' content={twitterId} />);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (twitterSite) {
|
|
||||||
htmlTags.push(<meta property='twitter:site' content={twitterSite} />);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (googlePlus) {
|
|
||||||
htmlTags.push(<link rel="publisher" href={googlePlus} />);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (facebookAdmins) {
|
|
||||||
htmlTags.push(<meta property='fb:admins' content={facebookAdmins} />);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (facebookAppId) {
|
|
||||||
htmlTags.push(<meta property='fb:app_id' content={facebookAppId} />);
|
|
||||||
}
|
|
||||||
|
|
||||||
return <Fragment>{htmlTags}</Fragment>;
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,53 +0,0 @@
|
||||||
const { Component } = require('inferno');
|
|
||||||
|
|
||||||
module.exports = class extends Component {
|
|
||||||
render() {
|
|
||||||
const { current, total, baseUrl, path, urlFor, prevTitle, nextTitle } = this.props;
|
|
||||||
|
|
||||||
function getPageUrl(i) {
|
|
||||||
return urlFor(i === 1 ? baseUrl : baseUrl + path + '/' + i + '/');
|
|
||||||
}
|
|
||||||
|
|
||||||
function pagination(c, m) {
|
|
||||||
const current = c;
|
|
||||||
const last = m;
|
|
||||||
const delta = 1;
|
|
||||||
const left = current - delta;
|
|
||||||
const right = current + delta + 1;
|
|
||||||
const range = [];
|
|
||||||
const elements = [];
|
|
||||||
let l;
|
|
||||||
|
|
||||||
for (let i = 1; i <= last; i++) {
|
|
||||||
if (i === 1 || i === last || (i >= left && i < right)) {
|
|
||||||
range.push(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const i of range) {
|
|
||||||
if (l) {
|
|
||||||
if (i - l === 2) {
|
|
||||||
elements.push(<li><a class="pagination-link" href={getPageUrl(l + 1)}>{l + 1}</a></li>);
|
|
||||||
} else if (i - l !== 1) {
|
|
||||||
elements.push(<li><span class="pagination-ellipsis" dangerouslySetInnerHTML={{ __html: '…' }}></span></li>);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
elements.push(<li><a class={`pagination-link${c === i ? ' is-current' : ''}`} href={getPageUrl(i)}>{i}</a></li>);
|
|
||||||
l = i;
|
|
||||||
}
|
|
||||||
return elements;
|
|
||||||
}
|
|
||||||
|
|
||||||
return <nav class="pagination is-centered mt-4" role="navigation" aria-label="pagination">
|
|
||||||
<div class={`pagination-previous${current > 1 ? '' : ' is-invisible is-hidden-mobile'}`}>
|
|
||||||
<a href={getPageUrl(current - 1)}>{prevTitle}</a>
|
|
||||||
</div>
|
|
||||||
<div class={`pagination-next${current < total ? '' : ' is-invisible is-hidden-mobile'}`}>
|
|
||||||
<a href={getPageUrl(current + 1)}>{nextTitle}</a>
|
|
||||||
</div>
|
|
||||||
<ul class="pagination-list is-hidden-mobile">
|
|
||||||
{pagination(current, total)}
|
|
||||||
</ul>
|
|
||||||
</nav>;
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,56 +0,0 @@
|
||||||
const urlFn = require('url');
|
|
||||||
const moment = require('moment');
|
|
||||||
const { Component } = require('inferno');
|
|
||||||
const { stripHTML, escapeHTML } = require('hexo-util');
|
|
||||||
|
|
||||||
module.exports = class extends Component {
|
|
||||||
render() {
|
|
||||||
const { title, url, author } = this.props;
|
|
||||||
let { description, images, date, updated } = this.props;
|
|
||||||
|
|
||||||
if (description) {
|
|
||||||
description = escapeHTML(stripHTML(description).substring(0, 200).trim())
|
|
||||||
.replace(/\n/g, ' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Array.isArray(images)) {
|
|
||||||
images = [images];
|
|
||||||
}
|
|
||||||
images = images.map(path => {
|
|
||||||
if (!urlFn.parse(path).host) {
|
|
||||||
// resolve `path`'s absolute path relative to current page's url
|
|
||||||
// `path` can be both absolute (starts with `/`) or relative.
|
|
||||||
return urlFn.resolve(url, path);
|
|
||||||
}
|
|
||||||
return path;
|
|
||||||
}).filter(url => url.endsWith('.jpg') || url.endsWith('.png') || url.endsWith('.gif'));
|
|
||||||
|
|
||||||
if (date && (moment.isMoment(date) || moment.isDate(date)) && !isNaN(date.valueOf())) {
|
|
||||||
date = date.toISOString();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (updated && (moment.isMoment(updated) || moment.isDate(updated)) && !isNaN(updated.valueOf())) {
|
|
||||||
updated = updated.toISOString();
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = {
|
|
||||||
'@context': 'https://schema.org',
|
|
||||||
'@type': 'BlogPosting',
|
|
||||||
'mainEntityOfPage': {
|
|
||||||
'@type': 'WebPage',
|
|
||||||
'@id': url
|
|
||||||
},
|
|
||||||
'headline': title,
|
|
||||||
'image': images,
|
|
||||||
'datePublished': date,
|
|
||||||
'dateModified': updated,
|
|
||||||
'author': {
|
|
||||||
'@type': 'Person',
|
|
||||||
'name': author
|
|
||||||
},
|
|
||||||
'description': description
|
|
||||||
};
|
|
||||||
|
|
||||||
return <script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(data) }}></script>;
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,5 +1,5 @@
|
||||||
const { Component } = require('inferno');
|
const { Component } = require('inferno');
|
||||||
const { cacheComponent } = require('../util/cache');
|
const { cacheComponent } = require('hexo-component-inferno/lib/util/cache');
|
||||||
|
|
||||||
class AnimeJs extends Component {
|
class AnimeJs extends Component {
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const { Component, Fragment } = require('inferno');
|
const { Component, Fragment } = require('inferno');
|
||||||
const { cacheComponent } = require('../util/cache');
|
const { cacheComponent } = require('hexo-component-inferno/lib/util/cache');
|
||||||
|
|
||||||
class BackToTop extends Component {
|
class BackToTop extends Component {
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
const { Component } = require('inferno');
|
|
||||||
const { cacheComponent } = require('../util/cache');
|
|
||||||
|
|
||||||
class BaiduAnalytics extends Component {
|
|
||||||
render() {
|
|
||||||
const { trackingId } = this.props;
|
|
||||||
|
|
||||||
const js = `var _hmt = _hmt || [];
|
|
||||||
(function() {
|
|
||||||
var hm = document.createElement("script");
|
|
||||||
hm.src = "//hm.baidu.com/hm.js?${trackingId}";
|
|
||||||
var s = document.getElementsByTagName("script")[0];
|
|
||||||
s.parentNode.insertBefore(hm, s);
|
|
||||||
})();`;
|
|
||||||
|
|
||||||
return <script dangerouslySetInnerHTML={{ __html: js }}></script>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = cacheComponent(BaiduAnalytics, 'plugin.baiduanalytics', props => {
|
|
||||||
const { head, plugin } = props;
|
|
||||||
if (!head || !plugin.tracking_id) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
trackingId: plugin.tracking_id
|
|
||||||
};
|
|
||||||
});
|
|
|
@ -1,15 +0,0 @@
|
||||||
const { Component } = require('inferno');
|
|
||||||
const { cacheComponent } = require('../util/cache');
|
|
||||||
|
|
||||||
class Busuanzi extends Component {
|
|
||||||
render() {
|
|
||||||
return <script src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" defer={true}></script>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = cacheComponent(Busuanzi, 'plugin.busuanzi', props => {
|
|
||||||
if (!props.head) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
});
|
|
|
@ -1,36 +0,0 @@
|
||||||
const { Component, Fragment } = require('inferno');
|
|
||||||
const { cacheComponent } = require('../util/cache');
|
|
||||||
|
|
||||||
class Gallery extends Component {
|
|
||||||
render() {
|
|
||||||
const { head, jsUrl, lightGallery, justifiedGallery } = this.props;
|
|
||||||
if (head) {
|
|
||||||
return <Fragment>
|
|
||||||
<link rel="stylesheet" href={lightGallery.cssUrl} />
|
|
||||||
<link rel="stylesheet" href={justifiedGallery.cssUrl} />
|
|
||||||
</Fragment>;
|
|
||||||
}
|
|
||||||
return <Fragment>
|
|
||||||
<script src={lightGallery.jsUrl} defer={true}></script>
|
|
||||||
<script src={justifiedGallery.jsUrl} defer={true}></script>
|
|
||||||
<script src={jsUrl} defer={true}></script>
|
|
||||||
</Fragment>;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = cacheComponent(Gallery, 'plugin.gallery', props => {
|
|
||||||
const { head, helper } = props;
|
|
||||||
return {
|
|
||||||
head,
|
|
||||||
jsUrl: helper.url_for('/js/gallery.js'),
|
|
||||||
lightGallery: {
|
|
||||||
jsUrl: helper.cdn('lightgallery', '1.6.8', 'dist/js/lightgallery.min.js'),
|
|
||||||
cssUrl: helper.cdn('lightgallery', '1.6.8', 'dist/css/lightgallery.min.css')
|
|
||||||
},
|
|
||||||
justifiedGallery: {
|
|
||||||
jsUrl: helper.cdn('justifiedGallery', '3.7.0', 'dist/js/jquery.justifiedGallery.min.js'),
|
|
||||||
cssUrl: helper.cdn('justifiedGallery', '3.7.0', 'dist/css/justifiedGallery.min.css')
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
|
@ -1,29 +0,0 @@
|
||||||
const { Component, Fragment } = require('inferno');
|
|
||||||
const { cacheComponent } = require('../util/cache');
|
|
||||||
|
|
||||||
class GoogleAnalytics extends Component {
|
|
||||||
render() {
|
|
||||||
const { trackingId } = this.props;
|
|
||||||
|
|
||||||
const js = `window.dataLayer = window.dataLayer || [];
|
|
||||||
function gtag(){dataLayer.push(arguments);}
|
|
||||||
gtag('js', new Date());
|
|
||||||
|
|
||||||
gtag('config', '${trackingId}');`;
|
|
||||||
|
|
||||||
return <Fragment>
|
|
||||||
<script src={`https://www.googletagmanager.com/gtag/js?id=${trackingId}`} async={true}></script>
|
|
||||||
<script dangerouslySetInnerHTML={{ __html: js }}></script>
|
|
||||||
</Fragment>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = cacheComponent(GoogleAnalytics, 'plugin.googleanalytics', props => {
|
|
||||||
const { head, plugin } = props;
|
|
||||||
if (!head || !plugin.tracking_id) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
trackingId: plugin.tracking_id
|
|
||||||
};
|
|
||||||
});
|
|
|
@ -1,31 +0,0 @@
|
||||||
const { Component, Fragment } = require('inferno');
|
|
||||||
const { cacheComponent } = require('../util/cache');
|
|
||||||
|
|
||||||
class Hotjar extends Component {
|
|
||||||
render() {
|
|
||||||
const { siteId } = this.props;
|
|
||||||
|
|
||||||
const js = `(function(h,o,t,j,a,r){
|
|
||||||
h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};
|
|
||||||
h._hjSettings={hjid:${siteId},hjsv:6};
|
|
||||||
a=o.getElementsByTagName('head')[0];
|
|
||||||
r=o.createElement('script');r.async=1;
|
|
||||||
r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;
|
|
||||||
a.appendChild(r);
|
|
||||||
})(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');`;
|
|
||||||
|
|
||||||
return <Fragment>
|
|
||||||
<script dangerouslySetInnerHTML={{ __html: js }}></script>
|
|
||||||
</Fragment>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = cacheComponent(Hotjar, 'plugin.hotjar', props => {
|
|
||||||
const { head, plugin } = props;
|
|
||||||
if (!head || !plugin.site_id) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
siteId: plugin.site_id
|
|
||||||
};
|
|
||||||
});
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue