hexo-tag-plugins
Version:
A number of tag plugins for theme-butterfly
639 lines (567 loc) • 20.4 kB
JavaScript
const urlFor = require('hexo-util').url_for.bind(hexo)
hexo.extend.filter.register('after_generate', function (locals) {
// 首先获取整体的配置项名称
const config = hexo.config.tag_plugins || hexo.theme.config.tag_plugins
// 如果配置开启
if (!(config && config.enable)) return
// 集体声明配置项
const data = {
issues: config.issues ? config.issues : false,
animaCDN: config.CDN.anima ? urlFor(config.CDN.anima) : 'https://cdn.jsdelivr.net/gh/l-lin/font-awesome-animation/dist/font-awesome-animation.min.css',
jqueryCDN: config.CDN.jquery ? urlFor(config.CDN.jquery) : 'https://cdn.jsdelivr.net/npm/jquery@latest/dist/jquery.min.js',
issuesCDN: config.CDN.issues ? urlFor(config.CDN.issues) : 'https://cdn.jsdelivr.net/npm/hexo-theme-volantis@latest/source/js/issues.min.js',
iconfontCDN: config.CDN.iconfont,
carouselCDN: config.CDN.carousel ? urlFor(config.CDN.carousel) : 'https://cdn.jsdelivr.net/npm/hexo-tag-plugins@latest/lib/carousel-touch.min.js'
}
//cdn资源声明
//样式资源
//head引入资源
const css_text = `<link rel="stylesheet" href="${data.animaCDN}" media="defer" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/hexo-tag-plugins@latest/lib/tag_plugins.min.css" media="defer" onload="this.media='all'"><script src="${data.carouselCDN}"></script><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/hexo-tag-plugins@latest/lib/mindmap.min.css" media="defer" onload="this.media='all'">`
//bottom引入资源
const jq = `<script defer src="${data.jqueryCDN}"></script>`
const issues = `<script defer src="${data.issuesCDN}"></script>`
//iconfont symbol引入
const iconfont_symbol = `<script async src="${data.iconfontCDN}"></script>`
// 注入脚本资源
hexo.extend.injector.register('head_end', css_text, "default");
// 注入样式资源
// kity mindmap
const mindmap = `<script defer src="https://cdn.jsdelivr.net/npm/kity@2.0.4/dist/kity.min.js"></script><script defer src="https://cdn.jsdelivr.net/npm/kityminder-core@1.4.50/dist/kityminder.core.min.js"></script><script defer src="https://cdn.jsdelivr.net/npm/hexo-tag-plugins@latest/lib/mindmap.min.js"></script>`
hexo.extend.injector.register('body_end', jq, "default");
if (data.issues){
hexo.extend.injector.register('body_end', issues, "default");
}
hexo.extend.injector.register("body_end", mindmap, "default");
if (data.iconfontCDN){
hexo.extend.injector.register('body_end', iconfont_symbol, "default");
}
},
hexo.extend.helper.register('priority', function(){
// 过滤器优先级,priority 值越低,过滤器会越早执行,默认priority是10
const pre_priority = hexo.config.tag_plugins.priority ? hexo.config.tag_plugins.priority : hexo.theme.config.tag_plugins.priority
const priority = pre_priority ? pre_priority : 10
return priority
})
)
//btns.js
function postBtns(args, content) {
return `<div class="btns ${args.join(' ')}">
${content}
</div>`;
}
function postCell(args, content) {
args = args.join(' ').split(',')
let text = args[0] || ''
let url = args[1] || ''
text = text.trim()
url = url.trim()
if (url.length > 0) {
url = "href='" + url + "'"
}
let icon = ''
let img = 'https://cdn.jsdelivr.net/gh/volantis-x/cdn-volantis@3/img/placeholder/d570170f4f12e1ee829ca0e85a7dffeb77343a.svg'
if (args.length > 2) {
if (args[2].indexOf(' fa-') > -1) {
icon = args[2].trim()
} else {
img = args[2].trim()
}
}
if (icon.length > 0) {
return `<a class="button" ${url} title='${text}'><i class='${icon}'></i>${text}</a>`
} else {
return `<a class="button" ${url} title='${text}'><img src='${img}'>${text}</a>`
}
}
hexo.extend.tag.register('btns', postBtns, {ends: true});
hexo.extend.tag.register('cell', postCell);
//checkbos.js
function postCheckbox(args) {
args = args.join(' ').split(',')
var cls = ''
var text = ''
var checked = false
if (args.length > 1) {
cls = (args[0] || '').trim()
if (cls.length > 0) {
cls = ' ' + cls
}
if (cls.indexOf('checked') > -1) {
checked = true
}
text = (args[1] || '').trim()
} else if (args.length > 0) {
text = (args[0] || '').trim()
}
if (text.length > 0) {
return `<div class='checkbox${cls}'><input type="checkbox" ${ checked ? 'checked="checked"' : '' }/>
${hexo.render.renderSync({text: text, engine: 'markdown'}).split('\n').join('')}
</div>`
}
}
function postRadio(args) {
args = args.join(' ').split(',')
var cls = ''
var text = ''
var checked = false
if (args.length > 1) {
cls = (args[0] || '').trim()
if (cls.length > 0) {
cls = ' ' + cls
}
if (cls.indexOf('checked') > -1) {
checked = true
}
text = (args[1] || '').trim()
} else if (args.length > 0) {
text = (args[0] || '').trim()
}
if (text.length > 0) {
return `<div class='checkbox${cls}'><input type="radio" ${ checked ? 'checked="checked"' : '' }/>
${hexo.render.renderSync({text: text, engine: 'markdown'}).split('\n').join('')}
</div>`
}
}
// {% checkbox text %}
// {% checkbox checked, text %}
// {% checkbox color checked, text %}
hexo.extend.tag.register('checkbox', postCheckbox);
hexo.extend.tag.register('radio', postRadio);
//folding.js
function postFolding(args, content) {
args = args.join(' ').split(',');
let style = ''
let title = ''
if (args.length > 1) {
style = args[0].trim()
title = args[1].trim()
} else if (args.length > 0) {
title = args[0].trim()
}
if (style != undefined) {
return `<details ${style}><summary> ${title} </summary>
<div class='content'>
${hexo.render.renderSync({text: content, engine: 'markdown'}).split('\n').join('')}
</div>
</details>`;
} else {
return `<details><summary> ${title} </summary>
<div class='content'>
${hexo.render.renderSync({text: content, engine: 'markdown'}).split('\n').join('')}
</div>
</details>`;
}
}
hexo.extend.tag.register('folding', postFolding, {ends: true});
//ghbdage.js
/*{% bdage right,left,[logo]||[color],[link],[title]||option %}*/
function bdage (args) {
args = args.join(' ').split('||')
let base= args[0]?args[0].split(','):''
let right = base[0]?encodeURI(base[0].trim()):''
let left = base[1]?encodeURI(base[1].trim()):''
let logo = base[2]?base[2].trim():''
let message = args[1]?args[1].split(','):''
let color = message[0]?message[0].trim():'orange'
let link = message[1]?message[1].trim():''
let title = message[2]?message[2].trim():''
let option = args[2]?args[2].trim():''
return `<object class="ghbdage" style="margin-inline:5px" title="${title}" standby="loading..." data="https://img.shields.io/badge/${left}-${right}-orange?logo=${logo}&color=${color}&link=${link}&${option}"></object>`
}
hexo.extend.tag.register('bdage',bdage);
//ghcard.js
/**
* https://github.com/anuraghazra/github-readme-stats
*/
// {% ghcard volantis-x %}
// {% ghcard volantis-x/hexo-theme-volantis %}
hexo.extend.tag.register('ghcard', function(args) {
args = args.join(' ').split(', ');
let path = args[0].trim();
let card = '';
card += '<a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/' + path + '">';
let url = '';
if (path.includes('/')) {
// is repo
let ps = path.split('/');
url += 'https://github-readme-stats.vercel.app/api/pin/?username=' + ps[0] + "&repo=" + ps[1];
} else {
// is user
url += 'https://github-readme-stats.vercel.app/api/?username=' + path;
}
if (args.length > 1) {
for (let i = 1; i < args.length; i++) {
let tmp = args[i].trim();
url += "&" + tmp;
}
}
if (!url.includes('&show_owner=')) {
url += '&show_owner=true';
}
card += '<img src="' + url + '"/>';
card += '</a>';
return card;
});
hexo.extend.tag.register('ghcardgroup', function(args, content) {
let ret = '';
// wrap
ret += '<div class="ghcard-group">';
ret += content;
ret += '</div>';
return ret;
}, {ends: true});
//iconfont.js
function iconFont(args) {
args = args.join(' ').split(',')
let p0 = args[0]
let p1 = args[1]?args[1]:1
return `<svg class="icon" style="width:${p1}em; height:${p1}em" aria-hidden="true"><use xlink:href="#${p0}"></use></svg>`;
}
hexo.extend.tag.register('icon',iconFont);
//image.js
;
// {% image url %}
// {% image url, alt=haha %}
// {% image url, width=50% %}
// {% image url, height=32px %}
// {% image url, bg=#eee %}
// {% image url, alt=haha, width=400px %}
// {% image url, alt=haha, width=400px, bg=#eee %}
hexo.extend.tag.register('image', function(args) {
args = args.join(' ').split(', ');
let url = args[0].trim();
let alt = '';
let bg = '';
let style = '';
if (args.length > 1) {
for (let i = 1; i < args.length; i++) {
let tmp = args[i].trim();
if (tmp.includes('alt=')) {
alt = tmp.substring(4, tmp.length);
} else if (tmp.includes('width=')) {
style += 'width:' + tmp.substring(6, tmp.length) + ';';
} else if (tmp.includes('height=')) {
style += 'height:' + tmp.substring(7, tmp.length) + ';';
} else if (tmp.includes('bg=')) {
bg = tmp.substring(3, tmp.length);
}
}
}
function img(url, alt, style) {
let img = '';
img += '<img class="img" src="' + url + '"';
if (alt.length > 0) {
img += ' alt="' + alt + '"';
}
if (style.length > 0) {
img += ' style="' + style + '"';
}
img += '/>';
return img;
}
let ret = '';
// wrap
ret += '<div class="img-wrap">';
// bg
ret += '<div class="img-bg"';
if (bg.length > 0) {
ret += ' style="background:' + bg + '"';
}
ret += '>';
ret += img(url, alt, style);
ret += '</div>';
if (alt.length > 0) {
ret += '<span class="image-caption">' + alt + '</span>';
}
ret += '</div>';
return ret;
});
// {% inlineimage url %}
// {% inlineimage url, height=22px %}
hexo.extend.tag.register('inlineimage', function(args) {
args = args.join(' ').split(', ');
let url = args[0].trim();
let ret = '';
ret += '<img no-lazy class="inline" src="' + url + '"';
let style = '';
if (args.length > 1) {
for (let i = 1; i < args.length; i++) {
let tmp = args[i].trim();
if (tmp.includes('height=')) {
style += 'height:' + tmp.substring(7, tmp.length) + ';';
}
}
}
if (style.length > 0) {
ret += ' style="' + style + '"';
} else {
ret += ' style="height:1.5em"';
}
ret += '/>';
return ret;
});
//inline-labels.js
hexo.extend.tag.register('u', function(args) {
return `<u>${args.join(' ')}</u>`;
});
hexo.extend.tag.register('emp', function(args) {
return `<emp>${args.join(' ')}</emp>`;
});
hexo.extend.tag.register('wavy', function(args) {
return `<wavy>${args.join(' ')}</wavy>`;
});
hexo.extend.tag.register('del', function(args) {
return `<del>${args.join(' ')}</del>`;
});
hexo.extend.tag.register('kbd', function(args) {
return `<kbd>${args.join(' ')}</kbd>`;
});
hexo.extend.tag.register('psw', function(args) {
return `<psw>${args.join(' ')}</psw>`;
});
//issues.js
// 从 issues 加载动态数据
// {% issues sites/timeline/friends | api=xxx | group=key:a,b,c %}
// 例如:
// {% issues sites | api=https://api.github.com/repos/volantis-x/examples/issues?sort=updated&state=open&page=1&per_page=100 | group=version:latest,v6,v5,v4,v3,v2,v1,v0 %}
hexo.extend.tag.register('issues', function(args) {
args = args.join(' ').split(' | ');
// 所有支持的参数
let type = args[0].trim();
let api = '';
let group = '';
// 解析
if (args.length > 1) {
for (let i = 1; i < args.length; i++) {
let tmp = args[i].trim();
if (tmp.includes('type=')) {
type = tmp.substring(5, tmp.length);
} else if (tmp.includes('api=')) {
api = tmp.substring(4, tmp.length);
} else if (tmp.includes('group=')) {
group = tmp.substring(6, tmp.length);
}
}
}
if (type.length == 0 || api.length == 0) {
return;
}
// 布局
let ret = '<div class="issues-api ' + type + '"';
ret += 'api="' + api + '"';
if (group.length > 0) {
ret += 'group="' + group + '"';
}
ret += '></div>';
return ret;
});
//link.js
// {% link title, url %}
// {% link title, url, img %}
hexo.extend.tag.register('link', function(args) {
args = args.join(' ').split(',')
let text = ''
let url = ''
let img = ''
if (args.length < 2) {
return
} else if (args.length == 2) {
text = args[0].trim()
url = args[1].trim()
} else if (args.length == 3) {
text = args[0].trim()
url = args[1].trim()
img = args[2].trim()
}
let result = '';
// 发现如果不套一层 div 在其它可渲染 md 的容器中容易被分解
result += '<div class="tag link"><a class="link-card" title="' + text + '" href="' + url + '">';
// left
result += '<div class="left">';
result += '<img src="' + (img || hexo.theme.config.tag_plugins.link.placeholder) + '"/>';
result += '</div>';
// right
result += '<div class="right"><p class="text">' + text + '</p><p class="url">' + url + '</p></div>';
result += '</a></div>';
return result;
});
hexo.extend.tag.register('linkgroup', function(args, content) {
let ret = '';
ret += '<div class="link-group">';
ret += content;
ret += '</div>';
return ret;
}, {ends: true});
//media.js
function postAudio(args) {
let src = args[0].trim()
return `<div class="audio"><audio controls preload><source src='${src}' type='audio/mp3'>Your browser does not support the audio tag.</audio></div>`;
}
function postVideo(args) {
let src = args[0].trim()
return `<div class="video"><video controls preload><source src='${src}' type='video/mp4'>Your browser does not support the video tag.</video></div>`;
}
function postVideos(args, content) {
args = args.join(' ').split(',')
var cls = args[0]
if (cls.length > 0) {
cls = ' ' + cls
}
var col = Number(args[1]) || 0;
if (col > 0) {
return `<div class="videos${cls}" col='${col}'>${content}</div>`
} else {
return `<div class="videos${cls}">${content}</div>`
}
}
hexo.extend.tag.register('audio', postAudio);
hexo.extend.tag.register('video', postVideo);
hexo.extend.tag.register('videos', postVideos, {ends: true});
//notation.js
function Nota(args) {
args = args.join(' ').split(',')
let p0 = args[0].trim()
let p1 = args[1].trim()
return `<span class='nota' data-nota='${p1}'>${p0}</span>`;
}
hexo.extend.tag.register('nota', Nota);
// {% nota 注释词汇 ,'注释内容,使用逗号间隔开了即可' %}
//poem.js
function poem (args, content) {
args = args.join(' ').split(',')
let p0 = args[0]
let p1 = args[1]?args[1]:''
return `<div class='poem'><div class='poem-title'>${p0}</div><div class='poem-author'>${p1}</div>${hexo.render.renderSync({ text: content, engine: 'markdown' })}</div>`
}
hexo.extend.tag.register('poem',poem,{ ends: true });
//poem.js
function postprogress(args) {
args = args.join(',').split(',')
if (args.length > 1) {
let pwidth = args[0].trim()
let pcolor = args[1].trim()
let text = args[2].trim()
return `<div class="progress"><div class="progress-bar-animated progress-bar progress-bar-striped bg-${pcolor}" style="width: ${pwidth}%" aria-valuenow="${pwidth}" aria-valuemin="0" aria-valuemax="100">${hexo.render.renderSync({text: text, engine: 'markdown'}).split('\n').join('')}</div></div>`;
}
}
hexo.extend.tag.register('progress', postprogress);
//progress.js
function postprogress(args) {
args = args.join(',').split(',')
if (args.length > 1) {
let pwidth = args[0].trim()
let pcolor = args[1].trim()
let text = args[2].trim()
return `<div class="progress"><div class="progress-bar-animated progress-bar progress-bar-striped bg-${pcolor}" style="width: ${pwidth}%" aria-valuenow="${pwidth}" aria-valuemin="0" aria-valuemax="100">${hexo.render.renderSync({text: text, engine: 'markdown'}).split('\n').join('')}</div></div>`;
}
}
hexo.extend.tag.register('progress', postprogress);
//site.js
function postSiteCardGroup(args, content) {
if (args.length > 0) {
return `<div class="site-card-group"><p class='p h2'>${args}</p>${content}</div>`;
} else {
return `<div class="site-card-group">${content}</div>`;
}
}
function postSiteCard(args) {
args = args.join(' ').split(', ')
// 所有支持的参数
let title = args[0].trim();
let url = '';
let screenshot = '';
let avatar = '';
let description = '';
// 解析
if (args.length > 1) {
for (let i = 1; i < args.length; i++) {
let tmp = args[i].trim();
if (tmp.includes('url=')) {
url = tmp.substring(4, tmp.length);
} else if (tmp.includes('screenshot=')) {
screenshot = tmp.substring(11, tmp.length);
} else if (tmp.includes('avatar=')) {
avatar = tmp.substring(7, tmp.length);
} else if (tmp.includes('description=')) {
description = tmp.substring(12, tmp.length);
}
}
}
// 布局
let result = '';
result += '<a class="site-card" href="' + url + '">';
result += '<div class="img"><img src="' + screenshot + '"/></div>';
result += '<div class="info">';
if (avatar.length > 0) {
result += '<img src="' + avatar + '"/>';
} else {
}
result += '<span class="title">' + title + '</span>';
if (description.length > 0) {
result += '<span class="desc">' + description + '</span>';
} else {
}
result += '</div></a>';
return result;
}
// {% site link, img, title %}
// {% site link, img, title, description %}
hexo.extend.tag.register('site', postSiteCard);
hexo.extend.tag.register('sitegroup', postSiteCardGroup, {ends: true});
//span.js
function postP(args) {
args = args.join(' ').split(',')
let p0 = args[0].trim()
let p1 = args[1].trim()
return `<p class='p ${p0}'>${p1}</p>`;
}
function postSpan(args) {
args = args.join(' ').split(',')
let p0 = args[0].trim()
let p1 = args[1].trim()
return `<span class='p ${p0}'>${p1}</span>`;
}
hexo.extend.tag.register('p', postP);
hexo.extend.tag.register('span', postSpan);
//timeline.js
function postTimeline(args, content) {
if (args.length > 0) {
return `<div class="timeline"><p class='p h2'>${args}</p>${content}</div>`;
} else {
return `<div class="timeline">${content}</div>`;
}
}
function postTimenode(args, content) {
args = args.join(' ').split(',')
var time = args[0]
return `<div class="timenode"><div class="meta"><p>${hexo.render.renderSync({text: time, engine: 'markdown'})}</p></div><div class="body">${hexo.render.renderSync({text: content, engine: 'markdown'}).split('\n').join('')}</div></div>`;
}
// {% timeline %}
// ... timenode ...
// {% endtimeline %}
hexo.extend.tag.register('timeline', postTimeline, {ends: true});
// {% timenode time %}
// what happened
// {% endtimenode %}
hexo.extend.tag.register('timenode', postTimenode, {ends: true});
//tip.js
function tip (args, content) {
return `<div class="tip ${args.join(' ')}">${hexo.render.renderSync({ text: content, engine: 'markdown' })}</div>`
}
hexo.extend.tag.register('tip',tip, { ends: true })
//carousel.js
function carousel (args, content) {
args = args.join(' ').split(',')
let carouselId = args[0]
let carouselname = args[1]?args[1]:'carousel'
return `<div id='${carouselId}' class='carousel'><div id="${carouselId}-drag-container" class="drag-container"><div id="${carouselId}-spin-container" class="spin-container">${hexo.render.renderSync({ text: content, engine: 'markdown' }).replace(/^(\s|<p>)+|(\s|<\/p>)+$/g, '')}<p>${carouselname}</p></div><div id="${carouselId}-carousel-ground" class="carousel-ground"></div></div></div><script type="text/javascript">carouselinit('${carouselId}');</script>`
}
hexo.extend.tag.register('carousel',carousel,{ ends: true });
// mindmap
function mindmap(args, content){
let height = args[0] ? args[0] : 300;
return `<blockquote class="mindmap" style="height: ${height}px;contenteditable: true;">${hexo.render.renderSync({ text: content, engine: 'markdown' })}</blockquote>`
}
hexo.extend.tag.register('mindmap',mindmap,{ ends: true });