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 CONFIG_PATH = path.join(hexo.theme_dir, '_config.yml');
|
||||
|
||||
const yaml = require('../include/util/yaml');
|
||||
const { SchemaLoader } = require('../include/util/schema');
|
||||
const yaml = require('hexo-component-inferno/lib/util/yaml');
|
||||
const { SchemaLoader } = require('hexo-component-inferno/lib/core/schema');
|
||||
const loader = SchemaLoader.load(require(path.join(SCHEMA_ROOT, 'config.json')), SCHEMA_ROOT);
|
||||
const schema = loader.getSchema('/config.json');
|
||||
logger.info('=== Checking the configuration file ===');
|
||||
|
@ -32,7 +32,7 @@ module.exports = hexo => {
|
|||
let cfg = yaml.parse(cfgStr);
|
||||
// Check config version
|
||||
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
|
||||
if (migrator.isOudated(cfg.version)) {
|
||||
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 deepmerge = require('deepmerge');
|
||||
const Migration = require('../util/migrate').Migration;
|
||||
const Migration = require('hexo-component-inferno/lib/core/migrate').Migration;
|
||||
|
||||
module.exports = class extends Migration {
|
||||
constructor() {
|
||||
super('3.0.0', null);
|
||||
}
|
||||
|
||||
doMigrate(config) {
|
||||
upgrade(config) {
|
||||
const result = deepmerge({}, config);
|
||||
result.head = {
|
||||
favicon: config.favicon || null,
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
const logger = require('hexo-log')();
|
||||
|
||||
module.exports = hexo => {
|
||||
logger.info('=== Patching Hexo ===');
|
||||
require('../include/generator/categories')(hexo);
|
||||
require('../include/generator/category')(hexo);
|
||||
require('../include/generator/tags')(hexo);
|
||||
require('../include/generator/insight')(hexo);
|
||||
require('../include/filter/locals')(hexo);
|
||||
require('../include/helper/cdn')(hexo);
|
||||
require('../include/helper/page')(hexo);
|
||||
require('../include/helper/thumbnail')(hexo);
|
||||
logger.info('=== Registering Hexo extensions ===');
|
||||
require('hexo-component-inferno/lib/hexo/filter/locals')(hexo);
|
||||
require('./generator/category')(hexo);
|
||||
require('./generator/insight')(hexo);
|
||||
require('hexo-component-inferno/lib/hexo/generator/categories')(hexo);
|
||||
require('hexo-component-inferno/lib/hexo/generator/tags')(hexo);
|
||||
require('hexo-component-inferno/lib/hexo/helper/cdn')(hexo);
|
||||
require('hexo-component-inferno/lib/hexo/helper/page')(hexo);
|
||||
require('hexo-component-inferno/lib/hexo/helper/thumbnail')(hexo);
|
||||
require('hexo-component-inferno/lib/core/view').init(hexo);
|
||||
|
||||
const hooks = [
|
||||
'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 { Component, Fragment } = require('inferno');
|
||||
const Paginator = require('./misc/paginator');
|
||||
const ArticleMedia = require('./common/article-media');
|
||||
const Paginator = require('hexo-component-inferno/lib/view/misc/paginator');
|
||||
const ArticleMedia = require('hexo-component-inferno/lib/view/common/article-media');
|
||||
|
||||
module.exports = class extends Component {
|
||||
render() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const { Component } = require('inferno');
|
||||
const Categories = require('./widget/categories');
|
||||
const Categories = require('hexo-component-inferno/lib/view/widget/categories');
|
||||
|
||||
module.exports = class extends Component {
|
||||
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 { Component } = require('inferno');
|
||||
const view = require('hexo-component-inferno/lib/core/view');
|
||||
|
||||
module.exports = class extends Component {
|
||||
render() {
|
||||
|
@ -15,7 +16,7 @@ module.exports = class extends Component {
|
|||
<h3 class="title is-5">{__('article.comments')}</h3>
|
||||
{(() => {
|
||||
try {
|
||||
const Comment = require('../comment/' + comment.type);
|
||||
const Comment = view.require('comment/' + comment.type);
|
||||
return <Comment config={config} page={page} helper={helper} comment={comment} />;
|
||||
} catch (e) {
|
||||
logger.w(`Icarus cannot load comment "${comment.type}"`);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
const logger = require('hexo-log')();
|
||||
const { Component } = require('inferno');
|
||||
const view = require('hexo-component-inferno/lib/core/view');
|
||||
|
||||
module.exports = class extends Component {
|
||||
render() {
|
||||
|
@ -17,7 +18,7 @@ module.exports = class extends Component {
|
|||
const type = service.type;
|
||||
if (typeof type === 'string') {
|
||||
try {
|
||||
const Donate = require('../donate/' + type);
|
||||
const Donate = view.require('donate/' + type);
|
||||
return <Donate helper={helper} donate={service} />;
|
||||
} catch (e) {
|
||||
logger.w(`Icarus cannot load donate button "${type}"`);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const { Component } = require('inferno');
|
||||
const { cacheComponent } = require('../util/cache');
|
||||
const { cacheComponent } = require('hexo-component-inferno/lib/util/cache');
|
||||
|
||||
class Footer extends Component {
|
||||
render() {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const { Component } = require('inferno');
|
||||
const MetaTags = require('../misc/meta');
|
||||
const OpenGraph = require('../misc/open_graph');
|
||||
const StructuredData = require('../misc/structured_data');
|
||||
const MetaTags = require('hexo-component-inferno/lib/view/misc/meta');
|
||||
const OpenGraph = require('hexo-component-inferno/lib/view/misc/open_graph');
|
||||
const StructuredData = require('hexo-component-inferno/lib/view/misc/structured_data');
|
||||
const Plugins = require('./plugins');
|
||||
|
||||
function getPageTitle(page, siteTitle, helper) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
const { Component, Fragment } = require('inferno');
|
||||
const { cacheComponent } = require('../util/cache');
|
||||
const classname = require('../util/classname');
|
||||
const { cacheComponent } = require('hexo-component-inferno/lib/util/cache');
|
||||
const classname = require('hexo-component-inferno/lib/util/classname');
|
||||
|
||||
function isSameLink(a, b) {
|
||||
function santize(url) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
const logger = require('hexo-log')();
|
||||
const { Component, Fragment } = require('inferno');
|
||||
const view = require('hexo-component-inferno/lib/core/view');
|
||||
|
||||
module.exports = class extends Component {
|
||||
render() {
|
||||
|
@ -13,7 +14,7 @@ module.exports = class extends Component {
|
|||
return null;
|
||||
}
|
||||
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} />;
|
||||
} catch (e) {
|
||||
logger.w(`Icarus cannot load plugin "${name}"`);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
const logger = require('hexo-log')();
|
||||
const { Component } = require('inferno');
|
||||
const view = require('hexo-component-inferno/lib/core/view');
|
||||
|
||||
module.exports = class extends Component {
|
||||
render() {
|
||||
|
@ -10,7 +11,7 @@ module.exports = class extends Component {
|
|||
}
|
||||
|
||||
try {
|
||||
const Search = require('../search/' + search.type);
|
||||
const Search = view.require('search/' + search.type);
|
||||
return <Search config={config} helper={helper} search={search} />;
|
||||
} catch (e) {
|
||||
logger.w(`Icarus cannot load search "${search.type}"`);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
const logger = require('hexo-log')();
|
||||
const { Component } = require('inferno');
|
||||
const view = require('hexo-component-inferno/lib/core/view');
|
||||
|
||||
module.exports = class extends Component {
|
||||
render() {
|
||||
|
@ -10,7 +11,7 @@ module.exports = class extends Component {
|
|||
}
|
||||
|
||||
try {
|
||||
const Share = require('../share/' + share.type);
|
||||
const Share = view.require('share/' + share.type);
|
||||
return <Share config={config} page={page} helper={helper} share={share} />;
|
||||
} catch (e) {
|
||||
logger.w(`Icarus cannot load share button "${share.type}"`);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
const logger = require('hexo-log')();
|
||||
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) {
|
||||
const result = {};
|
||||
|
@ -80,7 +81,7 @@ class Widgets extends Component {
|
|||
return null;
|
||||
}
|
||||
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} />;
|
||||
} catch (e) {
|
||||
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 Paginator = require('hexo-component-inferno/lib/view/misc/paginator');
|
||||
const Article = require('./common/article');
|
||||
const Paginator = require('./misc/paginator');
|
||||
|
||||
module.exports = class extends Component {
|
||||
render() {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
const { Component } = require('inferno');
|
||||
const classname = require('hexo-component-inferno/lib/util/classname');
|
||||
const Head = require('./common/head');
|
||||
const Navbar = require('./common/navbar');
|
||||
const Widgets = require('./common/widgets');
|
||||
const Footer = require('./common/footer');
|
||||
const Scripts = require('./common/scripts');
|
||||
const Search = require('./common/search');
|
||||
const classname = require('./util/classname');
|
||||
|
||||
module.exports = class extends Component {
|
||||
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 { cacheComponent } = require('../util/cache');
|
||||
const { cacheComponent } = require('hexo-component-inferno/lib/util/cache');
|
||||
|
||||
class AnimeJs extends Component {
|
||||
render() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const { Component, Fragment } = require('inferno');
|
||||
const { cacheComponent } = require('../util/cache');
|
||||
const { cacheComponent } = require('hexo-component-inferno/lib/util/cache');
|
||||
|
||||
class BackToTop extends Component {
|
||||
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