hexo-theme-gnix 1.2.1 → 2.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/include/hexo/renderer.js +58 -0
- package/include/register.js +1 -1
- package/layout/common/head.jsx +0 -15
- package/layout/common/plugins.jsx +0 -5
- package/layout/common/scripts.jsx +5 -0
- package/layout/plugin/cookie_consent.jsx +1 -45
- package/package.json +6 -3
- package/include/hexo/generator/manifest.js +0 -23
- package/layout/misc/web_app.jsx +0 -106
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const { transformSync } = require("esbuild");
|
|
2
|
+
const { createElement } = require("inferno-create-element");
|
|
3
|
+
const { renderToStaticMarkup } = require("inferno-server");
|
|
4
|
+
const fs = require("node:fs");
|
|
5
|
+
const Module = require("node:module");
|
|
6
|
+
|
|
7
|
+
Module._extensions[".jsx"] = (module, filename) => {
|
|
8
|
+
const content = fs.readFileSync(filename, "utf8");
|
|
9
|
+
const { code } = transformSync(content, {
|
|
10
|
+
loader: "jsx",
|
|
11
|
+
format: "cjs",
|
|
12
|
+
jsxFactory: "__createElement",
|
|
13
|
+
jsxFragment: "__Fragment",
|
|
14
|
+
banner:
|
|
15
|
+
"const __createElement = require('inferno-create-element').createElement; const __Fragment = require('inferno').Fragment;",
|
|
16
|
+
sourcefile: filename,
|
|
17
|
+
});
|
|
18
|
+
module._compile(code, filename);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
function compile(data) {
|
|
22
|
+
const Component = require(data.path);
|
|
23
|
+
const DOCTYPE = "<!doctype html>\n";
|
|
24
|
+
const startTag = "<html";
|
|
25
|
+
|
|
26
|
+
return (locals) => {
|
|
27
|
+
const element = createElement(Component, locals);
|
|
28
|
+
const markup = renderToStaticMarkup(element);
|
|
29
|
+
// test if the layout is root layout file so we can skip costly large string comparison
|
|
30
|
+
if ("layout" in locals && "view_dir" in locals && "filename" in locals) {
|
|
31
|
+
if (
|
|
32
|
+
locals.filename.startsWith(locals.view_dir) &&
|
|
33
|
+
locals.layout === false
|
|
34
|
+
) {
|
|
35
|
+
// this is root layout file, add doctype
|
|
36
|
+
return DOCTYPE + markup;
|
|
37
|
+
}
|
|
38
|
+
return markup;
|
|
39
|
+
}
|
|
40
|
+
// do not use substr, substring, slice to prevent string copy
|
|
41
|
+
for (let i = 0; i < 5; i++) {
|
|
42
|
+
if (markup.charAt(i).toLowerCase() !== startTag.charAt(i)) {
|
|
43
|
+
return markup;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return DOCTYPE + markup;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function renderer(data, locals) {
|
|
51
|
+
return compile(data)(locals);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
renderer.compile = compile;
|
|
55
|
+
|
|
56
|
+
module.exports = (hexo) => {
|
|
57
|
+
hexo.extend.renderer.register("jsx", "html", renderer, true);
|
|
58
|
+
};
|
package/include/register.js
CHANGED
|
@@ -3,9 +3,9 @@ module.exports = (hexo) => {
|
|
|
3
3
|
require("./hexo/generator/insight")(hexo);
|
|
4
4
|
require("./hexo/generator/categories")(hexo);
|
|
5
5
|
require("./hexo/generator/category")(hexo);
|
|
6
|
-
require("./hexo/generator/manifest")(hexo);
|
|
7
6
|
require("./hexo/generator/tags")(hexo);
|
|
8
7
|
require("./hexo/helper/cdn")(hexo);
|
|
9
8
|
require("./hexo/helper/page")(hexo);
|
|
10
9
|
require("./hexo/view").init(hexo);
|
|
10
|
+
require("./hexo/renderer")(hexo);
|
|
11
11
|
};
|
package/layout/common/head.jsx
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
const { Component } = require("../../include/util/common");
|
|
2
2
|
const MetaTags = require("../../layout/misc/meta");
|
|
3
|
-
const WebApp = require("../../layout/misc/web_app");
|
|
4
3
|
const OpenGraph = require("../../layout/misc/open_graph");
|
|
5
4
|
const StructuredData = require("../../layout/misc/structured_data");
|
|
6
5
|
const Plugins = require("./plugins");
|
|
@@ -37,7 +36,6 @@ module.exports = class extends Component {
|
|
|
37
36
|
const { url, head = {}, article } = config;
|
|
38
37
|
const {
|
|
39
38
|
meta = [],
|
|
40
|
-
manifest = {},
|
|
41
39
|
open_graph = {},
|
|
42
40
|
structured_data = {},
|
|
43
41
|
canonical_url = page.permalink,
|
|
@@ -116,13 +114,6 @@ module.exports = class extends Component {
|
|
|
116
114
|
{noIndex ? <meta name="robots" content="noindex" /> : null}
|
|
117
115
|
{meta?.length ? <MetaTags meta={meta} /> : null}
|
|
118
116
|
<title>{getPageTitle(page, config.title, helper)}</title>
|
|
119
|
-
<WebApp.Cacheable
|
|
120
|
-
helper={helper}
|
|
121
|
-
favicon={favicon}
|
|
122
|
-
icons={manifest.icons}
|
|
123
|
-
themeColor={manifest.theme_color}
|
|
124
|
-
name={manifest.name || config.title}
|
|
125
|
-
/>
|
|
126
117
|
{typeof open_graph === "object" && open_graph !== null ? (
|
|
127
118
|
<OpenGraph
|
|
128
119
|
type={open_graph.type || (is_post(page) ? "article" : "website")}
|
|
@@ -202,7 +193,6 @@ module.exports = class extends Component {
|
|
|
202
193
|
href={url_for("/css/responsive/desktop.css")}
|
|
203
194
|
media="screen and (min-width:1024px)"
|
|
204
195
|
/>
|
|
205
|
-
<script type="text/javascript" src="/js/theme-selector.js"></script>
|
|
206
196
|
<link
|
|
207
197
|
rel="preload"
|
|
208
198
|
as="style"
|
|
@@ -210,11 +200,6 @@ module.exports = class extends Component {
|
|
|
210
200
|
onload="this.onload=null;this.rel='stylesheet'"
|
|
211
201
|
/>
|
|
212
202
|
<link rel="stylesheet" href="/css/shiki/shiki.css" />
|
|
213
|
-
{/* Iconify Icons */}
|
|
214
|
-
<script
|
|
215
|
-
async
|
|
216
|
-
src="/js/host/iconify-icon/3.0.2/iconify-icon.min.js"
|
|
217
|
-
></script>
|
|
218
203
|
{/* Maple Mono CN */}
|
|
219
204
|
<link
|
|
220
205
|
rel="preload"
|
|
@@ -2,7 +2,6 @@ const {
|
|
|
2
2
|
Component,
|
|
3
3
|
Fragment,
|
|
4
4
|
loadComponent,
|
|
5
|
-
handleWidgetError,
|
|
6
5
|
} = require("../../include/util/common");
|
|
7
6
|
|
|
8
7
|
module.exports = class extends Component {
|
|
@@ -18,10 +17,6 @@ module.exports = class extends Component {
|
|
|
18
17
|
return null;
|
|
19
18
|
}
|
|
20
19
|
const Plugin = loadComponent(`plugin/${name}`);
|
|
21
|
-
if (!Plugin) {
|
|
22
|
-
handleWidgetError(`plugin "${name}"`);
|
|
23
|
-
return null;
|
|
24
|
-
}
|
|
25
20
|
return (
|
|
26
21
|
<Plugin
|
|
27
22
|
site={site}
|
|
@@ -18,6 +18,11 @@ module.exports = class extends Component {
|
|
|
18
18
|
head={false}
|
|
19
19
|
/>
|
|
20
20
|
<script defer data-pjax src="/js/main.js"></script>
|
|
21
|
+
<script
|
|
22
|
+
async
|
|
23
|
+
src="/js/host/iconify-icon/3.0.2/iconify-icon.min.js"
|
|
24
|
+
></script>
|
|
25
|
+
<script async src="/js/theme-selector.js"></script>
|
|
21
26
|
<script
|
|
22
27
|
defer
|
|
23
28
|
src="/js/host/medium-zoom/dist/medium-zoom.min.js"
|
|
@@ -1,27 +1,5 @@
|
|
|
1
1
|
const { Component, cacheComponent } = require("../../include/util/common");
|
|
2
|
-
|
|
3
|
-
* A JSX component for alerting users about the use of cookies.
|
|
4
|
-
*
|
|
5
|
-
* @see https://www.osano.com/cookieconsent/
|
|
6
|
-
* @example
|
|
7
|
-
* <CookieConsent
|
|
8
|
-
* head={true}
|
|
9
|
-
* type="info"
|
|
10
|
-
* theme="classic"
|
|
11
|
-
* static={false}
|
|
12
|
-
* position="bottom-left"
|
|
13
|
-
* policyLink="/path/to/cookie/policy"
|
|
14
|
-
* text={{
|
|
15
|
-
* message: 'This website uses cookies to improve your experience.',
|
|
16
|
-
* dismiss: 'Got it!',
|
|
17
|
-
* allow: 'Allow cookies',
|
|
18
|
-
* deny: 'Decline',
|
|
19
|
-
* link: 'Learn more',
|
|
20
|
-
* policy: 'Cookie Policy',
|
|
21
|
-
* }}
|
|
22
|
-
* cssUrl="/path/to/cookieconsent.css"
|
|
23
|
-
* jsUrl="/path/to/cookieconsent.js" />
|
|
24
|
-
*/
|
|
2
|
+
|
|
25
3
|
class CookieConsent extends Component {
|
|
26
4
|
render() {
|
|
27
5
|
const { head, text, jsUrl, cssUrl } = this.props;
|
|
@@ -74,28 +52,6 @@ class CookieConsent extends Component {
|
|
|
74
52
|
}
|
|
75
53
|
}
|
|
76
54
|
|
|
77
|
-
/**
|
|
78
|
-
* Cacheable JSX component for alerting users about the use of cookies.
|
|
79
|
-
* <p>
|
|
80
|
-
* This class is supposed to be used in combination with the <code>locals</code> hexo filter
|
|
81
|
-
* ({@link module:hexo/filter/locals}).
|
|
82
|
-
*
|
|
83
|
-
* @see module:util/cache.cacheComponent
|
|
84
|
-
* @example
|
|
85
|
-
* <CookieConsent.Cacheable
|
|
86
|
-
* head={true}
|
|
87
|
-
* plugin={{
|
|
88
|
-
* info: "info",
|
|
89
|
-
* theme: "classic",
|
|
90
|
-
* static: false,
|
|
91
|
-
* position: "bottom-left",
|
|
92
|
-
* policyLink: "/path/to/cookie/policy"
|
|
93
|
-
* }}
|
|
94
|
-
* helper={{
|
|
95
|
-
* __: function() {...},
|
|
96
|
-
* cdn: function() {...}
|
|
97
|
-
* }} />
|
|
98
|
-
*/
|
|
99
55
|
CookieConsent.Cacheable = cacheComponent(
|
|
100
56
|
CookieConsent,
|
|
101
57
|
"plugin.cookieconsent",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hexo-theme-gnix",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"author": "Efterklang <gaojiaxing0220@gmail.com>",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Second generation of Hexo theme Icarus, now with Catppuccin flavor and night mode support.",
|
|
@@ -33,9 +33,12 @@
|
|
|
33
33
|
"README.md"
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"date-fns": "^
|
|
36
|
+
"date-fns": "^4.1.0",
|
|
37
|
+
"esbuild": "^0.27.2",
|
|
37
38
|
"hexo-pagination": "^4.0.0",
|
|
38
|
-
"
|
|
39
|
+
"inferno": "^9.0.10",
|
|
40
|
+
"inferno-create-element": "^9.0.10",
|
|
41
|
+
"inferno-server": "^9.0.10",
|
|
39
42
|
"js-yaml": "^4.1.1"
|
|
40
43
|
},
|
|
41
44
|
"peerDependencies": {
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Web app manifest.json generator.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
module.exports = (hexo) => {
|
|
6
|
-
hexo.extend.generator.register("manifest", function (_locals) {
|
|
7
|
-
const url_for = hexo.extend.helper.get("url_for").bind(this);
|
|
8
|
-
let { manifest = {} } = this.theme?.config?.head || {};
|
|
9
|
-
|
|
10
|
-
manifest = Object.assign({}, manifest);
|
|
11
|
-
if (!manifest.name) {
|
|
12
|
-
manifest.name = this.config.title;
|
|
13
|
-
}
|
|
14
|
-
if (!manifest.start_url) {
|
|
15
|
-
manifest.start_url = url_for("/index.html");
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
return {
|
|
19
|
-
path: "/manifest.json",
|
|
20
|
-
data: JSON.stringify(manifest),
|
|
21
|
-
};
|
|
22
|
-
});
|
|
23
|
-
};
|
package/layout/misc/web_app.jsx
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Web app meta tags.
|
|
3
|
-
* @module view/misc/web_app
|
|
4
|
-
*/
|
|
5
|
-
const { Component, cacheComponent } = require("../../include/util/common");
|
|
6
|
-
/**
|
|
7
|
-
* Web app meta tags.
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* <WebApp
|
|
11
|
-
* name="******"
|
|
12
|
-
* manifest="/path/to/manifest.json"
|
|
13
|
-
* tileIcon="/path/to/image"
|
|
14
|
-
* themeColor="#000000"
|
|
15
|
-
* icons={[
|
|
16
|
-
* { src: '/path/to/image', sizes: '128x128 256x256' },
|
|
17
|
-
* { src: '/path/to/image', sizes: '512x512' },
|
|
18
|
-
* ]} />
|
|
19
|
-
*/
|
|
20
|
-
class WebApp extends Component {
|
|
21
|
-
render() {
|
|
22
|
-
const { name, manifest, tileIcon, themeColor } = this.props;
|
|
23
|
-
|
|
24
|
-
let icons = [];
|
|
25
|
-
if (Array.isArray(this.props.icons)) {
|
|
26
|
-
icons = this.props.icons.map((icon) => {
|
|
27
|
-
const { sizes, src } = icon;
|
|
28
|
-
if (src && sizes) {
|
|
29
|
-
return icon.sizes.split(/\s+/).map((size) => ({ sizes: size, src }));
|
|
30
|
-
}
|
|
31
|
-
return null;
|
|
32
|
-
});
|
|
33
|
-
icons = icons.filter(Boolean);
|
|
34
|
-
icons = [].concat(...icons);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return (
|
|
38
|
-
<>
|
|
39
|
-
<link rel="manifest" href={manifest} />
|
|
40
|
-
{themeColor ? <meta name="theme-color" content={themeColor} /> : null}
|
|
41
|
-
{/* Windows Pinned Site */}
|
|
42
|
-
<meta name="application-name" content={name} />
|
|
43
|
-
{tileIcon ? (
|
|
44
|
-
<meta name="msapplication-TileImage" content={tileIcon} />
|
|
45
|
-
) : null}
|
|
46
|
-
{themeColor ? (
|
|
47
|
-
<meta name="msapplication-TileColor" content={themeColor} />
|
|
48
|
-
) : null}
|
|
49
|
-
{/* iOS home screen launcher */}
|
|
50
|
-
<meta name="mobile-web-app-capable" content="yes" />
|
|
51
|
-
<meta name="apple-mobile-web-app-title" content={name} />
|
|
52
|
-
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
|
|
53
|
-
{icons.map((icon) => (
|
|
54
|
-
<link rel="apple-touch-icon" sizes={icon.sizes} href={icon.src} />
|
|
55
|
-
))}
|
|
56
|
-
</>
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Cacheable web app meta tags.
|
|
63
|
-
* <p>
|
|
64
|
-
* This class is supposed to be used in combination with the <code>locals</code> hexo filter
|
|
65
|
-
* ({@link module:hexo/filter/locals}) and manifest generator ({@link module:hexo/generator/manifest}).
|
|
66
|
-
*
|
|
67
|
-
* @see module:util/cache.cacheComponent
|
|
68
|
-
* @example
|
|
69
|
-
* <WebApp.Cacheable
|
|
70
|
-
* name="******"
|
|
71
|
-
* themeColor="#000000"
|
|
72
|
-
* favicon="/path/to/image"
|
|
73
|
-
* icons={[
|
|
74
|
-
* { src: '/path/to/image', sizes: '128x128 256x256' },
|
|
75
|
-
* { src: '/path/to/image', sizes: '512x512' },
|
|
76
|
-
* ]}
|
|
77
|
-
* helper={{ url_for: function() {...} }} />
|
|
78
|
-
*/
|
|
79
|
-
WebApp.Cacheable = cacheComponent(WebApp, "misc.webapp", (props) => {
|
|
80
|
-
const { name, themeColor, favicon, icons, helper } = props;
|
|
81
|
-
|
|
82
|
-
let tileIcon = null;
|
|
83
|
-
if (Array.isArray(icons)) {
|
|
84
|
-
tileIcon = icons.find(
|
|
85
|
-
(icon) => icon.sizes.toLowerCase().indexOf("144x144") > -1,
|
|
86
|
-
);
|
|
87
|
-
if (tileIcon) {
|
|
88
|
-
tileIcon = tileIcon.src;
|
|
89
|
-
} else if (icons.length) {
|
|
90
|
-
tileIcon = icons[0].src;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
if (!tileIcon) {
|
|
94
|
-
tileIcon = favicon;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
return {
|
|
98
|
-
name,
|
|
99
|
-
icons,
|
|
100
|
-
tileIcon,
|
|
101
|
-
themeColor,
|
|
102
|
-
manifest: helper.url_for("/manifest.json"),
|
|
103
|
-
};
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
module.exports = WebApp;
|