hexo-theme-stellar 1.32.3 → 1.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/_config.yml +27 -7
- package/_data/icons.yml +9 -2
- package/languages/en.yml +1 -0
- package/languages/zh-CN.yml +1 -0
- package/languages/zh-TW.yml +1 -0
- package/layout/_partial/comments/artalk/script.ejs +8 -7
- package/layout/_partial/head.ejs +7 -5
- package/layout/_partial/main/article/article_footer.ejs +8 -0
- package/layout/_partial/main/article/contributors.ejs +34 -0
- package/layout/_partial/main/article/read_next.ejs +2 -2
- package/layout/_partial/main/navbar/article_banner.ejs +1 -1
- package/layout/_partial/main/navbar/breadcrumb/blog.ejs +3 -3
- package/layout/_partial/main/navbar/breadcrumb/note.ejs +2 -2
- package/layout/_partial/main/navbar/breadcrumb/page.ejs +1 -1
- package/layout/_partial/main/navbar/breadcrumb/wiki.ejs +2 -2
- package/layout/_partial/main/navbar/dateinfo.ejs +1 -1
- package/layout/_partial/main/navbar/ghinfo.ejs +1 -1
- package/layout/_partial/main/navbar/nav_tabs_blog.ejs +12 -12
- package/layout/_partial/main/navbar/nav_tabs_wiki.ejs +2 -2
- package/layout/_partial/main/notebook/note_tags.ejs +1 -1
- package/layout/_partial/scripts/lazyload.ejs +1 -1
- package/layout/_partial/scripts/utils.ejs +69 -37
- package/layout/_partial/sidebar/index_leftbar.ejs +1 -1
- package/layout/_partial/sidebar/logo.ejs +1 -1
- package/layout/_partial/sidebar/menu.ejs +1 -1
- package/layout/_partial/widgets/components/link.ejs +1 -1
- package/layout/_partial/widgets/ghissues.ejs +7 -1
- package/layout/_partial/widgets/ghrepo.ejs +2 -2
- package/layout/_partial/widgets/ghuser.ejs +1 -1
- package/layout/_partial/widgets/recent.ejs +1 -1
- package/layout/_partial/widgets/related.ejs +2 -2
- package/layout/_partial/widgets/tagtree.ejs +1 -1
- package/layout/_partial/widgets/timeline.ejs +7 -1
- package/layout/_partial/widgets/toc.ejs +1 -3
- package/layout/_partial/widgets/tree.ejs +1 -1
- package/layout/archive.ejs +1 -1
- package/layout/categories.ejs +1 -1
- package/layout/index.ejs +1 -1
- package/layout/index_topic.ejs +1 -1
- package/layout/index_wiki.ejs +2 -2
- package/layout/notebooks.ejs +1 -1
- package/layout/notes.ejs +1 -1
- package/layout/tags.ejs +1 -1
- package/package.json +1 -1
- package/scripts/events/index.js +1 -1
- package/scripts/events/lib/config.js +7 -1
- package/scripts/filters/pretty_urls.js +25 -0
- package/scripts/generators/notebooks.js +27 -26
- package/scripts/helpers/json_ld.js +5 -4
- package/scripts/helpers/pretty_url.js +22 -0
- package/scripts/tags/index.js +2 -0
- package/scripts/tags/lib/albums.js +1 -1
- package/scripts/tags/lib/chat.js +1 -1
- package/scripts/tags/lib/friends.js +1 -1
- package/scripts/tags/lib/link.js +1 -1
- package/scripts/tags/lib/posters.js +1 -1
- package/scripts/tags/lib/rating.js +32 -0
- package/scripts/tags/lib/sites.js +1 -1
- package/scripts/tags/lib/timeline.js +2 -1
- package/scripts/tags/lib/vote.js +28 -0
- package/source/css/_common/button.styl +1 -0
- package/source/css/_common/loading.styl +1 -0
- package/source/css/_components/pages/article-story.styl +2 -0
- package/source/css/_components/partial/article-footer.styl +48 -0
- package/source/css/_components/partial/paginator.styl +1 -1
- package/source/css/_components/tag-plugins/friends.styl +1 -1
- package/source/css/_components/tag-plugins/image.styl +1 -0
- package/source/css/_components/tag-plugins/rating.styl +39 -0
- package/source/css/_components/tag-plugins/timeline.styl +7 -4
- package/source/css/_components/tag-plugins/vote.styl +49 -0
- package/source/css/_components/widgets/timeline.styl +1 -1
- package/source/css/_defines/theme_base.styl +1 -0
- package/source/css/_plugins/comments/artalk.styl +53 -10
- package/source/css/_plugins/lazyload.styl +4 -0
- package/source/js/main.js +12 -5
- package/source/js/search/local-search.js +3 -1
- package/source/js/services/artalk_latest_comment.js +1 -1
- package/source/js/services/contributors.js +56 -0
- package/source/js/services/fcircle.js +1 -1
- package/source/js/services/friends.js +1 -1
- package/source/js/services/friends_and_posts.js +1 -1
- package/source/js/services/ghinfo.js +1 -1
- package/source/js/services/giscus_latest_comment.js +1 -1
- package/source/js/services/memos.js +1 -1
- package/source/js/services/rating.js +142 -0
- package/source/js/services/siteinfo.js +1 -1
- package/source/js/services/sites.js +1 -1
- package/source/js/services/timeline.js +1 -1
- package/source/js/services/twikoo_latest_comment.js +1 -1
- package/source/js/services/vote.js +113 -0
- package/source/js/services/waline_latest_comment.js +1 -1
- package/source/js/services/weibo.js +1 -1
- package/layout/_partial/widgets/components/edit.ejs +0 -24
|
@@ -27,7 +27,13 @@ function layoutDiv() {
|
|
|
27
27
|
}
|
|
28
28
|
el += '<div class="widget-body fs14">';
|
|
29
29
|
el += '<div class="tag-plugin timeline data-service ds-timeline"';
|
|
30
|
-
|
|
30
|
+
// dataset
|
|
31
|
+
['api'].forEach(key => {
|
|
32
|
+
if (item[key]) {
|
|
33
|
+
el += ' data-' + key + '="' + item[key] + '"';
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
['user'].forEach(key => {
|
|
31
37
|
if (item[key]) {
|
|
32
38
|
el += ' ' + key + '="' + item[key] + '"';
|
|
33
39
|
}
|
|
@@ -19,7 +19,7 @@ function layoutDiv() {
|
|
|
19
19
|
el += `<widget class="widget-wrapper${scrollreveal(' ')} ghrepo">`
|
|
20
20
|
// body
|
|
21
21
|
el += '<div class="widget-body">';
|
|
22
|
-
el += '<div class="items data-service ds-ghinfo" api="https://' + theme.api_host.ghapi + '/repos/' + repo + '">';
|
|
22
|
+
el += '<div class="items data-service ds-ghinfo" data-api="https://' + theme.api_host.ghapi + '/repos/' + repo + '">';
|
|
23
23
|
el += '<a class="repo" href="https://github.com/' + repo + '" target="_blank" rel="external nofollow noopener noreferrer">';
|
|
24
24
|
el += '<div class="repo-name flex-row">';
|
|
25
25
|
el += icon('github:repo')
|
|
@@ -35,7 +35,7 @@ function layoutDiv() {
|
|
|
35
35
|
el += icon('github:fork')
|
|
36
36
|
el += '<span type="text" id="forks_count"></span>';
|
|
37
37
|
el += '</div>';
|
|
38
|
-
el += '<div class="flex-row data-service ds-ghinfo" index="0" api="https://' + theme.api_host.ghapi + '/repos/' + repo + '/tags">';
|
|
38
|
+
el += '<div class="flex-row data-service ds-ghinfo" index="0" data-api="https://' + theme.api_host.ghapi + '/repos/' + repo + '/tags">';
|
|
39
39
|
el += icon('github:tag')
|
|
40
40
|
el += '<span type="text" id="latest-tag-name">0</span>';
|
|
41
41
|
el += '</div>';
|
|
@@ -24,7 +24,7 @@ function layoutDiv() {
|
|
|
24
24
|
|
|
25
25
|
el += `<widget class="widget-wrapper${scrollreveal(' ')} user-card ghuser">`
|
|
26
26
|
// body
|
|
27
|
-
el += '<div class="widget-body data-service ds-ghinfo" api="https://' + theme.api_host.ghapi + '/users/' + item.username + '">';
|
|
27
|
+
el += '<div class="widget-body data-service ds-ghinfo" data-api="https://' + theme.api_host.ghapi + '/users/' + item.username + '">';
|
|
28
28
|
if (item.avatar) {
|
|
29
29
|
el += '<div class="avatar" ><img no-lazy type="img" id="avatar_url" src="' + config.avatar + '"></div>';
|
|
30
30
|
}
|
|
@@ -34,7 +34,7 @@ function layoutDiv() {
|
|
|
34
34
|
arr.length = item.limit
|
|
35
35
|
arr.forEach(post => {
|
|
36
36
|
if (!post) { return }
|
|
37
|
-
el += `<a class="item title" href="${
|
|
37
|
+
el += `<a class="item title" href="${pretty_url(post.link || post.path)}">`
|
|
38
38
|
el += '<span class="title">'
|
|
39
39
|
if (post.wiki) {
|
|
40
40
|
const proj = theme.wiki.tree[post.wiki];
|
|
@@ -15,7 +15,7 @@ function relatedPostsInTopic() {
|
|
|
15
15
|
el += `<div class="widget-body">`
|
|
16
16
|
for (let post of topic.pages) {
|
|
17
17
|
const isActive = post.path == page.path
|
|
18
|
-
el += `<a class="item${isActive ? ' active' : ''}" href="${
|
|
18
|
+
el += `<a class="item${isActive ? ' active' : ''}" href="${pretty_url(post.path)}">`
|
|
19
19
|
el += `<span class="title">${post.title}</span>`
|
|
20
20
|
if (isActive) {
|
|
21
21
|
el += icon('default:bookmark.active')
|
|
@@ -42,7 +42,7 @@ function relatedWiki() {
|
|
|
42
42
|
for (let id of relatedItem.items) {
|
|
43
43
|
// 同一个分组中的其它项目
|
|
44
44
|
let item = theme.wiki.tree[id]
|
|
45
|
-
el += `<a class="item wiki" href="${
|
|
45
|
+
el += `<a class="item wiki" href="${pretty_url(item.homepage?.path)}">`
|
|
46
46
|
el += `<span class="title">${item.title}</span>`
|
|
47
47
|
if (item.description && item.description.length > 0) {
|
|
48
48
|
el += `<span class="excerpt">${item.description}</span>`
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
<% function layoutTag(tag, level) { %>
|
|
11
11
|
<% const active = page.activeTag === tag.id %>
|
|
12
|
-
<a class="link<%= active ? ' active' : '' %>" href="<%=
|
|
12
|
+
<a class="link<%= active ? ' active' : '' %>" href="<%= pretty_url(tag.path) %>">
|
|
13
13
|
<span class="toc-text"<% if (level > 0) { %> style="padding-left: <%= level * 0.875 %>rem;"<% } %>>
|
|
14
14
|
<% if (tag.id === '') { %>
|
|
15
15
|
<%= __('meta.all_notes') %>
|
|
@@ -12,7 +12,13 @@ function layoutDiv() {
|
|
|
12
12
|
}
|
|
13
13
|
el += '<div class="widget-body fs14">';
|
|
14
14
|
el += `<div class="tag-plugin timeline data-service ds-${(item.type || 'timeline')}"`;
|
|
15
|
-
|
|
15
|
+
// dataset
|
|
16
|
+
['api'].forEach(key => {
|
|
17
|
+
if (item[key]) {
|
|
18
|
+
el += ' data-' + key + '="' + item[key] + '"';
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
['user', 'hide', 'limit'].forEach(key => {
|
|
16
22
|
if (item[key]) {
|
|
17
23
|
el += ' ' + key + '="' + item[key] + '"';
|
|
18
24
|
}
|
|
@@ -36,9 +36,8 @@ function layoutToc(fallback) {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
function layoutDiv(fallback) {
|
|
39
|
-
const editBtn = partial('components/edit', {map: item.edit_this_page})
|
|
40
39
|
const tocBody = layoutTocBody()
|
|
41
|
-
if (tocBody.trim().length == 0
|
|
40
|
+
if (tocBody.trim().length == 0) {
|
|
42
41
|
return ''
|
|
43
42
|
}
|
|
44
43
|
var el = ''
|
|
@@ -50,7 +49,6 @@ function layoutDiv(fallback) {
|
|
|
50
49
|
el += `</div>`
|
|
51
50
|
}
|
|
52
51
|
el += `<div class="widget-footer">`
|
|
53
|
-
el += editBtn
|
|
54
52
|
el += `<a class="top" onclick="util.scrollTop()">`
|
|
55
53
|
el += icon('default:upup')
|
|
56
54
|
el += `<span>${__('btn.top')}</span>`
|
package/layout/archive.ejs
CHANGED
|
@@ -39,7 +39,7 @@ function layoutArchiveList() {
|
|
|
39
39
|
return post.year == year
|
|
40
40
|
}).each(function(post) {
|
|
41
41
|
el += `<div class="archive-list">`
|
|
42
|
-
el +=`<a class='post fs14' href="${
|
|
42
|
+
el +=`<a class='post fs14' href="${pretty_url(post.link || post.path)}">`
|
|
43
43
|
el += `<time>${date(post.date, 'MM-DD')}</time>`
|
|
44
44
|
el += `<span>`
|
|
45
45
|
if (post.title) {
|
package/layout/categories.ejs
CHANGED
|
@@ -12,7 +12,7 @@ if (page.menu_id == undefined) {
|
|
|
12
12
|
<article class='<%- scrollreveal("") %>' id='cats'>
|
|
13
13
|
<% site.categories.sort('path').each(function(category){ %>
|
|
14
14
|
<div>
|
|
15
|
-
<a class="<%= category.parent ? 'cat child' : 'cat'%>" href="<%=
|
|
15
|
+
<a class="<%= category.parent ? 'cat child' : 'cat'%>" href="<%= pretty_url(category.path) %>">
|
|
16
16
|
<span class='name'><%- icon('default:category') %><%- category.name %></span>
|
|
17
17
|
<span class='badge'>(<%- category.posts.length %>)</span>
|
|
18
18
|
</a>
|
package/layout/index.ejs
CHANGED
|
@@ -12,7 +12,7 @@ function layout_post_card(layout, post, content) {
|
|
|
12
12
|
if (layout == 'post' && post.cover != undefined && post.poster != undefined) {
|
|
13
13
|
layout += ' photo';
|
|
14
14
|
}
|
|
15
|
-
el += `<a class="post-card${scrollreveal(' ')} ${layout}" href="${
|
|
15
|
+
el += `<a class="post-card${scrollreveal(' ')} ${layout}" href="${pretty_url(post.link || post.path)}">`
|
|
16
16
|
el += content;
|
|
17
17
|
el += '</a>';
|
|
18
18
|
return el;
|
package/layout/index_topic.ejs
CHANGED
|
@@ -8,7 +8,7 @@ function layout_topic_list(partial) {
|
|
|
8
8
|
continue
|
|
9
9
|
}
|
|
10
10
|
el += `<div class="post-list wiki topic">`
|
|
11
|
-
el += `<a class="post-card wiki topic${scrollreveal(' ')}" href="${
|
|
11
|
+
el += `<a class="post-card wiki topic${scrollreveal(' ')}" href="${pretty_url(topic.homepage?.path || '/')}">`
|
|
12
12
|
el += partial(topic)
|
|
13
13
|
el += `</a>`
|
|
14
14
|
el += `</div>`
|
package/layout/index_wiki.ejs
CHANGED
|
@@ -13,14 +13,14 @@ function layout_wiki_list(partial) {
|
|
|
13
13
|
if (page.filter === false) {
|
|
14
14
|
// wikiList
|
|
15
15
|
el += `<div class="post-list wiki">`
|
|
16
|
-
el += `<a class="post-card wiki${scrollreveal(' ')}" href="${
|
|
16
|
+
el += `<a class="post-card wiki${scrollreveal(' ')}" href="${pretty_url(proj.homepage?.path || '/')}">`
|
|
17
17
|
el += partial(proj)
|
|
18
18
|
el += `</a>`
|
|
19
19
|
el += `</div>`
|
|
20
20
|
} else if (proj.tags && proj.tags.includes(page.tagName) === true) {
|
|
21
21
|
// filtered wikiList
|
|
22
22
|
el += `<div class="post-list wiki filter">`
|
|
23
|
-
el += `<a class="post-card wiki${scrollreveal(' ')}" href="${
|
|
23
|
+
el += `<a class="post-card wiki${scrollreveal(' ')}" href="${pretty_url(proj.homepage?.path || '/')}">`
|
|
24
24
|
el += partial(proj)
|
|
25
25
|
el += `</a>`
|
|
26
26
|
el += `</div>`
|
package/layout/notebooks.ejs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<%# 笔记本列表页主体部分 %>
|
|
2
2
|
<% for (const notebook of Object.values(theme.notebooks.tree)) { %>
|
|
3
3
|
<div class="post-list wiki">
|
|
4
|
-
<a class="post-card wiki<%= scrollreveal(' ') %>" href="<%=
|
|
4
|
+
<a class="post-card wiki<%= scrollreveal(' ') %>" href="<%= pretty_url(notebook.base_dir) %>">
|
|
5
5
|
<%- include('_partial/main/notebook/notebook_card', { notebook: notebook }) %>
|
|
6
6
|
</a>
|
|
7
7
|
</div>
|
package/layout/notes.ejs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<% page.posts.each(post => { %>
|
|
4
4
|
<a
|
|
5
5
|
class="post-card<%= scrollreveal(' ') %> post"
|
|
6
|
-
href="<%=
|
|
6
|
+
href="<%= pretty_url(post.link || post.path) %><%= page.activeTag ? `?tag=${page.activeTag}` : '' %>"
|
|
7
7
|
>
|
|
8
8
|
<%- include('_partial/main/notebook/note_card', { note: post }) %>
|
|
9
9
|
</a>
|
package/layout/tags.ejs
CHANGED
|
@@ -11,7 +11,7 @@ if (page.menu_id == undefined) {
|
|
|
11
11
|
<div class='post-list'>
|
|
12
12
|
<article class='<%- scrollreveal("") %>' id='tags'>
|
|
13
13
|
<% site.tags.sort('length', -1).each(function(tag){ %>
|
|
14
|
-
<a class='tag' href="<%=
|
|
14
|
+
<a class='tag' href="<%= pretty_url(tag.path) %>">
|
|
15
15
|
<span class='name'><%= tag.name %></span>
|
|
16
16
|
</a>
|
|
17
17
|
<% }) %>
|
package/package.json
CHANGED
package/scripts/events/index.js
CHANGED
|
@@ -53,7 +53,7 @@ hexo.extend.filter.register('before_generate', async () => {
|
|
|
53
53
|
hasRun = true;
|
|
54
54
|
|
|
55
55
|
// 读取主题配置开关
|
|
56
|
-
const enabled = hexo.theme.config.
|
|
56
|
+
const enabled = hexo.theme.config.dependencies.lazyload?.fix_ratio === true;
|
|
57
57
|
|
|
58
58
|
const generateImageRatios = require('./lib/get_image_ratios');
|
|
59
59
|
const fixMarkdownImages = require('./lib/fix_image_tags');
|
|
@@ -11,11 +11,17 @@ const path = require('path')
|
|
|
11
11
|
|
|
12
12
|
module.exports = ctx => {
|
|
13
13
|
|
|
14
|
-
const { cache, language_switcher } = ctx.theme.config
|
|
14
|
+
const { cache, language_switcher, system } = ctx.theme.config
|
|
15
15
|
const warning = function(...args) {
|
|
16
16
|
ctx.log.warn(`Since ${args[0]} is turned on, the ${args[1]} is disabled to avoid potential hazards.`)
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
if (system.override_pretty_urls !== false) {
|
|
20
|
+
// 强制修改 pretty_urls 配置项
|
|
21
|
+
ctx.config.pretty_urls.trailing_index = false
|
|
22
|
+
ctx.config.pretty_urls.trailing_html = false
|
|
23
|
+
}
|
|
24
|
+
|
|
19
25
|
if (cache && cache.enable && language_switcher) {
|
|
20
26
|
warning('language_switcher', 'caching')
|
|
21
27
|
cache.enable = false
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// scripts/override-page-generator.js
|
|
2
|
+
|
|
3
|
+
hexo.extend.generator.register('page', function (locals) {
|
|
4
|
+
return locals.pages.map(page => {
|
|
5
|
+
const path = (
|
|
6
|
+
page.path.endsWith('.html') && !page.path.endsWith('/index.html')
|
|
7
|
+
)
|
|
8
|
+
? page.path.replace(/\.html$/, '/index.html')
|
|
9
|
+
: page.path;
|
|
10
|
+
|
|
11
|
+
const layout = (
|
|
12
|
+
page.layout === false ||
|
|
13
|
+
page.layout === 'false' ||
|
|
14
|
+
typeof page.layout === 'undefined'
|
|
15
|
+
) ? false : page.layout;
|
|
16
|
+
|
|
17
|
+
const isRawOutput = /\.(txt|json|xml|js|css)$/.test(path);
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
path,
|
|
21
|
+
layout,
|
|
22
|
+
data: isRawOutput ? page.content : page
|
|
23
|
+
};
|
|
24
|
+
});
|
|
25
|
+
});
|
|
@@ -1,38 +1,39 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* notebooks v1
|
|
3
3
|
*/
|
|
4
|
-
const pagination = require('hexo-pagination')
|
|
5
|
-
|
|
6
|
-
function paginationWithEmpty(base, posts, options={}) {
|
|
7
|
-
const { layout, data = {} } = options
|
|
8
|
-
if (posts.length === 0) {
|
|
9
|
-
base = `${base}/`
|
|
10
|
-
return [{
|
|
11
|
-
path: base,
|
|
12
|
-
layout: layout,
|
|
13
|
-
data: {
|
|
14
|
-
...data,
|
|
15
|
-
base: base,
|
|
16
|
-
total: 1,
|
|
17
|
-
current: 1,
|
|
18
|
-
current_url: base,
|
|
19
|
-
posts: posts,
|
|
20
|
-
prev: 0,
|
|
21
|
-
prev_link: '',
|
|
22
|
-
next: 0,
|
|
23
|
-
next_link: '',
|
|
24
|
-
}
|
|
25
|
-
}]
|
|
26
|
-
} else {
|
|
27
|
-
return pagination(base, posts, options)
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
4
|
|
|
31
5
|
hexo.extend.generator.register('notebooks', function (locals) {
|
|
32
6
|
const { site_tree, notebooks } = hexo.theme.config
|
|
33
7
|
if (!notebooks?.tree || Object.keys(notebooks.tree).length === 0) {
|
|
34
8
|
return []
|
|
35
9
|
}
|
|
10
|
+
// 不用 blog 和 notebooks 时不必依赖 hexo-pagination
|
|
11
|
+
const pagination = require('hexo-pagination')
|
|
12
|
+
|
|
13
|
+
function paginationWithEmpty(base, posts, options={}) {
|
|
14
|
+
const { layout, data = {} } = options
|
|
15
|
+
if (posts.length === 0) {
|
|
16
|
+
base = `${base}/`
|
|
17
|
+
return [{
|
|
18
|
+
path: base,
|
|
19
|
+
layout: layout,
|
|
20
|
+
data: {
|
|
21
|
+
...data,
|
|
22
|
+
base: base,
|
|
23
|
+
total: 1,
|
|
24
|
+
current: 1,
|
|
25
|
+
current_url: base,
|
|
26
|
+
posts: posts,
|
|
27
|
+
prev: 0,
|
|
28
|
+
prev_link: '',
|
|
29
|
+
next: 0,
|
|
30
|
+
next_link: '',
|
|
31
|
+
}
|
|
32
|
+
}]
|
|
33
|
+
} else {
|
|
34
|
+
return pagination(base, posts, options)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
36
37
|
|
|
37
38
|
const routes = []
|
|
38
39
|
|
|
@@ -13,6 +13,7 @@ hexo.extend.helper.register('json_ld', function(args) {
|
|
|
13
13
|
const structured_data = this.theme.structured_data;
|
|
14
14
|
const authorEmail = config.email;
|
|
15
15
|
const authorImage = config.avatar || (authorEmail ? this.gravatar(authorEmail) : null);
|
|
16
|
+
const isPage = page.layout == 'page';
|
|
16
17
|
|
|
17
18
|
const author = {
|
|
18
19
|
'@type': 'Person',
|
|
@@ -45,10 +46,10 @@ hexo.extend.helper.register('json_ld', function(args) {
|
|
|
45
46
|
headline: page.title,
|
|
46
47
|
mainEntityOfPage: {
|
|
47
48
|
'@type': 'WebPage',
|
|
48
|
-
'@id': this.
|
|
49
|
+
'@id': this.pretty_url(page.permalink)
|
|
49
50
|
},
|
|
50
51
|
publisher,
|
|
51
|
-
url: this.
|
|
52
|
+
url: this.pretty_url(page.permalink)
|
|
52
53
|
};
|
|
53
54
|
|
|
54
55
|
if (page.tags && page.tags.length > 0) {
|
|
@@ -69,9 +70,9 @@ hexo.extend.helper.register('json_ld', function(args) {
|
|
|
69
70
|
schema.thumbnailUrl = page.cover || page.banner;
|
|
70
71
|
schema.image = images;
|
|
71
72
|
|
|
72
|
-
} else if (
|
|
73
|
+
} else if (isPage || this.is_home()) {
|
|
73
74
|
|
|
74
|
-
const url = this.is_home() ? config.url : this.
|
|
75
|
+
const url = this.is_home() ? config.url : this.pretty_url(page.permalink);
|
|
75
76
|
schema = {
|
|
76
77
|
'@context': 'https://schema.org',
|
|
77
78
|
'@type': 'Website',
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
hexo.extend.helper.register('pretty_url', function (path = '') {
|
|
4
|
+
let url = this.url_for(path);
|
|
5
|
+
|
|
6
|
+
// 替换 /index.html → /
|
|
7
|
+
url = url.replace(/\/index\.html$/, '/');
|
|
8
|
+
|
|
9
|
+
// 替换 /about.html → /about/
|
|
10
|
+
url = url.replace(/\.html$/, '/');
|
|
11
|
+
|
|
12
|
+
// 如果没有扩展名,并且不以 / 结尾,补一个 /
|
|
13
|
+
const hasExtension = /\.[a-zA-Z0-9]+$/.test(url);
|
|
14
|
+
if (!hasExtension && !url.endsWith('/')) {
|
|
15
|
+
url += '/';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// 去除多余斜杠(避免 // 出现,但保留://协议部分)
|
|
19
|
+
url = url.replace(/([^:]\/)\/+/g, '$1');
|
|
20
|
+
|
|
21
|
+
return url;
|
|
22
|
+
});
|
package/scripts/tags/index.js
CHANGED
|
@@ -45,6 +45,8 @@ hexo.extend.tag.register('hashtag', require('./lib/hashtag')(hexo))
|
|
|
45
45
|
hexo.extend.tag.register('okr', require('./lib/okr')(hexo), {ends: true})
|
|
46
46
|
hexo.extend.tag.register('audio', require('./lib/audio')(hexo))
|
|
47
47
|
hexo.extend.tag.register('video', require('./lib/video')(hexo))
|
|
48
|
+
hexo.extend.tag.register('rating', require('./lib/rating')(hexo))
|
|
49
|
+
hexo.extend.tag.register('vote', require('./lib/vote')(hexo))
|
|
48
50
|
|
|
49
51
|
// read 阅读类
|
|
50
52
|
hexo.extend.tag.register('reel', require('./lib/read/reel')(hexo), true)
|
|
@@ -23,7 +23,7 @@ module.exports = ctx => function(args) {
|
|
|
23
23
|
var el = ''
|
|
24
24
|
el += `<div class="tag-plugin albums-wrap">`
|
|
25
25
|
if (api) {
|
|
26
|
-
el += `<div class="data-service ds-friends" api="${api}"><div class="tag-plugin gallery grid-box" layout="grid" ratio="square" ${ctx.args.joinTags(args, ['size']).join(' ')}></div></div>`
|
|
26
|
+
el += `<div class="data-service ds-friends" data-api="${api}"><div class="tag-plugin gallery grid-box" layout="grid" ratio="square" ${ctx.args.joinTags(args, ['size']).join(' ')}></div></div>`
|
|
27
27
|
} else if (args.group) {
|
|
28
28
|
const links = ctx.theme.config.links || {}
|
|
29
29
|
el += `<div class="tag-plugin gallery grid-box" layout="grid" ratio="square" ${ctx.args.joinTags(args, ['size']).join(' ')}>`
|
package/scripts/tags/lib/chat.js
CHANGED
|
@@ -410,7 +410,7 @@ module.exports = ctx => function(args, content) {
|
|
|
410
410
|
let urlTarget = cell['link'].includes('://') ? ' target="_blank" rel="external nofollow noopener noreferrer"' : ''
|
|
411
411
|
let linkFrom = cell['from'] || 'QQ小程序'
|
|
412
412
|
el += `
|
|
413
|
-
<a class="link-card rich" href="${cell['link']}"${urlTarget} api="${ctx.theme.config.tag_plugins.chat?.api + '?url=' + cell['link']}" cardlink autofill="title,icon,desc">
|
|
413
|
+
<a class="link-card rich" href="${cell['link']}"${urlTarget} data-api="${ctx.theme.config.tag_plugins.chat?.api + '?url=' + cell['link']}" cardlink autofill="title,icon,desc">
|
|
414
414
|
<div class="top">
|
|
415
415
|
<span class="title">${cell['link']}</span>
|
|
416
416
|
</div>
|
|
@@ -19,7 +19,7 @@ module.exports = ctx => function(args) {
|
|
|
19
19
|
|
|
20
20
|
var el = `<div class="tag-plugin ${args.posts ? 'users-posts-wrap' : 'users-wrap'}">`
|
|
21
21
|
if (api) {
|
|
22
|
-
el += `<div class="data-service ds-friends${args.posts ? '_and_posts' : ''}" ${ctx.args.joinTags(args, ['size']).join(' ')} api="${api}"><div class="grid-box"></div></div>`
|
|
22
|
+
el += `<div class="data-service ds-friends${args.posts ? '_and_posts' : ''}" ${ctx.args.joinTags(args, ['size']).join(' ')} data-api="${api}"><div class="grid-box"></div></div>`
|
|
23
23
|
} else if (args.group) {
|
|
24
24
|
const links = ctx.theme.config.links || {}
|
|
25
25
|
el += '<div class="grid-box">'
|
package/scripts/tags/lib/link.js
CHANGED
|
@@ -23,7 +23,7 @@ module.exports = ctx => function(args) {
|
|
|
23
23
|
var el = ''
|
|
24
24
|
el += `<div class="tag-plugin posters-wrap">`
|
|
25
25
|
if (api) {
|
|
26
|
-
el += `<div class="data-service ds-friends" api="${api}"><div class="tag-plugin gallery grid-box" layout="grid" ratio="square" ${ctx.args.joinTags(args, ['size']).join(' ')}></div></div>`
|
|
26
|
+
el += `<div class="data-service ds-friends" data-api="${api}"><div class="tag-plugin gallery grid-box" layout="grid" ratio="square" ${ctx.args.joinTags(args, ['size']).join(' ')}></div></div>`
|
|
27
27
|
} else if (args.group) {
|
|
28
28
|
const links = ctx.theme.config.links || {}
|
|
29
29
|
el += `<div class="tag-plugin gallery grid-box" layout="grid" ratio="portrait" ${ctx.args.joinTags(args, ['size']).join(' ')}>`
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* rating.js v1.0 | https://github.com/xaoxuu/hexo-theme-stellar/
|
|
3
|
+
* 格式与官方标签插件一致使用空格分隔,中括号内的是可选参数(中括号不需要写出来)
|
|
4
|
+
*
|
|
5
|
+
* rating:
|
|
6
|
+
* {% rating id %}
|
|
7
|
+
*
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
'use strict'
|
|
11
|
+
|
|
12
|
+
module.exports = ctx => function (args) {
|
|
13
|
+
args = ctx.args.map(args, ['id', 'icon'], ['title'])
|
|
14
|
+
|
|
15
|
+
const api = ctx.theme.config.data_services.rating.api
|
|
16
|
+
const id = args.id || 'default'
|
|
17
|
+
|
|
18
|
+
const star = ctx.utils.icon(args.icon || 'rating:star')
|
|
19
|
+
let el = `<div class="tag-plugin ds-rating" data-api="${api}" data-api="${api}" data-id="${id}">`
|
|
20
|
+
if (args.title) {
|
|
21
|
+
el += `<div class="header"><span>${args.title}</span></div>`
|
|
22
|
+
}
|
|
23
|
+
el += `<div class="body">`
|
|
24
|
+
for (let i = 1; i <= 5; i++) {
|
|
25
|
+
el += `<button class="star" data-value="${i}">${star}</button>`
|
|
26
|
+
}
|
|
27
|
+
el += `<span class="avg">(0.0)</span>`
|
|
28
|
+
el += `</div>`
|
|
29
|
+
el += `<div class="footer"><span class="count">0</span><span class="suffix">人已评分</span></div>`
|
|
30
|
+
el += `</div>`
|
|
31
|
+
return el.trim()
|
|
32
|
+
}
|
|
@@ -20,7 +20,7 @@ module.exports = ctx => function(args) {
|
|
|
20
20
|
var el = '<div class="tag-plugin sites-wrap">'
|
|
21
21
|
if (api) {
|
|
22
22
|
el += '<div class="data-service ds-sites"'
|
|
23
|
-
el += ' api="' + api + '"'
|
|
23
|
+
el += ' data-api="' + api + '"'
|
|
24
24
|
el += '>'
|
|
25
25
|
el += '<div class="grid-box"></div>'
|
|
26
26
|
el += '</div>'
|
|
@@ -36,13 +36,14 @@ function layoutNodeContent(ctx, content) {
|
|
|
36
36
|
|
|
37
37
|
module.exports = ctx => function(args, content = '') {
|
|
38
38
|
args = ctx.args.map(args, ['api', 'user', 'type', 'limit', 'hide', 'avatar'])
|
|
39
|
+
args['data-api'] = args.api
|
|
39
40
|
var el = ''
|
|
40
41
|
if (!args.type) {
|
|
41
42
|
args.type = 'timeline'
|
|
42
43
|
}
|
|
43
44
|
if (args.api && args.api.length > 0) {
|
|
44
45
|
el += `<div class="tag-plugin timeline data-service ds-${args.type}"`
|
|
45
|
-
el += ' ' + ctx.args.joinTags(args, ['api', 'user', 'limit', 'hide', 'avatar']).join(' ')
|
|
46
|
+
el += ' ' + ctx.args.joinTags(args, ['data-api', 'user', 'limit', 'hide', 'avatar']).join(' ')
|
|
46
47
|
el += '>'
|
|
47
48
|
} else {
|
|
48
49
|
el += '<div class="tag-plugin timeline">'
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vote.js v1.0 | https://github.com/xaoxuu/hexo-theme-stellar/
|
|
3
|
+
* 格式与官方标签插件一致使用空格分隔,中括号内的是可选参数(中括号不需要写出来)
|
|
4
|
+
*
|
|
5
|
+
* vote:
|
|
6
|
+
* {% vote id %}
|
|
7
|
+
*
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
'use strict'
|
|
11
|
+
|
|
12
|
+
module.exports = ctx => function (args) {
|
|
13
|
+
args = ctx.args.map(args, ['id', 'yes', 'no'], ['title'])
|
|
14
|
+
|
|
15
|
+
const api = ctx.theme.config.data_services.vote.api
|
|
16
|
+
const id = args.id || 'default'
|
|
17
|
+
|
|
18
|
+
var el = `<div class="tag-plugin ds-vote" data-api="${api}" data-id="${id}">`
|
|
19
|
+
if (args.title) {
|
|
20
|
+
el += `<div class="header"><span>${args.title}</span></div>`
|
|
21
|
+
}
|
|
22
|
+
el += `<div class="body">`
|
|
23
|
+
el += `<button class="vote-up">${ctx.utils.icon(args.yes || 'vote:thumbsup')} <span class="up">0</span></button>`
|
|
24
|
+
el += `<button class="vote-down">${ctx.utils.icon(args.no || 'vote:thumbsdown')} <span class="down">0</span></button>`
|
|
25
|
+
el += `</div>`
|
|
26
|
+
el += `</div>`
|
|
27
|
+
return el.trim()
|
|
28
|
+
}
|
|
@@ -40,6 +40,54 @@
|
|
|
40
40
|
padding-top: 1rem
|
|
41
41
|
border-top: 1px solid var(--block-border)
|
|
42
42
|
|
|
43
|
+
.article-footer #contributors
|
|
44
|
+
.header
|
|
45
|
+
display: flex
|
|
46
|
+
justify-content: space-between
|
|
47
|
+
a.edit
|
|
48
|
+
font-size: $fs-14
|
|
49
|
+
display: flex
|
|
50
|
+
align-items: center
|
|
51
|
+
color: inherit
|
|
52
|
+
background: var(--block)
|
|
53
|
+
padding: 0 .5rem
|
|
54
|
+
border-radius: $border-button
|
|
55
|
+
svg
|
|
56
|
+
width 1.2em
|
|
57
|
+
height: 1.2em
|
|
58
|
+
margin-right: 4px
|
|
59
|
+
color: var(--text-p4)
|
|
60
|
+
trans1 color
|
|
61
|
+
span
|
|
62
|
+
line-height: 1.5
|
|
63
|
+
trans1 color
|
|
64
|
+
trans1 background
|
|
65
|
+
&:hover
|
|
66
|
+
color: var(--theme)
|
|
67
|
+
background: var(--theme-a20)
|
|
68
|
+
svg
|
|
69
|
+
color: var(--theme)
|
|
70
|
+
.body
|
|
71
|
+
.loading-wrap
|
|
72
|
+
margin-top: 4px
|
|
73
|
+
padding: 0
|
|
74
|
+
height: 84px
|
|
75
|
+
.users-wrap .grid-box
|
|
76
|
+
margin-top: 4px
|
|
77
|
+
grid-template-columns: repeat(auto-fill, minmax(72px, 1fr))
|
|
78
|
+
grid-gap: 4px
|
|
79
|
+
&:empty
|
|
80
|
+
display: none
|
|
81
|
+
.users-wrap .user-card .card-link
|
|
82
|
+
background: var(--block)
|
|
83
|
+
trans1 all
|
|
84
|
+
&:hover
|
|
85
|
+
background: var(--theme-a20)
|
|
86
|
+
color: var(--theme)
|
|
87
|
+
img
|
|
88
|
+
width 32px
|
|
89
|
+
height: 32px
|
|
90
|
+
|
|
43
91
|
.article-footer .social-wrap
|
|
44
92
|
grid-gap: 0.5rem 2rem
|
|
45
93
|
margin: 1rem 0 0.5rem
|