` + str
16 | }
17 | })
18 | mydata += yy
19 | mydata += "\n"
20 | });
21 | if (!flag) {
22 | mydata += `
`
23 | }
24 | data.content = mydata
25 | }
26 | return data;
27 | });
--------------------------------------------------------------------------------
/scripts/filters/img.js:
--------------------------------------------------------------------------------
1 | /* global hexo */
2 |
3 | 'use strict';
4 |
5 | const imgRegex = /
<\/div>
$2<\/span><\/div>';
7 |
8 | hexo.extend.filter.register('after_post_render', function(data) {
9 | data.content = data.content.replace(imgRegex, imgReplacement);
10 | return data;
11 | });
--------------------------------------------------------------------------------
/scripts/filters/replace.js:
--------------------------------------------------------------------------------
1 | /* global hexo */
2 |
3 | 'use strict';
4 |
5 | hexo.extend.filter.register('after_render:html', function(data) {
6 | if (hexo.theme.config.replace) {
7 | const replacements = hexo.theme.config.replace.map(e => {
8 | const [a, b] = e.split(" => ");
9 | return { regex: new RegExp(a, "g"), replacement: b };
10 | });
11 |
12 | replacements.forEach(({ regex, replacement }) => {
13 | data = data.replace(regex, replacement);
14 | });
15 | }
16 | return data;
17 | }, 999999999999);
--------------------------------------------------------------------------------
/scripts/filters/z-lazyload.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const fs = require('hexo-fs');
4 |
5 | function lazyProcess(htmlContent, target) {
6 | const cfg = this.theme.config.plugins.lazyload;
7 | if (cfg == undefined || cfg.enable != true) {
8 | return htmlContent;
9 | }
10 | if (cfg.onlypost == true) {
11 | if (target != 'post') {
12 | return htmlContent;
13 | }
14 | }
15 | const loadingImg = cfg.loadingImg;
16 | return htmlContent.replace(/
/gi, function(str, p1, p2) {
17 | // might be duplicate
18 | if (/data-srcset/gi.test(str)) {
19 | return str;
20 | }
21 | if (/src="data:image(.*?)/gi.test(str)) {
22 | return str;
23 | }
24 | if (/no-lazy/gi.test(str)) {
25 | return str;
26 | }
27 | let cls = '';
28 | if (str.indexOf('class=') > -1) {
29 | cls = str.substring(str.indexOf('class='));
30 | if (cls.length > 7) {
31 | const c = cls.substring(6, 7);
32 | cls = cls.split(c);
33 | if (cls.length > 1) {
34 | cls = cls[0] + '"' + cls[1] + '"';
35 | }
36 | }
37 | }
38 | let result = str;
39 | let newCls = '';
40 | if (cls.length > 0 && result.includes('class=')) {
41 | newCls = cls.replace(/(class=|[\"]*)/g, '') + ' ';
42 | }
43 | const oldCls = newCls.trim();
44 | if (loadingImg) {
45 | newCls += 'lazyload placeholder';
46 | } else {
47 | newCls += 'lazyload';
48 | }
49 | if (cls.length > 0) {
50 | result = result.replace('"' + oldCls + '"', '"' + newCls + '"');
51 | }
52 | if (loadingImg) {
53 | return result.replace(p2, p2 + '" class="lazyload placeholder" ' + 'data-srcset="' + p2 + '" srcset="' + loadingImg);
54 | }
55 | return result.replace(p2, p2 + '" class="lazyload" ' + 'data-srcset="' + p2 + '" srcset="' + 'data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==');
56 |
57 | });
58 | }
59 |
60 | let processPost = function(data) {
61 | data.content = lazyProcess.call(this, data.content, 'post');
62 | return data;
63 | };
64 |
65 | let processSite = function(htmlContent) {
66 | return lazyProcess.call(this, htmlContent, 'site');
67 | };
68 |
69 | hexo.extend.filter.register('after_post_render', processPost);
70 | hexo.extend.filter.register('after_render:html', processSite);
71 |
--------------------------------------------------------------------------------
/scripts/helpers/first-style.js:
--------------------------------------------------------------------------------
1 | // 将首屏样式 first.styl 硬编码到HTML页面
2 | "use strict";
3 | const fs = require("hexo-fs");
4 |
5 | function generateFirstCSS() {
6 | let s = fs.readFileSync(
7 | hexo.theme.context.theme_dir + "source/css/first.styl"
8 | );
9 | hexo.renderStylus(s).then((css)=>{
10 | hexo.locals.set('FirstCSS', function(){
11 | return css
12 | });
13 | })
14 | }
15 | function getFirstCSS() {
16 | return hexo.locals.get('FirstCSS');
17 | }
18 | hexo.extend.filter.register("before_generate", generateFirstCSS);
19 | hexo.extend.helper.register("FirstCSS", getFirstCSS);
20 |
--------------------------------------------------------------------------------
/scripts/helpers/getList.js:
--------------------------------------------------------------------------------
1 | // yml string to list
2 | // yml 太烂了
3 |
4 | hexo.extend.helper.register('getList', function (list) {
5 | return list ? (typeof list === "string" ? [list] : [...list]) : [];
6 | });
--------------------------------------------------------------------------------
/scripts/helpers/head/autoCanonical.js:
--------------------------------------------------------------------------------
1 | /**
2 | * hexo-auto-canonical
3 | * https://github.com/hyunseob/hexo-auto-canonical.git
4 | * Copyright (c) 2015, HyunSeob
5 | * Licensed under the MIT license.
6 | */
7 |
8 | 'use strict';
9 |
10 | hexo.extend.helper.register('autoCanonical', function (config, page) {
11 | var base_url = config.url;
12 | if (config.url.charAt(config.url.length - 1) !== '/') base_url += '/';
13 |
14 | return '';
15 | });
--------------------------------------------------------------------------------
/scripts/helpers/head/generate_preload_fontfamily.js:
--------------------------------------------------------------------------------
1 | function getType(file) {
2 | var filename = file;
3 | var index1 = filename.lastIndexOf(".");
4 | var index2 = filename.length;
5 | var type = filename.substring(index1 + 1, index2);
6 | return type;
7 | }
8 | function getLink_preload(Url) {
9 | return `\n`
10 | }
11 |
12 | hexo.extend.helper.register("generate_preload_fontfamily", function (theme) {
13 | const hexo = this;
14 | let preload = "";
15 | if (theme.custom_css.fontfamily.logofont && theme.custom_css.fontfamily.logofont.url) {
16 | preload += getLink_preload(theme.custom_css.fontfamily.logofont.url)
17 | }
18 | if (theme.custom_css.fontfamily.bodyfont && theme.custom_css.fontfamily.bodyfont.url) {
19 | preload += getLink_preload(theme.custom_css.fontfamily.bodyfont.url)
20 | }
21 | return preload
22 | });
23 |
--------------------------------------------------------------------------------
/scripts/helpers/head/generate_seo.js:
--------------------------------------------------------------------------------
1 | hexo.extend.helper.register('generate_seo', function (theme, page) {
2 | const hexo = this;
3 | let robots_content="";
4 | if (page.robots) {
5 | robots_content = page.robots
6 | } else if (theme.seo && theme.seo.robots) {
7 | if (hexo.is_home()) {
8 | if (page.prev == 0) {
9 | robots_content=theme.seo.robots.home_first_page
10 | }else{
11 | robots_content=theme.seo.robots.home_other_pages
12 | }
13 | } else if (hexo.is_archive()) {
14 | robots_content=theme.seo.robots.archive
15 | } else if (hexo.is_category()) {
16 | robots_content=theme.seo.robots.category
17 | } else if (hexo.is_tag()) {
18 | robots_content=theme.seo.robots.tag
19 | }
20 | }
21 | if(robots_content){
22 | return ``
23 | }
24 | });
--------------------------------------------------------------------------------
/scripts/helpers/related-posts.js:
--------------------------------------------------------------------------------
1 | /**
2 | * https://github.com/tea3/hexo-related-popular-posts/wiki/More-Settings#customize-html
3 | */
4 |
5 | 'use strict';
6 | var util = require('hexo-util');
7 |
8 | // Examples of helper
9 | hexo.extend.helper.register('htmlGenerator', function(args) {
10 | if (!args || !args.json || args.json.length == 0) return '';
11 | const cfg = hexo.theme.config.article.body.footer_widget.related_posts;
12 | var returnHTML = '';
13 | var div = `
14 | ';
53 | return div;
54 | });
55 |
--------------------------------------------------------------------------------
/scripts/helpers/structured-data/index.js:
--------------------------------------------------------------------------------
1 | /*globals hexo */
2 | hexo.extend.helper.register("structured_data", require('./lib/'));
3 |
--------------------------------------------------------------------------------
/scripts/helpers/structured-data/lib/blogposting.js:
--------------------------------------------------------------------------------
1 | module.exports = (hexo, option) => {
2 | const { config, page: post } = hexo;
3 |
4 | const blogposting = {
5 | "@context": "https://schema.org.cn",
6 | "@type": "BlogPosting",
7 | headline: post.title || post.seo_title,
8 | description: post.description || hexo.strip_html(post.excerpt) || config.description,
9 | inLanguage: config.language,
10 | mainEntityOfPage: {
11 | "@type": "WebPage",
12 | "@id": post.permalink,
13 | },
14 | author: {
15 | "@type": "Person",
16 | name: option.person.name,
17 | image: {
18 | "@type": "ImageObject",
19 | url: option.logo.path,
20 | },
21 | url: option.person.url,
22 | },
23 | publisher: {
24 | "@type": "Organization",
25 | name: option.organization.name,
26 | logo: {
27 | "@type": "ImageObject",
28 | url: option.logo.path,
29 | width: option.logo.width,
30 | height: option.logo.height,
31 | },
32 | },
33 | url: post.permalink,
34 | };
35 |
36 | blogposting.wordCount = hexo.strip_html(post.excerpt).length;
37 |
38 | if (post.date) {
39 | blogposting.datePublished = post.date.toISOString();
40 | }
41 | if (post.updated) {
42 | blogposting.dateModified = post.updated.toISOString();
43 | }
44 | if (post.categories && post.categories.length) {
45 | if (post.categories.data) {
46 | blogposting.articleSection = post.categories.data[0].name;
47 | } else {
48 | blogposting.articleSection = post.categories[0];
49 | }
50 | }
51 |
52 | if (post.tags && post.tags.length) {
53 | if (post.tags.data) {
54 | blogposting.keywords = post.tags.map((tag) => tag.name).join(",");
55 | } else {
56 | blogposting.keywords = post.tags.map((tag) => tag).join(",");
57 | }
58 | }
59 | let image = post.headimg || "";
60 | if (image) {
61 | blogposting.image = {
62 | "@type": "ImageObject",
63 | url: image,
64 | width: 1024,
65 | height: 768,
66 | };
67 | }else{
68 | blogposting.image = {
69 | "@type": "ImageObject",
70 | url: option.logo.path,
71 | width: option.logo.width,
72 | height: option.logo.height,
73 | };
74 | }
75 |
76 | return blogposting;
77 | };
78 |
--------------------------------------------------------------------------------
/scripts/helpers/structured-data/lib/config.js:
--------------------------------------------------------------------------------
1 | module.exports = function (hexo) {
2 | const {config} = hexo;
3 | return {
4 | person: {
5 | name: config.author,
6 | url: config.url + config.root,
7 | sns: [],
8 | description: config.description,
9 | },
10 | logo: {
11 | path: /404/,
12 | width: 192,
13 | height: 192,
14 | },
15 | organization: {
16 | name: config.title,
17 | url: config.url + config.root,
18 | },
19 | website: {
20 | name: config.title,
21 | url: config.url + config.root,
22 | keywords: config.keywords,
23 | description: config.description,
24 | search: {
25 | name: "Site Search",
26 | url: config.url + "?s={search_term_string}",
27 | query: "required name=search_term_string",
28 | },
29 | },
30 | };
31 | };
32 |
--------------------------------------------------------------------------------
/scripts/helpers/structured-data/lib/index.js:
--------------------------------------------------------------------------------
1 | const config = require("./config");
2 |
3 | const WebSite = require("./website");
4 | const Organization = require("./organization");
5 | const Person = require("./person");
6 | const BlogPosting = require("./blogposting");
7 | const BreadcrumbList = require("./breadcrumblist");
8 |
9 | function isObject(item) {
10 | return item && typeof item === 'object' && !Array.isArray(item);
11 | }
12 |
13 | function merge(target, source) {
14 | for (const key in source) {
15 | if (isObject(target[key]) && isObject(source[key])) {
16 | merge(target[key], source[key]);
17 | } else {
18 | target[key] = source[key];
19 | }
20 | }
21 | return target;
22 | }
23 |
24 | module.exports = function () {
25 | const hexo = this;
26 | const option = merge(config(hexo), hexo.theme.structured_data.data);
27 | const builder = [Organization, Person, BreadcrumbList, WebSite, BlogPosting];
28 | const jsonld = JSON.stringify(builder.map((f) => f(hexo, option)));
29 | return ``;
30 | };
31 |
--------------------------------------------------------------------------------
/scripts/helpers/structured-data/lib/organization.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = (hexo, option) => {
3 | return {
4 | "@context": "https://schema.org.cn",
5 | "@type": "Organization",
6 | "name": option.organization.name,
7 | "url": option.organization.url,
8 | "logo": {
9 | "@type": "ImageObject",
10 | "url": option.logo.path,
11 | "width": option.logo.width,
12 | "height": option.logo.height
13 | }
14 | };
15 | };
16 |
--------------------------------------------------------------------------------
/scripts/helpers/structured-data/lib/person.js:
--------------------------------------------------------------------------------
1 | module.exports = (hexo, option) => {
2 | const { config } = hexo;
3 |
4 | return {
5 | "@context": "https://schema.org.cn",
6 | "@type": "Person",
7 | name: option.person.name,
8 | image: {
9 | "@type": "ImageObject",
10 | url: option.logo.path,
11 | },
12 | url: option.person.url,
13 | sameAs: option.person.sns,
14 | description: option.person.description,
15 | };
16 | };
17 |
--------------------------------------------------------------------------------
/scripts/helpers/structured-data/lib/website.js:
--------------------------------------------------------------------------------
1 | module.exports = (hexo,option) => {
2 | const { config } = hexo;
3 |
4 | return {
5 | "@context": "https://schema.org.cn",
6 | "@type": "WebSite",
7 | name: option.website.name,
8 | url: option.website.url,
9 | keywords: option.website.keywords,
10 | description: option.website.description,
11 | author: {
12 | "@type": "Person",
13 | name: option.person.name,
14 | image: {
15 | "@type": "ImageObject",
16 | url: option.logo.path,
17 | },
18 | url: option.person.url,
19 | description: option.person.description,
20 | },
21 | publisher: {
22 | "@type": "Organization",
23 | name: option.organization.name,
24 | url: option.organization.url,
25 | logo: {
26 | "@type": "ImageObject",
27 | url: option.logo.path,
28 | width: option.logo.width,
29 | height: option.logo.height,
30 | },
31 | },
32 | potentialAction: {
33 | "@type": "SearchAction",
34 | name: option.website.search.name,
35 | target: {
36 | "@type": "EntryPoint",
37 | urlTemplate: option.website.search.url,
38 | },
39 | "query-input": option.website.search.query,
40 | },
41 | };
42 | };
43 |
--------------------------------------------------------------------------------
/scripts/tags/btn.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function postBtn(args) {
4 | if(/::/g.test(args)){
5 | args = args.join(' ').split('::');
6 | }
7 | else{
8 | args = args.join(' ').split(',');
9 | }
10 | let cls = '';
11 | let text = '';
12 | let url = '';
13 | let icon = '';
14 | if (args.length > 3) {
15 | cls = args[0];
16 | text = args[1];
17 | url = args[2];
18 | icon = args[3];
19 | } else if (args.length > 2) {
20 | if (args[2].indexOf(' fa-') > -1) {
21 | // text, url, icon
22 | text = args[0];
23 | url = args[1];
24 | icon = args[2];
25 | } else {
26 | cls = args[0];
27 | text = args[1];
28 | url = args[2];
29 | }
30 | } else if (args.length > 1) {
31 | text = args[0];
32 | url = args[1];
33 | } else if (args.length > 0) {
34 | text = args[0];
35 | }
36 |
37 | cls = cls.trim();
38 | icon = icon.trim();
39 | text = text.trim();
40 | url = url.trim();
41 | if (url.length > 0) {
42 | url = 'href=\'' + url + '\'';
43 | }
44 | if (cls.length > 0) {
45 | cls = ' ' + cls;
46 | }
47 | if (icon.length > 0) {
48 | return `${text}`;
49 | }
50 | return `${text}`;
51 |
52 | }
53 |
54 | hexo.extend.tag.register('btn', postBtn);
55 |
--------------------------------------------------------------------------------
/scripts/tags/btns.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function postBtns(args, content) {
4 | return `
5 | ${content}
6 |
`;
7 | }
8 |
9 | function postCell(args, content) {
10 | if(/::/g.test(args)){
11 | args = args.join(' ').split('::');
12 | }
13 | else{
14 | args = args.join(' ').split(',');
15 | }
16 | let text = args[0] || '';
17 | let url = args[1] || '';
18 | text = text.trim();
19 | url = url.trim();
20 | if (url.length > 0) {
21 | url = 'href=\'' + url + '\'';
22 | }
23 | let icon = '';
24 | let img = hexo.theme.config.default.image;
25 | if (args.length > 2) {
26 | if (args[2].indexOf(' fa-') > -1) {
27 | icon = args[2].trim();
28 | } else {
29 | img = args[2].trim();
30 | }
31 | }
32 | if (icon.length > 0) {
33 | return `${text}`;
34 | }
35 | return `
${text}`;
36 |
37 | }
38 |
39 | hexo.extend.tag.register('btns', postBtns, {ends: true});
40 | hexo.extend.tag.register('cell', postCell);
41 |
--------------------------------------------------------------------------------
/scripts/tags/checkbox.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function postCheckbox(args) {
4 | if(/::/g.test(args)){
5 | args = args.join(' ').split('::');
6 | }
7 | else{
8 | args = args.join(' ').split(',');
9 | }
10 | var cls = '';
11 | var text = '';
12 | var checked = false;
13 | if (args.length > 1) {
14 | cls = (args[0] || '').trim();
15 | if (cls.length > 0) {
16 | cls = ' ' + cls;
17 | }
18 | if (cls.indexOf('checked') > -1) {
19 | checked = true;
20 | }
21 | text = (args[1] || '').trim();
22 | } else if (args.length > 0) {
23 | text = (args[0] || '').trim();
24 | }
25 | if (text.length > 0) {
26 | return `
27 | ${hexo.render.renderSync({text: text, engine: 'markdown'}).split('\n').join('')}
28 |
`;
29 | }
30 | }
31 | function postRadio(args) {
32 | if(/::/g.test(args)){
33 | args = args.join(' ').split('::');
34 | }
35 | else{
36 | args = args.join(' ').split(',');
37 | }
38 | var cls = '';
39 | var text = '';
40 | var checked = false;
41 | if (args.length > 1) {
42 | cls = (args[0] || '').trim();
43 | if (cls.length > 0) {
44 | cls = ' ' + cls;
45 | }
46 | if (cls.indexOf('checked') > -1) {
47 | checked = true;
48 | }
49 | text = (args[1] || '').trim();
50 | } else if (args.length > 0) {
51 | text = (args[0] || '').trim();
52 | }
53 | if (text.length > 0) {
54 | return `
55 | ${hexo.render.renderSync({text: text, engine: 'markdown'}).split('\n').join('')}
56 |
`;
57 | }
58 | }
59 | // {% checkbox text %}
60 | // {% checkbox checked, text %}
61 | // {% checkbox color checked, text %}
62 | hexo.extend.tag.register('checkbox', postCheckbox);
63 | hexo.extend.tag.register('radio', postRadio);
64 |
--------------------------------------------------------------------------------
/scripts/tags/fancybox.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function renderImg(content) {
4 | return `${hexo.render.renderSync({text: content, engine: 'markdown'}).split('\n').join('')}`;
5 | }
6 |
7 | function buidAlt(alt) {
8 | if (!!alt && alt !== 'image') {
9 | return `${alt}`
10 | } else {
11 | return '';
12 | }
13 | }
14 |
15 | function buidImgFancybox(content, group) {
16 | let html = renderImg(content).trim();
17 | if(html.startsWith('') && html.endsWith('
')) { // 去除无用的 p 标签包裹
18 | html=html.substring(0, html.length-4).substring(3);
19 | }
20 |
21 | let imageTags = html.includes('image-caption') ? 'image' : undefined;
22 | let imgList = html.match(//g) || [];
23 | imgList.forEach(item => {
24 | const url = (item.match(/\ssrc=['"](.*?)['"]/) || [])[1];
25 | const alt = (item.match(/\salt=['"](.*?)['"]/) || [])[1] || '';
26 | const newItem = item.replace('img', 'img fancybox itemprop="contentUrl"'); // 避免出现重复替换,打个标
27 | const result = ``;
28 | html = html.replace(item, result.trim());
29 | })
30 | return html;
31 | }
32 |
33 | function postFancybox(args, content) {
34 | if(/::/g.test(args)){
35 | args = args.join(' ').split('::');
36 | }
37 | else{
38 | args = args.join(' ').split(',');
39 | }
40 | const cls = args[0];
41 | const col = Number(args[1]) || 0;
42 | const group = (args[2] || 'default').trim();
43 |
44 | if (col > 0) {
45 | return `${buidImgFancybox(content, group)}
`;
46 | }
47 | return `${buidImgFancybox(content, group)}
`;
48 | }
49 |
50 |
51 |
52 | hexo.extend.tag.register('gallery', postFancybox, {ends: true});
53 |
--------------------------------------------------------------------------------
/scripts/tags/folding.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function postFolding(args, content) {
4 | if(/::/g.test(args)){
5 | args = args.join(' ').split('::');
6 | }
7 | else{
8 | args = args.join(' ').split(',');
9 | }
10 | let style = '';
11 | let title = '';
12 | if (args.length > 1) {
13 | style = args[0].trim();
14 | title = args[1].trim();
15 | } else if (args.length > 0) {
16 | title = args[0].trim();
17 | }
18 | if (style != undefined) {
19 | return ` ${title}
20 |
21 | ${hexo.render.renderSync({text: content, engine: 'markdown'}).split('\n').join('')}
22 |
23 | `;
24 | }
25 | return ` ${title}
26 |
27 | ${hexo.render.renderSync({text: content, engine: 'markdown'}).split('\n').join('')}
28 |
29 | `;
30 |
31 |
32 | }
33 |
34 | hexo.extend.tag.register('folding', postFolding, {ends: true});
35 |
--------------------------------------------------------------------------------
/scripts/tags/ghcard.js:
--------------------------------------------------------------------------------
1 | /**
2 | * https://github.com/anuraghazra/github-readme-stats
3 | */
4 |
5 | 'use strict';
6 |
7 | // {% ghcard volantis-x %}
8 | // {% ghcard volantis-x/hexo-theme-volantis %}
9 | hexo.extend.tag.register('ghcard', function(args) {
10 | if(/::/g.test(args)){
11 | args = args.join(' ').split('::');
12 | }
13 | else{
14 | args = args.join(' ').split(',');
15 | }
16 | const path = args[0].trim();
17 | let card = '';
18 | card += '';
19 | let url = '';
20 | if (path.includes('/')) {
21 | // is repo
22 | const ps = path.split('/');
23 | url += 'https://github-readme-stats.xaoxuu.com/api/pin/?username=' + ps[0] + '&repo=' + ps[1];
24 | } else {
25 | // is user
26 | url += 'https://github-readme-stats.xaoxuu.com/api/?username=' + path;
27 | }
28 | if (args.length > 1) {
29 | for (let i = 1; i < args.length; i++) {
30 | const tmp = args[i].trim();
31 | url += '&' + tmp;
32 | }
33 | }
34 | if (!url.includes('&show_owner=')) {
35 | url += '&show_owner=true';
36 | }
37 | card += '
';
38 | card += '';
39 | return card;
40 | });
41 |
42 | hexo.extend.tag.register('ghcardgroup', function(args, content) {
43 | let ret = '';
44 | // wrap
45 | ret += '';
46 | ret += content;
47 | ret += '
';
48 | return ret;
49 | }, {ends: true});
50 |
--------------------------------------------------------------------------------
/scripts/tags/inline-labels.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function createTag(tagName) {
4 | return function(args) {
5 | return `<${tagName}>${args.join(' ')}${tagName}>`;
6 | };
7 | }
8 |
9 | hexo.extend.tag.register('u', createTag('u'));
10 | hexo.extend.tag.register('emp', createTag('emp'));
11 | hexo.extend.tag.register('wavy', createTag('wavy'));
12 | hexo.extend.tag.register('del', createTag('del'));
13 | hexo.extend.tag.register('kbd', createTag('kbd'));
14 | hexo.extend.tag.register('psw', createTag('psw'));
--------------------------------------------------------------------------------
/scripts/tags/link.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | // {% link title, url %}
4 | // {% link title, url, img %}
5 | hexo.extend.tag.register('link', function(args) {
6 | if(/::/g.test(args)){
7 | args = args.join(' ').split('::');
8 | }
9 | else{
10 | args = args.join(' ').split(',');
11 | }
12 | let text = '';
13 | let url = '';
14 | let img = '';
15 | if (args.length < 2) {
16 | return;
17 | } else if (args.length == 2) {
18 | text = args[0].trim();
19 | url = args[1].trim();
20 | } else if (args.length == 3) {
21 | text = args[0].trim();
22 | url = args[1].trim();
23 | img = args[2].trim();
24 | }
25 | let result = '';
26 | // 发现如果不套一层 div 在其它可渲染 md 的容器中容易被分解
27 | result += '';
35 |
36 | return result;
37 | });
38 |
39 | hexo.extend.tag.register('linkgroup', function(args, content) {
40 | let ret = '';
41 | ret += '';
42 | ret += content;
43 | ret += '
';
44 | return ret;
45 | }, {ends: true});
46 |
--------------------------------------------------------------------------------
/scripts/tags/md.js:
--------------------------------------------------------------------------------
1 |
2 | hexo.extend.tag.register('md', function(args) {
3 | const {config} = hexo;
4 | const md_path = args[0].trim();
5 | let md_id = "md-" + hexo.createUuid()
6 | let mat = `
7 |
8 |
56 | `
57 |
58 | return mat
59 | });
60 |
--------------------------------------------------------------------------------
/scripts/tags/media.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function postAudio(args) {
4 | const src = args[0].trim();
5 | return ``;
6 | }
7 |
8 | function postVideo(args) {
9 | const {config} = hexo;
10 | const src = args[0].trim();
11 | // m3u8 https://github.com/volantis-x/hexo-theme-volantis/issues/606
12 | // 文件扩展名为 .m3u8
13 | if (hexo.getType(src) === "m3u8") {
14 | let video_id = `video-${hexo.createUuid()}`
15 | return `
16 | `;
28 | }
29 | return ``;
30 | }
31 |
32 | function postVideos(args, content) {
33 | if(/::/g.test(args)){
34 | args = args.join(' ').split('::');
35 | }
36 | else{
37 | args = args.join(' ').split(',');
38 | }
39 | var cls = args[0];
40 | if (cls.length > 0) {
41 | cls = ' ' + cls;
42 | }
43 | var col = Number(args[1]) || 0;
44 | if (col > 0) {
45 | return `${content}
`;
46 | }
47 | return `${content}
`;
48 |
49 | }
50 |
51 | hexo.extend.tag.register('audio', postAudio);
52 | hexo.extend.tag.register('video', postVideo);
53 | hexo.extend.tag.register('videos', postVideos, {ends: true});
54 |
--------------------------------------------------------------------------------
/scripts/tags/pandown.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | // {% pandown type, url, pwd, fname %}
4 | hexo.extend.tag.register('pandown', function(args) {
5 | if(/::/g.test(args)){
6 | args = args.join(' ').split('::');
7 | }
8 | else{
9 | args = args.join(' ').split(',');
10 | }
11 | let type = '';
12 | let url = '';
13 | let pwd = '';
14 | let fname = '';
15 | if (args.length < 4) {
16 | return;
17 | } else if (args[0].trim() === 'yun') {
18 | return '对不起,pandown-tags不支持自定义
Sorry, pandown-tags does not support customization
'
19 | } else {
20 | type = args[0].trim();
21 | url = args[1].trim();
22 | pwd = args[2].trim();
23 | fname = args[3].trim();
24 | }
25 | let result = '';
26 | // js
27 | result += ''
32 | return result;
33 | });
34 |
--------------------------------------------------------------------------------
/scripts/tags/span.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function postP(args) {
4 | if(/::/g.test(args)){
5 | args = args.join(' ').split('::');
6 | }
7 | else{
8 | args = args.join(' ').split(',');
9 | }
10 | const p0 = args[0].trim();
11 | const p1 = args[1].trim();
12 | return `${p1}
`;
13 | }
14 | function postSpan(args) {
15 | if(/::/g.test(args)){
16 | args = args.join(' ').split('::');
17 | }
18 | else{
19 | args = args.join(' ').split(',');
20 | }
21 | const p0 = args[0].trim();
22 | const p1 = args[1].trim();
23 | return `${p1}`;
24 | }
25 |
26 | hexo.extend.tag.register('p', postP);
27 | hexo.extend.tag.register('span', postSpan);
28 |
--------------------------------------------------------------------------------
/scripts/tags/swiper.js:
--------------------------------------------------------------------------------
1 | /**
2 | * swiper.js v1 | https://github.com/xaoxuu/hexo-theme-stellar/
3 | * 格式与官方标签插件一致使用空格分隔,中括号内的是可选参数(中括号不需要写出来)
4 | *
5 | * {% swiper %}
6 | * 
7 | * {% endswiper %}
8 | */
9 |
10 | 'use strict';
11 |
12 | hexo.extend.tag.register('swiper', function (args, content) {
13 | args = hexo.args.map(args, ['width']);
14 | var el = '';
15 | function slide() {
16 | let imgs = hexo.render.renderSync({ text: content, engine: 'markdown' });
17 | imgs = imgs.match(/
/gi);
18 | if (imgs && imgs.length > 0) {
19 | imgs.forEach((img, i) => {
20 | img = img.replace('
' + img + '';
22 | });
23 | }
24 | }
25 | el += '
0) {
27 | el += ' ' + hexo.args.joinTags(args, 'width').join(' ');
28 | }
29 | el += '>';
30 | el += '
';
31 | slide();
32 | el += '
';
33 | el += '';
34 | el += '
';
35 | el += '
';
36 | el += '
';
37 | return el;
38 | }, { ends: true });
--------------------------------------------------------------------------------
/scripts/tags/table.js:
--------------------------------------------------------------------------------
1 | /**
2 | * table.js | https://github.com/volantis-x/hexo-theme-volantis
3 | */
4 |
5 | 'use strict';
6 |
7 | // {% table title %}
8 | // table markdown
9 | // {% endtable %}
10 |
11 | function postTable(args, content) {
12 | let ret = '';
13 | ret += '
';
14 | ret += hexo.render.renderSync({text: content, engine: 'markdown'});
15 | ret += '
';
16 | return ret;
17 | }
18 |
19 | hexo.extend.tag.register('table', postTable, {ends: true});
20 |
--------------------------------------------------------------------------------
/scripts/tags/timeline.js:
--------------------------------------------------------------------------------
1 | /**
2 | * timeline.js | https://volantis.js.org/v3/tag-plugins/#Timeline
3 | */
4 |
5 | 'use strict';
6 |
7 | function postTimeline(args, content) {
8 | if (args.length > 0) {
9 | return `
`;
10 | }
11 | return `
${content}
`;
12 |
13 | }
14 |
15 | function postTimenode(args, content) {
16 | if(/::/g.test(args)){
17 | args = args.join(' ').split('::');
18 | }
19 | else{
20 | args = args.join(' ').split(',');
21 | }
22 | var time = args[0];
23 | return `
${hexo.render.renderSync({text: content, engine: 'markdown'}).split('\n').join('')}
`;
24 | }
25 |
26 |
27 | // {% timeline %}
28 | // ... timenode ...
29 | // {% endtimeline %}
30 | hexo.extend.tag.register('timeline', postTimeline, {ends: true});
31 |
32 | // {% timenode time %}
33 | // what happened
34 | // {% endtimenode %}
35 | hexo.extend.tag.register('timenode', postTimenode, {ends: true});
36 |
--------------------------------------------------------------------------------
/source/css/Readme.md:
--------------------------------------------------------------------------------
1 | # 样式文件说明
2 |
3 | ## 样式拆分说明
4 |
5 | 方案是对 https://blog.skk.moe/post/improve-fcp-for-my-blog/ 的开源实现
6 |
7 | ### first.styl
8 |
9 | 首屏样式, 内含 首屏基础样式、 cover、 navbar、 首屏search、首屏暗黑模式、首屏字体 等样式, 首屏样式采用硬编码的方式写在HTML中.
10 |
11 | 内联硬编码自动化方案 see:scripts/helpers/first-style/index.js
12 |
13 | ### style.styl
14 |
15 | 异步加载样式, 除首屏样式外的其他样式, 最终生成 /css/style.css 异步加载.
16 |
17 | ## 暗黑模式样式说明
18 |
19 | 暗黑模式样式被拆分为首屏暗黑模式样式和异步暗黑模式样式,其中在 source/css/ 文件夹下:
20 |
21 | _first/dark_first.styl : 包含 首屏暗黑模式样式 的 暗黑模式 CSS 变量 和 强制覆盖样式
22 |
23 | _style/_plugins/_dark : 异步暗黑模式样式文件夹
24 |
25 | _style/_plugins/_dark/dark_async.styl : 包含 异步暗黑模式样式 的 暗黑模式 CSS 变量
26 |
27 | _style/_plugins/_dark/dark_plugins.styl : 包含 异步暗黑模式样式 的 强制覆盖样式
28 |
29 |
--------------------------------------------------------------------------------
/source/css/_defines/Readme.md:
--------------------------------------------------------------------------------
1 | # 定义变量
2 |
3 | 这里存放一些 变量 或 工具函数 ,不建议存放样式
--------------------------------------------------------------------------------
/source/css/_defines/effect.styl:
--------------------------------------------------------------------------------
1 | @require('func')
2 | // shadow
3 | $boxshadow-card = 0 1px 2px 0px rgba(0, 0, 0, 0.1)
4 | $boxshadow-card-float = 0 2px 4px 0px rgba(0, 0, 0, 0.1), 0 4px 8px 0px rgba(0, 0, 0, 0.1), 0 8px 16px 0px rgba(0, 0, 0, 0.1)
5 |
6 | $boxshadow-float = 0 4px 8px 0px rgba(0, 0, 0, 0.1)
7 |
8 | $boxshadow-dropmenu = 0 2px 4px 0px rgba(0, 0, 0, 0.08), 0 4px 8px 0px rgba(0, 0, 0, 0.08), 0 8px 16px 0px rgba(0, 0, 0, 0.08)
9 |
10 | $textshadow = 0 1px 2px 0px rgba(0, 0, 0, 0.1)
11 |
12 |
--------------------------------------------------------------------------------
/source/css/_defines/func.styl:
--------------------------------------------------------------------------------
1 | // 为1个属性设置动画
2 | trans1($op, $time = 0.2s)
3 | transition: $op $time ease-out
4 |
5 | // 为2个属性设置动画
6 | trans2($op1, $op2)
7 | transition: $op1 0.2s ease-out, $op2 0.2s ease-out
8 |
9 | trans2pro($op1, $t1, $op2, $t2)
10 | transition: $op1 $t1 ease-out, $op2 $t2 ease-out
11 |
12 | trans3($op1, $op2, $op3)
13 | transition: $op1 0.2s ease-out, $op2 0.2s ease-out, $op3 0.2s ease-out
14 |
15 | trans($time = 0.28s)
16 | transition: all $time ease
17 |
18 | hoverable-card()
19 | trans()
20 | &:hover
21 | box-shadow: 0 0 4px rgba(0,0,0,.1), 0 0 8px rgba(0,0,0,.08)
22 |
23 | txt-ellipsis()
24 | white-space: nowrap
25 | overflow: hidden
26 | text-overflow: ellipsis
27 |
28 | placeholder(rules)
29 | &::-webkit-input-placeholder
30 | rules()
31 | &:-moz-placeholder
32 | rules()
33 | &::-moz-placeholder
34 | rules()
35 | &:-ms-input-placeholder
36 | rules()
37 |
38 | disable-user-select()
39 | user-select: none
40 |
41 | scrollbar($w = 4px, $b = 2px, $c = $color-theme, $h = $color-hover)
42 | &::-webkit-scrollbar
43 | height: $w
44 | width: $w
45 | &::-webkit-scrollbar-track-piece
46 | background: transparent
47 | &::-webkit-scrollbar-thumb
48 | background: $c
49 | cursor: pointer
50 | border-radius: $b
51 | &:hover
52 | background: $h
53 |
54 |
55 | scrollbar-codeblock()
56 | &::-webkit-scrollbar
57 | height: 4px
58 | width: 4px
59 | &::-webkit-scrollbar-track-piece
60 | background: transparent
61 | &::-webkit-scrollbar-thumb
62 | background: transparent
63 | cursor: pointer
64 | border-radius: $border-codeblock
65 | &:hover
66 | &::-webkit-scrollbar-thumb
67 | background: alpha($color-text, .5)
68 | &:hover
69 | background: $color-hover
70 |
--------------------------------------------------------------------------------
/source/css/_defines/layout.styl:
--------------------------------------------------------------------------------
1 | // device defines
2 | $device-mobile-s = 320px
3 | $device-mobile-m = 375px
4 | $device-mobile-l = 425px
5 | $device-mobile = 500px
6 | $device-tablet = 768px
7 | $device-laptop = 1024px
8 | $device-desktop = 1440px
9 | $device-2k = 2048px
10 | $device-4k = 2560px
11 |
12 |
13 | // site layout
14 | $layout-width = convert(hexo-config('custom_css.max_width')) || 1080px
15 | $sidebar = 240px
16 | $modal-threshold = 680px
17 | $navbar-height = convert(hexo-config('custom_css.navbar.height')) || 64px
18 |
19 | // gap
20 | $gap = convert(hexo-config('custom_css.gap.base')) || 16px // base gap
21 | $gap-h2 = convert(hexo-config('custom_css.gap.h2')) || 48px
22 | $gap-h3 = convert(hexo-config('custom_css.gap.h3')) || 32px
23 | $gap-h4 = convert(hexo-config('custom_css.gap.h4')) || 16px
24 | // 新的段落间距,以实际字体大小为基准
25 | $gap-p = convert(hexo-config('custom_css.gap.p')) || 1em
26 |
27 |
28 |
29 | // border width
30 | $border-line = 2px
31 |
32 | // border radius
33 | $border-card = convert(hexo-config('custom_css.border_radius.card')) || 12px
34 | $border-codeblock = convert(hexo-config('custom_css.border_radius.codeblock')) || 4px
35 | $border-searchbar = convert(hexo-config('custom_css.border_radius.searchbar')) || 8px
36 | $border-button = convert(hexo-config('custom_css.border_radius.button')) || 2px
37 |
38 | // text align
39 | $textalign-h1 = convert(hexo-config('custom_css.body.text_align.h1')) || left
40 | $textalign-h2 = convert(hexo-config('custom_css.body.text_align.h2')) || left
41 | $textalign-h3 = convert(hexo-config('custom_css.body.text_align.h3')) || left
42 | $textalign-h4 = convert(hexo-config('custom_css.body.text_align.h4')) || left
43 | $textalign-p = convert(hexo-config('custom_css.body.text_align.p')) || justify
44 |
--------------------------------------------------------------------------------
/source/css/_first/fontfamily_first.styl:
--------------------------------------------------------------------------------
1 | if hexo-config('custom_css.fontfamily.bodyfont')
2 | if hexo-config('custom_css.fontfamily.bodyfont.name')
3 | @font-face
4 | font-family: hexo-config('custom_css.fontfamily.bodyfont.name')
5 | src: url(hexo-config('custom_css.fontfamily.bodyfont.url'))
6 | font-weight: hexo-config('custom_css.fontfamily.bodyfont.weight')
7 | font-style: hexo-config('custom_css.fontfamily.bodyfont.style')
8 | font-display: swap
9 |
10 | if hexo-config('custom_css.fontfamily.logofont')
11 | if hexo-config('custom_css.fontfamily.logofont.name')
12 | @font-face
13 | font-family: hexo-config('custom_css.fontfamily.logofont.name')
14 | src: url(hexo-config('custom_css.fontfamily.logofont.url'))
15 | font-weight: hexo-config('custom_css.fontfamily.logofont.weight')
16 | font-style: hexo-config('custom_css.fontfamily.logofont.style')
17 | font-display: swap
--------------------------------------------------------------------------------
/source/css/_first/search_first.styl:
--------------------------------------------------------------------------------
1 | #u-search
2 | $border-card = 4px
3 | display: none
4 | position: fixed
5 | top: 0
6 | left: 0
7 | width: 100%
8 | height: 100%
9 | padding: 60px 20px
10 | z-index: 1001
11 | @media screen and (max-width: $modal-threshold)
12 | padding: 0px
13 |
--------------------------------------------------------------------------------
/source/css/_style/_base/fontfamily_async.styl:
--------------------------------------------------------------------------------
1 | if hexo-config('custom_css.fontfamily.codefont')
2 | if hexo-config('custom_css.fontfamily.codefont.name')
3 | @font-face
4 | font-family: hexo-config('custom_css.fontfamily.codefont.name')
5 | src: url(hexo-config('custom_css.fontfamily.codefont.url'))
6 | font-weight: hexo-config('custom_css.fontfamily.codefont.weight')
7 | font-style: hexo-config('custom_css.fontfamily.codefont.style')
8 | font-display: swap
9 |
--------------------------------------------------------------------------------
/source/css/_style/_layout/footer.styl:
--------------------------------------------------------------------------------
1 | footer.footer
2 | position: relative
3 | padding: 40px 10px 120px 10px
4 | width: 100%
5 | color: var(--color-site-footer)
6 | margin: 0px auto
7 | &,p
8 | font-size: $fontsize-code
9 | overflow: hidden
10 | text-align: center
11 | .licenses
12 | color: fade(@color_text_main, 50%)
13 | .social-wrapper
14 | display: flex
15 | justify-content: center
16 | flex-wrap: wrap
17 | margin: 4px $gap * 0.5
18 |
19 | a
20 | color: var(--color-site-footer)
21 | padding: 0
22 | trans()
23 | &:hover
24 | color: $color-hover
25 | &:not(.social):hover
26 | text-decoration: underline
27 | &.social
28 | position: relative
29 | display: inline-block
30 | text-align: center
31 | display: flex
32 | justify-content: center
33 | align-items: center
34 | min-width: 36px
35 | min-height: 36px
36 | margin: 4px
37 | opacity: .75
38 | border-radius: 4px
39 | font-size: 1rem
40 | img
41 | margin: 8px
42 | height: 24px
43 | &:hover
44 | color: $color-hover
45 | background: alpha(@color, 0.1)
46 |
47 |
48 |
49 | .copyright
50 | margin-top: $gap
51 | p
52 | font-size: $fontsize-footnote
53 |
54 | @media screen and (max-width: $device-tablet)
55 | justify-content: center
56 |
--------------------------------------------------------------------------------
/source/css/_style/_layout/friends-simpleuser.styl:
--------------------------------------------------------------------------------
1 | // layout/friends.ejs
2 | if hexo-config('pages.friends.layout_scheme') != 'traditional'
3 | .md .simpleuser-group
4 | margin: 0
5 | display: grid
6 | grid-template-columns: repeat(auto-fill, 112px)
7 | .md .simpleuser
8 | text-align: center
9 | padding: 1em .5em
10 | border-radius: 4px
11 | img
12 | display: block
13 | width: 50px
14 | height 50px
15 | border-radius: 50px
16 | object-fit: cover
17 | img+span
18 | display: block
19 | font-size: $fontsize-meta
20 | line-height: 1.2
21 | color: var(--color-text)
22 | &:hover
23 | background: var(--color-site-bg)
24 |
--------------------------------------------------------------------------------
/source/css/_style/_layout/img.styl:
--------------------------------------------------------------------------------
1 | .md
2 | img
3 | position: relative
4 | trans()
5 | @media screen and (max-width: $device-mobile)
6 | box-shadow: none
7 | div>img,p>img
8 | display: block
9 | margin: auto
10 | border-radius: 4px
11 | @media screen and (max-width: $device-mobile)
12 | border-radius: 2px
13 | span
14 | img
15 | display: inline
16 | margin: auto
17 |
18 |
19 | // image
20 | .md .img-wrap
21 | margin: 1.5rem auto
22 | text-align: center
23 | border-radius: 2px
24 | overflow: hidden
25 | .img-bg
26 | width: 100%
27 | .image-caption
28 | display: block
29 | margin: .75rem auto
30 | font-size: $fontsize-code
31 | color: var(--color-meta)
32 | &:empty
33 | display: none
34 |
--------------------------------------------------------------------------------
/source/css/_style/_layout/loading.styl:
--------------------------------------------------------------------------------
1 | svg.loading
2 | display: block
3 | position: absolute
4 | color: var(--text-p3)
5 | width: 100%
6 | height: 2rem
7 | margin: auto
8 | animation: spin infinite 2s
9 | animation-timing-function: linear
10 | @keyframes spin
11 | from
12 | transform:rotate(0deg)
13 | to
14 | transform:rotate(360deg)
15 |
--------------------------------------------------------------------------------
/source/css/_style/_layout/md.styl:
--------------------------------------------------------------------------------
1 | // 以后关于 md 渲染方面的都写到这里
2 | .md
3 | >p
4 | padding-top: 4px
5 | h1,h2,h3,h4,h5,h6
6 | position: relative
7 | pointer-events: none
8 | margin-top: 0
9 | font-weight: 500
10 | >a
11 | color: inherit
12 | pointer-events: auto
13 | &:hover
14 | color: $color-hover
15 | &:before
16 | content: ''
17 | display: block
18 | margin-top: 0 - $navbar-height + $gap
19 | height: $navbar-height + $gap * 2
20 | visibility: hidden
21 | pointer-events: none
22 | h1,h2
23 | &:before
24 | margin-top: $gap-h2 - $navbar-height - $gap * 1
25 | .article-meta+h1,.article-meta+h2
26 | margin-top: $gap-h2 - $navbar-height - $gap * 4
27 | h3,h4,h5,h6
28 | margin-bottom: $gap-p
29 | h3
30 | &:before
31 | margin-top: $gap-h3 - $navbar-height - $gap
32 | h4
33 | &:before
34 | margin-top: $gap-h4 - $navbar-height - $gap
35 | h5
36 | font-weight: bold
37 | h2+h3:before
38 | margin-top: $gap-h2 - $navbar-height - $gap * 4
39 | ul,ol
40 | font-size: $fontsize-list
41 | list-style: initial
42 | padding-left: 8px
43 | margin-left: $gap
44 | margin-top: $gap-p
45 | margin-bottom: $gap-p
46 | ul,ol
47 | margin-top: 0
48 | margin-bottom: 0
49 | li
50 | margin-top: 0px
51 | margin-bottom: 0px
52 | li
53 | margin-top: 0
54 | margin-bottom: 0
55 | p
56 | margin-top: 4px
57 | margin-bottom: 0
58 | &.task-list
59 | padding-left: 0
60 | margin-left: 4px
61 | li
62 | list-style: none
63 | input
64 | margin-right: 4px
65 |
66 |
67 | ul>li
68 | list-style: initial
69 | ol>li
70 | list-style: decimal
71 |
72 | .div-ori-link
73 | display: block
74 | text-align: center
75 | margin: 4rem 0
76 | .ori-link
77 | margin: auto
78 | padding: 1em 3em
79 | border: 1px solid $color-theme
80 | border-radius: $border-button
81 | color: $color-theme
82 | font-weight: 500
83 | &:hover
84 | color: $color-hover
85 | border-color: $color-hover
86 |
--------------------------------------------------------------------------------
/source/css/_style/_layout/pagination.styl:
--------------------------------------------------------------------------------
1 | #l_main
2 | .prev-next
3 | width: 100%
4 | display: flex
5 | justify-content: space-between
6 | align-items: baseline
7 | color: var(--color-meta)
8 | margin: 0
9 | font-weight: 600
10 | .prev
11 | text-align: left
12 | border-top-right-radius: 32px
13 | border-bottom-right-radius: 32px
14 |
15 | .next
16 | text-align: right
17 | border-top-left-radius: 32px
18 | border-bottom-left-radius: 32px
19 |
20 | p
21 | margin: $gap
22 |
23 | section
24 | color: var(--color-meta)
25 | padding: $gap
26 | border-radius: $border-card
27 | &:hover
28 | color: $color-hover
29 |
30 |
31 | // 文章中
32 | .article
33 | .prev-next
34 | width: 100%
35 | display: flex
36 | justify-content: space-between
37 | align-content: flex-start
38 | margin-top: $gap * 0.5
39 | >a
40 | width: 100%
41 | padding: $gap * 0.5
42 | color: var(--color-meta)
43 | background: var(--color-block)
44 | border-radius: $border-codeblock
45 | &:hover
46 | background: bgcolor($color-hover)
47 | p.title
48 | color: $color-hover
49 | p
50 | margin: $gap * 0.5 .5rem
51 | p.title
52 | font-weight: 600
53 | font-size: $fontsize-h5
54 | >i
55 | width: 1rem
56 | p.content
57 | font-size: $fontsize-meta
58 | font-weight: 400
59 | text-align: justify
60 | word-break: break-all
61 | &:only-child
62 | margin-left: 0
63 | margin-right: 0
64 | .prev
65 | p.title
66 | text-align: left
67 | margin-left: 0
68 | margin-right: $gap * 0.5
69 |
70 | .next
71 | p.title
72 | text-align: right
73 | margin-left: $gap * 0.5
74 | margin-right: 0
75 |
--------------------------------------------------------------------------------
/source/css/_style/_layout/snackbar.styl:
--------------------------------------------------------------------------------
1 | .snackbar-wrap
2 | position: fixed
3 | width: 100%
4 | left: 0
5 | bottom: 0
6 | background: $color-theme
7 | padding: $gap
8 | z-index: 2
9 |
10 | .snackbar-content
11 | max-width: $layout-width
12 | margin: $gap auto
13 | @media screen and (max-width: $layout-width)
14 | max-width: 100%
15 |
16 | .snackbar-content
17 | p
18 | margin-top: .5rem
19 | margin-bottom: .5rem
20 | color: $color-inner
21 | .title
22 | font-size: $fontsize-h2
23 | font-weight: 600
24 | .action
25 | display: block
26 | margin: 1.5rem 0 - $gap * 0.25
27 | a
28 | margin: $gap * 0.25
29 | cursor: pointer
30 | color: $color-inner
31 | display: inline-block
32 | padding: .4em 2em
33 | font-weight: 600
34 | border-radius: 2px
35 | border: 1px solid $color-inner
36 | &:hover
37 | color: $color-theme
38 | background: $color-inner
39 |
40 | .snackbar-wrap
41 | &[theme='warning']
42 | background: #F7E751
43 | .snackbar-content
44 | p
45 | color: black
46 | a
47 | color: black
48 | border-color: black
49 | &:hover
50 | color: #F7E751
51 | background: black
52 |
--------------------------------------------------------------------------------
/source/css/_style/_layout/video.styl:
--------------------------------------------------------------------------------
1 | .md .video-wrap
2 | margin: 1.5rem auto
3 |
--------------------------------------------------------------------------------
/source/css/_style/_plugins/_dark/dark_async.styl:
--------------------------------------------------------------------------------
1 | // 异步加载的暗黑模式 暗黑模式 CSS 变量
2 |
3 | async_dark()
4 | // tag plugin from stellar
5 | --block-hover: mix($c-block-dark, $c-text-dark, 95)
6 | --text-p1: $c-text-dark
7 | --text-p3: mix($c-text-light, $c-site-bg-light, 60)
8 | --card: $c-card-light
9 |
10 | // waline Dark Color https://github.com/volantis-x/hexo-theme-volantis/issues/633
11 | if hexo-config('comments.service')=='waline'
12 | --waline-white: #000 !important
13 | --waline-light-grey: #666 !important
14 | --waline-dark-grey: #999 !important
15 | --waline-text-color: #888 !important
16 | --waline-bg-color: #1e1e1e !important
17 | --waline-bg-color-light: #272727 !important
18 | --waline-border-color: #333 !important
19 | --waline-disable-bgcolor: #444 !important
20 | --waline-disable-color: #272727 !important
21 | --waline-bq-color: #272727 !important
22 | --waline-info-bgcolor: #272727 !important
23 | --waline-info-color: #666 !important
24 |
25 |
26 | // Custom Files
27 | for $injects_darkVar in hexo-config('injects.darkVar')
28 | @import $injects_darkVar;
29 | // eg:
30 | // body
31 | // --color-site-body: blue !important
32 |
33 | @media (prefers-color-scheme: dark)
34 | :root
35 | --color-mode: 'dark'
36 | :root:not([color-scheme])
37 | async_dark()
38 | @import 'dark_plugins'
39 | [color-scheme='dark']
40 | async_dark()
41 | @import 'dark_plugins'
42 |
--------------------------------------------------------------------------------
/source/css/_style/_plugins/_highlight/highlightjs/clipboard.styl:
--------------------------------------------------------------------------------
1 | //代码块复制按钮
2 | .highlight
3 | //方便copy代码按钮(btn-copy)的定位
4 | position: relative
5 |
6 | .btn-copy
7 | z-index: 1
8 | display: inline-block
9 | cursor: pointer
10 | border: none
11 | disable-user-select()
12 | -webkit-appearance: none
13 | font-family: Menlo, $fontfamily-code
14 | font-size: 11px
15 | font-weight: bold
16 | padding: $gap * 0.25 $gap * 0.5
17 | >i
18 | margin-right: 4px
19 | color: var(--color-meta)
20 | background: var(--color-block)
21 | border-radius: 3px
22 | box-shadow: $boxshadow-card
23 | position: absolute
24 | top: 1px
25 | right: 1px
26 | opacity: 0
27 | trans()
28 | &:hover
29 | color: $color-hover
30 | background: bgcolor($color-hover)
31 |
32 | .highlight:hover .btn-copy
33 | opacity: 1
34 |
35 | .article pre:hover .btn-copy
36 | opacity: 1
37 |
--------------------------------------------------------------------------------
/source/css/_style/_plugins/_highlight/highlightjs/language.styl:
--------------------------------------------------------------------------------
1 | if hexo-config('custom_css.body.highlight.language') == true
2 | .hljs,.highlight
3 | &:before
4 | position: absolute
5 | top: 0
6 | right: 0
7 | color: var(--color-meta)
8 | font-size: 13px
9 | padding: 4px 8px
10 | &.md:before,&.markdown:before
11 | content: "md"
12 | &.yaml:before
13 | content: "YAML"
14 | &.json:before
15 | content: "JSON"
16 |
17 | &.html:before
18 | content: "HTML"
19 | &.js:before,&.javascript:before
20 | content: "JS"
21 | &.css:before
22 | content: "CSS"
23 | &.less:before
24 | content: "Less"
25 | &.stylus:before
26 | content: "Stylus"
27 |
28 | &.bash:before
29 | content: "bash"
30 | &.shell:before
31 | content: "shell"
32 | &.sh:before
33 | content: "sh"
34 | &.ini:before
35 | content: "ini"
36 |
37 | &.c:before
38 | content: "C"
39 | &.cpp:before
40 | content: "C++"
41 | &.objc:before,&.objectivec:before
42 | content: "Objective-C"
43 | &.swift:before
44 | content: "Swift"
45 |
46 | &.java:before
47 | content: "Java"
48 | &.python:before
49 | content: "Python"
50 | &.php:before
51 | content: "PHP"
52 | &.rust:before
53 | content: "Rust"
54 | &.sql:before
55 | content: "SQL"
56 | &.ruby:before
57 | content: "Ruby"
58 | &.makefile:before
59 | content: "Makefile"
60 | &.go:before
61 | content: "Go"
62 | &.typescript:before
63 | content: "TypeScript"
--------------------------------------------------------------------------------
/source/css/_style/_plugins/_highlight/index.styl:
--------------------------------------------------------------------------------
1 | @import hexo-config('plugins.code_highlight')
2 |
--------------------------------------------------------------------------------
/source/css/_style/_plugins/_highlight/prismjs/clipboard.styl:
--------------------------------------------------------------------------------
1 | //代码块复制按钮
2 | .code-toolbar
3 | //方便copy代码按钮(btn-copy)的定位
4 | position: relative
5 |
6 | .btn-copy
7 | z-index: 1
8 | display: inline-block
9 | cursor: pointer
10 | border: none
11 | disable-user-select()
12 | -webkit-appearance: none
13 | font-family: Menlo, $fontfamily-code
14 | font-size: 11px
15 | font-weight: bold
16 | padding: $gap * 0.25 $gap * 0.5
17 | >i
18 | margin-right: 4px
19 | color: var(--color-meta)
20 | background: var(--color-card)
21 | border-radius: 3px
22 | box-shadow: $boxshadow-card
23 | position: absolute
24 | top: 5px
25 | right: 5px
26 | opacity: 0
27 | trans()
28 | &:hover
29 | color: $color-hover
30 | background: bgcolor($color-hover)
31 |
32 | .code-toolbar:hover .btn-copy
33 | opacity: 1
--------------------------------------------------------------------------------
/source/css/_style/_plugins/_highlight/prismjs/index.styl:
--------------------------------------------------------------------------------
1 | @import 'clipboard'
2 | @import 'language'
3 |
4 | pre
5 | position: relative
6 | -webkit-font-smoothing: auto
7 | -moz-osx-font-smoothing: auto
8 | scrollbar()
9 |
--------------------------------------------------------------------------------
/source/css/_style/_plugins/_highlight/prismjs/language.styl:
--------------------------------------------------------------------------------
1 | if hexo-config('custom_css.body.highlight.language') == true
2 | pre
3 | &:before
4 | position: absolute
5 | top: 0
6 | right: 0
7 | color: var(--color-meta)
8 | font-size: 13px
9 | padding: 4px 8px
10 | &.language-md:before,&.markdown:before
11 | content: "md"
12 | &.language-yaml:before
13 | content: "YAML"
14 | &.language-json:before
15 | content: "JSON"
16 |
17 | &.language-html:before
18 | content: "HTML"
19 | &.language-js:before,&.language-javascript:before
20 | content: "JS"
21 | &.language-css:before
22 | content: "CSS"
23 | &.language-less:before
24 | content: "Less"
25 | &.language-stylus:before
26 | content: "Stylus"
27 |
28 | &.language-bash:before
29 | content: "bash"
30 | &.language-shell:before
31 | content: "shell"
32 | &.language-sh:before
33 | content: "sh"
34 | &.language-ini:before
35 | content: "ini"
36 |
37 | &.language-c:before
38 | content: "C"
39 | &.language-cpp:before
40 | content: "C++"
41 | &.language-objc:before,&.language-objectivec:before
42 | content: "Objective-C"
43 | &.language-swift:before
44 | content: "Swift"
45 |
46 | &.language-java:before
47 | content: "Java"
48 | &.language-python:before
49 | content: "Python"
50 | &.language-php:before
51 | content: "PHP"
52 | &.language-rust:before
53 | content: "Rust"
54 | &.language-sql:before
55 | content: "SQL"
56 | &.language-ruby:before
57 | content: "Ruby"
58 | &.language-makefile:before
59 | content: "Makefile"
60 | &.language-go:before
61 | content: "Go"
62 | &.language-typescript:before
63 | content: "TypeScript"
64 |
--------------------------------------------------------------------------------
/source/css/_style/_plugins/_rightmenu/reading.styl:
--------------------------------------------------------------------------------
1 | .common_read
2 | z-index: auto !important
3 | opacity: 1 !important
4 | overflow: visible !important
5 | transform: none !important
6 | animation: none !important
7 | position: relative !important
8 |
9 | .body-wrapper.common_read
10 | display: block
11 |
12 | #safearea.common_read
13 | padding-bottom: 16px
14 | @media screen and (max-width: 900px)
15 | padding: 0
16 | margin: 0
17 |
18 | #l_body.common_read
19 | z-index: 2147483646 !important;
20 |
21 | .read_cover
22 | min-height: 10px !important
23 | @media screen and (max-width: 900px)
24 | min-height: 0 !important
25 |
26 | .common_read_bkg
27 | background-color: var(--color-read-bkg) !important
28 | opacity: 1 !important
29 | display: block !important
30 | position: fixed !important
31 | top: 0 !important
32 | left: 0 !important
33 | right: 0 !important
34 | bottom: 0 !important
35 | z-index: 2147483645 !important
36 | transition: opacity 1s cubic-bezier(.23,1,.32,1) 0ms !important
37 |
38 | .common_read_hide
39 | opacity: 0 !important
40 | z-index: -2147483645 !important
41 |
42 | .common_read_main
43 | width: 840px !important;
44 | padding: 0 !important;
45 | margin: 0 auto;
46 | float: initial !important;
47 | @media screen and (max-width: 900px)
48 | width: auto !important;
49 |
50 | .post_read
51 | background-color: var(--color-read-post) !important
52 | z-index: 2147483646 !important
53 | overflow: visible !important
54 | font-size: 1.15rem !important
55 | border-radius: 0 !important;
56 | box-shadow: 0 6px 12px 3px #00000033
--------------------------------------------------------------------------------
/source/css/_style/_plugins/aplayer.styl:
--------------------------------------------------------------------------------
1 | @media screen and (max-width: $device-mobile)
2 | .l_header
3 | .list-v
4 | .aplayer,.aplayer-pic
5 | border-radius: $border-card * 0.5
6 | width: 64px
7 | height: 64px
8 |
9 | .aplayer-container
10 | display: flex
11 | justify-content: center
12 | min-height: 100px
13 | meting-js
14 | max-width: 100%
15 |
16 |
17 | .aplayer
18 | max-width: 500px
19 | border-radius: 4px
20 | color: var(--color-text)
21 | font-family: $fontfamily
22 | .aplayer-list
23 | text-align: left
24 | @media screen and (max-width: $device-mobile)
25 | border-radius: $border-card
26 |
27 | .l_header
28 | .aplayer-volume-wrap
29 | display: none !important // 隐藏导航栏播放器音量调节 see: https://github.com/volantis-x/hexo-theme-volantis/issues/328
30 |
31 |
32 | if hexo-config('plugins.aplayer.autoHide')
33 | .aplayer.aplayer-fixed.aplayer-narrow .aplayer-body
34 | left: -66px !important
35 | &:hover
36 | left: 0px !important
37 |
--------------------------------------------------------------------------------
/source/css/_style/_plugins/fancybox.styl:
--------------------------------------------------------------------------------
1 | .fancybox__container
2 | padding 10px !important
3 | .fancybox__slide
4 | padding 2.5rem !important
5 | .f-button
6 | &:first-child
7 | border-radius 12px 0 0 12px
8 | &:last-child
9 | border-radius 0 12px 12px 0
10 |
--------------------------------------------------------------------------------
/source/css/_style/_plugins/fontcolor.styl:
--------------------------------------------------------------------------------
1 | // Icon 颜色
2 | // https://flatuicolors.com/palette/defo
3 | .fa,
4 | .fas,
5 | .far,
6 | .fad,
7 | .fal,
8 | .fa-solid,
9 | .fa-regular,
10 | .fa-duotone,
11 | .fa-light,
12 | .fa-thin,
13 | // 图标颜色自定义
14 | .iziToast>.iziToast-body .iziToast-icon
15 | &.red
16 | color: $color-md-red
17 | &.pink
18 | color: $color-md-pink
19 | &.purple
20 | color: $color-md-purple
21 | &.indigo
22 | color: $color-md-indigo
23 | &.light-blue
24 | color: $color-md-light-blue
25 | &.deep-blue
26 | color: $color-md-deep-blue
27 | &.teal
28 | color: $color-md-teal
29 | &.light-green
30 | color: $color-md-light-green
31 | &.orange
32 | color: $color-md-orange
33 | &.deep-orange
34 | color: $color-md-deep-orange
35 | &.brown
36 | color: $color-md-brown
37 | &.blue-grey
38 | color: $color-md-blue-grey
39 | &.yellow
40 | color: $color-md-yellow
41 |
42 | &.TURQUOISE
43 | color: #1abc9c
44 | &.EMERALD
45 | color: #2ecc71
46 | &.PETERRIVE
47 | color: #3498db
48 | &.AMETHYST
49 | color: #9b59b6
50 | &.WETASPHALT
51 | color: #34495e
52 |
53 | &.GREENSEA
54 | color: #16a085
55 | &.NEPHRITIS
56 | color: #27ae60
57 | &.BELIZEHOLE
58 | color: #2980b9
59 | &.WISTERIA
60 | color: #8e44ad
61 | &.MIDNIGHTBLUE
62 | color: #2c3e50
63 |
64 | &.SUNFLOWER
65 | color: #f1c40f
66 | &.CARROT
67 | color: #e67e22
68 | &.ALIZARIN
69 | color: #e74c3c
70 | &.CLOUDS
71 | color: #ecf0f1
72 | &.CONCRETE
73 | color: #95a5a6
74 |
75 | &.ORANGE
76 | color: #f39c12
77 | &.PUMPKIN
78 | color: #d35400
79 | &.POMEGRANATE
80 | color: #c0392b
81 | &.SILVER
82 | color: #bdc3c7
83 | &.ASBESTOS
84 | color: #7f8c8d
--------------------------------------------------------------------------------
/source/css/_style/_plugins/index.styl:
--------------------------------------------------------------------------------
1 | @import 'mathjax'
2 | @import 'fontcolor'
3 |
4 |
5 | if hexo-config('plugins.code_highlight')
6 | @import '_highlight'
7 | if hexo-config('plugins.message.enable')
8 | @import 'message'
9 | if hexo-config('plugins.aplayer.enable')
10 | @import 'aplayer'
11 | if hexo-config('plugins.tianliGPT.enable')
12 | @import 'tianliGPT'
13 | if hexo-config('comments.service')=='gitalk'
14 | @import 'gitalk'
15 | if hexo-config('custom_css.cursor.enable')
16 | @import 'cursor'
17 | if hexo-config('rightmenus.enable')
18 | @import '_rightmenu/*'
19 |
20 | @import 'fancybox'
21 |
22 | // 暗黑模式样式放到最后加载
23 | if hexo-config('plugins.darkmode.enable')
24 | @import '_dark/dark_async'
--------------------------------------------------------------------------------
/source/css/_style/_plugins/mathjax.styl:
--------------------------------------------------------------------------------
1 | .article
2 | mjx-container
3 | font-family: $fontfamily-code
4 | padding: $gap $gap * 0.5
5 | border-radius: $border-codeblock
6 | min-width: 0 !important
7 | mjx-container[jax="CHTML"][display="true"], .has-jax
8 | overflow: auto hidden
9 | mjx-container + br
10 | display: none
11 |
--------------------------------------------------------------------------------
/source/css/_style/_plugins/message.styl:
--------------------------------------------------------------------------------
1 | // 覆盖消息提示的样式
2 | //.iziToast-wrapper
3 | // z-index: 2147483647 !important
4 | .iziToast-texts
5 | max-width: 300px !important
6 | min-width: 200px !important
7 | @media screen and (max-width: 500px)
8 | max-width: unset !important
9 | min-width: unset !important
10 | .iziToast-title
11 | margin-bottom: 6px !important
12 | font-size: 1rem !important
13 | .iziToast-message
14 | word-break: break-all !important
15 |
--------------------------------------------------------------------------------
/source/css/_style/_tag-plugins/Readme.md:
--------------------------------------------------------------------------------
1 | 这里存放 tag 标签 的样式
2 |
3 | 为便于管理样式, 文件名使用 tag 名称命名
4 |
5 | tag.json 索引 tag 标签名称和使用的样式文件的对应关系
6 |
7 |
--------------------------------------------------------------------------------
/source/css/_style/_tag-plugins/dropmenu.styl:
--------------------------------------------------------------------------------
1 | div.dropmenu-wrapper
2 | display: inline-block
3 |
4 | div.dropmenu
5 | position: relative
6 | display: inline-block
7 | trans()
8 | color: $color-link
9 | &:hover
10 | color: inherit
11 | >ul
12 | display: block
13 | left: 0
14 | margin-left: 0
15 | margin-top: 0px
16 | ul>li
17 | list-style: none
18 | >a
19 | &:hover
20 | text-decoration: none !important
21 | .list-v .list-v
22 | left: "calc(100% - 0.5 * %s)" % $gap
23 |
--------------------------------------------------------------------------------
/source/css/_style/_tag-plugins/frame.styl:
--------------------------------------------------------------------------------
1 | .md .frame-wrap
2 | position: relative
3 | overflow: hidden
4 | margin: 0 auto
5 | max-width: 100%
6 | display: flex
7 | flex-direction: column
8 | align-items: center
9 | img,video
10 | border-radius: 0
11 | .md .frame-wrap .frame
12 | z-index: 1
13 | display: block
14 | position: absolute;
15 | background-size: 100%;
16 | background-repeat: no-repeat;
17 | overflow: hidden;
18 |
19 | .md .img-wrap .frame-wrap
20 | &[part]
21 | height: auto
22 |
23 | .md .frame-wrap
24 | iphone11
25 | img,video
26 | width: 287px
27 | margin-top: 19px
28 | margin-bottom: 20px
29 | .frame
30 | background-image: url(https://cdn.jsdelivr.net/gh/volantis-x/cdn-volantis@3/img/frame/iphone11.svg);
31 | width: 329px
32 | height: 658px
33 | &[part='top']
34 | img,video
35 | margin-bottom: 0 !important
36 | &:not([part='bottom'])
37 | .frame
38 | top: 0
39 | &[part='bottom']
40 | img,video
41 | bottom: 0
42 | margin-top: 0 !important
43 | .frame
44 | bottom: 0
45 |
46 | @media screen and (max-width: $device-mobile)
47 | .md .frame-wrap
48 | iphone11
49 | img,video
50 | width: 208px
51 | margin-top: 13px
52 | margin-bottom: 14px
53 | .frame
54 | width: 238px
55 | height: 476px
56 |
--------------------------------------------------------------------------------
/source/css/_style/_tag-plugins/friends.styl:
--------------------------------------------------------------------------------
1 | .users-wrap
2 | overflow: hidden
3 | .group-header
4 | margin: 0 0 1rem
5 | p
6 | margin: 0
7 | font-size: $fs-14
8 | &:first-child
9 | font-size: 1.25rem
10 | font-weight: 500
11 | .group-body
12 | width: 100%
13 | display: flex
14 | flex-wrap: wrap
15 | align-items: stretch
16 | margin-bottom: 2rem
17 | .friendsjs-wrap
18 | display: block
19 | .loading-wrap
20 | min-height: 50px
21 | margin: 2rem 0
22 | text-align: center
23 |
24 | .users-wrap .user-card
25 | flex-shrink: 1
26 | display: flex
27 | align-items: stretch
28 | width: 12.5%
29 | @media screen and (max-width: 980px)
30 | width: 14.28%
31 | @media screen and (max-width: 900px)
32 | width: 16.66%
33 | @media screen and (max-width: 820px)
34 | width: 20%
35 | @media screen and (max-width: $device-tablet)
36 | width: 16.66%
37 | @media screen and (max-width: $device-mobile)
38 | width: 25%
39 | .card-link
40 | margin: 0
41 | width: 100%
42 | color: var(--text-p1)
43 | font-size: 10px
44 | font-weight: 500
45 | display: flex
46 | justify-content: flex-start
47 | flex-direction: column
48 | align-items: center
49 | text-align: center
50 | line-height: 1.2
51 | border-radius: 4px
52 | overflow: hidden
53 | position: relative
54 | padding: 1rem 0.5rem
55 | img
56 | object-fit: cover
57 | display: block
58 | width: 48px
59 | height: 48px
60 | background: var(--card)
61 | border-radius: 64px
62 | margin: 0 0 0.5rem
63 |
64 | // transform
65 | .users-wrap .user-card .card-link
66 | >img
67 | trans2 transform box-shadow
68 | &:hover
69 | background: var(--block-hover)
70 | img
71 | transform: scale(1.2) rotate(8deg)
72 | box-shadow: $boxshadow-card-float
73 |
--------------------------------------------------------------------------------
/source/css/_style/_tag-plugins/ghcard.styl:
--------------------------------------------------------------------------------
1 | a.ghcard
2 | display: inline-block
3 | line-height: 0
4 |
5 | .md .ghcard-group
6 | column-count: 2
7 | column-gap: 0
8 | margin: 0 0 - $gap * 0.5
9 | .ghcard
10 | margin: $gap * 0.5
11 |
--------------------------------------------------------------------------------
/source/css/_style/_tag-plugins/image.styl:
--------------------------------------------------------------------------------
1 | .md .img
2 | object-fit: contain
3 |
4 | img.inline
5 | display: inline !important
6 | vertical-align: middle
7 | transform: translateY(-4px)
8 |
--------------------------------------------------------------------------------
/source/css/_style/_tag-plugins/link.styl:
--------------------------------------------------------------------------------
1 | .md .tag.link
2 | margin-top: $gap-p
3 | margin-bottom: $gap-p
4 |
5 | .md .link-card
6 | margin-right: $gap-p
7 | background: var(--color-block)
8 | display: inline-flex
9 | align-items: center
10 | cursor: pointer
11 | text-align: center
12 | width: $device-mobile-l - 4 * $gap
13 | max-width: 100%
14 | box-shadow: $boxshadow-card
15 | @media screen and (max-width: $device-mobile-l)
16 | max-width: 100%
17 | width: 100%
18 | color: var(--color-p)
19 | border-radius: $border-card
20 | &:hover
21 | box-shadow: $boxshadow-float, $boxshadow-card-float
22 |
23 |
24 | .md .link-card
25 | div.left,div.right
26 | pointer-events: none
27 | div.left
28 | width: 54px
29 | height: 54px
30 | margin: 12px
31 | overflow: hidden
32 | flex-shrink: 0
33 | position: relative
34 | i
35 | font-size: 32px
36 | line-height: 48px
37 | margin-left: 4px
38 | img
39 | display: block
40 | position: absolute
41 | border-radius: $border-card / 4
42 | top: 50%
43 | left: 50%
44 | transform: translate(-50%, -50%)
45 | div.right
46 | overflow: hidden
47 | margin-right: 16px
48 | p
49 | margin: 0
50 | txt-ellipsis()
51 | p.text
52 | font-weight: bold
53 | p.url
54 | flex-shrink: 0
55 | color: var(--color-meta)
56 | font-size: $fontsize-code
57 |
58 | .md .link-group
59 | display: grid
60 | grid-template-columns: 1fr 1fr
61 | @media screen and (max-width: $device-mobile-l * 2)
62 | grid-template-columns: 1fr
63 | grid-gap: $gap
64 | .tag.link
65 | margin: 0
66 | .link-card
67 | width: 100%
68 |
--------------------------------------------------------------------------------
/source/css/_style/_tag-plugins/media.styl:
--------------------------------------------------------------------------------
1 | $sp = 4px
2 |
3 | audio,video
4 | border-radius: $border-codeblock
5 | max-width: 100%
6 | video
7 | z-index: 1
8 | trans()
9 | &:hover
10 | box-shadow: 0 4px 8px 0px rgba(0, 0, 0, 0.24), 0 8px 16px 0px rgba(0, 0, 0, 0.24)
11 |
12 | div.video
13 | line-height: 0
14 | text-align: center
15 |
16 | div.videos
17 | max-width: "calc(100% + 2 * %s)" % $sp
18 | display: flex
19 | flex-wrap: wrap
20 | justify-content: flex-start
21 | align-items: flex-end
22 | margin: $gap-p 0 - $sp
23 | .video,iframe
24 | width: 100%
25 | margin: $sp
26 |
27 | iframe
28 | border-radius: $border-codeblock
29 | width: 100%
30 | min-height: 300px
31 | &.left
32 | justify-content: flex-start
33 | &.center
34 | justify-content: center
35 | &.right
36 | justify-content: flex-end
37 | &.stretch
38 | align-items: stretch
39 | &[col='1']
40 | .video,iframe
41 | width: 100%
42 | &[col='2']
43 | .video,iframe
44 | width: "calc(50% - 2 * %s)" % $sp
45 | &[col='3']
46 | .video,iframe
47 | width: "calc(33.33% - 2 * %s)" % $sp
48 | &[col='4']
49 | .video,iframe
50 | width: "calc(25% - 2 * %s)" % $sp
51 |
--------------------------------------------------------------------------------
/source/css/_style/_tag-plugins/span.styl:
--------------------------------------------------------------------------------
1 | p.p.subtitle
2 | font-weight: bold
3 | color: mix($color-theme, $color-text, 75)
4 | font-size: 1.25rem !important
5 | padding-top: 1.5rem
6 | &:first-child
7 | padding-top: 1rem
8 |
9 | span.p,p.p
10 | &.logo
11 | font-family: $fontfamily-logo
12 | &.code
13 | font-family: $fontfamily-code
14 | &.left
15 | display: block
16 | text-align: left
17 | &.center
18 | display: block
19 | text-align: center
20 | &.right
21 | display: block
22 | text-align: right
23 |
24 | span.p,p.p
25 | &.small
26 | font-size: $fontsize-meta
27 | &.large
28 | font-size: $fontsize-large
29 | line-height: 1.4
30 | &.huge
31 | font-size: $fontsize-huge
32 | line-height: 1.4
33 | &.ultra
34 | font-size: $fontsize-ultra
35 | line-height: 1.4
36 | &.small,&.large,&.huge,&.ultra
37 | margin: 0
38 | padding: 0
39 | &.bold
40 | font-weight: bold
41 | &.h1,&.h2
42 | padding-bottom: .2rem
43 | font-weight: 500
44 | &.h1
45 | font-size: $fontsize-h1
46 | color: var(--color-h1)
47 | padding-top: $gap-p * 2
48 | &.h2
49 | font-size: $fontsize-h2
50 | color: var(--color-h2)
51 | padding-top: $gap-p * 2
52 | border-bottom: 1px solid alpha($color-text, .1)
53 | &.h3
54 | font-size: $fontsize-h3
55 | color: var(--color-h3)
56 | padding-top: $gap-p * 2
57 | &.h4
58 | font-size: $fontsize-h4
59 | color: var(--color-h4)
60 | padding-top: $gap-p * 2
61 | &.h5
62 | font-size: $fontsize-h5
63 | color: var(--color-h5)
64 | padding-top: $gap-p * 1.5
65 |
66 | span.p,p.p
67 | &.red
68 | color: $color-mac-red
69 | &.yellow
70 | color: $color-mac-yellow
71 | &.green
72 | color: $color-mac-green
73 | &.cyan
74 | color: $color-mac-cyan
75 | &.blue
76 | color: $color-md-blue
77 | &.purple
78 | color: $color-md-purple
79 | &.gray
80 | color: #999
81 |
--------------------------------------------------------------------------------
/source/css/_style/_tag-plugins/swiper.styl:
--------------------------------------------------------------------------------
1 | .swiper-container
2 | width: 100%
3 | border-radius: 4px
4 | --gap-p: 2rem
5 | .swiper-container:not(.swiper-container-initialized)
6 | display: none
7 | div.swiper-slide
8 | text-align: center
9 | display: -webkit-box
10 | display: -ms-flexbox
11 | display: -webkit-flex
12 | display: flex
13 | align-self: center
14 | -webkit-box-pack: center
15 | -ms-flex-pack: center
16 | -webkit-justify-content: center
17 | justify-content: center
18 | -webkit-box-align: center
19 | -ms-flex-align: center
20 | -webkit-align-items: center
21 | align-items: center
22 | width: 50%
23 | img
24 | border-radius: 4px
25 |
26 | .swiper-container[width='max'] div.swiper-slide
27 | width: 100%
28 |
29 | .swiper-container[width='min'] div.swiper-slide
30 | width: 25%
31 |
32 | .swiper-button-prev,.swiper-button-next
33 | padding: 1rem 0.5rem
34 | margin-top: -2rem !important
35 | border-radius: 4px
36 | background: alpha(white, 0.25)
37 | trans1 background
38 | --swiper-theme-color: black !important
39 | &:after
40 | font-size: 1.2rem !important
41 | font-weight: 700 !important
42 | &:hover
43 | background: white !important
44 | --swiper-theme-color: $color-hover !important
--------------------------------------------------------------------------------
/source/css/_style/_tag-plugins/table.styl:
--------------------------------------------------------------------------------
1 | .md
2 | .table
3 | overflow: auto
4 | margin-top: $gap-p
5 | margin-bottom: $gap-p
6 | table
7 | display: table
8 | width: 100%
9 |
--------------------------------------------------------------------------------
/source/css/_style/_tag-plugins/tabs.styl:
--------------------------------------------------------------------------------
1 | $border-color = alpha($color-p, .2)
2 | $tbr = 4px
3 |
4 | div.tabs
5 | display: block
6 | position: relative
7 | margin-top: $gap-p
8 | margin-bottom: $gap-p
9 | border-radius: $tbr
10 | background: var(--color-card)
11 | border: 1px solid $border-color
12 | font-size: $fontsize-list
13 | .highlight,p,ul,ol,div.note,details
14 | margin-top: $gap-p
15 | margin-bottom: $gap-p
16 |
17 | div.tabs
18 | ul.nav-tabs
19 | display: flex
20 | overflow-x: auto
21 | white-space: nowrap
22 | justify-content: flex-start
23 | margin: 0 !important
24 | padding: 8px 8px 0 8px
25 | background: var(--color-block)
26 | border-radius: $tbr $tbr 0 0
27 | line-height: 1.5
28 | li.tab
29 | list-style-type: none
30 | margin-top: 0
31 | margin-bottom: 0
32 | &:last-child
33 | padding-right: $gap
34 | a
35 | display: block
36 | cursor: pointer
37 | border-radius: $tbr $tbr 0 0
38 | padding: $gap * 0.5
39 | text-align: center
40 | font-size: $fontsize-meta
41 | line-height: inherit
42 | font-weight: bold
43 | color: var(--color-meta)
44 | border: 1px solid transparent
45 | &:hover
46 | color: var(--color-p)
47 | i
48 | pointer-events: none
49 | &.active a
50 | cursor: default
51 | color: var(--color-p)
52 | background: $color-card
53 | border: 1px solid $border-color
54 | border-bottom: 1px solid var(--color-card)
55 |
56 | .tab-content
57 | border-top: 1px solid $border-color
58 | margin-top: -1px
59 | .tab-pane
60 | padding: $gap
61 | &:not(.active)
62 | display: none
63 | &.active
64 | display: block
65 | >
66 | p,.tabs,ul,ol,.highlight,.note
67 | &:first-child
68 | margin-top: 0
69 | &:last-child
70 | margin-bottom: 0
71 |
--------------------------------------------------------------------------------
/source/css/_style/_tag-plugins/tag.json:
--------------------------------------------------------------------------------
1 | {
2 | "note": ["note.styl"],
3 | "tabs": ["tabs.styl"],
4 | "u": ["text.styl"],
5 | "emp": ["text.styl"],
6 | "wavy": ["text.styl"],
7 | "del": ["text.styl"],
8 | "kbd": ["text.styl"],
9 | "psw": ["text.styl"],
10 | "span": ["span.styl"],
11 | "p": ["span.styl"],
12 | "noteblock": ["note.styl"],
13 | "folding": ["folding.styl"],
14 | "checkbox": ["checkbox.styl"],
15 | "radio": ["checkbox.styl"],
16 | "timeline": ["timeline.styl"],
17 | "timenode": ["timeline.styl"],
18 | "link": ["link.styl"],
19 | "btn": ["btns.styl"],
20 | "btns": ["btns.styl"],
21 | "table": ["table.styl"],
22 | "ghcard": ["ghcard.styl"],
23 | "sites": ["sites.styl"],
24 | "menu": ["dropmenu.styl"],
25 | "inlineimage": ["image.styl"],
26 | "image": ["image.styl"],
27 | "gallery": ["fancybox.styl"],
28 | "audio": ["media.styl"],
29 | "video": ["media.styl"],
30 | "videos": ["media.styl"],
31 | "frame": ["frame.styl"],
32 | "contributors": ["friends.styl"],
33 | "friends": ["friends.styl"],
34 | "swiper": ["swiper.styl"]
35 | }
--------------------------------------------------------------------------------
/source/css/_style/_tag-plugins/text.styl:
--------------------------------------------------------------------------------
1 | .article
2 | del
3 | color: mix($color-p, $color-card, 60)
4 | text-decoration-color: @color
5 | u
6 | color: var(--color-text)
7 | text-decoration: none
8 | border-bottom: 1px solid $color-mac-red
9 | emp
10 | color: var(--color-text)
11 | border-bottom: 4px dotted $color-mac-red
12 | wavy
13 | color: var(--color-text)
14 | text-decoration-style: wavy
15 | text-decoration-line: underline
16 | text-decoration-color: $color-mac-red
17 | psw
18 | color: transparent
19 | background: mix($color-text, $color-card, 50)
20 | border-radius: 2px
21 | trans()
22 | &:hover
23 | color: var(--color-p)
24 | background: none
25 | kbd
26 | border-radius: 4px
27 | border: 1px solid mix($color-block, $color-text, 80)
28 | border-bottom-width: 2px
29 | background: mix($color-block, $color-card, 50)
30 | padding-left: 4px
31 | padding-right: 4px
--------------------------------------------------------------------------------
/source/css/_style/_tag-plugins/timeline.styl:
--------------------------------------------------------------------------------
1 | div.timenode
2 | position: relative
3 | &:before, &:after
4 | content: ''
5 | z-index: 1
6 | position: absolute
7 | background: alpha($color-theme, .5)
8 | width: 2px
9 | left: 7px
10 | &:before
11 | top: 0px
12 | height: 6px
13 | &:after
14 | top: 26px
15 | height: "calc(100% - %s)" % 26px
16 | &:last-child
17 | &:after
18 | height: "calc(100% - 26px - %s)" % $gap
19 | border-bottom-left-radius: 2px
20 | border-bottom-right-radius: 2px
21 | .meta,.body
22 | max-width: "calc(100% - %s)" % (16px + 8px)
23 | .meta
24 | position: relative
25 | color: var(--color-meta)
26 | font-size: $fontsize-meta
27 | line-height: 32px
28 | height: 32px
29 | &:before, &:after
30 | content: ''
31 | position: absolute
32 | top: 8px
33 | z-index: 2
34 | &:before
35 | background: alpha($color-theme, .5)
36 | width: 16px
37 | height: 16px
38 | border-radius: 8px
39 | &:after
40 | background: $color-theme
41 | margin-left: 2px
42 | margin-top: 2px
43 | width: 12px
44 | height: 12px
45 | border-radius: 6px
46 | transform: scale(0.5)
47 | trans()
48 | p
49 | font-weight: bold
50 | margin: 0 0 0 16px + 8px
51 | .body
52 | margin: 4px 0 $gap 16px + 8px
53 | padding: $gap
54 | border-radius: $border-card
55 | background: var(--color-block)
56 | display: inline-block
57 | &:empty
58 | display: none
59 | >*
60 | &:first-child
61 | margin-top: $gap-p * 0.25
62 | &:last-child
63 | margin-bottom: $gap-p * 0.25
64 | .highlight
65 | border: 1px solid mix($color-block, $color-text, 90)
66 |
67 |
68 | div.timenode:hover
69 | .meta
70 | color: var(--color-text)
71 | &:before
72 | background: alpha($color-hover, .5)
73 | &:after
74 | background: $color-hover
75 | transform: scale(1)
76 |
--------------------------------------------------------------------------------
/source/css/_style/index.styl:
--------------------------------------------------------------------------------
1 | @import '_base/*'
2 |
3 | @import '_layout/*'
4 |
5 | @import '_tag-plugins/*'
6 |
7 | // 暗黑模式样式放到最后加载
8 | @import '_plugins/index'
--------------------------------------------------------------------------------
/source/css/first.styl:
--------------------------------------------------------------------------------
1 | #safearea {
2 | display: none
3 | }
4 |
5 | if hexo-config('content_visibility')
6 | // https://web.dev/content-visibility/
7 | // https://www.caniuse.com/?search=content-visibility
8 | /*
9 | * Workaround for Chrome bug, part 1
10 | * Chunk rendering for all but the first article.
11 | * /layout/_partial/scripts/content-visibility-scroll-fix.ejs
12 | */
13 | .post-story + .post-story{
14 | content-visibility: auto;
15 | contain-intrinsic-size: 10px 500px;
16 | }
17 |
18 | @import '_defines/*'
19 |
20 | // Project
21 | @import '_first/*'
22 |
23 | // Custom Files
24 | for $injects_first in hexo-config('injects.first')
25 | @import $injects_first;
--------------------------------------------------------------------------------
/source/css/style.styl:
--------------------------------------------------------------------------------
1 | #safearea{
2 | display: block
3 | }
4 |
5 | @import '_defines/*'
6 |
7 | // Project
8 | @import '_style'
9 |
10 | // Custom Files
11 | for $injects_style in hexo-config('injects.style')
12 | @import $injects_style;
13 |
14 |
--------------------------------------------------------------------------------
21 | 22 | 23 | 24 | <% if(theme.article.body.meta_library.artalkcount.desc) { %> 25 | <%- theme.article.body.meta_library.artalkcount.desc %> 26 | <% } %> 27 |
28 | 29 |