mirror of
https://github.com/next-theme/hexo-theme-next.git
synced 2026-01-21 19:32:34 +00:00
Unit testing using Mocha and Chai (#59)
This commit is contained in:
parent
e02e104ac2
commit
cfb4130825
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -1 +1,2 @@
|
|||||||
source/lib/* linguist-vendored
|
source/lib/* linguist-vendored
|
||||||
|
test/* linguist-vendored
|
||||||
|
|||||||
1
.github/workflows/linter.yml
vendored
1
.github/workflows/linter.yml
vendored
@ -10,4 +10,5 @@ jobs:
|
|||||||
- name: Use Node.js
|
- name: Use Node.js
|
||||||
uses: actions/setup-node@v1
|
uses: actions/setup-node@v1
|
||||||
- run: npm install
|
- run: npm install
|
||||||
|
- run: npm run eslint
|
||||||
- run: npm test
|
- run: npm test
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
.github/
|
.github/
|
||||||
|
test/
|
||||||
.editorconfig
|
.editorconfig
|
||||||
.eslintrc.json
|
.eslintrc.json
|
||||||
.gitattributes
|
.gitattributes
|
||||||
|
|||||||
45
gulpfile.js
45
gulpfile.js
@ -1,45 +0,0 @@
|
|||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
const gulp = require('gulp');
|
|
||||||
const shell = require('gulp-shell');
|
|
||||||
const yaml = require('js-yaml');
|
|
||||||
|
|
||||||
gulp.task('lint', shell.task([
|
|
||||||
'npm run eslint'
|
|
||||||
]));
|
|
||||||
|
|
||||||
gulp.task('lint:stylus', shell.task([
|
|
||||||
'npm run stylint'
|
|
||||||
]));
|
|
||||||
|
|
||||||
gulp.task('validate:config', cb => {
|
|
||||||
const themeConfig = fs.readFileSync(path.join(__dirname, '_config.yml'));
|
|
||||||
|
|
||||||
try {
|
|
||||||
yaml.safeLoad(themeConfig);
|
|
||||||
return cb();
|
|
||||||
} catch (error) {
|
|
||||||
return cb(new Error(error));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('validate:languages', cb => {
|
|
||||||
const languagesPath = path.join(__dirname, 'languages');
|
|
||||||
const errors = [];
|
|
||||||
|
|
||||||
fs.readdirSync(languagesPath).forEach(lang => {
|
|
||||||
if (!lang.endsWith('.yml')) return;
|
|
||||||
const languagePath = path.join(languagesPath, lang);
|
|
||||||
try {
|
|
||||||
yaml.safeLoad(fs.readFileSync(languagePath), {
|
|
||||||
filename: path.relative(__dirname, languagePath)
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
errors.push(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return errors.length === 0 ? cb() : cb(errors);
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('default', gulp.series('lint', 'validate:config', 'validate:languages'));
|
|
||||||
16
package.json
16
package.json
@ -2,11 +2,11 @@
|
|||||||
"name": "hexo-theme-next",
|
"name": "hexo-theme-next",
|
||||||
"version": "8.0.0-rc.4",
|
"version": "8.0.0-rc.4",
|
||||||
"description": "Elegant and powerful theme for Hexo.",
|
"description": "Elegant and powerful theme for Hexo.",
|
||||||
"main": "gulpfile.js",
|
"main": "package.json",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "gulp",
|
"eslint": "eslint scripts/ source/js test/",
|
||||||
"eslint": "eslint source/js scripts/",
|
"stylint": "stylint source/css/",
|
||||||
"stylint": "stylint source/css/"
|
"test": "mocha test/index.js"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -24,17 +24,19 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://theme-next.js.org",
|
"homepage": "https://theme-next.js.org",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"chai": "4.2.0",
|
||||||
"eslint": "7.3.1",
|
"eslint": "7.3.1",
|
||||||
"eslint-config-theme-next": "1.2.0",
|
"eslint-config-theme-next": "1.2.0",
|
||||||
"gulp": "4.0.2",
|
"hexo": "5.0.0",
|
||||||
"gulp-shell": "0.8.0",
|
"hexo-renderer-marked": "3.0.0",
|
||||||
"husky": "4.2.5",
|
"husky": "4.2.5",
|
||||||
"js-yaml": "3.14.0",
|
"js-yaml": "3.14.0",
|
||||||
|
"mocha": "8.0.1",
|
||||||
"stylint": "2.0.0"
|
"stylint": "2.0.0"
|
||||||
},
|
},
|
||||||
"husky": {
|
"husky": {
|
||||||
"hooks": {
|
"hooks": {
|
||||||
"pre-commit": "gulp"
|
"pre-commit": "npm run eslint && npm test"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,11 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
|
const nextFont = require('./font');
|
||||||
|
const nextUrl = require('./next-url');
|
||||||
|
|
||||||
|
hexo.extend.helper.register('next_font', nextFont);
|
||||||
|
hexo.extend.helper.register('next_url', nextUrl);
|
||||||
|
|
||||||
hexo.extend.helper.register('next_inject', function(point) {
|
hexo.extend.helper.register('next_inject', function(point) {
|
||||||
return this.theme.injects[point]
|
return this.theme.injects[point]
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
/* global hexo */
|
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// https://developers.google.com/fonts/docs/getting_started
|
// https://developers.google.com/fonts/docs/getting_started
|
||||||
hexo.extend.helper.register('next_font', function() {
|
module.exports = function() {
|
||||||
const config = this.theme.font;
|
const config = this.theme.font;
|
||||||
|
|
||||||
if (!config || !config.enable) return '';
|
if (!config || !config.enable) return '';
|
||||||
@ -24,4 +22,4 @@ hexo.extend.helper.register('next_font', function() {
|
|||||||
|
|
||||||
// Merge extra parameters to the final processed font string
|
// Merge extra parameters to the final processed font string
|
||||||
return fontFamilies ? `<link rel="stylesheet" href="${fontHost}/css?family=${fontFamilies}&display=swap&subset=latin,latin-ext">` : '';
|
return fontFamilies ? `<link rel="stylesheet" href="${fontHost}/css?family=${fontFamilies}&display=swap&subset=latin,latin-ext">` : '';
|
||||||
});
|
};
|
||||||
|
|||||||
@ -1,16 +1,13 @@
|
|||||||
/* global hexo */
|
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { htmlTag } = require('hexo-util');
|
const { htmlTag } = require('hexo-util');
|
||||||
const { parse } = require('url');
|
const { parse } = require('url');
|
||||||
|
|
||||||
hexo.extend.helper.register('next_url', function(path, text, options = {}) {
|
module.exports = function(path, text, options = {}) {
|
||||||
const { config } = this;
|
const { config, theme } = this;
|
||||||
const data = parse(path);
|
const data = parse(path);
|
||||||
const siteHost = parse(config.url).hostname || config.url;
|
const siteHost = parse(config.url).hostname || config.url;
|
||||||
|
|
||||||
const theme = hexo.theme.config;
|
|
||||||
let exturl = '';
|
let exturl = '';
|
||||||
let tag = 'a';
|
let tag = 'a';
|
||||||
let attrs = { href: this.url_for(path) };
|
let attrs = { href: this.url_for(path) };
|
||||||
@ -58,4 +55,4 @@ hexo.extend.helper.register('next_url', function(path, text, options = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return htmlTag(tag, attrs, decodeURI(text), false);
|
return htmlTag(tag, attrs, decodeURI(text), false);
|
||||||
});
|
};
|
||||||
|
|||||||
@ -2,11 +2,9 @@
|
|||||||
* button.js | https://theme-next.js.org/docs/tag-plugins/button
|
* button.js | https://theme-next.js.org/docs/tag-plugins/button
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* global hexo */
|
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
function postButton(args) {
|
module.exports = ctx => function(args) {
|
||||||
args = args.join(' ').split(',');
|
args = args.join(' ').split(',');
|
||||||
const url = args[0];
|
const url = args[0];
|
||||||
const text = (args[1] || '').trim();
|
const text = (args[1] || '').trim();
|
||||||
@ -14,7 +12,7 @@ function postButton(args) {
|
|||||||
const title = (args[3] || '').trim();
|
const title = (args[3] || '').trim();
|
||||||
|
|
||||||
if (!url) {
|
if (!url) {
|
||||||
hexo.log.warn('URL can NOT be empty.');
|
ctx.log.warn('URL can NOT be empty.');
|
||||||
}
|
}
|
||||||
if (icon.length > 0) {
|
if (icon.length > 0) {
|
||||||
if (!icon.startsWith('fa')) icon = 'fa fa-' + icon;
|
if (!icon.startsWith('fa')) icon = 'fa fa-' + icon;
|
||||||
@ -22,7 +20,4 @@ function postButton(args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return `<a class="btn" href="${url}"${title.length > 0 ? ` title="${title}"` : ''}>${icon}${text}</a>`;
|
return `<a class="btn" href="${url}"${title.length > 0 ? ` title="${title}"` : ''}>${icon}${text}</a>`;
|
||||||
}
|
};
|
||||||
|
|
||||||
hexo.extend.tag.register('button', postButton, {ends: false});
|
|
||||||
hexo.extend.tag.register('btn', postButton, {ends: false});
|
|
||||||
|
|||||||
@ -2,22 +2,17 @@
|
|||||||
* caniuse.js | https://theme-next.js.org/docs/tag-plugins/caniuse
|
* caniuse.js | https://theme-next.js.org/docs/tag-plugins/caniuse
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* global hexo */
|
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
function caniUse(args) {
|
module.exports = ctx => function(args) {
|
||||||
args = args.join('').split('@');
|
args = args.join('').split('@');
|
||||||
const feature = args[0];
|
const feature = args[0];
|
||||||
const periods = args[1] || 'current';
|
const periods = args[1] || 'current';
|
||||||
|
|
||||||
if (!feature) {
|
if (!feature) {
|
||||||
hexo.log.warn('Caniuse feature can NOT be empty.');
|
ctx.log.warn('Caniuse feature can NOT be empty.');
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
return `<iframe data-feature="${feature}" src="https://caniuse.bitsofco.de/embed/index.html?feat=${feature}&periods=${periods}&accessible-colours=false" frameborder="0" width="100%" height="400px"></iframe>`;
|
return `<iframe data-feature="${feature}" src="https://caniuse.bitsofco.de/embed/index.html?feat=${feature}&periods=${periods}&accessible-colours=false" frameborder="0" width="100%" height="400px"></iframe>`;
|
||||||
}
|
};
|
||||||
|
|
||||||
hexo.extend.tag.register('caniuse', caniUse);
|
|
||||||
hexo.extend.tag.register('can', caniUse);
|
|
||||||
|
|||||||
@ -2,15 +2,10 @@
|
|||||||
* center-quote.js | https://theme-next.js.org/docs/tag-plugins/
|
* center-quote.js | https://theme-next.js.org/docs/tag-plugins/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* global hexo */
|
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
function centerQuote(args, content) {
|
module.exports = ctx => function(args, content) {
|
||||||
return `<blockquote class="blockquote-center">
|
return `<blockquote class="blockquote-center">
|
||||||
${hexo.render.renderSync({ text: content, engine: 'markdown' })}
|
${ctx.render.renderSync({ text: content, engine: 'markdown' })}
|
||||||
</blockquote>`;
|
</blockquote>`;
|
||||||
}
|
};
|
||||||
|
|
||||||
hexo.extend.tag.register('centerquote', centerQuote, {ends: true});
|
|
||||||
hexo.extend.tag.register('cq', centerQuote, {ends: true});
|
|
||||||
|
|||||||
@ -2,8 +2,6 @@
|
|||||||
* group-pictures.js | https://theme-next.js.org/docs/tag-plugins/group-pictures
|
* group-pictures.js | https://theme-next.js.org/docs/tag-plugins/group-pictures
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* global hexo */
|
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const LAYOUTS = {
|
const LAYOUTS = {
|
||||||
@ -123,17 +121,14 @@ const templates = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function groupPicture(args, content) {
|
module.exports = ctx => function(args, content) {
|
||||||
args = args[0].split('-');
|
args = args[0].split('-');
|
||||||
const group = parseInt(args[0], 10);
|
const group = parseInt(args[0], 10);
|
||||||
const layout = parseInt(args[1], 10);
|
const layout = parseInt(args[1], 10);
|
||||||
|
|
||||||
content = hexo.render.renderSync({text: content, engine: 'markdown'});
|
content = ctx.render.renderSync({ text: content, engine: 'markdown' });
|
||||||
|
|
||||||
const pictures = content.match(/<img[\s\S]*?>/g);
|
const pictures = content.match(/<img[\s\S]*?>/g);
|
||||||
|
|
||||||
return `<div class="group-picture">${templates.dispatch(pictures, group, layout)}</div>`;
|
return `<div class="group-picture">${templates.dispatch(pictures, group, layout)}</div>`;
|
||||||
}
|
};
|
||||||
|
|
||||||
hexo.extend.tag.register('grouppicture', groupPicture, {ends: true});
|
|
||||||
hexo.extend.tag.register('gp', groupPicture, {ends: true});
|
|
||||||
|
|||||||
55
scripts/tags/index.js
Normal file
55
scripts/tags/index.js
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/* global hexo */
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const postButton = require('./button')(hexo);
|
||||||
|
|
||||||
|
hexo.extend.tag.register('button', postButton);
|
||||||
|
hexo.extend.tag.register('btn', postButton);
|
||||||
|
|
||||||
|
const caniUse = require('./caniuse')(hexo);
|
||||||
|
|
||||||
|
hexo.extend.tag.register('caniuse', caniUse);
|
||||||
|
hexo.extend.tag.register('can', caniUse);
|
||||||
|
|
||||||
|
const centerQuote = require('./center-quote')(hexo);
|
||||||
|
|
||||||
|
hexo.extend.tag.register('centerquote', centerQuote, true);
|
||||||
|
hexo.extend.tag.register('cq', centerQuote, true);
|
||||||
|
|
||||||
|
const groupPicture = require('./group-pictures')(hexo);
|
||||||
|
|
||||||
|
hexo.extend.tag.register('grouppicture', groupPicture, true);
|
||||||
|
hexo.extend.tag.register('gp', groupPicture, true);
|
||||||
|
|
||||||
|
const postLabel = require('./label')(hexo);
|
||||||
|
|
||||||
|
hexo.extend.tag.register('label', postLabel);
|
||||||
|
|
||||||
|
const linkGrid = require('./link-grid');
|
||||||
|
|
||||||
|
hexo.extend.tag.register('linkgrid', linkGrid, true);
|
||||||
|
hexo.extend.tag.register('lg', linkGrid, true);
|
||||||
|
|
||||||
|
const mermaid = require('./mermaid');
|
||||||
|
|
||||||
|
hexo.extend.tag.register('mermaid', mermaid, true);
|
||||||
|
|
||||||
|
const postNote = require('./note')(hexo);
|
||||||
|
|
||||||
|
hexo.extend.tag.register('note', postNote, true);
|
||||||
|
hexo.extend.tag.register('subnote', postNote, true);
|
||||||
|
|
||||||
|
const pdf = require('./pdf')(hexo);
|
||||||
|
|
||||||
|
hexo.extend.tag.register('pdf', pdf);
|
||||||
|
|
||||||
|
const postTabs = require('./tabs')(hexo);
|
||||||
|
|
||||||
|
hexo.extend.tag.register('tabs', postTabs, true);
|
||||||
|
hexo.extend.tag.register('subtabs', postTabs, true);
|
||||||
|
hexo.extend.tag.register('subsubtabs', postTabs, true);
|
||||||
|
|
||||||
|
const postVideo = require('./video');
|
||||||
|
|
||||||
|
hexo.extend.tag.register('video', postVideo);
|
||||||
@ -2,18 +2,14 @@
|
|||||||
* label.js | https://theme-next.js.org/docs/tag-plugins/label
|
* label.js | https://theme-next.js.org/docs/tag-plugins/label
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* global hexo */
|
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
function postLabel(args) {
|
module.exports = ctx => function(args) {
|
||||||
args = args.join(' ').split('@');
|
args = args.join(' ').split('@');
|
||||||
const classes = args[0] || 'default';
|
const classes = args[0] || 'default';
|
||||||
const text = args[1] || '';
|
const text = args[1] || '';
|
||||||
|
|
||||||
if (!text) hexo.log.warn('Label text must be defined!');
|
if (!text) ctx.log.warn('Label text must be defined!');
|
||||||
|
|
||||||
return `<mark class="label ${classes.trim()}">${text}</mark>`;
|
return `<mark class="label ${classes.trim()}">${text}</mark>`;
|
||||||
}
|
};
|
||||||
|
|
||||||
hexo.extend.tag.register('label', postLabel, {ends: false});
|
|
||||||
|
|||||||
@ -2,17 +2,15 @@
|
|||||||
* link-grid.js | https://theme-next.js.org/docs/tag-plugins/link-grid
|
* link-grid.js | https://theme-next.js.org/docs/tag-plugins/link-grid
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* global hexo */
|
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
function linkGrid(args, content) {
|
module.exports = function(args, content) {
|
||||||
const image = args[0] || '/images/avatar.gif';
|
const image = args[0] || '/images/avatar.gif';
|
||||||
const delimiter = args[1] || '|';
|
const delimiter = args[1] || '|';
|
||||||
const comment = args[2] || '%';
|
const comment = args[2] || '%';
|
||||||
|
|
||||||
const links = content.split('\n').map(item => {
|
const links = content.split('\n').filter(line => line.trim() !== '').map(line => {
|
||||||
item = item.split(delimiter).map(arg => arg.trim());
|
const item = line.split(delimiter).map(arg => arg.trim());
|
||||||
if (item[0][0] === comment) return '';
|
if (item[0][0] === comment) return '';
|
||||||
return `<div class="link-grid-container">
|
return `<div class="link-grid-container">
|
||||||
<div class="link-grid-image" style="background-image: url(${item[3] || image});"></div>
|
<div class="link-grid-image" style="background-image: url(${item[3] || image});"></div>
|
||||||
@ -21,7 +19,4 @@ function linkGrid(args, content) {
|
|||||||
</div>`;
|
</div>`;
|
||||||
});
|
});
|
||||||
return `<div class="link-grid">${links.join('')}</div>`;
|
return `<div class="link-grid">${links.join('')}</div>`;
|
||||||
}
|
};
|
||||||
|
|
||||||
hexo.extend.tag.register('linkgrid', linkGrid, {ends: true});
|
|
||||||
hexo.extend.tag.register('lg', linkGrid, {ends: true});
|
|
||||||
|
|||||||
@ -2,15 +2,11 @@
|
|||||||
* mermaid.js | https://theme-next.js.org/docs/tag-plugins/mermaid
|
* mermaid.js | https://theme-next.js.org/docs/tag-plugins/mermaid
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* global hexo */
|
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
function mermaid(args, content) {
|
module.exports = function(args, content) {
|
||||||
return `<pre class="mermaid" style="text-align: center;">
|
return `<pre class="mermaid" style="text-align: center;">
|
||||||
${args.join(' ')}
|
${args.join(' ')}
|
||||||
${content}
|
${content}
|
||||||
</pre>`;
|
</pre>`;
|
||||||
}
|
};
|
||||||
|
|
||||||
hexo.extend.tag.register('mermaid', mermaid, {ends: true});
|
|
||||||
|
|||||||
@ -2,11 +2,9 @@
|
|||||||
* note.js | https://theme-next.js.org/docs/tag-plugins/note
|
* note.js | https://theme-next.js.org/docs/tag-plugins/note
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* global hexo */
|
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
function postNote(args, content) {
|
module.exports = ctx => function(args, content) {
|
||||||
const keywords = ['default', 'primary', 'info', 'success', 'warning', 'danger', 'no-icon'];
|
const keywords = ['default', 'primary', 'info', 'success', 'warning', 'danger', 'no-icon'];
|
||||||
const className = [];
|
const className = [];
|
||||||
const summary = [];
|
const summary = [];
|
||||||
@ -17,14 +15,11 @@ function postNote(args, content) {
|
|||||||
className.push(arg);
|
className.push(arg);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
content = hexo.render.renderSync({ text: content, engine: 'markdown' });
|
content = ctx.render.renderSync({ text: content, engine: 'markdown' });
|
||||||
if (summary.length === 0) {
|
if (summary.length === 0) {
|
||||||
return `<div class="note ${args.join(' ')}">${content}</div>`;
|
return `<div class="note ${args.join(' ')}">${content}</div>`;
|
||||||
}
|
}
|
||||||
return `<details class="note ${className.join(' ')}"><summary>${hexo.render.renderSync({ text: summary.join(' '), engine: 'markdown' })}</summary>
|
return `<details class="note ${className.join(' ')}"><summary>${ctx.render.renderSync({ text: summary.join(' '), engine: 'markdown' })}</summary>
|
||||||
${content}
|
${content}
|
||||||
</details>`;
|
</details>`;
|
||||||
}
|
};
|
||||||
|
|
||||||
hexo.extend.tag.register('note', postNote, {ends: true});
|
|
||||||
hexo.extend.tag.register('subnote', postNote, {ends: true});
|
|
||||||
|
|||||||
@ -2,13 +2,9 @@
|
|||||||
* pdf.js | https://theme-next.js.org/docs/tag-plugins/pdf
|
* pdf.js | https://theme-next.js.org/docs/tag-plugins/pdf
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* global hexo */
|
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
function pdf(args) {
|
module.exports = ctx => function(args) {
|
||||||
const theme = hexo.theme.config;
|
const theme = ctx.theme.config;
|
||||||
return `<div class="pdfobject-container" data-target="${args[0]}" data-height="${args[1] || theme.pdf.height}"></div>`;
|
return `<div class="pdfobject-container" data-target="${args[0]}" data-height="${args[1] || theme.pdf.height}"></div>`;
|
||||||
}
|
};
|
||||||
|
|
||||||
hexo.extend.tag.register('pdf', pdf, {ends: false});
|
|
||||||
|
|||||||
@ -2,11 +2,9 @@
|
|||||||
* tabs.js | https://theme-next.js.org/docs/tag-plugins/tabs
|
* tabs.js | https://theme-next.js.org/docs/tag-plugins/tabs
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* global hexo */
|
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
function postTabs(args, content) {
|
module.exports = ctx => function(args, content) {
|
||||||
const tabBlock = /<!--\s*tab (.*?)\s*-->\n([\w\W\s\S]*?)<!--\s*endtab\s*-->/g;
|
const tabBlock = /<!--\s*tab (.*?)\s*-->\n([\w\W\s\S]*?)<!--\s*endtab\s*-->/g;
|
||||||
|
|
||||||
args = args.join(' ').split(',');
|
args = args.join(' ').split(',');
|
||||||
@ -19,7 +17,7 @@ function postTabs(args, content) {
|
|||||||
let tabNav = '';
|
let tabNav = '';
|
||||||
let tabContent = '';
|
let tabContent = '';
|
||||||
|
|
||||||
if (!tabName) hexo.log.warn('Tabs block must have unique name!');
|
if (!tabName) ctx.log.warn('Tabs block must have unique name!');
|
||||||
|
|
||||||
while ((match = tabBlock.exec(content)) !== null) {
|
while ((match = tabBlock.exec(content)) !== null) {
|
||||||
matches.push(match[1]);
|
matches.push(match[1]);
|
||||||
@ -30,7 +28,7 @@ function postTabs(args, content) {
|
|||||||
let [caption = '', icon = ''] = matches[i].split('@');
|
let [caption = '', icon = ''] = matches[i].split('@');
|
||||||
let postContent = matches[i + 1];
|
let postContent = matches[i + 1];
|
||||||
|
|
||||||
postContent = hexo.render.renderSync({text: postContent, engine: 'markdown'}).trim();
|
postContent = ctx.render.renderSync({ text: postContent, engine: 'markdown' }).trim();
|
||||||
|
|
||||||
const abbr = tabName + ' ' + ++tabId;
|
const abbr = tabName + ' ' + ++tabId;
|
||||||
const href = abbr.toLowerCase().split(' ').join('-');
|
const href = abbr.toLowerCase().split(' ').join('-');
|
||||||
@ -52,8 +50,4 @@ function postTabs(args, content) {
|
|||||||
tabContent = `<div class="tab-content">${tabContent}</div>`;
|
tabContent = `<div class="tab-content">${tabContent}</div>`;
|
||||||
|
|
||||||
return `<div class="tabs" id="${tabName.toLowerCase().split(' ').join('-')}">${tabNav + tabContent}</div>`;
|
return `<div class="tabs" id="${tabName.toLowerCase().split(' ').join('-')}">${tabNav + tabContent}</div>`;
|
||||||
}
|
};
|
||||||
|
|
||||||
hexo.extend.tag.register('tabs', postTabs, {ends: true});
|
|
||||||
hexo.extend.tag.register('subtabs', postTabs, {ends: true});
|
|
||||||
hexo.extend.tag.register('subsubtabs', postTabs, {ends: true});
|
|
||||||
|
|||||||
@ -2,12 +2,8 @@
|
|||||||
* video.js | https://theme-next.js.org/docs/tag-plugins/
|
* video.js | https://theme-next.js.org/docs/tag-plugins/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* global hexo */
|
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
function postVideo(args) {
|
module.exports = function(args) {
|
||||||
return `<video src="${args}" preload="metadata" controls playsinline poster="">Sorry, your browser does not support the video tag.</video>`;
|
return `<video src="${args}" preload="metadata" controls playsinline poster="">Sorry, your browser does not support the video tag.</video>`;
|
||||||
}
|
};
|
||||||
|
|
||||||
hexo.extend.tag.register('video', postVideo, {ends: false});
|
|
||||||
|
|||||||
86
test/helpers/font.js
Normal file
86
test/helpers/font.js
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
require('chai').should();
|
||||||
|
const Hexo = require('hexo');
|
||||||
|
const hexo = new Hexo();
|
||||||
|
|
||||||
|
const fontStyles = ':300,300italic,400,400italic,700,700italic';
|
||||||
|
const fontHost = '//fonts.googleapis.com';
|
||||||
|
|
||||||
|
describe('font', () => {
|
||||||
|
const nextFont = require('../../scripts/helpers/font').bind(hexo);
|
||||||
|
|
||||||
|
before(() => {
|
||||||
|
hexo.theme.font = {};
|
||||||
|
});
|
||||||
|
|
||||||
|
it('font disabled', () => {
|
||||||
|
hexo.theme.font.enable = false;
|
||||||
|
hexo.theme.font.title = {
|
||||||
|
family : 'Amatic SC',
|
||||||
|
external: true
|
||||||
|
};
|
||||||
|
nextFont().should.eql('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('no external font', () => {
|
||||||
|
hexo.theme.font.enable = true;
|
||||||
|
hexo.theme.font.title = {
|
||||||
|
family : 'Amatic SC',
|
||||||
|
external: false
|
||||||
|
};
|
||||||
|
nextFont().should.eql('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('trivial', () => {
|
||||||
|
hexo.theme.font.enable = true;
|
||||||
|
hexo.theme.font.title = {
|
||||||
|
family : 'Amatic SC',
|
||||||
|
external: true
|
||||||
|
};
|
||||||
|
hexo.theme.font.headings = {
|
||||||
|
family : 'Palatino',
|
||||||
|
external: false
|
||||||
|
};
|
||||||
|
nextFont().should.eql(`<link rel="stylesheet" href="${fontHost}/css?family=Amatic+SC${fontStyles}&display=swap&subset=latin,latin-ext">`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('multiple', () => {
|
||||||
|
hexo.theme.font.enable = true;
|
||||||
|
hexo.theme.font.title = {
|
||||||
|
family : 'Amatic SC',
|
||||||
|
external: true
|
||||||
|
};
|
||||||
|
hexo.theme.font.headings = {
|
||||||
|
family : 'Palatino',
|
||||||
|
external: true
|
||||||
|
};
|
||||||
|
nextFont().should.eql(`<link rel="stylesheet" href="${fontHost}/css?family=Amatic+SC${fontStyles}|Palatino${fontStyles}&display=swap&subset=latin,latin-ext">`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('duplicate', () => {
|
||||||
|
hexo.theme.font.enable = true;
|
||||||
|
hexo.theme.font.title = {
|
||||||
|
family : 'Palatino',
|
||||||
|
external: true
|
||||||
|
};
|
||||||
|
hexo.theme.font.headings = {
|
||||||
|
family : 'Palatino',
|
||||||
|
external: true
|
||||||
|
};
|
||||||
|
nextFont().should.eql(`<link rel="stylesheet" href="${fontHost}/css?family=Palatino${fontStyles}&display=swap&subset=latin,latin-ext">`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fallback font', () => {
|
||||||
|
hexo.theme.font.enable = true;
|
||||||
|
hexo.theme.font.title = {
|
||||||
|
family : 'Roboto Slab, Noto Serif SC',
|
||||||
|
external: true
|
||||||
|
};
|
||||||
|
hexo.theme.font.headings = {
|
||||||
|
family : 'Palatino',
|
||||||
|
external: true
|
||||||
|
};
|
||||||
|
nextFont().should.eql(`<link rel="stylesheet" href="${fontHost}/css?family=Roboto+Slab${fontStyles}|Noto+Serif+SC${fontStyles}|Palatino${fontStyles}&display=swap&subset=latin,latin-ext">`);
|
||||||
|
});
|
||||||
|
});
|
||||||
6
test/helpers/index.js
Normal file
6
test/helpers/index.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
describe('Helpers', () => {
|
||||||
|
require('./font');
|
||||||
|
require('./next-url');
|
||||||
|
});
|
||||||
40
test/helpers/next-url.js
Normal file
40
test/helpers/next-url.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
require('chai').should();
|
||||||
|
const Hexo = require('hexo');
|
||||||
|
const hexo = new Hexo();
|
||||||
|
|
||||||
|
function btoa(str) {
|
||||||
|
return Buffer.from(str).toString('base64');
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('next-url', () => {
|
||||||
|
const nextUrl = require('../../scripts/helpers/next-url').bind(hexo);
|
||||||
|
|
||||||
|
before(() => {
|
||||||
|
hexo.config.url = 'https://example.com';
|
||||||
|
hexo.url_for = require('hexo/lib/plugins/helper/url_for').bind(hexo);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('text', () => {
|
||||||
|
nextUrl('/child/', 'Text').should.eql('<a href="/child/">Text</a>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('icon', () => {
|
||||||
|
nextUrl('/child/', '<i class="fab fa-fort-awesome"></i>').should.eql('<a href="/child/"><i class="fab fa-fort-awesome"></i></a>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('class', () => {
|
||||||
|
nextUrl('/child/', 'Text', { class: 'theme-link' }).should.eql('<a href="/child/" class="theme-link">Text</a>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('external', () => {
|
||||||
|
nextUrl('https://theme-next.js.org', 'Text').should.eql('<a href="https://theme-next.js.org/" rel="noopener" target="_blank">Text</a>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('exturl enabled', () => {
|
||||||
|
hexo.theme.exturl = true;
|
||||||
|
const encoded = btoa('https://theme-next.js.org');
|
||||||
|
nextUrl('https://theme-next.js.org', 'Text').should.eql(`<span class="exturl" data-url="${encoded}">Text</span>`);
|
||||||
|
});
|
||||||
|
});
|
||||||
7
test/index.js
vendored
Normal file
7
test/index.js
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
describe('NexT', () => {
|
||||||
|
require('./helpers');
|
||||||
|
require('./tags');
|
||||||
|
require('./validate');
|
||||||
|
});
|
||||||
33
test/tags/button.js
Normal file
33
test/tags/button.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
require('chai').should();
|
||||||
|
const Hexo = require('hexo');
|
||||||
|
const hexo = new Hexo();
|
||||||
|
|
||||||
|
describe('button', () => {
|
||||||
|
const postButton = require('../../scripts/tags/button')(hexo);
|
||||||
|
|
||||||
|
it('only url', () => {
|
||||||
|
postButton(['#']).should.eql('<a class="btn" href="#"></a>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('url and text', () => {
|
||||||
|
postButton('#, Hello world'.split(' ')).should.eql('<a class="btn" href="#">Hello world</a>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('url and icon (Font Awesome 4)', () => {
|
||||||
|
postButton('#,, home fa-5x'.split(' ')).should.eql('<a class="btn" href="#"><i class="fa fa-home fa-5x"></i></a>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('url and icon', () => {
|
||||||
|
postButton('#,, fab fa-fort-awesome fa-5x'.split(' ')).should.eql('<a class="btn" href="#"><i class="fab fa-fort-awesome fa-5x"></i></a>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('url, text and title', () => {
|
||||||
|
postButton('#, Hello world,, Title'.split(' ')).should.eql('<a class="btn" href="#" title="Title">Hello world</a>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('url, text, icon and title', () => {
|
||||||
|
postButton('#, Hello world, home, Title'.split(' ')).should.eql('<a class="btn" href="#" title="Title"><i class="fa fa-home"></i>Hello world</a>');
|
||||||
|
});
|
||||||
|
});
|
||||||
17
test/tags/caniuse.js
Normal file
17
test/tags/caniuse.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
require('chai').should();
|
||||||
|
const Hexo = require('hexo');
|
||||||
|
const hexo = new Hexo();
|
||||||
|
|
||||||
|
describe('caniuse', () => {
|
||||||
|
const caniUse = require('../../scripts/tags/caniuse')(hexo);
|
||||||
|
|
||||||
|
it('only feature', () => {
|
||||||
|
caniUse(['loading-lazy-attr']).should.eql('<iframe data-feature="loading-lazy-attr" src="https://caniuse.bitsofco.de/embed/index.html?feat=loading-lazy-attr&periods=current&accessible-colours=false" frameborder="0" width="100%" height="400px"></iframe>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('feature and periods', () => {
|
||||||
|
caniUse('fetch @ future_3,future_2,future_1'.split(' ')).should.eql('<iframe data-feature="fetch" src="https://caniuse.bitsofco.de/embed/index.html?feat=fetch&periods=future_3,future_2,future_1&accessible-colours=false" frameborder="0" width="100%" height="400px"></iframe>');
|
||||||
|
});
|
||||||
|
});
|
||||||
21
test/tags/center-quote.js
Normal file
21
test/tags/center-quote.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
require('chai').should();
|
||||||
|
const Hexo = require('hexo');
|
||||||
|
const hexo = new Hexo();
|
||||||
|
|
||||||
|
const content = 'Test **Bold** *Italic*';
|
||||||
|
const result = '<p>Test <strong>Bold</strong> <em>Italic</em></p>';
|
||||||
|
|
||||||
|
describe('center-quote', () => {
|
||||||
|
const centerQuote = require('../../scripts/tags/center-quote')(hexo);
|
||||||
|
|
||||||
|
before(() => hexo.init().then(() => hexo.loadPlugin(require.resolve('hexo-renderer-marked'))));
|
||||||
|
|
||||||
|
it('markdown content', () => {
|
||||||
|
centerQuote([], content).should.eql(`<blockquote class="blockquote-center">
|
||||||
|
${result}
|
||||||
|
|
||||||
|
</blockquote>`);
|
||||||
|
});
|
||||||
|
});
|
||||||
45
test/tags/group-pictures.js
Normal file
45
test/tags/group-pictures.js
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
require('chai').should();
|
||||||
|
const Hexo = require('hexo');
|
||||||
|
const hexo = new Hexo();
|
||||||
|
|
||||||
|
describe('group-pictures', () => {
|
||||||
|
const groupPicture = require('../../scripts/tags/group-pictures')(hexo);
|
||||||
|
|
||||||
|
before(() => hexo.init().then(() => hexo.loadPlugin(require.resolve('hexo-renderer-marked'))));
|
||||||
|
|
||||||
|
it('layout 3-1', () => {
|
||||||
|
groupPicture(['3-1'], `
|
||||||
|

|
||||||
|

|
||||||
|
`).should.eql('<div class="group-picture"><div class="group-picture-row"><div class="group-picture-column" style="width: 33.333333333333336%;"><img src="/images/sample.png"></div><div class="group-picture-column" style="width: 33.333333333333336%;"><img src="/images/sample.png"></div><div class="group-picture-column" style="width: 33.333333333333336%;"><img src="/images/sample.png"></div></div></div>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('layout 5-2', () => {
|
||||||
|
groupPicture(['5-2'], `
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
`).should.eql('<div class="group-picture"><div class="group-picture-row"><div class="group-picture-column" style="width: 50%;"><img src="/images/sample.png"></div><div class="group-picture-column" style="width: 50%;"><img src="/images/sample.png"></div></div><div class="group-picture-row"><div class="group-picture-column" style="width: 100%;"><img src="/images/sample.png"></div></div><div class="group-picture-row"><div class="group-picture-column" style="width: 50%;"><img src="/images/sample.png"></div><div class="group-picture-column" style="width: 50%;"><img src="/images/sample.png"></div></div></div>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('remove text', () => {
|
||||||
|
groupPicture(['3-1'], `
|
||||||
|

|
||||||
|
Text
|
||||||
|

|
||||||
|
Text
|
||||||
|
`).should.eql('<div class="group-picture"><div class="group-picture-row"><div class="group-picture-column" style="width: 33.333333333333336%;"><img src="/images/sample.png"></div><div class="group-picture-column" style="width: 33.333333333333336%;"><img src="/images/sample.png"></div><div class="group-picture-column" style="width: 33.333333333333336%;"><img src="/images/sample.png"></div></div></div>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('no layout', () => {
|
||||||
|
groupPicture(['NaN-NaN'], `
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
`).should.eql('<div class="group-picture"><div class="group-picture-row"><div class="group-picture-column" style="width: 33.333333333333336%;"><img src="/images/sample.png"></div><div class="group-picture-column" style="width: 33.333333333333336%;"><img src="/images/sample.png"></div><div class="group-picture-column" style="width: 33.333333333333336%;"><img src="/images/sample.png"></div></div><div class="group-picture-row"><div class="group-picture-column" style="width: 50%;"><img src="/images/sample.png"></div><div class="group-picture-column" style="width: 50%;"><img src="/images/sample.png"></div></div></div>');
|
||||||
|
});
|
||||||
|
});
|
||||||
15
test/tags/index.js
Normal file
15
test/tags/index.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
describe('Tags', () => {
|
||||||
|
require('./button');
|
||||||
|
require('./caniuse');
|
||||||
|
require('./center-quote');
|
||||||
|
require('./group-pictures');
|
||||||
|
require('./label');
|
||||||
|
require('./link-grid');
|
||||||
|
require('./mermaid');
|
||||||
|
require('./note');
|
||||||
|
require('./pdf');
|
||||||
|
require('./tabs');
|
||||||
|
require('./video');
|
||||||
|
});
|
||||||
17
test/tags/label.js
Normal file
17
test/tags/label.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
require('chai').should();
|
||||||
|
const Hexo = require('hexo');
|
||||||
|
const hexo = new Hexo();
|
||||||
|
|
||||||
|
describe('label', () => {
|
||||||
|
const postLabel = require('../../scripts/tags/label')(hexo);
|
||||||
|
|
||||||
|
it('only text', () => {
|
||||||
|
postLabel('@Hello world'.split(' ')).should.eql('<mark class="label default">Hello world</mark>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('classes and text', () => {
|
||||||
|
postLabel('primary@Hello world'.split(' ')).should.eql('<mark class="label primary">Hello world</mark>');
|
||||||
|
});
|
||||||
|
});
|
||||||
49
test/tags/link-grid.js
Normal file
49
test/tags/link-grid.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
require('chai').should();
|
||||||
|
|
||||||
|
const result = `<div class="link-grid"><div class="link-grid-container">
|
||||||
|
<div class="link-grid-image" style="background-image: url(/images/sample.png);"></div>
|
||||||
|
<p>Theme NexT</p><p>Stay Simple. Stay NexT.</p>
|
||||||
|
<a href="https://theme-next.js.org/"></a>
|
||||||
|
</div><div class="link-grid-container">
|
||||||
|
<div class="link-grid-image" style="background-image: url(/images/sample.png);"></div>
|
||||||
|
<p>Theme NexT</p><p>Stay Simple. Stay NexT.</p>
|
||||||
|
<a href="https://theme-next.js.org/"></a>
|
||||||
|
</div></div>`;
|
||||||
|
|
||||||
|
describe('link-grid', () => {
|
||||||
|
const linkGrid = require('../../scripts/tags/link-grid');
|
||||||
|
|
||||||
|
it('default', () => {
|
||||||
|
linkGrid([], `
|
||||||
|
Theme NexT | https://theme-next.js.org/ | Stay Simple. Stay NexT. | /images/sample.png
|
||||||
|
Theme NexT | https://theme-next.js.org/ | Stay Simple. Stay NexT. | /images/sample.png`).should.eql(result);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('comment', () => {
|
||||||
|
linkGrid([], `
|
||||||
|
Theme NexT | https://theme-next.js.org/ | Stay Simple. Stay NexT. | /images/sample.png
|
||||||
|
Theme NexT | https://theme-next.js.org/ | Stay Simple. Stay NexT. | /images/sample.png
|
||||||
|
% Theme NexT | https://theme-next.js.org/ | Stay Simple. Stay NexT. | /images/sample.png`).should.eql(result);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('default image', () => {
|
||||||
|
linkGrid(['/images/sample.png'], `
|
||||||
|
Theme NexT | https://theme-next.js.org/ | Stay Simple. Stay NexT. |
|
||||||
|
Theme NexT | https://theme-next.js.org/ | Stay Simple. Stay NexT. |`).should.eql(result);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('custom delimiter', () => {
|
||||||
|
linkGrid(['/images/sample.png', ','], `
|
||||||
|
Theme NexT , https://theme-next.js.org/ , Stay Simple. Stay NexT. , /images/sample.png
|
||||||
|
Theme NexT , https://theme-next.js.org/ , Stay Simple. Stay NexT. , /images/sample.png`).should.eql(result);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('custom delimiter and comment', () => {
|
||||||
|
linkGrid(['/images/sample.png', ',', '#'], `
|
||||||
|
Theme NexT , https://theme-next.js.org/ , Stay Simple. Stay NexT. , /images/sample.png
|
||||||
|
Theme NexT , https://theme-next.js.org/ , Stay Simple. Stay NexT. , /images/sample.png
|
||||||
|
# Theme NexT , https://theme-next.js.org/ , Stay Simple. Stay NexT. , /images/sample.png`).should.eql(result);
|
||||||
|
});
|
||||||
|
});
|
||||||
19
test/tags/mermaid.js
Normal file
19
test/tags/mermaid.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
require('chai').should();
|
||||||
|
|
||||||
|
const result = `A[Hard] -->|Text| B(Round)
|
||||||
|
B --> C{Decision}
|
||||||
|
C -->|One| D[Result 1]
|
||||||
|
C -->|Two| E[Result 2]`;
|
||||||
|
|
||||||
|
describe('mermaid', () => {
|
||||||
|
const mermaid = require('../../scripts/tags/mermaid');
|
||||||
|
|
||||||
|
it('default', () => {
|
||||||
|
mermaid(['graph', 'TD'], result).should.eql(`<pre class="mermaid" style="text-align: center;">
|
||||||
|
graph TD
|
||||||
|
${result}
|
||||||
|
</pre>`);
|
||||||
|
});
|
||||||
|
});
|
||||||
55
test/tags/note.js
Normal file
55
test/tags/note.js
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
require('chai').should();
|
||||||
|
const Hexo = require('hexo');
|
||||||
|
const hexo = new Hexo();
|
||||||
|
|
||||||
|
const content = 'Test **Bold** *Italic*';
|
||||||
|
const result = '<p>Test <strong>Bold</strong> <em>Italic</em></p>';
|
||||||
|
const args = 'This is a *summary*'.split(' ');
|
||||||
|
const summary = '<summary><p>This is a <em>summary</em>';
|
||||||
|
|
||||||
|
describe('note', () => {
|
||||||
|
const postNote = require('../../scripts/tags/note')(hexo);
|
||||||
|
|
||||||
|
before(() => hexo.init().then(() => hexo.loadPlugin(require.resolve('hexo-renderer-marked'))));
|
||||||
|
|
||||||
|
it('only text', () => {
|
||||||
|
postNote([], content).should.eql(`<div class="note ">${result}
|
||||||
|
</div>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('classes and text', () => {
|
||||||
|
postNote(['primary'], content).should.eql(`<div class="note primary">${result}
|
||||||
|
</div>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('classes, no-icon and text', () => {
|
||||||
|
postNote(['primary', 'no-icon'], content).should.eql(`<div class="note primary no-icon">${result}
|
||||||
|
</div>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('summary and text', () => {
|
||||||
|
postNote(args, content).should.eql(`<details class="note ">${summary}</p>
|
||||||
|
</summary>
|
||||||
|
${result}
|
||||||
|
|
||||||
|
</details>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('classes, summary and text', () => {
|
||||||
|
postNote(['primary'].concat(args), content).should.eql(`<details class="note primary">${summary}</p>
|
||||||
|
</summary>
|
||||||
|
${result}
|
||||||
|
|
||||||
|
</details>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('classes, no-icon, summary and text', () => {
|
||||||
|
postNote(['primary', 'no-icon'].concat(args), content).should.eql(`<details class="note primary no-icon">${summary}</p>
|
||||||
|
</summary>
|
||||||
|
${result}
|
||||||
|
|
||||||
|
</details>`);
|
||||||
|
});
|
||||||
|
});
|
||||||
23
test/tags/pdf.js
Normal file
23
test/tags/pdf.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
require('chai').should();
|
||||||
|
const Hexo = require('hexo');
|
||||||
|
const hexo = new Hexo();
|
||||||
|
|
||||||
|
describe('pdf', () => {
|
||||||
|
const pdf = require('../../scripts/tags/pdf')(hexo);
|
||||||
|
|
||||||
|
before(() => {
|
||||||
|
hexo.theme.config.pdf = {
|
||||||
|
height: '500px'
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
it('default', () => {
|
||||||
|
pdf(['https://example.com/sample.pdf']).should.eql('<div class="pdfobject-container" data-target="https://example.com/sample.pdf" data-height="500px"></div>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('custom height', () => {
|
||||||
|
pdf(['https://example.com/sample.pdf', '1000px']).should.eql('<div class="pdfobject-container" data-target="https://example.com/sample.pdf" data-height="1000px"></div>');
|
||||||
|
});
|
||||||
|
});
|
||||||
96
test/tags/tabs.js
Normal file
96
test/tags/tabs.js
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
require('chai').should();
|
||||||
|
const Hexo = require('hexo');
|
||||||
|
const hexo = new Hexo();
|
||||||
|
|
||||||
|
const content = 'Test **Bold** *Italic*';
|
||||||
|
const result = '<p>Test <strong>Bold</strong> <em>Italic</em></p>';
|
||||||
|
const container = '<div class="tabs" id="name"><ul class="nav-tabs">';
|
||||||
|
|
||||||
|
describe('tabs', () => {
|
||||||
|
const postTabs = require('../../scripts/tags/tabs')(hexo);
|
||||||
|
|
||||||
|
before(() => hexo.init().then(() => hexo.loadPlugin(require.resolve('hexo-renderer-marked'))));
|
||||||
|
|
||||||
|
it('empty', () => {
|
||||||
|
postTabs(['name']).should.eql(`${container}</ul><div class="tab-content"></div></div>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('default', () => {
|
||||||
|
postTabs(['name'],
|
||||||
|
`<!-- tab -->
|
||||||
|
${content}
|
||||||
|
<!-- endtab -->
|
||||||
|
|
||||||
|
<!-- tab -->
|
||||||
|
${content}
|
||||||
|
<!-- endtab -->`).should.eql(`${container}<li class="tab active"><a href="#name-1">name 1</a></li><li class="tab"><a href="#name-2">name 2</a></li></ul><div class="tab-content"><div class="tab-pane active" id="name-1">${result}</div><div class="tab-pane" id="name-2">${result}</div></div></div>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('selected index', () => {
|
||||||
|
postTabs('name, 2'.split(' '),
|
||||||
|
`<!-- tab -->
|
||||||
|
${content}
|
||||||
|
<!-- endtab -->
|
||||||
|
|
||||||
|
<!-- tab -->
|
||||||
|
${content}
|
||||||
|
<!-- endtab -->`).should.eql(`${container}<li class="tab"><a href="#name-1">name 1</a></li><li class="tab active"><a href="#name-2">name 2</a></li></ul><div class="tab-content"><div class="tab-pane" id="name-1">${result}</div><div class="tab-pane active" id="name-2">${result}</div></div></div>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('no tab selected', () => {
|
||||||
|
postTabs('name, -1'.split(' '),
|
||||||
|
`<!-- tab -->
|
||||||
|
${content}
|
||||||
|
<!-- endtab -->
|
||||||
|
|
||||||
|
<!-- tab -->
|
||||||
|
${content}
|
||||||
|
<!-- endtab -->`).should.eql(`${container}<li class="tab"><a href="#name-1">name 1</a></li><li class="tab"><a href="#name-2">name 2</a></li></ul><div class="tab-content"><div class="tab-pane" id="name-1">${result}</div><div class="tab-pane" id="name-2">${result}</div></div></div>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('label', () => {
|
||||||
|
postTabs('name'.split(' '),
|
||||||
|
`<!-- tab Tab 1 -->
|
||||||
|
${content}
|
||||||
|
<!-- endtab -->
|
||||||
|
|
||||||
|
<!-- tab Tab 2 -->
|
||||||
|
${content}
|
||||||
|
<!-- endtab -->`).should.eql(`${container}<li class="tab active"><a href="#name-1">Tab 1</a></li><li class="tab"><a href="#name-2">Tab 2</a></li></ul><div class="tab-content"><div class="tab-pane active" id="name-1">${result}</div><div class="tab-pane" id="name-2">${result}</div></div></div>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('icon (Font Awesome 4)', () => {
|
||||||
|
postTabs('name'.split(' '),
|
||||||
|
`<!-- tab @home -->
|
||||||
|
${content}
|
||||||
|
<!-- endtab -->
|
||||||
|
|
||||||
|
<!-- tab @home -->
|
||||||
|
${content}
|
||||||
|
<!-- endtab -->`).should.eql(`${container}<li class="tab active"><a href="#name-1"><i class="fa fa-home"></i></a></li><li class="tab"><a href="#name-2"><i class="fa fa-home"></i></a></li></ul><div class="tab-content"><div class="tab-pane active" id="name-1">${result}</div><div class="tab-pane" id="name-2">${result}</div></div></div>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('icon', () => {
|
||||||
|
postTabs('name'.split(' '),
|
||||||
|
`<!-- tab @fab fa-fort-awesome -->
|
||||||
|
${content}
|
||||||
|
<!-- endtab -->
|
||||||
|
|
||||||
|
<!-- tab @fab fa-fort-awesome -->
|
||||||
|
${content}
|
||||||
|
<!-- endtab -->`).should.eql(`${container}<li class="tab active"><a href="#name-1"><i class="fab fa-fort-awesome"></i></a></li><li class="tab"><a href="#name-2"><i class="fab fa-fort-awesome"></i></a></li></ul><div class="tab-content"><div class="tab-pane active" id="name-1">${result}</div><div class="tab-pane" id="name-2">${result}</div></div></div>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('label and icon', () => {
|
||||||
|
postTabs('name, -1'.split(' '),
|
||||||
|
`<!-- tab Tab 1@home -->
|
||||||
|
${content}
|
||||||
|
<!-- endtab -->
|
||||||
|
|
||||||
|
<!-- tab Tab 1@home -->
|
||||||
|
${content}
|
||||||
|
<!-- endtab -->`).should.eql(`${container}<li class="tab"><a href="#name-1"><i class="fa fa-home"></i>Tab 1</a></li><li class="tab"><a href="#name-2"><i class="fa fa-home"></i>Tab 1</a></li></ul><div class="tab-content"><div class="tab-pane" id="name-1">${result}</div><div class="tab-pane" id="name-2">${result}</div></div></div>`);
|
||||||
|
});
|
||||||
|
});
|
||||||
11
test/tags/video.js
Normal file
11
test/tags/video.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
require('chai').should();
|
||||||
|
|
||||||
|
describe('video', () => {
|
||||||
|
const postVideo = require('../../scripts/tags/video');
|
||||||
|
|
||||||
|
it('default', () => {
|
||||||
|
postVideo(['https://example.com/sample.mp4']).should.eql('<video src="https://example.com/sample.mp4" preload="metadata" controls playsinline poster="">Sorry, your browser does not support the video tag.</video>');
|
||||||
|
});
|
||||||
|
});
|
||||||
28
test/validate/index.js
Normal file
28
test/validate/index.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const yaml = require('js-yaml');
|
||||||
|
const should = require('chai').should();
|
||||||
|
|
||||||
|
describe('Validate', () => {
|
||||||
|
it('config', () => {
|
||||||
|
const themeConfig = fs.readFileSync(path.join(__dirname, '../../_config.yml'));
|
||||||
|
should.not.throw(() => {
|
||||||
|
yaml.safeLoad(themeConfig);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('language', () => {
|
||||||
|
const languagesPath = path.join(__dirname, '../../languages');
|
||||||
|
should.not.throw(() => {
|
||||||
|
fs.readdirSync(languagesPath).forEach(lang => {
|
||||||
|
if (!lang.endsWith('.yml')) return;
|
||||||
|
const languagePath = path.join(languagesPath, lang);
|
||||||
|
yaml.safeLoad(fs.readFileSync(languagePath), {
|
||||||
|
filename: path.relative(__dirname, languagePath)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
x
Reference in New Issue
Block a user