hexo-theme-gnix 1.1.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/README.md +106 -0
- package/include/hexo/filter/locals.js +109 -0
- package/include/hexo/generator/categories.js +12 -0
- package/include/hexo/generator/category.js +52 -0
- package/include/hexo/generator/insight.js +50 -0
- package/include/hexo/generator/manifest.js +23 -0
- package/include/hexo/generator/tags.js +12 -0
- package/include/hexo/helper/cdn.js +21 -0
- package/include/hexo/helper/page.js +27 -0
- package/include/hexo/view.js +40 -0
- package/include/register.js +11 -0
- package/include/util/common.js +33 -0
- package/languages/en.yml +47 -0
- package/languages/fr.yml +46 -0
- package/languages/ja.yml +46 -0
- package/languages/zh-CN.yml +47 -0
- package/languages/zh-TW.yml +47 -0
- package/layout/archive.jsx +118 -0
- package/layout/categories.jsx +137 -0
- package/layout/category.jsx +38 -0
- package/layout/comment/disqus.jsx +79 -0
- package/layout/comment/disqusjs.jsx +127 -0
- package/layout/comment/giscus.jsx +193 -0
- package/layout/comment/gitalk.jsx +141 -0
- package/layout/comment/twikoo.jsx +63 -0
- package/layout/comment/utterances.jsx +86 -0
- package/layout/comment/valine.jsx +143 -0
- package/layout/comment/waline.jsx +156 -0
- package/layout/common/article.jsx +131 -0
- package/layout/common/article_cover.jsx +33 -0
- package/layout/common/article_media.jsx +34 -0
- package/layout/common/comment.jsx +38 -0
- package/layout/common/footer.jsx +228 -0
- package/layout/common/head.jsx +242 -0
- package/layout/common/navbar.jsx +219 -0
- package/layout/common/plugins.jsx +39 -0
- package/layout/common/scripts.jsx +49 -0
- package/layout/common/search.jsx +22 -0
- package/layout/common/theme_selector.jsx +79 -0
- package/layout/common/toc.jsx +53 -0
- package/layout/index.jsx +29 -0
- package/layout/layout.jsx +34 -0
- package/layout/misc/article_licensing.jsx +114 -0
- package/layout/misc/meta.jsx +61 -0
- package/layout/misc/open_graph.jsx +164 -0
- package/layout/misc/paginator.jsx +90 -0
- package/layout/misc/structured_data.jsx +110 -0
- package/layout/misc/web_app.jsx +106 -0
- package/layout/page.jsx +12 -0
- package/layout/plugin/bing_webmaster.jsx +47 -0
- package/layout/plugin/busuanzi.jsx +40 -0
- package/layout/plugin/clarity.jsx +22 -0
- package/layout/plugin/cookie_consent.jsx +136 -0
- package/layout/plugin/google_analytics.jsx +66 -0
- package/layout/plugin/google_tag_mamager.jsx +41 -0
- package/layout/plugin/netlify.jsx +39 -0
- package/layout/plugin/pjax.jsx +20 -0
- package/layout/plugin/statcounter.jsx +69 -0
- package/layout/plugin/twitter_conversion_tracking.jsx +51 -0
- package/layout/post.jsx +16 -0
- package/layout/search/insight.jsx +53 -0
- package/layout/tag.jsx +29 -0
- package/layout/tags.jsx +55 -0
- package/package.json +42 -0
- package/scripts/index.js +1 -0
- package/source/css/callout_blocks.css +204 -0
- package/source/css/default.css +1590 -0
- package/source/css/font/woff2/Futura-Book.woff2 +0 -0
- package/source/css/font/woff2/Paris2024-Variable.woff2 +0 -0
- package/source/css/font/woff2/doto.woff2 +0 -0
- package/source/css/optional/chinese.css +17 -0
- package/source/css/responsive/desktop.css +164 -0
- package/source/css/responsive/mobile.css +46 -0
- package/source/css/responsive/tablet.css +46 -0
- package/source/css/responsive/touch.css +254 -0
- package/source/css/shiki/shiki.min.css +1 -0
- package/source/css/twikoo.css +2143 -0
- package/source/img/avatar.webp +0 -0
- package/source/img/background.webp +0 -0
- package/source/img/favicon.svg +6 -0
- package/source/img/logo.svg +9 -0
- package/source/img/og_image.png +0 -0
- package/source/js/busuanzi.js +46 -0
- package/source/js/host/cookieconsent/3.1.1/build/cookieconsent.min.css +6 -0
- package/source/js/host/cookieconsent/3.1.1/build/cookieconsent.min.js +1 -0
- package/source/js/host/iconify-icon/3.0.2/iconify-icon.min.js +12 -0
- package/source/js/host/medium-zoom/dist/medium-zoom.min.js +2 -0
- package/source/js/host/mermaid/mermaid.min.js +2811 -0
- package/source/js/host/pjax/0.2.8/pjax.min.js +1 -0
- package/source/js/host/twikoo/1.6.41/dist/twikoo.all.min.js +2 -0
- package/source/js/insight.js +330 -0
- package/source/js/instant-page.min.js +1 -0
- package/source/js/live2d_Asoul/Model/Ava/Ava.4096/texture_00.webp +0 -0
- package/source/js/live2d_Asoul/Model/Ava/Ava.moc3 +0 -0
- package/source/js/live2d_Asoul/Model/Ava/Ava.model3.json +323 -0
- package/source/js/live2d_Asoul/Model/Ava/Ava.physics3.json +1225 -0
- package/source/js/live2d_Asoul/Model/Ava/motions/Ava_idle.motion3.json +1 -0
- package/source/js/live2d_Asoul/Model/Ava/motions/Ava_shake01.motion3.json +1 -0
- package/source/js/live2d_Asoul/Model/Ava/motions/Ava_shake02.motion3.json +1 -0
- package/source/js/live2d_Asoul/Model/Ava/motions/Ava_tap01.motion3.json +1 -0
- package/source/js/live2d_Asoul/Model/Ava/motions/Ava_tap02.motion3.json +1 -0
- package/source/js/live2d_Asoul/Model/Ava/motions/Ava_tap03.motion3.json +1 -0
- package/source/js/live2d_Asoul/Model/Ava/motions/Ava_tap04.motion3.json +1 -0
- package/source/js/live2d_Asoul/Model/Ava/motions/Ava_tap05.motion3.json +1 -0
- package/source/js/live2d_Asoul/Model/Ava/motions/Ava_tap06.motion3.json +1 -0
- package/source/js/live2d_Asoul/Model/Ava/motions/Ava_tap07.motion3.json +1 -0
- package/source/js/live2d_Asoul/Model/Ava/motions/Ava_tap08.motion3.json +1 -0
- package/source/js/live2d_Asoul/Model/Ava/motions/Ava_tap09.motion3.json +1 -0
- package/source/js/live2d_Asoul/Model/Ava/motions/Ava_tap10.motion3.json +1 -0
- package/source/js/live2d_Asoul/Model/Ava/motions/Ava_tap11.motion3.json +1 -0
- package/source/js/live2d_Asoul/Model/Ava/raw.ex.json +16 -0
- package/source/js/live2d_Asoul/Model/Ava/raw.model3.json +321 -0
- package/source/js/live2d_Asoul/Model/Diana/Diana.4096/texture_00.webp +0 -0
- package/source/js/live2d_Asoul/Model/Diana/Diana.moc3 +0 -0
- package/source/js/live2d_Asoul/Model/Diana/Diana.model3.json +212 -0
- package/source/js/live2d_Asoul/Model/Diana/Diana.physics3.json +764 -0
- package/source/js/live2d_Asoul/Model/Diana/motions/Diana_idle.motion3.json +1 -0
- package/source/js/live2d_Asoul/Model/Diana/motions/Diana_tap01.motion3.json +1 -0
- package/source/js/live2d_Asoul/Model/Diana/motions/Diana_tap02.motion3.json +1 -0
- package/source/js/live2d_Asoul/Model/Diana/motions/Diana_tap03.motion3.json +1 -0
- package/source/js/live2d_Asoul/Model/Diana/motions/Diana_tap04.motion3.json +1 -0
- package/source/js/live2d_Asoul/Model/Diana/motions/Diana_tap05.motion3.json +1 -0
- package/source/js/live2d_Asoul/Model/Diana/motions/Diana_tap06.motion3.json +1 -0
- package/source/js/live2d_Asoul/Model/Diana/motions/Diana_tap07.motion3.json +1 -0
- package/source/js/live2d_Asoul/Model/Diana/motions/Diana_tap08.motion3.json +1 -0
- package/source/js/live2d_Asoul/Model/Diana/motions/Diana_tap09.motion3.json +1 -0
- package/source/js/live2d_Asoul/Model/Diana/motions/Diana_tap10.motion3.json +1 -0
- package/source/js/live2d_Asoul/Model/Diana/motions/Diana_tap11.motion3.json +1 -0
- package/source/js/live2d_Asoul/Model/Diana/raw.ex.json +16 -0
- package/source/js/live2d_Asoul/Model/Diana/raw.model3.json +210 -0
- package/source/js/live2d_Asoul/TweenLite.js +12 -0
- package/source/js/live2d_Asoul/cubism4.min.js +2 -0
- package/source/js/live2d_Asoul/live2dcubismcore.min.js +9 -0
- package/source/js/live2d_Asoul/load.js +231 -0
- package/source/js/live2d_Asoul/pio.css +161 -0
- package/source/js/live2d_Asoul/pio.js +296 -0
- package/source/js/live2d_Asoul/pio_sdk4.js +149 -0
- package/source/js/live2d_Asoul/pixi.min.js +9 -0
- package/source/js/main.js +218 -0
- package/source/js/pjax.js +29 -0
- package/source/js/shiki/shiki.js +191 -0
- package/source/js/theme-selector.js +206 -0
- package/util/cache.js +47 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
common:
|
|
2
|
+
archive:
|
|
3
|
+
one: "ARCHIVE"
|
|
4
|
+
other: "ARCHIVE"
|
|
5
|
+
category:
|
|
6
|
+
one: "CATEGORY"
|
|
7
|
+
other: "CATEGORY"
|
|
8
|
+
tag:
|
|
9
|
+
one: "TAGS"
|
|
10
|
+
other: "TAGS"
|
|
11
|
+
post:
|
|
12
|
+
one: "POST"
|
|
13
|
+
other: "POST"
|
|
14
|
+
page:
|
|
15
|
+
one: "PAGE"
|
|
16
|
+
other: "PAGE"
|
|
17
|
+
prev: "Previous"
|
|
18
|
+
next: "Next"
|
|
19
|
+
article:
|
|
20
|
+
created_at: "%s"
|
|
21
|
+
more: "Read"
|
|
22
|
+
comments: "评论"
|
|
23
|
+
edited: "编辑于"
|
|
24
|
+
word_count:
|
|
25
|
+
one: "约%d字"
|
|
26
|
+
other: "约%d字"
|
|
27
|
+
licensing:
|
|
28
|
+
author: "Author"
|
|
29
|
+
created_at: "Posted on"
|
|
30
|
+
updated_at: "Updated on"
|
|
31
|
+
licensed_under: "License under"
|
|
32
|
+
plugin:
|
|
33
|
+
visit_count: "%sPV" # post页面显示的page view次数
|
|
34
|
+
visitor_count: 'PV <span id="busuanzi_site_pv">-</span> UV <span id="busuanzi_site_uv">-</span> '
|
|
35
|
+
cookie_consent:
|
|
36
|
+
message: 此网站使用 Cookie,以启用评论系统和分析功能。
|
|
37
|
+
dismiss: 知道了
|
|
38
|
+
allow: 允许使用Cookie
|
|
39
|
+
deny: 拒绝
|
|
40
|
+
link: 了解更多
|
|
41
|
+
policy: Cookie政策
|
|
42
|
+
search:
|
|
43
|
+
search: "搜索"
|
|
44
|
+
hint: "想要查找什么...(Ctrl/ + K)"
|
|
45
|
+
no_result: "未找到搜索结果"
|
|
46
|
+
untitled: "(无标题)"
|
|
47
|
+
empty_preview: "(无内容预览)"
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
common:
|
|
2
|
+
archive:
|
|
3
|
+
one: "彙整"
|
|
4
|
+
other: "彙整"
|
|
5
|
+
category:
|
|
6
|
+
one: "分類"
|
|
7
|
+
other: "分類"
|
|
8
|
+
tag:
|
|
9
|
+
one: "標籤"
|
|
10
|
+
other: "標籤"
|
|
11
|
+
post:
|
|
12
|
+
one: "文章"
|
|
13
|
+
other: "文章"
|
|
14
|
+
page:
|
|
15
|
+
one: "頁面"
|
|
16
|
+
other: "頁面"
|
|
17
|
+
prev: "上一頁"
|
|
18
|
+
next: "下一頁"
|
|
19
|
+
article:
|
|
20
|
+
created_at: "%s發表"
|
|
21
|
+
more: "繼續閱讀"
|
|
22
|
+
comments: "評論"
|
|
23
|
+
edited: "編輯于"
|
|
24
|
+
word_count:
|
|
25
|
+
one: "大約%d個字"
|
|
26
|
+
other: "大約%d個字"
|
|
27
|
+
licensing:
|
|
28
|
+
author: "作者"
|
|
29
|
+
created_at: "發表於"
|
|
30
|
+
updated_at: "更新於"
|
|
31
|
+
licensed_under: "許可協議"
|
|
32
|
+
plugin:
|
|
33
|
+
visit_count: "%s次訪問"
|
|
34
|
+
visitor_count: "共%s個訪客"
|
|
35
|
+
cookie_consent:
|
|
36
|
+
message: 此網站使用Cookie來改善您的體驗。
|
|
37
|
+
dismiss: 知道了!
|
|
38
|
+
allow: 允許使用Cookie
|
|
39
|
+
deny: 拒絕
|
|
40
|
+
link: 了解更多
|
|
41
|
+
policy: Cookie政策
|
|
42
|
+
search:
|
|
43
|
+
search: "搜尋"
|
|
44
|
+
hint: "請輸入關鍵字..."
|
|
45
|
+
no_result: "未找到搜索結果"
|
|
46
|
+
untitled: "(無標題)"
|
|
47
|
+
empty_preview: "(無內容預覽)"
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
const moment = require("moment");
|
|
2
|
+
const { Component, Fragment } = require("../include/util/common");
|
|
3
|
+
const { toMomentLocale } = require("hexo/dist/plugins/helper/date");
|
|
4
|
+
const Paginator = require("./misc/paginator");
|
|
5
|
+
const ArticleMedia = require("./common/article_media");
|
|
6
|
+
|
|
7
|
+
module.exports = class extends Component {
|
|
8
|
+
render() {
|
|
9
|
+
const { config, page, helper } = this.props;
|
|
10
|
+
const { url_for, __, date_xml, date } = helper;
|
|
11
|
+
|
|
12
|
+
const language = toMomentLocale(
|
|
13
|
+
page.lang || page.language || config.language,
|
|
14
|
+
);
|
|
15
|
+
const timelineCss = `
|
|
16
|
+
span.year {
|
|
17
|
+
position: absolute;
|
|
18
|
+
top: 1.5rem;
|
|
19
|
+
right: 1.5rem;
|
|
20
|
+
z-index: 0;
|
|
21
|
+
font-size: 7.5rem;
|
|
22
|
+
font-weight: bolder;
|
|
23
|
+
font-family: Paris2024;
|
|
24
|
+
color: hsl(from var(--mauve) h s l / 0.15);
|
|
25
|
+
line-height: 1;
|
|
26
|
+
user-select: none;
|
|
27
|
+
}
|
|
28
|
+
.timeline .archive-item {
|
|
29
|
+
display: flex;
|
|
30
|
+
text-align: left;
|
|
31
|
+
align-items: flex-start;
|
|
32
|
+
}
|
|
33
|
+
.timeline .archive-item a {
|
|
34
|
+
color: var(--text);
|
|
35
|
+
transition: color 0.2s;
|
|
36
|
+
}
|
|
37
|
+
.timeline .archive-item a:hover {
|
|
38
|
+
color: var(--peach);
|
|
39
|
+
}
|
|
40
|
+
.archive-item + .archive-item {
|
|
41
|
+
border: none;
|
|
42
|
+
margin-top: 0;
|
|
43
|
+
padding-top: 1rem;
|
|
44
|
+
}
|
|
45
|
+
`;
|
|
46
|
+
function renderArticleList(posts, year, month = null) {
|
|
47
|
+
const time = moment(
|
|
48
|
+
[page.year, page.month ? page.month - 1 : null].filter(
|
|
49
|
+
(i) => i !== null,
|
|
50
|
+
),
|
|
51
|
+
);
|
|
52
|
+
return (
|
|
53
|
+
<div class="card">
|
|
54
|
+
<div class="card-content">
|
|
55
|
+
<span class="year">
|
|
56
|
+
{month === null
|
|
57
|
+
? year
|
|
58
|
+
: time.locale(language).format("MMMM YYYY")}
|
|
59
|
+
</span>
|
|
60
|
+
<div class="timeline">
|
|
61
|
+
{posts.map((post) => {
|
|
62
|
+
const categories = post.categories.map((category) => ({
|
|
63
|
+
url: url_for(category.path),
|
|
64
|
+
name: category.name,
|
|
65
|
+
}));
|
|
66
|
+
return (
|
|
67
|
+
<ArticleMedia
|
|
68
|
+
url={url_for(post.link || post.path)}
|
|
69
|
+
title={post.title}
|
|
70
|
+
date={date(post.date)}
|
|
71
|
+
dateXml={date_xml(post.date)}
|
|
72
|
+
categories={categories}
|
|
73
|
+
/>
|
|
74
|
+
);
|
|
75
|
+
})}
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
let articleList;
|
|
83
|
+
if (!page.year) {
|
|
84
|
+
const years = {};
|
|
85
|
+
page.posts.each((p) => {
|
|
86
|
+
years[p.date.year()] = null;
|
|
87
|
+
});
|
|
88
|
+
articleList = Object.keys(years)
|
|
89
|
+
.sort((a, b) => b - a)
|
|
90
|
+
.map((year) => {
|
|
91
|
+
const posts = page.posts.filter(
|
|
92
|
+
(p) => p.date.year() === parseInt(year, 10),
|
|
93
|
+
);
|
|
94
|
+
return renderArticleList(posts, year, null);
|
|
95
|
+
});
|
|
96
|
+
} else {
|
|
97
|
+
articleList = renderArticleList(page.posts, page.year, page.month);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<Fragment>
|
|
102
|
+
<style dangerouslySetInnerHTML={{ __html: timelineCss }}></style>
|
|
103
|
+
{articleList}
|
|
104
|
+
{page.total > 1 ? (
|
|
105
|
+
<Paginator
|
|
106
|
+
current={page.current}
|
|
107
|
+
total={page.total}
|
|
108
|
+
baseUrl={page.base}
|
|
109
|
+
path={config.pagination_dir}
|
|
110
|
+
urlFor={url_for}
|
|
111
|
+
prevTitle={__("common.prev")}
|
|
112
|
+
nextTitle={__("common.next")}
|
|
113
|
+
/>
|
|
114
|
+
) : null}
|
|
115
|
+
</Fragment>
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
const { Component, cacheComponent } = require("../include/util/common");
|
|
2
|
+
|
|
3
|
+
class Categories extends Component {
|
|
4
|
+
renderList(categories, showCount) {
|
|
5
|
+
return categories.map((category) => (
|
|
6
|
+
<li>
|
|
7
|
+
<a
|
|
8
|
+
class={`level is-mobile${category.isCurrent ? " is-active" : ""}`}
|
|
9
|
+
href={category.url}
|
|
10
|
+
>
|
|
11
|
+
<span class="level-start">
|
|
12
|
+
<span class="level-item">{category.name}</span>
|
|
13
|
+
</span>
|
|
14
|
+
{showCount ? (
|
|
15
|
+
<span class="level-end">
|
|
16
|
+
<span class="level-item" style="font-family: monospace">
|
|
17
|
+
{category.count}
|
|
18
|
+
</span>
|
|
19
|
+
</span>
|
|
20
|
+
) : null}
|
|
21
|
+
</a>
|
|
22
|
+
{category.children.length ? (
|
|
23
|
+
<ul>{this.renderList(category.children, false)}</ul>
|
|
24
|
+
) : null}
|
|
25
|
+
</li>
|
|
26
|
+
));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
render() {
|
|
30
|
+
const { showCount, categories } = this.props;
|
|
31
|
+
const categoriesListCSS = `
|
|
32
|
+
.card-content a {
|
|
33
|
+
padding: 0.5em 0.75em;
|
|
34
|
+
color: var(--text);
|
|
35
|
+
}
|
|
36
|
+
.card-content a.level:hover {
|
|
37
|
+
background-color: var(--base);
|
|
38
|
+
}
|
|
39
|
+
.card-content li ul {
|
|
40
|
+
border-left: 1px solid var(--surface0);
|
|
41
|
+
margin: 0.75em;
|
|
42
|
+
padding-left: 0.75em;
|
|
43
|
+
}`;
|
|
44
|
+
return (
|
|
45
|
+
<div class="card widget" data-type="categories">
|
|
46
|
+
<style>{categoriesListCSS}</style>
|
|
47
|
+
<div class="card-content">
|
|
48
|
+
<ul>{this.renderList(categories, showCount)}</ul>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
Categories.Cacheable = cacheComponent(
|
|
56
|
+
Categories,
|
|
57
|
+
"widget.categories",
|
|
58
|
+
(props) => {
|
|
59
|
+
const { page, helper, widget = {} } = props;
|
|
60
|
+
const {
|
|
61
|
+
categories = props.site.categories,
|
|
62
|
+
orderBy = "name",
|
|
63
|
+
order = 1,
|
|
64
|
+
showCurrent = false,
|
|
65
|
+
showCount = true,
|
|
66
|
+
} = widget;
|
|
67
|
+
const { url_for, _p } = helper;
|
|
68
|
+
|
|
69
|
+
if (!categories || !categories.length) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
let depth = 0;
|
|
74
|
+
try {
|
|
75
|
+
depth = parseInt(props.depth, 10);
|
|
76
|
+
} catch (_e) {}
|
|
77
|
+
|
|
78
|
+
function prepareQuery(parent) {
|
|
79
|
+
const query = {};
|
|
80
|
+
|
|
81
|
+
if (parent) {
|
|
82
|
+
query.parent = parent;
|
|
83
|
+
} else {
|
|
84
|
+
query.parent = { $exists: false };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return categories
|
|
88
|
+
.find(query)
|
|
89
|
+
.sort(orderBy, order)
|
|
90
|
+
.filter((cat) => cat.length);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function hierarchicalList(level, parent) {
|
|
94
|
+
return prepareQuery(parent).map((cat, _) => {
|
|
95
|
+
let children = [];
|
|
96
|
+
if (!depth || level + 1 < depth) {
|
|
97
|
+
children = hierarchicalList(level + 1, cat._id);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
let isCurrent = false;
|
|
101
|
+
if (showCurrent && page) {
|
|
102
|
+
for (let j = 0; j < cat.length; j++) {
|
|
103
|
+
const post = cat.posts.data[j];
|
|
104
|
+
if (post && post._id === page._id) {
|
|
105
|
+
isCurrent = true;
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// special case: category page
|
|
110
|
+
isCurrent = isCurrent || page.base?.startsWith(cat.path);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
children,
|
|
115
|
+
isCurrent,
|
|
116
|
+
name: cat.name,
|
|
117
|
+
count: cat.length,
|
|
118
|
+
url: url_for(cat.path),
|
|
119
|
+
};
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return {
|
|
124
|
+
showCount,
|
|
125
|
+
categories: hierarchicalList(0),
|
|
126
|
+
title: _p("common.category", Infinity),
|
|
127
|
+
};
|
|
128
|
+
},
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
module.exports = class extends Component {
|
|
132
|
+
render() {
|
|
133
|
+
const { site, page, helper } = this.props;
|
|
134
|
+
|
|
135
|
+
return <Categories.Cacheable site={site} page={page} helper={helper} />;
|
|
136
|
+
}
|
|
137
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const { Component, Fragment } = require("../include/util/common");
|
|
2
|
+
const Index = require("./index");
|
|
3
|
+
|
|
4
|
+
module.exports = class extends Component {
|
|
5
|
+
render() {
|
|
6
|
+
const { config, page, helper } = this.props;
|
|
7
|
+
const { url_for, _p } = helper;
|
|
8
|
+
|
|
9
|
+
return (
|
|
10
|
+
<Fragment>
|
|
11
|
+
<nav class="breadcrumb" aria-label="breadcrumbs">
|
|
12
|
+
<ul>
|
|
13
|
+
<li>
|
|
14
|
+
{" "}
|
|
15
|
+
<font style="color: var(--green)">$</font> ls
|
|
16
|
+
<a href={url_for("/categories/")}>
|
|
17
|
+
{_p("common.category", Infinity)}
|
|
18
|
+
</a>
|
|
19
|
+
</li>
|
|
20
|
+
{page.parents.map((category) => {
|
|
21
|
+
return (
|
|
22
|
+
<li>
|
|
23
|
+
<a href={url_for(category.path)}>{category.name}</a>
|
|
24
|
+
</li>
|
|
25
|
+
);
|
|
26
|
+
})}
|
|
27
|
+
<li class="is-active">
|
|
28
|
+
<a href="#" aria-current="page">
|
|
29
|
+
{page.category}
|
|
30
|
+
</a>
|
|
31
|
+
</li>
|
|
32
|
+
</ul>
|
|
33
|
+
</nav>
|
|
34
|
+
<Index config={config} page={page} helper={helper} />
|
|
35
|
+
</Fragment>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Disqus comment JSX component.
|
|
3
|
+
* @module view/comment/disqus
|
|
4
|
+
*/
|
|
5
|
+
const { Component, cacheComponent } = require("../../include/util/common");
|
|
6
|
+
/**
|
|
7
|
+
* Disqus comment JSX component.
|
|
8
|
+
*
|
|
9
|
+
* @see https://disqus.com/admin/install/platforms/universalcode/
|
|
10
|
+
* @example
|
|
11
|
+
* <Disqus
|
|
12
|
+
* shortname="******"
|
|
13
|
+
* disqusId="******"
|
|
14
|
+
* permalink="/page/permanent/path"
|
|
15
|
+
* path="/path/to/page" />
|
|
16
|
+
*/
|
|
17
|
+
class Disqus extends Component {
|
|
18
|
+
render() {
|
|
19
|
+
const { shortname, disqusId, path, permalink } = this.props;
|
|
20
|
+
if (!shortname) {
|
|
21
|
+
return (
|
|
22
|
+
<div class="notification is-danger">
|
|
23
|
+
You forgot to set the <code>shortname</code> for Disqus. Please set it
|
|
24
|
+
in <code>_config.yml</code>.
|
|
25
|
+
</div>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
const js = `var disqus_config = function () {
|
|
29
|
+
this.page.url = '${permalink}';
|
|
30
|
+
this.page.identifier = '${disqusId || path}';
|
|
31
|
+
};
|
|
32
|
+
(function() {
|
|
33
|
+
var d = document, s = d.createElement('script');
|
|
34
|
+
s.src = '//' + '${shortname}' + '.disqus.com/embed.js';
|
|
35
|
+
s.setAttribute('data-timestamp', +new Date());
|
|
36
|
+
(d.head || d.body).appendChild(s);
|
|
37
|
+
})();`;
|
|
38
|
+
return (
|
|
39
|
+
<>
|
|
40
|
+
<div id="disqus_thread">
|
|
41
|
+
<noscript>
|
|
42
|
+
Please enable JavaScript to view the{" "}
|
|
43
|
+
<a href="//disqus.com/?ref_noscript">comments powered by Disqus.</a>
|
|
44
|
+
</noscript>
|
|
45
|
+
</div>
|
|
46
|
+
<script dangerouslySetInnerHTML={{ __html: js }}></script>
|
|
47
|
+
</>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Cacheable Disqus comment JSX component.
|
|
54
|
+
* <p>
|
|
55
|
+
* This class is supposed to be used in combination with the <code>locals</code> hexo filter
|
|
56
|
+
* ({@link module:hexo/filter/locals}).
|
|
57
|
+
*
|
|
58
|
+
* @see module:util/cache.cacheComponent
|
|
59
|
+
* @example
|
|
60
|
+
* <Disqus.Cacheable
|
|
61
|
+
* comment={{ shortname: '*******' }}
|
|
62
|
+
* page={{
|
|
63
|
+
* path: '/path/to/page',
|
|
64
|
+
* disqusId: '******',
|
|
65
|
+
* permalink: '/page/permanent/link'
|
|
66
|
+
* }} />
|
|
67
|
+
*/
|
|
68
|
+
Disqus.Cacheable = cacheComponent(Disqus, "comment.disqus", (props) => {
|
|
69
|
+
const { comment, page } = props;
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
path: page.path,
|
|
73
|
+
shortname: comment.shortname,
|
|
74
|
+
disqusId: page.disqusId,
|
|
75
|
+
permalink: page.permalink,
|
|
76
|
+
};
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
module.exports = Disqus;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DisqusJS comment JSX component.
|
|
3
|
+
* @module view/comment/disqusjs
|
|
4
|
+
*/
|
|
5
|
+
const { Component, cacheComponent } = require("../../include/util/common");
|
|
6
|
+
/**
|
|
7
|
+
* DisqusJS comment JSX component.
|
|
8
|
+
*
|
|
9
|
+
* @see https://github.com/SukkaW/DisqusJS
|
|
10
|
+
* @example
|
|
11
|
+
* <DisqusJs
|
|
12
|
+
* shortname="******"
|
|
13
|
+
* apiKey="******"
|
|
14
|
+
* api="******"
|
|
15
|
+
* admin="******"
|
|
16
|
+
* adminLabel={false}
|
|
17
|
+
* nesting={4}
|
|
18
|
+
* disqusId="******"
|
|
19
|
+
* path="/path/to/page"
|
|
20
|
+
* permalink="/page/permanent/path"
|
|
21
|
+
* pageTitle="******"
|
|
22
|
+
* siteTitle="******"
|
|
23
|
+
* jsUrl="/path/to/disqus.js"
|
|
24
|
+
* cssUrl="/path/to/disqusjs.css" />
|
|
25
|
+
*/
|
|
26
|
+
class DisqusJs extends Component {
|
|
27
|
+
render() {
|
|
28
|
+
const {
|
|
29
|
+
shortname,
|
|
30
|
+
apiKey,
|
|
31
|
+
api,
|
|
32
|
+
admin,
|
|
33
|
+
adminLabel,
|
|
34
|
+
nesting,
|
|
35
|
+
disqusId,
|
|
36
|
+
path,
|
|
37
|
+
permalink,
|
|
38
|
+
pageTitle,
|
|
39
|
+
siteTitle,
|
|
40
|
+
jsUrl,
|
|
41
|
+
cssUrl,
|
|
42
|
+
} = this.props;
|
|
43
|
+
if (!shortname) {
|
|
44
|
+
return (
|
|
45
|
+
<div class="notification is-danger">
|
|
46
|
+
You forgot to set the <code>shortname</code> or <code>api_key</code>{" "}
|
|
47
|
+
for Disqus. Please set it in <code>_config.yml</code>.
|
|
48
|
+
</div>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
const url = permalink || path;
|
|
52
|
+
const identifier = disqusId || path;
|
|
53
|
+
const js = `new DisqusJS({
|
|
54
|
+
shortname: '${shortname}',
|
|
55
|
+
apikey: ${JSON.stringify(apiKey)},
|
|
56
|
+
${siteTitle ? `siteName: ${JSON.stringify(siteTitle)},` : ""}
|
|
57
|
+
${identifier ? `identifier: ${JSON.stringify(identifier)},` : ""}
|
|
58
|
+
${url ? `url: ${JSON.stringify(url)},` : ""}
|
|
59
|
+
${pageTitle ? `title: ${JSON.stringify(pageTitle)},` : ""}
|
|
60
|
+
${api ? `api: ${JSON.stringify(api)},` : ""}
|
|
61
|
+
${admin ? `admin: ${JSON.stringify(admin)},` : ""}
|
|
62
|
+
${adminLabel ? `adminLabel: ${JSON.stringify(adminLabel)},` : ""}
|
|
63
|
+
${nesting ? `nesting: ${JSON.stringify(nesting)},` : ""}
|
|
64
|
+
});`;
|
|
65
|
+
return (
|
|
66
|
+
<>
|
|
67
|
+
<link rel="stylesheet" href={cssUrl} />
|
|
68
|
+
<div id="disqus_thread">
|
|
69
|
+
<noscript>
|
|
70
|
+
Please enable JavaScript to view the{" "}
|
|
71
|
+
<a href="//disqus.com/?ref_noscript">comments powered by Disqus.</a>
|
|
72
|
+
</noscript>
|
|
73
|
+
</div>
|
|
74
|
+
<script src={jsUrl}></script>
|
|
75
|
+
<script dangerouslySetInnerHTML={{ __html: js }}></script>
|
|
76
|
+
</>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Cacheable DisqusJS comment JSX component.
|
|
83
|
+
* <p>
|
|
84
|
+
* This class is supposed to be used in combination with the <code>locals</code> hexo filter
|
|
85
|
+
* ({@link module:hexo/filter/locals}).
|
|
86
|
+
*
|
|
87
|
+
* @see module:util/cache.cacheComponent
|
|
88
|
+
* @example
|
|
89
|
+
* <DisqusJs.Cacheable
|
|
90
|
+
* comment={{
|
|
91
|
+
* shortname: '******',
|
|
92
|
+
* api_key: '******',
|
|
93
|
+
* api: '******',
|
|
94
|
+
* admin: '******',
|
|
95
|
+
* admin_label: false,
|
|
96
|
+
* nesting: 4
|
|
97
|
+
* }}
|
|
98
|
+
* page={{
|
|
99
|
+
* path: '/path/to/page',
|
|
100
|
+
* disqusId: '******',
|
|
101
|
+
* permalink: '******'
|
|
102
|
+
* title: '******'
|
|
103
|
+
* }}
|
|
104
|
+
* config={{ title: '******' }}
|
|
105
|
+
* helper={{ cdn: function() { ... } }} />
|
|
106
|
+
*/
|
|
107
|
+
DisqusJs.Cacheable = cacheComponent(DisqusJs, "comment.disqusjs", (props) => {
|
|
108
|
+
const { config, page, helper, comment } = props;
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
path: page.path,
|
|
112
|
+
shortname: comment.shortname,
|
|
113
|
+
apiKey: comment.api_key,
|
|
114
|
+
api: comment.api,
|
|
115
|
+
admin: comment.admin,
|
|
116
|
+
adminLabel: comment.admin_label,
|
|
117
|
+
nesting: comment.nesting,
|
|
118
|
+
disqusId: page.disqusId,
|
|
119
|
+
permalink: page.permalink,
|
|
120
|
+
pageTitle: page.title,
|
|
121
|
+
siteTitle: config.title,
|
|
122
|
+
jsUrl: helper.cdn("disqusjs", "1.3.0", "dist/disqus.js"),
|
|
123
|
+
cssUrl: helper.cdn("disqusjs", "1.3.0", "dist/disqusjs.css"),
|
|
124
|
+
};
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
module.exports = DisqusJs;
|