更新版本

This commit is contained in:
浪子 2024-06-14 14:03:34 +08:00
parent b0850b5902
commit ebe51c2356
31 changed files with 861 additions and 1209 deletions

View File

@ -47,6 +47,7 @@ theme = 'farallon'
authorName = '老孙'
authorDescription = '资深网民孙先生'
authorAvatar = 'https://i.sunpeiwen.com/source/img/logo.jpg'
icon = 'https://i.sunpeiwen.com/source/img/logo.jpg'
commentDomain = ''
telegram = 'https://t.me/s/imsunpw'
feed = '/index.xml'
@ -54,12 +55,16 @@ theme = 'farallon'
instagram = 'https://www.instagram.com/imsunpw/'
github = 'https://github.com/jkjoy'
footer_sns = true
post_like = true
post_view = true
actionDomain = 'https://v.wpista.com/'
dbAPIBase = 'https://db.imsun.org/'
twikoo = 'https://twikoo.ima.cm/'
[outputs]
home = [ "HTML","JSON","RSS","SITEMAP"]
page = ["HTML"]
[markup.tableOfContents]
endLevel = 5
startLevel = 3

View File

@ -1,155 +0,0 @@
# Hugo Theme Farallon
![Hugo Theme Farallon](https://static.fatesinger.com/2023/06/u1ak8xgmyn9ec24r.png)
Farallon is a simple single column hugo theme with perfect performace and elegance design.
## Usage
```
git submodule add https://github.com/bigfa/hugo-theme-farallon.git themes/farallon
echo "theme = 'farallon'" >> hugo.toml
```
[Full demo site](https://github.com/bigfa/bigfa.github.io)
## Release Notes
### 0.3.7
- add footer sns icons
### 0.3.6
- add post category card
- add github icon
### 0.3.5
- add author sns icons
### 0.3.4
- change category file name
### 0.3.3
- add post type memo
### 0.3.2
- add story author card
### 0.3.1
- add sticky icon
- fixed db list style in dark mode
### 0.3.0
- add search
### 0.2.11
- add link shortcode
### 0.2.10
- fixed category list and tag list style
- relative time support i18n
### 0.2.9
- fixed url render error
- add friend links template
### 0.2.8
- add `pre` and `code` style
### 0.2.7
- refactory taxonomy
### 0.2.6
- toc style changed
### 0.2.5
- Fixed ol list style error
### 0.2.4
- Added a gear template
### 0.2.3
- Added a “back to top” button.
### 0.2.2
- Added support for table of contents (TOC).
### 0.2.1
- Fixed compatibility issues with older versions of SCSS.
### 0.2.0
- Added dark mode support.
- Fixed footer style issues on mobile devices.
### 0.1.0
- Added theme information.
### 0.0.8
- Fixed date formatting issue on Safari browser.
### 0.0.7
- Changed to local item retrieval without the need for a token.
### 0.0.6
- Added support for Douban items.
Usage:
Scan the QR code with WeChat at https://node.wpista.com/.
Enter your Douban numeric ID and click “Save” to automatically sync your Douban records.
Click “Get integration token” to generate a token.
Add the following parameter to your site configuration:
```
[params]
wpdToken = 'token generated above'
```
### 0.0.5
- Fixed styling issues on category/tag pages.
### 0.0.4
- Added relative time display.
- Included sample data.
### 0.0.3
- Used normalize.css.
### 0.0.2
- Added menu settings.
- Added a parameter to control the display of site owner information.
### 0.0.1
- Initial setup.

View File

@ -1,153 +0,0 @@
# Hugo Theme Farallon
![Hugo 主题 Farallon](https://static.fatesinger.com/2023/06/u1ak8xgmyn9ec24r.png)
## 使用方法
```
git submodule add https://github.com/bigfa/hugo-theme-farallon.git themes/farallon
echo "theme = 'farallon'" >> hugo.toml
```
[完整演示站点](https://github.com/bigfa/bigfa.github.io)
## Release Note
### 0.3.7
- 增加页脚 SNS 图标
### 0.3.6
- 增加文章分类卡片
- 增加 Github 图标
### 0.3.5
- 增加作者 SNS 图标
### 0.3.4
- 修改分类文件名
### 0.3.3
- 增加状态文章格式
### 0.3.2
- 文章页增加作者信息
### 0.3.1
- 增加置顶标识
- 修复豆瓣页面暗黑模式下的样式问题
### 0.3.0
- 增加搜索
### 0.2.11
- 文章内链短代码
### 0.2.10
- 修正分类和标签归档页样式问题
- 相对时间多语言支持
### 0.2.9
- 修复链接渲染错误
- 增加友情链接页面模版
### 0.2.8
- 增加 `pre``code` 标签样式
### 0.2.7
- 整理分类页面
### 0.2.6
- 文章目录样式更新
### 0.2.5
- 有序列表样式修正
### 0.2.4
- 增加了一个卡片页面
### 0.2.3
- 增加了返回顶部按钮
### 0.2.2
- 增加 TOC 支持
### 0.2.1
- 修复 scss 低版本兼容性问题
### 0.2.0
- 增加暗黑模式支持
- 修复移动端 footer 样式问题
### 0.1.0
- 添加主题信息
### 0.0.8
- 修复 safari 浏览器下时间格式化错误的问题
### 0.0.7
- 修改为本地获取条目,无需设置 token
### 0.0.6
- 新增豆瓣条目支持
使用方法
微信扫码登录https://node.wpista.com/
输入你的豆瓣数字 id点击保存即可自动同步豆瓣记录。
点击 Get integration token 会生成一个 token。
在你的站点配置中加入参数
```
[params]
wpdToken= '上面生成的token'
```
### 0.0.5
- 修复分类页/标签页样式错误
### 0.0.4
- 增加相对时间
- 加入示例数据
### 0.0.3
- 使用`normalize.css`
### 0.0.2
- 增加菜单设置
- 增加一个是否显示站长信息的参数
### 0.0.1
初始化

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 351 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -13,7 +13,7 @@ body {
font: {
weight: 400;
style: normal;
family: "LXGW WenKai Screen", PingFang SC, Hiragino Sans GB, Microsoft YaHei,
family: "Open Sans", PingFang SC, Hiragino Sans GB, Microsoft YaHei,
STHeiti, WenQuanYi Micro Hei, Helvetica, Arial, sans-serif;
size: 16px;
}
@ -613,3 +613,30 @@ textarea {
margin-right: 4px;
}
}
.notice--wrapper {
background-color: rgba(0, 0, 0, 0.9);
color: #fff;
font-size: 12px;
max-width: 800px;
padding: 10px 15px;
border-radius: 8px;
position: fixed;
z-index: 1000;
top: 15px;
left: 50%;
transform: translateX(-50%);
//transform: translateY(-100px);
transition: 0.5s transform;
// &.is-active {
//transform: translateX(-50%);
// transform: translateY(0);
// }
}
@media (max-width: 768px) {
.notice--wrapper {
width: 80%;
}
}

View File

@ -1,4 +1,16 @@
.db {
&--container {
--db-item-width: 150px;
--db-item-height: 215px;
--db-music-width: 150px;
--db-music-height: 150px;
--db-primary-color: var(--farallon-hover-color);
--db-background-white: var(--farallon-background-white);
--db-background-gray: var(--farallon-background-gray);
--db-border-color: var(--farallon-border-color);
--db-text-light: var(--farallon-text-light);
}
&--nav {
padding: 30px 0 20px;
display: flex;
@ -7,7 +19,7 @@
&Item {
font-size: 20px;
cursor: pointer;
border-bottom: 1px solid rgba($color: #000000, $alpha: 0);
border-bottom: 1px solid rgba(0, 0, 0, 0);
transition: 0.5s border-color;
display: flex;
align-items: center;
@ -30,12 +42,12 @@
}
&--image {
width: 150px;
height: 215px;
width: var(--db-item-width);
height: var(--db-item-height);
object-fit: cover;
border-radius: 4px;
&:hover {
box-shadow: 0 0 10px var(--farallon-border-color);
box-shadow: 0 0 10px var(--db-border-color);
}
}
@ -45,14 +57,14 @@
line-height: 1.4;
a {
&:hover {
color: var(--farallon-hover-color);
color: var(--db-primary-color);
text-decoration: underline;
}
}
}
&--genreItem {
background: var(--farallon-background-gray);
background: var(--db-background-gray);
font-size: 12px;
padding: 5px 12px;
border-radius: 4px;
@ -61,12 +73,12 @@
line-height: 1.4;
cursor: pointer;
&.is-active {
background-color: var(--farallon-main-color);
color: var(--farallon-background-white);
background-color: var(--db-primary-color);
color: var(--db-background-white);
}
&:hover {
background-color: var(--farallon-hover-color);
color: var(--farallon-background-white);
background-color: var(--db-primary-color);
color: var(--db-background-white);
}
}
@ -85,46 +97,18 @@
display: flex;
align-items: center;
font-size: 14px;
color: var(--text-gray-lightest);
color: var(--db-text-light);
}
&--item {
width: 150px;
width: var(--db-item-width);
margin-right: 20px;
margin-bottom: 20px;
position: relative;
&__music img {
width: 150px;
height: 150px;
width: var(--db-music-width);
height: var(--db-music-height);
object-fit: cover;
}
.top250 {
position: absolute;
left: 0;
top: 0;
background: #f5c518;
color: #000000;
border-radius: 4px 4px 4px 0;
line-height: 1;
padding: 3px 10px 3px 5px;
font-size: 12px;
display: flex;
margin-bottom: 2px;
font-weight: 900;
&:after {
content: "";
border-top-left-radius: 0;
border-bottom-left-radius: 0;
right: 0;
top: 0;
margin-right: -0.2rem;
border-radius: 0 0 4px 4px;
background: inherit;
height: 100%;
position: absolute;
width: 0.75rem;
transform: skewX(-20deg);
}
}
}
}
@ -383,75 +367,3 @@
flex-direction: column;
}
}
.project {
&--headline {
font-size: 32px;
margin-top: 50px;
line-height: 1.5;
font-weight: 900;
}
&--subtitle {
font-size: 18px;
font-weight: 200;
color: var(--farallon-text-light);
}
}
.theme {
&--item {
padding: 25px 0;
font-size: 20px;
border-bottom: 1px solid var(--farallon-border-color-light);
&:last-child {
border-bottom: 0;
}
h3 {
line-height: 1;
margin: 0;
}
}
&--tags {
display: flex;
align-items: center;
margin-top: 20px;
a {
border: 1px solid var(--farallon-main-color);
color: var(--farallon-main-color);
line-height: 1.2;
font-size: 12px;
padding: 3px 12px;
border-radius: 4px;
margin-right: 20px;
font-weight: bold;
&:hover {
border-color: var(--farallon-hover-color);
background-color: var(--farallon-hover-color);
color: var(--farallon-background-white);
}
}
}
}
.plugin {
&--item {
padding: 15px 0;
font-size: 20px;
border-bottom: 1px solid var(--farallon-border-color-light);
&:last-child {
border-bottom: 0;
}
a {
&:hover {
color: var(--farallon-main-color);
text-decoration: underline;
}
}
.desc {
font-size: 14px;
color: var(--faraallon-text-gray);
}
}
}

View File

@ -28,6 +28,8 @@
code {
background-color: rgba(0, 0, 0, 0);
font-size: 100%;
margin: 0;
padding: 0;
}
// font-family: source-code-pro, Menlo, Monaco, "Courier New", Courier,
// monospace;

View File

@ -40,7 +40,7 @@
&:hover,
&.is-active {
svg {
fill: var(--jl-hover-color);
fill: var(--farallon-hover-color);
}
}
}
@ -292,3 +292,43 @@
}
}
}
.button--like {
border: 0;
background-color: rgba(0, 0, 0, 0);
cursor: pointer;
display: flex;
align-items: center;
.count {
font-size: 14px;
margin-left: 3px;
font-weight: bold;
color: var(--farallon-text-gray);
}
&.is-active {
svg {
fill: var(--farallon-main-color);
}
.icon--active {
display: block;
}
.icon--default {
display: none;
}
.count {
color: var(--farallon-hover-color);
}
}
&:hover {
.count {
color: var(--farallon-hover-color);
}
}
.icon--active {
display: none;
}
.icon--block {
display: none;
}
}

View File

@ -0,0 +1,152 @@
import { farallonHelper } from "./utils";
interface farallonActionsOptions {
singleSelector?: string;
likeButtonSelctor?: string;
articleSelector?: string;
viewSelector?: string;
actionDomain: string;
text?: string;
}
class farallonActions extends farallonHelper {
singleSelector: string = ".post--single";
likeButtonSelctor: string = ".like-btn";
articleSelector: string = ".post--item";
viewSelector: string = ".article--views";
actionDomain: string;
text: string = "";
likeButton: HTMLElement | null = null;
post_id: string;
is_single: boolean = false;
constructor(config: farallonActionsOptions) {
super();
this.singleSelector = config.singleSelector ?? this.singleSelector;
this.likeButtonSelctor =
config.likeButtonSelctor ?? this.likeButtonSelctor;
this.articleSelector = config.articleSelector ?? this.articleSelector;
this.viewSelector = config.viewSelector ?? this.viewSelector;
this.actionDomain = config.actionDomain;
this.text = config.text ?? this.text;
this.is_single = document.querySelector(this.singleSelector)
? true
: false;
if (this.is_single) {
const postSingle = document.querySelector(
this.singleSelector
) as HTMLElement;
this.post_id = postSingle.dataset.id ?? "";
this.initArticleLike();
this.initArticleView();
} else {
this.initArticlesView();
}
}
initArticleView() {
fetch(this.actionDomain + "post/" + this.post_id + "/view", {
method: "post",
}).then((res) => {
res.json().then((data) => {
(
document.querySelector(this.viewSelector) as HTMLElement
).innerText = data.views + this.text;
});
});
}
initArticlesView() {
const articles: HTMLElement[] = Array.from(
document.querySelectorAll(this.articleSelector)
);
if (articles.length === 0) return;
let ids: Array<String> = [];
articles.forEach((article: HTMLElement) => {
return ids.push(article.dataset.id!);
});
const idsString = ids.join(",");
fetch(this.actionDomain + "post/views?post_ids=" + idsString).then(
(res) => {
res.json().then((data) => {
const result = data.results;
articles.forEach((article: HTMLElement) => {
if (!article.querySelector(this.viewSelector)) return;
(
article.querySelector(
this.viewSelector
) as HTMLElement
).innerText =
(result.find(
(item: any) =>
item.post_id == article.dataset.id
)
? result.find(
(item: any) =>
item.post_id == article.dataset.id
).views
: 0) + this.text;
});
});
}
);
}
initArticleLike() {
this.likeButton = document.querySelector(this.likeButtonSelctor);
if (this.likeButton) {
fetch(this.actionDomain + "post/" + this.post_id + "/like").then(
(res) => {
res.json().then((data) => {
(
this.likeButton!.querySelector(
".count"
) as HTMLElement
).innerText = data.likes;
});
}
);
this.likeButton.addEventListener("click", () => {
this.handleLike();
});
if (this.getCookie("like_" + this.post_id)) {
this.likeButton.classList.add("is-active");
}
}
}
handleLike() {
if (this.getCookie("like_" + this.post_id)) {
return this.showNotice("You have already liked this post");
}
if (this.likeButton) {
const url = this.actionDomain + "post/" + this.post_id + "/like";
fetch(url, {
method: "post",
})
.then((response) => {
return response.json();
})
.then((data) => {
this.showNotice("Thanks for your like");
const countElement = this.likeButton?.querySelector(
".count"
) as HTMLElement;
if (countElement) {
countElement.innerText = data.likes;
}
this.setCookie("like_" + this.post_id, "1", 1);
});
this.likeButton?.classList.add("is-active");
}
}
}
export default farallonActions;

View File

@ -1,34 +1,65 @@
//@ts-nocheck
class farallonDate {
selector: string;
timeFormat: any = {
second: "second ago",
seconds: "seconds ago",
minute: "minute ago",
minutes: "minutes ago",
hour: "hour ago",
hours: "hours ago",
day: "day ago",
days: "days ago",
week: "week ago",
weeks: "weeks ago",
month: "month ago",
months: "months ago",
year: "year ago",
years: "years ago",
};
doms: Array<any> = [];
VERSION: string = "0.3.7";
constructor(config: any) {
this.selector = config.selector;
if (config.timeFormat) {
this.timeFormat = config.timeFormat;
}
this.init();
setTimeout(() => {
this.refresh();
}, 1000 * 5);
import { farallonHelper } from "./utils";
import farallonDate from "./date.ts";
import farallonActions from "./action.ts";
import { farallonComment } from "./comment.ts";
import Douban from "./db.ts";
declare global {
interface Window {
actionDomain: string;
timeFormat: string;
dbAPIBase: string;
}
}
class farallonBase extends farallonHelper {
is_single: boolean = false;
post_id: number = 0;
is_archive: boolean = false;
VERSION: string = "0.4.3";
like_btn: any;
selctor: string = ".like-btn";
actionDomain: string = window.actionDomain;
constructor() {
super();
this.initCopyright();
this.initThemeSwitch();
this.initBack2Top();
this.initSearch();
}
initSearch() {
document
.querySelector('[data-action="show-search"]')!
.addEventListener("click", () => {
document
.querySelector(".site--header__center .inner")!
.classList.toggle("search--active");
});
}
initBack2Top() {
if (document.querySelector(".backToTop")) {
const backToTop = document.querySelector(
".backToTop"
) as HTMLElement;
window.addEventListener("scroll", () => {
const t = window.scrollY || window.pageYOffset;
// console.log(t);
// const documentHeight = document.body.clientHeight;
//const windowHeight = window.innerHeight;
// const percent = Math.ceil((t / (documentHeight - windowHeight)) * 100);
t > 200
? backToTop!.classList.add("is-active")
: backToTop!.classList.remove("is-active");
});
backToTop.addEventListener("click", () => {
window.scrollTo({ top: 0, behavior: "smooth" });
});
}
}
initCopyright() {
const copyright = `<div class="site--footer__info">
Theme <a href="https://fatesinger.com/101971" target="_blank">farallon</a> by bigfa / version ${this.VERSION}
</div>`;
@ -46,75 +77,7 @@ class farallonDate {
});
}
init() {
this.doms = Array.from(document.querySelectorAll(this.selector));
this.doms.forEach((dom: any) => {
dom.innerText = this.humanize_time_ago(
dom.attributes["datetime"].value
);
});
}
humanize_time_ago(datetime: string) {
const time = new Date(datetime);
const between: number =
Date.now() / 1000 - Number(time.getTime() / 1000);
if (between < 3600) {
return `${Math.ceil(between / 60)} ${
Math.ceil(between / 60) == 1
? this.timeFormat.second
: this.timeFormat.seconds
}`;
} else if (between < 86400) {
return `${Math.ceil(between / 3600)} ${
Math.ceil(between / 3660) == 1
? this.timeFormat.hour
: this.timeFormat.hours
}`;
} else if (between < 86400 * 30) {
return `${Math.ceil(between / 86400)} ${
Math.ceil(between / 86400) == 1
? this.timeFormat.day
: this.timeFormat.days
}`;
} else if (between < 86400 * 30 * 12) {
return `${Math.ceil(between / (86400 * 30))} ${
Math.ceil(between / (86400 * 30)) == 1
? this.timeFormat.month
: this.timeFormat.months
}`;
} else {
return (
time.getFullYear() +
"-" +
(time.getMonth() + 1) +
"-" +
time.getDate()
);
}
}
refresh() {
this.doms.forEach((dom: any) => {
dom.innerText = this.humanize_time_ago(
dom.attributes["datetime"].value
);
});
}
}
new farallonDate({
selector: ".humane--time",
//@ts-ignore
timeFormat: window.timeFormat,
});
class farallonBase {
is_single: boolean = false;
post_id: number = 0;
is_archive: boolean = false;
VERSION: string = "0.2.3";
constructor() {
initThemeSwitch() {
const theme = localStorage.getItem("theme")
? localStorage.getItem("theme")
: "auto";
@ -165,25 +128,26 @@ class farallonBase {
if (item.classList.contains("is-active")) return;
document
.querySelectorAll(".fixed--theme span")
.forEach((item) => {
.forEach((item: Element) => {
item.classList.remove("is-active");
});
// @ts-ignore
if (item.dataset.actionValue == "dark") {
if ((item as HTMLElement).dataset.actionValue == "dark") {
localStorage.setItem("theme", "dark");
document.querySelector("body")!.classList.remove("auto");
document.querySelector("body")!.classList.add("dark");
item.classList.add("is-active");
//this.showNotice('夜间模式已开启');
// @ts-ignore
} else if (item.dataset.actionValue == "light") {
} else if (
(item as HTMLElement).dataset.actionValue == "light"
) {
localStorage.setItem("theme", "light");
document.querySelector("body")!.classList.remove("auto");
document.querySelector("body")!.classList.remove("dark");
item.classList.add("is-active");
//this.showNotice('夜间模式已关闭');
// @ts-ignore
} else if (item.dataset.actionValue == "auto") {
} else if (
(item as HTMLElement).dataset.actionValue == "auto"
) {
localStorage.setItem("theme", "auto");
document.querySelector("body")!.classList.remove("dark");
document.querySelector("body")!.classList.add("auto");
@ -192,68 +156,24 @@ class farallonBase {
}
});
});
if (document.querySelector(".backToTop")) {
const backToTop = document.querySelector(
".backToTop"
) as HTMLElement;
window.addEventListener("scroll", () => {
const t = window.scrollY || window.pageYOffset;
// console.log(t);
// const documentHeight = document.body.clientHeight;
//const windowHeight = window.innerHeight;
// const percent = Math.ceil((t / (documentHeight - windowHeight)) * 100);
t > 200
? backToTop!.classList.add("is-active")
: backToTop!.classList.remove("is-active");
});
backToTop.addEventListener("click", () => {
window.scrollTo({ top: 0, behavior: "smooth" });
});
}
document
.querySelector('[data-action="show-search"]')!
.addEventListener("click", () => {
document
.querySelector(".site--header__center .inner")!
.classList.toggle("search--active");
});
}
getCookie(t: any) {
if (0 < document.cookie.length) {
var e = document.cookie.indexOf(t + "=");
if (-1 != e) {
e = e + t.length + 1;
var n = document.cookie.indexOf(";", e);
return (
-1 == n && (n = document.cookie.length),
document.cookie.substring(e, n)
);
}
}
return "";
}
setCookie(t: any, e: any, n: any) {
var o = new Date();
o.setTime(o.getTime() + 24 * n * 60 * 60 * 1e3);
var i = "expires=" + o.toUTCString();
document.cookie = t + "=" + e + ";" + i + ";path=/";
}
showNotice(message: any, type: any = "success") {
const html = `<div class="notice--wrapper">${message}</div>`;
document.querySelector("body")!.insertAdjacentHTML("beforeend", html);
document.querySelector(".notice--wrapper")!.classList.add("is-active");
setTimeout(() => {
document.querySelector(".notice--wrapper")!.remove();
}, 3000);
}
}
new farallonActions({
singleSelector: ".post--single",
articleSelector: ".post--item",
likeButtonSelctor: ".like-btn",
actionDomain: window.actionDomain,
});
new farallonBase();
new farallonDate({
selector: ".humane--time",
timeFormat: window.timeFormat,
});
new farallonComment();
new Douban({
baseAPI: window.dbAPIBase,
container: ".db--container",
});

View File

@ -1,5 +1,4 @@
//@ts-nocheck
class farallonComment {
export class farallonComment {
loading: boolean = false;
post_id: any;
total: any = 0;
@ -8,15 +7,16 @@ class farallonComment {
constructor() {
if (!document.querySelector(".post--ingle__comments")) return;
this.post_id = document.querySelector(
".post--ingle__comments"
)!.dataset.id;
this.post_id = (
document.querySelector(".post--ingle__comments") as HTMLElement
).dataset.id;
this.fetchComments();
this.init();
}
fetchComments() {
fetch(
// @ts-ignore
window.commentDomain +
"/post/" +
this.post_id +
@ -58,9 +58,11 @@ class farallonComment {
<span class="comment-reply-link u-cursorPointer " onclick="return addComment.moveForm('comment-${
i.id
}', '${i.id}', 'respond', '${
document.querySelector(
".post--ingle__comments"
)!.dataset.id
(
document.querySelector(
".post--ingle__comments"
) as HTMLElement
).dataset.id
}')"><svg viewBox="0 0 24 24" width="14" height="14" aria-hidden="true" class=""><g><path d="M12 3.786c-4.556 0-8.25 3.694-8.25 8.25s3.694 8.25 8.25 8.25c1.595 0 3.081-.451 4.341-1.233l1.054 1.7c-1.568.972-3.418 1.534-5.395 1.534-5.661 0-10.25-4.589-10.25-10.25S6.339 1.786 12 1.786s10.25 4.589 10.25 10.25c0 .901-.21 1.77-.452 2.477-.592 1.731-2.343 2.477-3.917 2.334-1.242-.113-2.307-.74-3.013-1.647-.961 1.253-2.45 2.011-4.092 1.78-2.581-.363-4.127-2.971-3.76-5.578.366-2.606 2.571-4.688 5.152-4.325 1.019.143 1.877.637 2.519 1.342l1.803.258-.507 3.549c-.187 1.31.761 2.509 2.079 2.629.915.083 1.627-.356 1.843-.99.2-.585.345-1.224.345-1.83 0-4.556-3.694-8.25-8.25-8.25zm-.111 5.274c-1.247-.175-2.645.854-2.893 2.623-.249 1.769.811 3.143 2.058 3.319 1.247.175 2.645-.854 2.893-2.623.249-1.769-.811-3.144-2.058-3.319z"></path></g></svg></span> </div>
</div>
</div>
@ -93,8 +95,9 @@ class farallonComment {
<span class="comment-reply-link u-cursorPointer " onclick="return addComment.moveForm('comment-${
item.id
}', '${item.id}', 'respond', '${
document.querySelector(".post--ingle__comments")!
.dataset.id
(document.querySelector(
".post--ingle__comments"
) as HTMLElement)!.dataset.id
}')"><svg viewBox="0 0 24 24" width="14" height="14" aria-hidden="true" class=""><g><path d="M12 3.786c-4.556 0-8.25 3.694-8.25 8.25s3.694 8.25 8.25 8.25c1.595 0 3.081-.451 4.341-1.233l1.054 1.7c-1.568.972-3.418 1.534-5.395 1.534-5.661 0-10.25-4.589-10.25-10.25S6.339 1.786 12 1.786s10.25 4.589 10.25 10.25c0 .901-.21 1.77-.452 2.477-.592 1.731-2.343 2.477-3.917 2.334-1.242-.113-2.307-.74-3.013-1.647-.961 1.253-2.45 2.011-4.092 1.78-2.581-.363-4.127-2.971-3.76-5.578.366-2.606 2.571-4.688 5.152-4.325 1.019.143 1.877.637 2.519 1.342l1.803.258-.507 3.549c-.187 1.31.761 2.509 2.079 2.629.915.083 1.627-.356 1.843-.99.2-.585.345-1.224.345-1.83 0-4.556-3.694-8.25-8.25-8.25zm-.111 5.274c-1.247-.175-2.645.854-2.893 2.623-.249 1.769.811 3.143 2.058 3.319 1.247.175 2.645-.854 2.893-2.623.249-1.769-.811-3.144-2.058-3.319z"></path></g></svg></span> </div>
</div>
</div>
@ -158,8 +161,9 @@ class farallonComment {
(value, key: any) => (formDataObj[key] = value)
);
this.loading = true;
// @ts-ignore
fetch(
// @ts-ignore
window.commentDomain +
"/post/" +
this.post_id +
@ -205,20 +209,23 @@ class farallonComment {
</div>
</div>
</li>`; // @ts-ignore
const parent_id =
const parent_id = (
document.querySelector(
"#comment_parent"
)?.value;
) as HTMLInputElement
)?.value;
// @ts-ignore
(a.style.display = "none"), // @ts-ignore
(a.onclick = null), // @ts-ignore
(document.getElementById(
"comment_parent"
((
document.getElementById(
"comment_parent"
) as HTMLInputElement
).value = "0"),
n && // @ts-ignore
i && // @ts-ignore
(n.parentNode.insertBefore(i, n),
n.parentNode.removeChild(n));
n.parentNode &&
n.parentNode.removeChild(n);
if (document.querySelector(".comment-body__fresh"))
document
.querySelector(".comment-body__fresh")
@ -264,5 +271,3 @@ class farallonComment {
}
}
}
new farallonComment();

View File

@ -0,0 +1,88 @@
class farallonDate {
readonly selector: string;
timeFormat: any = {
second: "second ago",
seconds: "seconds ago",
minute: "minute ago",
minutes: "minutes ago",
hour: "hour ago",
hours: "hours ago",
day: "day ago",
days: "days ago",
week: "week ago",
weeks: "weeks ago",
month: "month ago",
months: "months ago",
year: "year ago",
years: "years ago",
};
doms: Array<any> = [];
constructor(config: any) {
this.selector = config.selector;
if (config.timeFormat) {
this.timeFormat = config.timeFormat;
}
this.init();
setTimeout(() => {
this.refresh();
}, 1000 * 5);
}
init() {
this.doms = Array.from(document.querySelectorAll(this.selector));
this.doms.forEach((dom: any) => {
dom.innerText = this.humanize_time_ago(
dom.attributes["datetime"].value
);
});
}
humanize_time_ago(datetime: string) {
const time = new Date(datetime);
const between: number =
Date.now() / 1000 - Number(time.getTime() / 1000);
if (between < 3600) {
return `${Math.ceil(between / 60)} ${
Math.ceil(between / 60) == 1
? this.timeFormat.second
: this.timeFormat.seconds
}`;
} else if (between < 86400) {
return `${Math.ceil(between / 3600)} ${
Math.ceil(between / 3660) == 1
? this.timeFormat.hour
: this.timeFormat.hours
}`;
} else if (between < 86400 * 30) {
return `${Math.ceil(between / 86400)} ${
Math.ceil(between / 86400) == 1
? this.timeFormat.day
: this.timeFormat.days
}`;
} else if (between < 86400 * 30 * 12) {
return `${Math.ceil(between / (86400 * 30))} ${
Math.ceil(between / (86400 * 30)) == 1
? this.timeFormat.month
: this.timeFormat.months
}`;
} else {
return (
time.getFullYear() +
"-" +
(time.getMonth() + 1) +
"-" +
time.getDate()
);
}
}
refresh() {
this.doms.forEach((dom: any) => {
dom.innerText = this.humanize_time_ago(
dom.attributes["datetime"].value
);
});
}
}
export default farallonDate;

View File

@ -1,109 +1,140 @@
class FARALLON_DOUBAN {
ver: string;
interface StatusObject {
name: string;
value: string;
}
interface DoubanConfig {
baseAPI: string;
container: string;
types?: Array<string>;
onChange?: (value: string) => void;
}
interface DoubanObject {
subject_id: string;
name: string;
card_subtitle: string;
create_time: any;
douban_score: string;
link: string;
type: string;
poster: string;
pubdate: string;
year: string;
status: string;
}
class Douban {
readonly ver: string;
type: any;
finished: boolean;
paged: number;
genre_list: Array<any>;
subjects: Array<any>;
genre: Array<any>;
baseAPI: string = "https://node.wpista.com/v1/outer/";
token: string;
constructor(config: any) {
this.ver = "1.0.1";
genre_list: Array<StatusObject>;
subjects: Array<DoubanObject>;
status: string;
baseAPI: string;
types: Array<string>;
container: string;
constructor(config: DoubanConfig) {
this.container = config.container;
this.types = config.types ?? [
"movie",
"book",
"music",
"game",
"drama",
];
this.baseAPI = config.baseAPI;
this.ver = "1.0.6";
this.type = "movie";
this.status = "done";
this.finished = false;
this.paged = 1;
this.genre_list = [];
this.genre = [];
this.genre_list = [
{
name: "已看",
value: "done",
},
{
name: "在看",
value: "doing",
},
{
name: "想看",
value: "mark",
},
];
this.subjects = [];
this.token = config.token;
this._create();
}
on(t: any, e: any, n: any) {
var a = document.querySelectorAll(e);
a.forEach((item) => {
item.addEventListener(t, n);
on(event: string, element: string, callback: any) {
const nodeList: NodeList = document.querySelectorAll(element);
nodeList.forEach((item) => {
item.addEventListener(event, callback);
});
}
_fetchGenres() {
document.querySelector(".db--genres")!.innerHTML = "";
fetch(
this.baseAPI + "genres?token=" + this.token + "&type=" + this.type
)
.then((response) => response.json())
.then((t) => {
// @ts-ignore
if (t.data.length) {
this.genre_list = t.data;
this._renderGenre();
}
});
}
_handleGenreClick() {
this.on("click", ".db--genreItem", (t: any) => {
_handleGenreClick(): void {
this.on("click", ".db--genreItem", (t: MouseEvent) => {
const self = t.currentTarget as HTMLElement;
if (self.classList.contains("is-active")) {
const index = this.genre.indexOf(self.innerText);
self.classList.remove("is-active");
this.genre.splice(index, 1);
this.paged = 1;
this.finished = false;
this.subjects = [];
this._fetchData();
return;
}
document.querySelector(".db--list")!.innerHTML = "";
document.querySelector(".lds-ripple")!.classList.remove("u-hide");
self.classList.add("is-active");
this.genre.push(self.innerText);
this.status = self.dataset.status || ""; // Provide a default value of an empty string if self.dataset.status is undefined
this._renderGenre();
this.paged = 1;
this.finished = false;
this.subjects = [];
this._fetchData();
return;
});
}
_renderGenre() {
_reanderTypes(): void {
document.querySelector(".db--nav")!.innerHTML = this.types
.map((item: string) => {
return `<span class="db--navItem JiEun${
this.type == item ? " current" : ""
}" data-type="${item}">${item}</span>`;
})
.join("");
this._handleNavClick();
}
_renderGenre(): void {
document.querySelector(".db--genres")!.innerHTML = this.genre_list
.map((item: any) => {
.map((item: StatusObject) => {
return `<span class="db--genreItem${
this.genre_list.includes(item.name) ? " is-active" : ""
}">${item.name}</span>`;
this.status == item.value ? " is-active" : ""
}" data-status="${item.value}">${item.name}</span>`;
})
.join("");
this._handleGenreClick();
}
_fetchData() {
fetch(
this.baseAPI +
"faves?token=" +
this.token +
"&type=" +
this.type +
"&paged=" +
this.paged +
"&genre=" +
JSON.stringify(this.genre)
)
_fetchData(): void {
const params: URLSearchParams = new URLSearchParams({
paged: this.paged.toString(),
type: this.type,
status: this.status,
});
fetch(this.baseAPI + "list?" + params.toString())
.then((response) => response.json())
.then((t: any) => {
if (t.data.length) {
console.log(t.results);
if (t.results.length) {
if (
document
.querySelector(".db--list")!
.classList.contains("db--list__card")
) {
this.subjects = [...this.subjects, ...t.data];
this.subjects = [...this.subjects, ...t.results];
this._randerDateTemplate();
} else {
this.subjects = [...this.subjects, ...t.data];
this.subjects = [...this.subjects, ...t.results];
this._randerListTemplate();
}
document
@ -118,7 +149,7 @@ class FARALLON_DOUBAN {
});
}
_randerDateTemplate() {
_randerDateTemplate(): void {
const result = this.subjects.reduce((result, item) => {
const date = new Date(item.create_time);
const year = date.getFullYear();
@ -135,14 +166,12 @@ class FARALLON_DOUBAN {
let html = ``;
for (let key in result) {
const date = key.split("-");
html += `<div class="db--listBydate"><div class="db--titleDate "><div class="db--titleDate__day">${date[1]}</div><div class="db--titleDate__month">${date[0]}</div></div><div class="db--dateList__card">`;
html += `<div class="db--listBydate"><div class="db--titleDate"><div class="db--titleDate__day">${date[1]}</div><div class="db--titleDate__month">${date[0]}</div></div><div class="db--dateList__card">`;
html += result[key]
.map((movie: any) => {
return `<div class="db--item">${
movie.is_top250
? '<span class="top250">Top 250</span>'
: ""
}<img src="${
return `<div class="db--item${
this.type == "music" ? " db--item__music" : ""
}"><img src="${
movie.poster
}" referrerpolicy="no-referrer" class="db--image"><div class="db--score ">${
movie.douban_score > 0
@ -161,22 +190,20 @@ class FARALLON_DOUBAN {
document.querySelector(".db--list")!.innerHTML = html;
}
_randerListTemplate() {
_randerListTemplate(): void {
document.querySelector(".db--list")!.innerHTML = this.subjects
.map((item: any) => {
return `<div class="db--item">${
item.is_top250 ? '<span class="top250">Top 250</span>' : ""
}<img src="${
.map((item) => {
return `<div class="db--item"><img src="${
item.poster
}" referrerpolicy="no-referrer" class="db--image"><div class="ipc-signpost ">${
item.create_time
}</div><div class="db--score ">${
item.douban_score > 0
item.douban_score
? '<svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor" ><path d="M12 20.1l5.82 3.682c1.066.675 2.37-.322 2.09-1.584l-1.543-6.926 5.146-4.667c.94-.85.435-2.465-.799-2.567l-6.773-.602L13.29.89a1.38 1.38 0 0 0-2.581 0l-2.65 6.53-6.774.602C.052 8.126-.453 9.74.486 10.59l5.147 4.666-1.542 6.926c-.28 1.262 1.023 2.26 2.09 1.585L12 20.099z"></path></svg>' +
item.douban_score
: ""
}${
item.year > 0 ? " · " + item.year : ""
item.year ? " · " + item.year : ""
}</div><div class="db--title"><a href="${
item.link
}" target="_blank">${item.name}</a></div>
@ -186,7 +213,7 @@ class FARALLON_DOUBAN {
.join("");
}
_handleScroll() {
_handleScroll(): void {
window.addEventListener("scroll", () => {
var t = window.scrollY || window.pageYOffset;
const moreElement = document.querySelector(
@ -208,25 +235,18 @@ class FARALLON_DOUBAN {
});
}
_handleNavClick() {
this.on("click", ".db--navItem", (t: any) => {
if (t.currentTarget.classList.contains("current")) return;
this.genre = [];
this.type = t.currentTarget.dataset.type;
if (this.type != "book") {
this._fetchGenres();
document
.querySelector(".db--genres")
?.classList.remove("u-hide");
} else {
document.querySelector(".db--genres")!.classList.add("u-hide");
}
_handleNavClick(): void {
this.on("click", ".db--navItem", (t: MouseEvent) => {
const self = t.currentTarget as HTMLElement;
if (self.classList.contains("current")) return;
this.status = "done";
this.type = self.dataset.type;
this._renderGenre();
document.querySelector(".db--list")!.innerHTML = "";
document.querySelector(".lds-ripple")!.classList.remove("u-hide");
document
.querySelector(".db--navItem.current")!
.classList.remove("current");
const self = t.target;
self.classList.add("current");
this.paged = 1;
this.finished = false;
@ -235,35 +255,26 @@ class FARALLON_DOUBAN {
});
}
_create() {
_create(): void {
if (document.querySelector(".db--container")) {
const container = document.querySelector(
".db--container"
this.container
) as HTMLElement;
if (container.dataset.token) {
this.token = container.dataset.token;
} else {
return;
}
const currentNavItem = document.querySelector(
".db--navItem.current"
);
if (currentNavItem instanceof HTMLElement) {
this.type = currentNavItem.dataset.type;
}
const currentType = document.querySelector(
".db--list"
) as HTMLElement;
if (currentType.dataset.type) this.type = currentType.dataset.type;
if (this.type == "movie") {
document
.querySelector(".db--genres")!
.classList.remove("u-hide");
}
this._fetchGenres();
if (!container) return;
container.innerHTML = `<nav class="db--nav">
</nav>
<div class="db--genres">
</div>
<div class="db--list db--list__card">
</div>
<div class="block-more block-more__centered">
<div class="lds-ripple">
</div>
</div>`;
this._renderGenre();
this._reanderTypes();
this._fetchData();
this._handleScroll();
this._handleNavClick();
}
if (document.querySelector(".js-db")) {
@ -272,10 +283,7 @@ class FARALLON_DOUBAN {
const id = db.dataset.id;
const type = db.dataset.type;
const nodeParent = db.parentNode as HTMLElement;
fetch(
// @ts-ignore
this.baseAPI + `${type}/${id}?token=${this.token}`
).then((response) => {
fetch(this.baseAPI + `${type}/${id}`).then((response) => {
response.json().then((t) => {
if (t.data) {
const data = t.data;
@ -305,14 +313,13 @@ class FARALLON_DOUBAN {
}
}
_fetchCollection(item: any) {
_fetchCollection(item: any): void {
const type = item.dataset.style ? item.dataset.style : "card";
fetch(
// @ts-ignore
obvInit.api +
"v1/movies?type=" +
this.baseAPI +
"/list?type=" +
item.dataset.type +
"&paged=1&genre=&start_time=" +
"&paged=1&start_time=" +
item.dataset.start +
"&end_time=" +
item.dataset.end
@ -322,39 +329,30 @@ class FARALLON_DOUBAN {
if (t.length) {
if (type == "card") {
item.innerHTML += t
.map((movie: any) => {
.map((movie: DoubanObject) => {
return `<div class="doulist-item">
<div class="doulist-subject">
<div class="db--viewTime ">Marked ${
movie.create_time
}</div>
<div class="doulist-post"><img referrerpolicy="no-referrer" src="${
movie.poster
}"></div><div class="doulist-content"><div class="doulist-title"><a href="${
movie.link
}" class="cute" target="_blank" rel="external nofollow">${
movie.name
}</a></div><div class="rating"><span class="allstardark"><span class="allstarlight" style="width:75%"></span></span><span class="rating_nums">${
movie.douban_score
}</span></div><div class="abstract">${
movie.remark || movie.card_subtitle
}</div></div></div></div>`;
<div class="db--viewTime ">Marked ${movie.create_time}</div>
<div class="doulist-post"><img referrerpolicy="no-referrer" src="${movie.poster}"></div><div class="doulist-content"><div class="doulist-title"><a href="${movie.link}" class="cute" target="_blank" rel="external nofollow">${movie.name}</a></div><div class="rating"><span class="allstardark"><span class="allstarlight" style="width:75%"></span></span><span class="rating_nums">${movie.douban_score}</span></div><div class="abstract">${movie.card_subtitle}</div></div></div></div>`;
})
.join("");
} else {
const result = t.reduce((result: any, item: any) => {
if (
Object.prototype.hasOwnProperty.call(
result,
item.create_time
)
) {
result[item.create_time].push(item);
} else {
result[item.create_time] = [item];
}
return result;
}, {});
const result = t.reduce(
(result: any, item: DoubanObject) => {
if (
Object.prototype.hasOwnProperty.call(
result,
item.create_time
)
) {
result[item.create_time].push(item);
} else {
result[item.create_time] = [item];
}
return result;
},
{}
);
let html = ``;
for (let key in result) {
html += `<div class="db--date">${key}</div><div class="db--dateList">`;
@ -387,7 +385,4 @@ class FARALLON_DOUBAN {
}
}
new FARALLON_DOUBAN({
// @ts-ignore
token: window.WPD_TOKEN,
});
export default Douban;

View File

@ -0,0 +1,39 @@
interface Helper {
getCookie(key: string): string;
setCookie(key: string, value: string, n: number): void;
showNotice(message: string, type: any): void;
}
export abstract class farallonHelper implements Helper {
getCookie(key: string) {
if (0 < document.cookie.length) {
var e = document.cookie.indexOf(key + "=");
if (-1 != e) {
e = e + key.length + 1;
var n = document.cookie.indexOf(";", e);
return (
-1 == n && (n = document.cookie.length),
document.cookie.substring(e, n)
);
}
}
return "";
}
setCookie(key: string, value: string, n: number) {
var o = new Date();
o.setTime(o.getTime() + 24 * n * 60 * 60 * 1e3);
var i = "expires=" + o.toUTCString();
document.cookie = key + "=" + value + ";" + i + ";path=/";
}
showNotice(message: string, type: any = "success") {
const html = `<div class="notice--wrapper">${message}</div>`;
document.querySelector("body")!.insertAdjacentHTML("beforeend", html);
document.querySelector(".notice--wrapper")!.classList.add("is-active");
setTimeout(() => {
document.querySelector(".notice--wrapper")!.remove();
}, 3000);
}
}

View File

@ -1,3 +0,0 @@
module github.com/bigfa/hugo-theme-farallon
go 1.22.2

View File

@ -4,10 +4,9 @@
{{ $url :=index ($urls) 0 }}
{{ $dbtype := replaceRE $regex "$1" $url }}
{{ $dbid := replaceRE $regex "$2" $url }}
{{ $dbFetch := getJSON "https://node.wpista.com/v1/outer/" $dbtype "/" $dbid
"?token=2bfb9a8d037a7352c9d369b85d33ac83e39a" }}
{{ $dbFetch := getJSON "https://dbapi.wpista.com/" $dbtype "/" $dbid }}
{{ if $dbFetch }}
{{ $subject := $dbFetch.data }}
{{ $subject := $dbFetch }}
{{ $number := (float $subject.douban_score) }}
<div class="doulist-item">
<div class="doulist-subject">

View File

@ -1,12 +1,12 @@
{{ define "main" }}
<div class="page--archive">
{{ range .Pages.ByPublishDate.Reverse.GroupByDate "2006" }}
{{ if (where .Pages "Section" "story") }}
{{ if (where .Pages "Section" "post") }}
<h2 class="archive--title__year">{{ .Key }}</h2>
{{ range .Pages.ByPublishDate.Reverse.GroupByDate "January" }}
<h3 class="archive--title__month">{{ .Key }}</h3>
<ul class="archive--list">
{{ range ((where .Pages "Section" "story")) }}
{{ range ((where .Pages "Section" "post")) }}
<li class="archive--item">
<div class="archive--title">
<a href="{{ .RelPermalink }}">

View File

@ -1,6 +1,7 @@
{{ define "main" }}
<main class="site--main">
<article class="post--single" itemscope="itemscope" itemtype="http://schema.org/Article">
<article class="post--single" itemscope="itemscope" itemtype="http://schema.org/Article"
data-id="{{ .File.UniqueID}}">
<div class="post--single__meta">
<svg class="icon" viewBox="0 0 1024 1024" width="16" height="16">
<path
@ -21,6 +22,15 @@
<a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a>
{{ end }}
{{ end }}
{{ if .Site.Params.post_view }}
<svg class="icon" viewBox="0 0 24 24" width="16" height="16" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M12 9C10.3431 9 9 10.3431 9 12C9 13.6569 10.3431 15 12 15C13.6569 15 15 13.6569 15 12C15 10.3431 13.6569 9 12 9ZM11 12C11 11.4477 11.4477 11 12 11C12.5523 11 13 11.4477 13 12C13 12.5523 12.5523 13 12 13C11.4477 13 11 12.5523 11 12Z" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M21.83 11.2807C19.542 7.15186 15.8122 5 12 5C8.18777 5 4.45796 7.15186 2.17003 11.2807C1.94637 11.6844 1.94361 12.1821 2.16029 12.5876C4.41183 16.8013 8.1628 19 12 19C15.8372 19 19.5882 16.8013 21.8397 12.5876C22.0564 12.1821 22.0536 11.6844 21.83 11.2807ZM12 17C9.06097 17 6.04052 15.3724 4.09173 11.9487C6.06862 8.59614 9.07319 7 12 7C14.9268 7 17.9314 8.59614 19.9083 11.9487C17.9595 15.3724 14.939 17 12 17Z" />
</svg>
<span class="article--views"></span>
{{ end }}
</div>
<h2 class="post--single__title">{{ .Title }}</h2>
{{ if .IsTranslated }}
@ -48,6 +58,23 @@
<div class="post--single__content graph" itemprop="articleBody">
{{ .Content }}
</div>
{{ if .Site.Params.post_like }}
<div class="post--single__action">
<button class="button--like like-btn" aria-label="like the post">
<svg class="icon--active" viewBox="0 0 1024 1024" width="32" height="32">
<path
d="M780.8 204.8c-83.2-44.8-179.2-19.2-243.2 44.8L512 275.2 486.4 249.6c-64-64-166.4-83.2-243.2-44.8C108.8 275.2 89.6 441.6 185.6 537.6l32 32 153.6 153.6 102.4 102.4c25.6 25.6 57.6 25.6 83.2 0l102.4-102.4 153.6-153.6 32-32C934.4 441.6 915.2 275.2 780.8 204.8z">
</path>
</svg>
<svg class="icon--default" viewBox="0 0 1024 1024" width="32" height="32">
<path
d="M332.8 249.6c38.4 0 83.2 19.2 108.8 44.8L467.2 320 512 364.8 556.8 320l25.6-25.6c32-32 70.4-44.8 108.8-44.8 19.2 0 38.4 6.4 57.6 12.8 44.8 25.6 70.4 57.6 76.8 108.8 6.4 44.8-6.4 89.6-38.4 121.6L512 774.4 236.8 492.8C204.8 460.8 185.6 416 192 371.2c6.4-44.8 38.4-83.2 76.8-108.8C288 256 313.6 249.6 332.8 249.6L332.8 249.6M332.8 185.6C300.8 185.6 268.8 192 243.2 204.8 108.8 275.2 89.6 441.6 185.6 537.6l281.6 281.6C480 832 499.2 838.4 512 838.4s32-6.4 38.4-19.2l281.6-281.6c96-96 76.8-262.4-57.6-332.8-25.6-12.8-57.6-19.2-89.6-19.2-57.6 0-115.2 25.6-153.6 64L512 275.2 486.4 249.6C448 211.2 390.4 185.6 332.8 185.6L332.8 185.6z">
</path>
</svg>
<span class="count"></span>
</button>
</div>
{{ end }}
<div class="tag--list">
{{ range (.GetTerms "tags") }}
<a href="{{ .RelPermalink }}" class="artile--tag">{{ .LinkTitle }}</a>
@ -73,26 +100,7 @@
{{ if .Params.story_id }}
{{ partial "commentlist.html" . }}
{{ end }}
<div id="comments" class="responsesWrapper">
<h3 class="comments--title"><svg viewBox="0 0 24 24" class="icon" aria-hidden="true" width="16" height="16">
<g>
<path
d="M1.751 10c0-4.42 3.584-8 8.005-8h4.366c4.49 0 8.129 3.64 8.129 8.13 0 2.96-1.607 5.68-4.196 7.11l-8.054 4.46v-3.69h-.067c-4.49.1-8.183-3.51-8.183-8.01zm8.005-6c-3.317 0-6.005 2.69-6.005 6 0 3.37 2.77 6.08 6.138 6.01l.351-.01h1.761v2.3l5.087-2.81c1.951-1.08 3.163-3.13 3.163-5.36 0-3.39-2.744-6.13-6.129-6.13H9.756z">
</path>
</g>
</svg>评论</h3>
<ol class="commentlist sulliComment--list">
</ol>
<div id="tcomment"></div>
<script src="https://cdn.staticfile.org/twikoo/1.6.32/twikoo.all.min.js"></script>
<script>
twikoo.init({
envId: 'https://t.imsun.org',
el: '#tcomment',
})
</script>
</div>
{{ partial "twikoo.html" . }}
</article>
<!-- {{ if or .PrevPage .NextPage }}
<nav class="navigation post-navigation is-active">

View File

@ -3,401 +3,6 @@
{{ if $.Site.Params.showprofile }}
{{ partial "profile.html" . }}
{{ end }}
<style>
:root {
/* GitHub Light Color */
--ht-main: #334155;
--ht-day-bg: #ebedf0;
--ht-tooltip: #24292f;
--ht-tooltip-bg: #fff;
--ht-lv-0: #ebedf0;
--ht-lv-1: #9be9a8;
--ht-lv-2: #40c463;
--ht-lv-3: #30a14e;
--ht-lv-4: #216e39;
}
[data-theme="dark"] {
/* GitHub Dark Dimmed Color */
--ht-main: #94a3b8;
--ht-day-bg: #161b22;
--ht-tooltip: #24292f;
--ht-tooltip-bg: #fff;
--ht-lv-0: #161b22;
--ht-lv-1: #0e4429;
--ht-lv-2: #006d32;
--ht-lv-3: #26a641;
--ht-lv-4: #39d353;
}
.heatmap_container {
display: flex;
flex-direction: column;
align-items: flex-end;
font-size: 10px;
line-height: 12px;
color: var(--ht-main);
}
.heatmap_content {
display: flex;
flex-direction: row;
align-items: flex-end
}
.heatmap_week {
display: flex;
margin-top: 0.25rem;
margin-right: 0.25rem;
flex-direction: column;
justify-content: flex-end;
align-items: flex-end;
text-align: right
}
.heatmap_main {
display: flex;
flex-direction: column
}
.heatmap_month {
display: flex;
margin-top: 0.25rem;
margin-right: 0.25rem;
flex-direction: row;
justify-content: flex-end;
align-items: flex-end;
text-align: right;
}
.heatmap {
display: flex;
flex-direction: row;
height: 84px;
}
.heatmap_footer {
display: flex;
margin-top: 0.5rem;
align-items: center
}
.heatmap_level {
display: flex;
gap: 2px;
margin: 0 0.25rem;
flex-direction: row;
align-items: center;
width: max-content;
height: 10px
}
.heatmap_level_item {
display: block;
border-radius: 0.125rem;
width: 10px;
height: 10px;
}
.heatmap_level_0 {
background: var(--ht-lv-0);
}
.heatmap_level_1 {
background: var(--ht-lv-1);
}
.heatmap_level_2 {
background: var(--ht-lv-2);
}
.heatmap_level_3 {
background: var(--ht-lv-3);
}
.heatmap_level_4 {
background: var(--ht-lv-4);
}
.heatmap_week {
display: flex;
flex-direction: column;
}
.heatmap_day {
width: 10px;
height: 10px;
background-color: var(--ht-day-bg);
margin: 1px;
border-radius: 2px;
display: inline-block;
position: relative;
}
.heatmap_tooltip {
position: absolute;
bottom: 12px;
left: 50%;
width: max-content;
color: var(--ht-tooltip);
background-color: var(--ht-tooltip-bg);
font-size: 12px;
line-height: 16px;
padding: 8px;
border-radius: 3px;
white-space: pre-wrap;
opacity: 1;
transition: 0.3s;
z-index: 1000;
text-align: right;
transform: translateX(-50%);
}
.heatmap_tooltip_count,
.heatmap_tooltip_post {
display: inline-block;
}
.heatmap_tooltip_title,
.heatmap_tooltip_date {
display: block;
}
.heatmap_tooltip_date {
margin: 0 0.25rem;
}
.heatmap_day_level_0 {
background-color: var(--ht-lv-0);
}
.heatmap_day_level_1 {
background-color: var(--ht-lv-1);
}
.heatmap_day_level_2 {
background-color: var(--ht-lv-2);
}
.heatmap_day_level_3 {
background-color: var(--ht-lv-3);
}
.heatmap_day_level_4 {
background-color: var(--ht-lv-4);
}
</style> <div id="heatmap" style="max-width: 900px;height: 110px;margin-bottom: 40px;"></div>
<div class="heatmap_container"> <!-- 全部用 Flex 排版 -->
<div class="heatmap_footer">
<div class="heatmap_less">Less</div>
<div class="heatmap_level">
<span class="heatmap_level_item heatmap_level_0"></span>
<span class="heatmap_level_item heatmap_level_1"></span>
<span class="heatmap_level_item heatmap_level_2"></span>
<span class="heatmap_level_item heatmap_level_3"></span>
<span class="heatmap_level_item heatmap_level_4"></span>
</div>
<div class="heatmap_more">More</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/echarts@5.5.0/dist/echarts.min.js"></script>
<script type="text/javascript">
var chartDom = document.getElementById('heatmap');
var myChart = echarts.init(chartDom);
window.onresize = function() {
myChart.resize();
};
var option;
var dataMap = new Map();
{{ range ((where .Site.RegularPages "Type" "posts")) }}
var key = {{ .Date.Format "2006-01-02" }};
var value = dataMap.get(key);
var link = {{ .RelPermalink}};
var title = {{ .Title }};
// multiple posts in same day
if (value == null) {
dataMap.set(key, [{link, title}]);
} else {
value.push({link, title});
}
{{- end -}}
var data = [];
for (const [key, value] of dataMap.entries()) {
data.push([key, value.length]);
}
var startDate = new Date();
var year_Mill = startDate.setFullYear((startDate.getFullYear() - 1));
var startDate = +new Date(year_Mill);
var endDate = +new Date();
startDate = echarts.format.formatTime('yyyy-MM-dd', startDate);
endDate = echarts.format.formatTime('yyyy-MM-dd', endDate);
// 检测浏览器主题模式并选择颜色方案
var prefersDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
// 定义明亮模式下的颜色方案
var lightTheme = {
backgroundColor: '#FFFFFF',
fangkuaicolor:'#F4F4F4',
gaoliangcolor: ['#9be9a8'],
riqiColor: '#999',
textbrcolor: '#FFF',
xiankuangcolor:'rgba(0, 0, 0, 0.0)',
};
// 定义暗黑模式下的颜色方案
var darkTheme = {
backgroundColor: '#1A1718',
fangkuaicolor:'#282325',
gaoliangcolor: ['#0e4429'],
riqiColor: '#666',
textbrcolor: '#332D2F',
xiankuangcolor:'rgba(0, 0, 0, 0.0)',
};
// 根据浏览器主题模式选择当前主题
var currentTheme = prefersDarkMode ? darkTheme : lightTheme;
option = {
tooltip: {
hideDelay: 1000,
enterable: true,
backgroundColor: currentTheme.textbrcolor,
borderWidth: 0, // 边框宽度为0
formatter: function (p) {
const date = p.data[0];
const posts = dataMap.get(date);
var content = `<span style="font-size: 0.75rem;font-family: var(--font-family-code);">${date}</span>`;
for (const [i, post] of posts.entries()) {
content += "<br>";
var link = post.link;
var title = post.title;
content += `<a href="${link}" target="_blank">${title}</a>` + '<br>';
}
return content;
}
},
visualMap: {
show: false,
inRange: {
color: currentTheme.gaoliangcolor
},
},
calendar: {
left: 20,
top:20,
bottom:0,
right: 0,
cellSize: ['auto', 13],
range: [startDate, endDate],
itemStyle: {
color: currentTheme.fangkuaicolor,
borderWidth: 3.5,
borderColor: currentTheme.backgroundColor,
},
yearLabel: { show: false },
monthLabel: {
nameMap: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
textStyle: {
color: currentTheme.riqiColor,
}
},
dayLabel: {
firstDay: 1,
nameMap: ['日', '一', '', '三', '', '五', ''],
textStyle: {
color: currentTheme.riqiColor
}
},
splitLine: {
lineStyle: {
color: currentTheme.xiankuangcolor,
}
}
},
series: {
type: 'heatmap',
coordinateSystem: 'calendar',
data: data,
}
};
myChart.setOption(option);
myChart.on('click', function(params) {
if (params.componentType === 'series') {
// open the first post on the day
const post = dataMap.get(params.data[0])[0];
const link = window.location.origin + post.link;
window.open(link, '_blank').focus();
}
});
function createDay(date, title, count, post) {
const day = document.createElement("div");
day.className = "heatmap_day";
day.setAttribute("data-title", title);
day.setAttribute("data-count", count);
day.setAttribute("data-post", post);
day.setAttribute("data-date", date);
day.addEventListener("mouseenter", function () {
const tooltip = document.createElement("div");
tooltip.className = "heatmap_tooltip";
let tooltipContent = "";
if (post && parseInt(post, 10) !== 0) {
tooltipContent += '<span class="heatmap_tooltip_post">' + '共 ' + post + ' 篇' + '</span>';
}
if (count && parseInt(count, 10) !== 0) {
tooltipContent += '<span class="heatmap_tooltip_count">' + ' ' + count + ' 字;' + '</span>';
}
if (title && parseInt(title, 10) !== 0) {
tooltipContent += '<span class="heatmap_tooltip_title">' + title + '</span>';
}
if (date) {
tooltipContent += '<span class="heatmap_tooltip_date">' + date + '</span>';
}
tooltip.innerHTML = tooltipContent;
day.appendChild(tooltip);
});
day.addEventListener("mouseleave", function () {
const tooltip = day.querySelector(".heatmap_tooltip");
if (tooltip) {
day.removeChild(tooltip);
}
});
if (count == 0) {
day.classList.add("heatmap_day_level_0");
} else if (count > 0 && count < 1000) {
day.classList.add("heatmap_day_level_1");
} else if (count >= 1000 && count < 2000) {
day.classList.add("heatmap_day_level_2");
} else if (count >= 2000 && count < 3000) {
day.classList.add("heatmap_day_level_3");
} else {
day.classList.add("heatmap_day_level_4");
}
return day;
}
</script>
<div class="articleList">
{{ $pages := where .Site.RegularPages "Type" "in" .Site.Params.mainSections }}
{{ $paginator := .Paginate ($pages) }}
@ -409,7 +14,7 @@ function createDay(date, title, count, post) {
{{ end }}
{{ end }}
</div>
{{ $paginator := .Paginate (where .Pages "Type" "posts") }}
{{ $paginator := .Paginate (where .Pages "Type" "story") }}
{{partial "pagination.html" .}}
</main>
{{ end }}

View File

@ -0,0 +1,23 @@
{{ define "main" }}
<div class="site--main">
<h1 class="post--single__title">{{.Title}}</h1>
{{ if .IsTranslated }}
<div class="translatedCard">
<h4>{{ i18n "translations" }}</h4>
<ul>
{{ range .Translations }}
<li>
<a href="{{ .Permalink }}">{{ .Lang }}: {{ .Title }}{{ if .IsPage }}{{ end
}}</a>
</li>
{{ end }}
</ul>
</div>
{{ end }}
<div class="graph u-marginBottom30">
{{ .Content }}
</div>
</div>
{{ end }}

View File

@ -0,0 +1,24 @@
{{ define "main" }}
<div class="site--main site--main__gears">
<h1 class="post--single__title">{{.Title}}</h1>
<h2 class="post--single__subtitle">{{ .Params.subtitle }}</h2>
<div class="good--list">
{{ range .Params.faves }}
<div class="good--item">
<div class="img-spacer">
<img src="{{ .cover }}">
</div>
<div class="good--name">
<div class="brand">{{ .brand }} · {{ .cat }}</div>
{{ .title }}
</div>
</div>
{{ end }}
</div>
<div class="graph u-marginBottom30">
{{ .Content }}
</div>
</div>
{{ end }}

View File

@ -0,0 +1,22 @@
{{ define "main" }}
<div class="site--main site--main__gears">
<h1 class="post--single__title">{{.Title}}</h1>
<h2 class="post--single__subtitle">{{ .Params.subtitle }}</h2>
<div class="template--linksWrap">
<ul class="link-items">
{{ range .Params.links }}
<li class="link-item">
<a class="link-item-inner effect-apollo" href="{{ .link }}" title="Just a blog" target="_blank">
<span class="sitename"><strong>{{ .title }}</strong>{{ .description }}</span>
</a>
</li>
{{ end }}
</ul>
</div>
<div class="graph u-marginBottom30">
{{ .Content }}
</div>
</div>
{{ end }}

View File

@ -0,0 +1,8 @@
{{ define "main" }}
<div class="site--main">
<div class="db--container">
</div>
</div>
{{ end }}

View File

@ -0,0 +1,79 @@
{{ define "main" }}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/instantsearch.css@8.1.0/themes/reset-min.css"
integrity="sha256-2AeJLzExpZvqLUxMfcs+4DWcMwNfpnjUeAAvEtPr0wU=" crossorigin="anonymous">
<div class="site--main">
<header class="archive-header archive-header__search">
<div id="searchbox"></div>
</header>
<div id="hits" class="articleList"></div>
<div id="pagination"></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/algoliasearch@4.20.0/dist/algoliasearch-lite.umd.js"
integrity="sha256-DABVk+hYj0mdUzo+7ViJC6cwLahQIejFvC+my2M/wfM=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/instantsearch.js@4.60.0/dist/instantsearch.production.min.js"
integrity="sha256-9242vN47QUX50UG5Gf5XDO1YREWCEJRyXHofh5fsl24=" crossorigin="anonymous"></script>
<script>
const searchClient = algoliasearch('{{ .Site.Params.searchAPPID }}', '{{ .Site.Params.searchKey }}');
const search = instantsearch({
indexName: '{{ .Site.Params.indexName }}',
searchClient,
insights: false
});
search.addWidgets([
instantsearch.widgets.searchBox({
container: '#searchbox',
showReset: false,
placeholder: 'Search for stories',
cssClasses: {
form: ['search-form'],
input: ['search-field']
},
templates: {
submit: `<input type="submit" class="search-submit" value="Search">`
}
}),
instantsearch.widgets.hits({
container: '#hits',
templates: {
item(hit, { html, components, sendEvent }) {
const time = new Date(hit.date);
const date = time.toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric',
});
const lngString = '{{ .Site.Language }}';
const uri = hit.uri.replace("/" + lngString + "/", "/");
const cover = hit.cover ? html`<img src="${hit.cover}" class="cover" itemprop="image" />` : '';
return html`<article class="post--item" itemtype="http://schema.org/Article" itemscope="itemscope">
<div class="content">
<h2 class="post--title">
<a href="${uri}">${components.Highlight({ attribute: 'title', hit })}</a>
</h2>
<div class="description">${hit.description}</div>
<div class="meta">
<svg class="icon" viewBox="0 0 1024 1024" width="16" height="16">
<path
d="M512 97.52381c228.912762 0 414.47619 185.563429 414.47619 414.47619s-185.563429 414.47619-414.47619 414.47619S97.52381 740.912762 97.52381 512 283.087238 97.52381 512 97.52381z m0 73.142857C323.486476 170.666667 170.666667 323.486476 170.666667 512s152.81981 341.333333 341.333333 341.333333 341.333333-152.81981 341.333333-341.333333S700.513524 170.666667 512 170.666667z m36.571429 89.697523v229.86362h160.865523v73.142857H512a36.571429 36.571429 0 0 1-36.571429-36.571429V260.388571h73.142858z">
</path>
</svg>${date}
</div>
</div>
${cover}
</article>
`;
},
},
})
]);
search.start();
const queryString = window.location.search;
const params = new URLSearchParams(queryString);
search.helper.setQuery(params.get("s")).search();
</script>
{{ end }}

View File

@ -21,12 +21,6 @@
</svg>
</div>
</div>
<script defer src="https://status.sunpeiwen.com/pa.js"
id="pianjs"
data-code="QSTjqdKiwF3tg6zFb8gkSzRQLNiRPkCI"
data-hit-endpoint="https://status.sunpeiwen.com/hit"
data-event-endpoint="https://status.sunpeiwen.com/event"
data-session-endpoint="https://status.sunpeiwen.com/session"></script>
</footer>
<div class="backToTop">
@ -53,13 +47,13 @@
<script type="text/javascript">
window.WPD_TOKEN = "{{ .Site.Params.wpdToken }}";
window.commentDomain = "{{ .Site.Params.commentDomain }}";
window.actionDomain = "{{ .Site.Params.actionDomain }}";
window.dbAPIBase = "{{ .Site.Params.dbAPIBase }}";
</script>
{{- $opts := dict "minify" hugo.IsProduction -}}
{{- $replay := resources.Get "js/comment.min.js" | js.Build $opts -}}
{{- $db := resources.Get "ts/db.ts" | js.Build $opts -}}
{{- $app := resources.Get "ts/app.ts" | js.Build $opts -}}
{{- $comment := resources.Get "ts/comment.ts" | js.Build $opts -}}
{{ $ts := slice $replay $db $app $comment | resources.Concat "ts/bundle.js" }}
{{ $ts := slice $replay $app | resources.Concat "ts/bundle.js" }}
<script type="text/javascript" src="{{ $ts.RelPermalink }}" defer></script>
{{ range .Site.Params.customJS }}
{{ if ( or ( hasPrefix . "http://" ) ( hasPrefix . "https://" ) ) }}

View File

@ -17,11 +17,10 @@
{{ end }}
<link rel="stylesheet" href="{{ $styles.Permalink }}" integrity="{{ $styles.Data.Integrity }}" media="screen">
{{ $favicon := resources.Get "images/favicon.png" }}
<link type="image/vnd.microsoft.icon" href="{{ $favicon.RelPermalink }}" rel="shortcut icon">
<link type="image/vnd.microsoft.icon" href="{{ $.Site.Params.icon }}" rel="shortcut icon">
{{ if .OutputFormats.Get "RSS" }}
{{ with .OutputFormats.Get "RSS" }}
<link href="{{ .RelPermalink }}" rel="alternate" type="application/rss+xml" title="{{ $.Site.Title }}" />
<link href="{{ .RelPermalink }}" rel="feed" type="application/rss+xml" title="{{ $.Site.Title }}" />
{{ end }}
{{ end }}
<link rel="stylesheet" href="https://cdnjs.sgcd.net/lxgw-wenkai-screen-webfont/lxgwwenkaigbscreen.css" />
{{ end }}

View File

@ -1,8 +1,7 @@
<article class="post--item post--item__status" itemtype="http://schema.org/Article" itemscope="itemscope">
<div class="content">
<header>
{{ $logo := resources.Get "images/logo.jpeg" }}
<img src="{{ $logo.RelPermalink }}" class="avatar" width="48" height="48" />
<img src="{{ $.Site.Params.authorAvatar }}" class="avatar" width="48" height="48" />
<a datetime='{{.Date.Format "2006-01-02 15:04:01" }}' class="humane--time" href="{{ .Permalink }}"
itemprop="datePublished">{{
.Date |

View File

@ -1,6 +1,6 @@
<header class="site--header">
<a href="{{ site.Home.Permalink }}" class="site--url">{{ $logo := resources.Get "images/logo.jpeg" }}
<img src="{{ $logo.RelPermalink }}" class="avatar" />
<img src="{{ $.Site.Params.authorAvatar }}" class="avatar" />
<span class="u-xs-show">
{{ $.Site.Title }}
</span>

View File

@ -1,4 +1,4 @@
<article class="post--item" itemtype="http://schema.org/Article" itemscope="itemscope">
<article class="post--item" itemtype="http://schema.org/Article" itemscope="itemscope" data-id="{{ .File.UniqueID}}">
<div class="content">
<h2 class="post--title" itemprop="headline">
<a href="{{ .Permalink }}">
@ -34,6 +34,15 @@
<a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a>
{{ end }}
{{ end }}
{{ if .Site.Params.post_view }}
<svg class="icon" viewBox="0 0 24 24" width="16" height="16" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M12 9C10.3431 9 9 10.3431 9 12C9 13.6569 10.3431 15 12 15C13.6569 15 15 13.6569 15 12C15 10.3431 13.6569 9 12 9ZM11 12C11 11.4477 11.4477 11 12 11C12.5523 11 13 11.4477 13 12C13 12.5523 12.5523 13 12 13C11.4477 13 11 12.5523 11 12Z" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M21.83 11.2807C19.542 7.15186 15.8122 5 12 5C8.18777 5 4.45796 7.15186 2.17003 11.2807C1.94637 11.6844 1.94361 12.1821 2.16029 12.5876C4.41183 16.8013 8.1628 19 12 19C15.8372 19 19.5882 16.8013 21.8397 12.5876C22.0564 12.1821 22.0536 11.6844 21.83 11.2807ZM12 17C9.06097 17 6.04052 15.3724 4.09173 11.9487C6.06862 8.59614 9.07319 7 12 7C14.9268 7 17.9314 8.59614 19.9083 11.9487C17.9595 15.3724 14.939 17 12 17Z" />
</svg>
<span class="article--views"></span>
{{ end }}
</div>
</div>
{{ if .Content }}

View File

@ -0,0 +1,9 @@
<div id="tcomment"> </div>
<script src="https://cdn.staticfile.org/twikoo/1.6.36/twikoo.all.min.js"></script>
<script>
twikoo.init({
envId: '{{ .Site.Params.twikoo }}',
el: '#tcomment',
})
</script>