Compare commits

..

58 Commits

Author SHA1 Message Date
Cell fd0b171e5f 🔖 Chore(release): 0.3.4 2024-04-25 17:33:49 +08:00
Cell 7ceed732d2 🔧 Chore: update npm scripts 2024-04-25 17:33:25 +08:00
Cell e07904b0f6 🔖 Chore(release): 0.3.3 2024-04-25 13:12:25 +08:00
Cell 5f5d019f09 🔧 Chore: update release workflow 2024-04-25 13:12:02 +08:00
Cell f4e8babd12 🐛 Fix: unencoded Content in Search Leads to JavaScript Execution Risk in autocomplete-js
Fixes #416
2024-04-25 10:46:55 +08:00
Cell 1ed0acdf35 🐛 Fix: fix echarts and mermaid theme switch error 2024-04-24 20:14:17 +08:00
Cell 3b89a4eaab Feat: refactor FixItDecryptor and add confirm btn
Resolved #437
2024-04-24 17:39:17 +08:00
Cell 20433ed50d 🐛 Fix: using fixit-encryptor shortcode in an unencrypted article caused other styles of the article to not take effect
Fixes #410
2024-04-24 10:35:13 +08:00
Cell 6c83d0630c 🐛 Fix: fix fixit-encryptor shortcode invalid
Fixes #410
Fixes #429
Caused by #420
2024-04-24 09:52:03 +08:00
Cell 79b5c27ed8 🐛 Fix: fix syntax error 2024-04-24 08:59:36 +08:00
asaraog dfeaf0e9a7 🎉 Feat: add Hindi language 2024-04-24 08:59:36 +08:00
Cell 1e493fef48 ⬆️ Fix: update Artalk comments to the latest version and and useBackendConf param
Fixes #415
2024-04-23 17:42:53 +08:00
Cell 7f19569336 🔧 Chore: improve auto changelog configuration
Resolved #434
2024-04-22 21:58:06 +08:00
Cell 429698a096 🔧 Chore: add changelog template and workflow 2024-04-22 17:38:56 +08:00
Cell 09440190aa 🐛 Fix: fix image llightgallery render error (#420) 2024-04-22 12:15:51 +08:00
Cell 1217640d40 🍻 Chore: add random staging id for staging element 2024-04-22 11:31:11 +08:00
Cell 300bbe9a44 🔥 Chore: remove data store in id partials function 2024-04-22 11:23:25 +08:00
Cell 7ec41cdb00 ♻️ Refactor: refactor echarts shortcode data store way (#420) 2024-04-22 11:06:58 +08:00
Cell fd13ca782b ♻️ Refactor: refactor mapbox shortcode data store way (#420) 2024-04-22 10:11:05 +08:00
Cell bae1678c59 🐛 Fix: fix typeit shotrcode miss space when build with --minify param 2024-04-20 17:06:08 +08:00
Cell 72bd72f5ed ♻️ Refactor: refactor typeit shortcode and feature (#420) 2024-04-20 16:30:16 +08:00
Cell c09f141034 ♻️ Refactor: refactor code block rendering 2024-04-19 00:33:35 +08:00
Cell a2d8eaa249 🐛 Fix: fix encrypted-hidden invaild in mobile 2024-04-19 00:31:51 +08:00
Cell ff8e5fc7bf 💄 Style: update comment iframe width 2024-04-13 11:11:43 +08:00
Cell 84e9eea483 Feat: add partial function get-remote-json, and deprecated getJSON function 2024-04-10 15:39:54 +08:00
Cell 5705048952 Feat: add githubTokenHeader into Scratch 2024-04-10 14:34:19 +08:00
Cell d379911220 Feat: add new partial function format-number 2024-04-10 11:04:44 +08:00
Cell 773a8a7eb9 Perf: code optimization 2024-04-08 17:47:57 +08:00
Cell 6ab33ff7bf Feat: add onlyMainSection option for page auto heading numbering 2024-04-08 17:46:31 +08:00
Cell dc0b96210a 📝 Docs: update README 2024-04-06 13:41:37 +08:00
Cell 4dc8d0f7d7 💄 Style: use the same proportions as the cover image of https://dev.to/ 2024-03-27 17:38:34 +08:00
Cell 76fec05da2 🐛 Fix: fix search config read error 2024-03-26 16:38:48 +08:00
Cell 54c773368e Feat: improve readme template 2024-03-26 16:37:35 +08:00
Cell 05693d8b4c 🔧 Chore: update giscus.json 2024-03-26 12:16:11 +08:00
Cell 38cf4ee0de 🐛 Fix: mermaid init error 2024-03-23 21:42:10 +08:00
Cell 3df577cb0d ⬆️ Fix: bump Mermaid from 9.x to 10.x and fix error (#420) 2024-03-08 16:23:37 +08:00
Cell 063d8fa219 🐛 Fix: fix shortcode render error (#420)
mermaid, echarts, music
2024-03-07 22:09:36 +08:00
Cell 7f38d99ae4 💄 Style: update define list style 2024-03-07 15:41:22 +08:00
Cell c771bce957 Docs: update license 2024-03-01 14:43:48 +08:00
Cell 2ea592b4a3 🐛 Fix: use function to get params replace of .Scatch (#420) 2024-02-23 20:50:52 +08:00
Cell a9fd15e47d 🔧 Chore: update custom.js.example to ES6 style 2024-02-23 17:27:49 +08:00
Cell d6be3c1fc2 🔧 Chore: expose theme version number to theme.js 2024-02-23 17:03:19 +08:00
Cell c9af0b9018 🔖 Chore(release): 0.3.2 2024-02-23 10:48:02 +08:00
Cell b2b47095eb 🐛 Fix: to create a scratch pad that is not reset on server rebuilds, use the Store method instead of Scratch method (fixes #417) 2024-02-23 10:33:08 +08:00
Cell 002ebda06f 🐛 Fix: remove symbolic links of themes
fixed #419
2024-02-22 11:24:04 +08:00
Cell 551938f0b4 Revert "🐛 Fix: to create a scratch pad that is not reset on server rebuilds, use the Store method instead of Scratch method (fixes #417)"
This reverts commit 9d6ee9feef.
2024-02-21 14:32:05 +08:00
Cell 9d6ee9feef 🐛 Fix: to create a scratch pad that is not reset on server rebuilds, use the Store method instead of Scratch method (fixes #417) 2024-02-21 14:20:25 +08:00
Cell 1bd56105b7 🐛 Fix: remove sizes="auto" prop what was used for lazysizes.js in old FixIt version (resolve #411)
refer to https://github.com/whatwg/html/issues/9448
2024-01-28 23:18:23 +08:00
Cell b7dba0713e 🐛 Fix: fix regular page in post navigation 2024-01-16 16:04:57 +08:00
Cell dd4f422dba 📝 Docs: update contributing file 2024-01-16 15:54:09 +08:00
Cell aaebdfb02c 🙈 Chore: add .gitattributes 2024-01-16 10:22:56 +08:00
Cell 9eb18b9e75 🔖 Chore(release): 0.3.1 2024-01-11 14:40:18 +08:00
Cell 594c89eb1e 🔧 Chore: remove atomic-algolia (#404) 2024-01-11 11:13:35 +08:00
Cell 976d1ea82a 📝 Chore: remove the docs Git submodule and add the demo directory (resolve #404) 2024-01-10 15:40:42 +08:00
Cell b16a06893c 🐛 Fix: comment the theme field in the default theme configuration
Fix the bug that the theme cannot be loaded through hugo modules
2024-01-10 14:05:58 +08:00
Cell 32711ff29c 🐛 Fix: heading style in terms and list page 2024-01-03 11:39:26 +08:00
Cell 38eb829194 Revert: "Chore: replace git submodule with hugo module to load theme components" 2024-01-02 10:29:09 +08:00
Cell 4c9b5b6773 🔧 Chore: update default menus 2024-01-01 19:40:06 +08:00
105 changed files with 1264 additions and 7019 deletions
+18
View File
@@ -0,0 +1,18 @@
{
"output": "CHANGELOG.md",
"template": ".auto-changelog/template.hbs",
"handlebarsSetup": ".auto-changelog/setup.js",
"sortCommits": "relevance",
"commitLimit": false,
"replaceText": {
"^(Feat|feat):": ":sparkles: Feat:",
"^(Fix|fix):": ":bug: Fix:",
"^(Build|build):": ":hammer: Build:",
"^(Refactor|refactor):": ":recycle: Refactor:",
"^(Style|style):": ":lipstick: Style:",
"^(Perf|perf):": ":zap: Perf:",
"^(Test|test):": ":white_check_mark: Test:",
"^(Docs|docs):": ":memo: Docs:",
"^(Chore|chore):": ":wrench: Chore:"
}
}
+31
View File
@@ -0,0 +1,31 @@
// Custom Handlebars helpers
module.exports = function (Handlebars) {
/**
* Handlebars helper to replace a string with another string
* @param {String} context the string to replace
* @param {Object} options
* @param {String} options.hash.from the string to replace
* @param {String} options.hash.to the string to replace with
* @example {{replace "foo bar" from="foo" to="baz"}} => "baz bar"
*/
Handlebars.registerHelper('replace', function (context, options) {
return context.replace(options.hash.from, options.hash.to)
})
/**
* Handlebars helper to convert a name to a GitHub username
* @param {String} context name to convert
* @param {Object} options
* @param {Boolean} [options.hash.linked=true] whether to return a linked username
* @example {{githubUser "Cell"}} => "Lruihao"
*/
Handlebars.registerHelper('githubUser', function (context, { hash: { linked = false }}) {
const map = {
'Cell': "Lruihao",
}
const username = map[context] || context
if (linked) {
return `[@${username}](https://github.com/${username})`
}
return `@${username}`
})
}
+70
View File
@@ -0,0 +1,70 @@
# Changelog
All notable changes to this project will be documented in this file.
{{!-- if need, set replaceText in config.json "#(\\d+)": "[#$1](https://github.com/hugo-fixit/FixIt/issues/$1)" --}}
{{#each releases}}
{{#if href}}
## [{{title}}]({{href}}){{#if tag}} - {{isoDate}}{{/if}}
{{else}}
## {{title}}{{#if tag}} - {{isoDate}}{{/if}}
{{/if}}
{{#if summary}}
{{summary}}
{{/if}}
{{!-- List commits with `Breaking change: ` somewhere in the message --}}
{{#commit-list commits heading='### :boom: Breaking Changes' message='^(Breaking change|BREAKING CHANGE):'}}
- {{subject}} [`{{shorthash}}`]({{href}}) by {{githubUser author}}
{{/commit-list}}
{{!-- List commits that add new features, but exclude those that have `:sparkles:` in the message --}}
{{#commit-list commits heading='### :tada: New Features' message='(:tada:|Feat:|feat:)' exclude='^:sparkles:'}}
- {{subject}} [`{{shorthash}}`]({{href}}) by {{githubUser author}}
{{/commit-list}}
{{!-- List commits that enhance existing features, but exclude those that have `:tada:` in the message --}}
{{#commit-list commits heading='### :sparkles: Enhancements' message='(:sparkles:|Feat:|feat:|Perf:|perf:)' exclude='^:tada:'}}
- {{subject}} [`{{shorthash}}`]({{href}}) by {{githubUser author}}
{{/commit-list}}
{{!-- List commits that bug fixes --}}
{{#commit-list commits heading='### :bug: Bug Fixes' message='(:bug:|Fix:|fix:)'}}
- {{subject}} [`{{shorthash}}`]({{href}}) by {{githubUser author}}
{{/commit-list}}
{{!-- List commits that improve the documentation --}}
{{#commit-list commits heading='### :memo: Documentation' message='(:memo:|Docs:|docs:)'}}
- {{subject}} [`{{shorthash}}`]({{href}}) by {{githubUser author}}
{{/commit-list}}
{{!-- List other changes commits --}}
{{#commit-list commits heading='### :wrench: Other Changes' message='(Refactor:|refactor:|Style:|style:|Test:|test:|Chore:|chore:|Build:|build:)'}}
- {{subject}} [`{{shorthash}}`]({{href}}) by {{githubUser author}}
{{/commit-list}}
- **Full Changelog**: {{href}}
---
### Uncategorized
{{#if merges}}
#### Merged pull requests
{{#each merges}}
{{!-- {{#if href}}[`#{{id}}`]({{href}}){{/if}} --}}
- {{#if commit.breaking}}**Breaking change:** {{/if}}{{message}} by {{githubUser author}} in {{#if id}}#{{id}}{{/if}}
{{/each}}
{{/if}}
{{#if fixes}}
#### Closed issues
{{#each fixes}}
- {{#if commit.breaking}}**Breaking change:** {{/if}}{{commit.subject}}{{#each fixes}} {{#if id}}#{{id}}{{/if}}{{/each}} by {{githubUser commit.author}}
{{/each}}
{{/if}}
{{/each}}
+1
View File
@@ -0,0 +1 @@
assets/lib/**/* linguist-vendored
-48
View File
@@ -1,48 +0,0 @@
name: Update Algolia Search Index
on:
push:
branches:
- master
paths:
- "docs"
workflow_dispatch:
jobs:
algolia-atomic:
runs-on: ubuntu-latest
steps:
- name: Check out repository code
uses: actions/checkout@v4
with:
submodules: recursive # Fetch Hugo themes (true OR recursive)
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: "latest"
extended: true
- name: Build
run: |
npm install
npm run build
- name: Update Algolia Index (en)
env:
ALGOLIA_APP_ID: YKOM6PKLUY
ALGOLIA_ADMIN_KEY: ${{ secrets.ALGOLIA_ADMIN_KEY }}
ALGOLIA_INDEX_NAME: "index.en"
ALGOLIA_INDEX_FILE: "./docs/public/index.json"
run: |
npm run algolia
- name: Update Algolia Index (zh-cn)
env:
ALGOLIA_APP_ID: YKOM6PKLUY
ALGOLIA_ADMIN_KEY: ${{ secrets.ALGOLIA_ADMIN_KEY }}
ALGOLIA_INDEX_NAME: "index.zh-cn"
ALGOLIA_INDEX_FILE: "./docs/public/zh-cn/index.json"
run: |
npm run algolia
+1 -1
View File
@@ -18,4 +18,4 @@ jobs:
hugo-version: latest
extended: true
- name: Build Hugo static files
run: hugo -v --source=docs --gc --minify
run: hugo -v --source=demo --gc --minify
+45
View File
@@ -0,0 +1,45 @@
# This is a basic workflow to help you get started with Actions
name: Release for new tag
# Controls when the action will run.
on:
# Triggers the workflow on push or pull request events but only for the master branch
push:
tags:
- 'v*.*.*'
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0 # Fetch all history for generating release notes
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 18
- name: Install dependencies and generate release notes
run: |
npm install
npm run release -- --starting-version ${{ github.ref_name }}
- name: GitHub Release
uses: softprops/action-gh-release@v2
with:
# Creates a draft release. Defaults to false
draft: true
body_path: CHANGELOG.md
+1 -1
View File
@@ -25,4 +25,4 @@ $RECYCLE.BIN/
## Linux
.directory
CHANGELOG.md
-3
View File
@@ -1,3 +0,0 @@
[submodule "docs"]
path = docs
url = https://github.com/hugo-fixit/docs.git
+7 -1
View File
@@ -7,7 +7,7 @@ First, fork this repository by clicking the fork button.
Next, clone your forked repo.
```bash
git clone --recursive https://github.com/hugo-fixit/FixIt.git && cd FixIt
git clone https://github.com/hugo-fixit/FixIt.git && cd FixIt
```
Then, install the dev dependencies.
@@ -27,6 +27,12 @@ npm run server
npm run server:production
```
If you want to do docs-related theme changes, the simplest way is to have both `FixIt` and `fixit-docs` cloned as sibling directories, and then run:
```bash
npm run server:docs
```
Finally, create a new pull request at <https://github.com/hugo-fixit/FixIt/pulls> to submit your contribution 🎉
## Git standard for developers
+1 -1
View File
@@ -2,7 +2,7 @@ The MIT License (MIT)
Copyright (c) 2018 LIUZHICHAO.COM
Copyright (c) 2019-2020 DILLONZQ.COM
Copyright (c) 2021-2023 LRUIHAO.CN
Copyright (c) 2021-2024 Lruihao (https://lruihao.cn)
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
+22 -57
View File
@@ -6,65 +6,27 @@
👉 English README | [简体中文说明](README.zh-cn.md)
> [FixIt](https://github.com/hugo-fixit/FixIt) is a **clean**, **elegant** but **advanced** blog theme for [Hugo](https://gohugo.io/).
[FixIt](https://github.com/hugo-fixit/FixIt) is a **clean**, **elegant** but **advanced** blog theme for [Hugo](https://gohugo.io/).
It is based on the original [LoveIt Theme](https://github.com/dillonzq/LoveIt), [KeepIt Theme](https://github.com/Fastbyte01/KeepIt) and [LeaveIt Theme](https://github.com/liuzc/LeaveIt).
It is based on the original [LoveIt Theme](https://github.com/dillonzq/LoveIt), [KeepIt Theme](https://github.com/Fastbyte01/KeepIt) and [LeaveIt Theme](https://github.com/liuzc/LeaveIt).[^1]
The FixIt theme inherits the excellent features of these themes, and adds new features and optimizations on those basis. Please read [Why Choose FixIt](#why-choose-fixit) to learn more.
![Hugo Theme FixIt](https://fixit.lruihao.cn/images/Apple-Devices-Preview.jpg)
![Hugo Theme FixIt](https://fixit.lruihao.cn/images/apple-devices-preview.webp)
## Getting started
Head to the [getting started page](http://fixit.lruihao.cn/documentation/getting-started/) or start with a template:
- [Installation](https://fixit.lruihao.cn/documentation/installation/)
- [Getting Started](https://fixit.lruihao.cn/documentation/getting-started/)
- [Content Management](https://fixit.lruihao.cn/documentation/content-management/)
- [Advanced Usage](https://fixit.lruihao.cn/documentation/advanced/)
- [hugo-fixit/hugo-fixit-blog-git](https://github.com/hugo-fixit/hugo-fixit-blog-git)
- [hugo-fixit/hugo-fixit-blog-go](https://github.com/hugo-fixit/hugo-fixit-blog-go)
Alternatively, you can run the [documentation site](https://fixit.lruihao.cn/) locally. For more details, see [hugo-fixit/docs](https://github.com/hugo-fixit/docs).
## [Documentation](https://fixit.lruihao.cn/categories/documentation/)
## Template repository
Head to this [documentation page](https://fixit.lruihao.cn/documentation/basics/) for a complete guidence to get started with the FixIt theme.
Or run [Documentation Site](https://fixit.lruihao.cn) locally, see more details from [Contributing](#contributing).
In addition, there is the [FixIt wiki](https://github.com/hugo-fixit/FixIt/wiki).
## Migrate from LoveIt
If you are currently using the LoveIt theme (or some other themes), it is very easy to migrate to FixIt.
You can add this repo as a submodule of your site directory. Alternatively, you can install the theme in [other ways](https://fixit.lruihao.cn/documentation/basics/#install-theme).
```bash
git submodule add https://github.com/hugo-fixit/FixIt.git themes/FixIt
```
And later you can update the submodule in your site directory to the latest commit using this command:
```bash
git submodule update --remote --merge
```
Next, go to the `hugo.toml` and change the default theme to `FixIt`.
```diff
- theme = "LoveIt"
+ theme = "FixIt"
```
Now the migration is finished and everything is ready 🎉
## Why choose FixIt
The FixIt theme inherits the excellent features of themes such as LoveIt, and adds new features and optimizations on those basis, as detailed in [Features](#features). In addition, the FixIt theme has the following advantages:
- Complete Chinese and English official documentations
- Community support: Theme official website, Discussions and official QQ group
- Continuously and actively update
- Constantly incorporate suggestions and ideas from all sides
- Highly open theme customizable section
In short, if you prefer the design language and freedom of the FixIt theme, and if you like to personalize your own themes as I do, the FixIt theme may be more suitable for you.
- [hugo-fixit/hugo-fixit-start](https://github.com/hugo-fixit/hugo-fixit-start)
- [hugo-fixit/hugo-fixit-start1](https://github.com/hugo-fixit/hugo-fixit-start1)
- [hugo-fixit/docs](https://github.com/hugo-fixit/docs)
- [Lruihao/hugo-blog](https://github.com/Lruihao/hugo-blog)
## Who used FixIt
@@ -180,7 +142,7 @@ Make sure that you follow [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) while contrib
## Acknowledgements
<details open>
<details>
<summary>Thanks to the authors of following resources included in the theme:</summary>
- [normalize.css](https://github.com/necolas/normalize.css)
@@ -220,7 +182,7 @@ Make sure that you follow [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) while contrib
</details>
<details open>
<details>
<summary>The FixIt also draws on some features of the following projects, and thanks to their authors as well:</summary>
- [DoIt](https://github.com/HEIGE-PCloud/DoIt)
@@ -234,15 +196,18 @@ FixIt is licensed under the **MIT** license. Check the [LICENSE file](LICENSE) f
## Author
[Lruihao](https://github.com/Lruihao "Follow me on GitHub")
Follow [Lruihao](https://github.com/Lruihao "Follow me on GitHub")
## Sponsor
Giving me a Star 🌟 is already the greatest encouragement and support for me.\
If you enjoy the theme, please consider buying me a coffee ☕️.
[![Open Source Love](https://badges.frapsoft.com/os/v1/open-source.svg?v=103)](https://github.com/hugo-fixit/FixIt)
If you enjoy the theme, please consider buying me a coffee ☕️. Thanks!
- [PayPal](https://paypal.me/Lruihao)
- [Alipay](images/alipay.jpg)
- [Wechat](images/wechatpay.jpg)
Thanks! ❤️
Don't forget to leave a ⭐️ if you like this theme, thanks!
[^1]: The theme name is interesting: "leave it, keep it, love it, fix it". Appears and leaves, loves but cannot keep. Doesn't it look like that damn love and BUG? 🤣
+25 -60
View File
@@ -6,65 +6,27 @@
👉 [English README](README.md) | 简体中文说明
> [FixIt](https://github.com/hugo-fixit/FixIt) 是一个**简洁**、**优雅**且**高效**的 [Hugo](https://gohugo.io/) 博客主题。
[FixIt](https://github.com/hugo-fixit/FixIt) 是一个**简洁**、**优雅**且**高效**的 [Hugo](https://gohugo.io/) 博客主题。[]
它的原型基于 [LoveIt 主题](https://github.com/dillonzq/LoveIt)[KeepIt 主题](https://github.com/Fastbyte01/KeepIt) 和 [LeaveIt 主题](https://github.com/liuzc/LeaveIt)。
它的原型基于 [LoveIt 主题](https://github.com/dillonzq/LoveIt)[KeepIt 主题](https://github.com/Fastbyte01/KeepIt) 和 [LeaveIt 主题](https://github.com/liuzc/LeaveIt)。[^1]
FixIt 主题继承了这些主题的优秀功能,并在此基础上添加了新的功能与优化,请阅读 [为什么选择 FixIt](#为什么选择-FixIt) 来了解更多。
![Hugo Theme FixIt](https://fixit.lruihao.cn/images/apple-devices-preview.webp)
![Hugo Theme FixIt](https://fixit.lruihao.cn/images/Apple-Devices-Preview.jpg)
## 主题文档
## 快速上手
- [安装篇](https://fixit.lruihao.cn/zh-cn/documentation/installation/)
- [入门篇](https://fixit.lruihao.cn/zh-cn/documentation/getting-started/)
- [内容管理](https://fixit.lruihao.cn/zh-cn/documentation/content-management/)
- [进阶篇](https://fixit.lruihao.cn/zh-cn/documentation/advanced/)
前往 [快速上手页面](https://fixit.lruihao.cn/zh-cn/documentation/getting-started/) 或从一个模板直接开始:
或者在本地运行 [文档站点](https://fixit.lruihao.cn/zh-cn/),更多细节详见 [hugo-fixit/docs](https://github.com/hugo-fixit/docs)。
- [hugo-fixit/hugo-fixit-blog-git](https://github.com/hugo-fixit/hugo-fixit-blog-git)
- [hugo-fixit/hugo-fixit-blog-go](https://github.com/hugo-fixit/hugo-fixit-blog-go)
## 模板仓库
## [完整文档](https://fixit.lruihao.cn/zh-cn/categories/documentation/)
前往这篇 [文档](https://fixit.lruihao.cn/zh-cn/documentation/basics/),阅读关于安装与使用的详细指南。
或者在本地运行 [文档站点](https://fixit.lruihao.cn/zh-cn/),更多细节详见 [参与贡献](#参与贡献)。
除此之外,还有 [FixIt 主题维基](https://github.com/hugo-fixit/FixIt/wiki)。
## 从 LoveIt 迁移
如果你现在正在使用 LoveIt 主题(或者一些其他的主题),你可以很容易地迁移至 FixIt。
你可以将这个主题仓库添加为你的网站目录的子模块。或者,你可以通过 [其他方式](https://fixit.lruihao.cn/zh-cn/documentation/basics/#install-theme) 安装主题。
```bash
git submodule add https://github.com/hugo-fixit/FixIt.git themes/FixIt
```
之后,你可以在站点目录通过这条命令来将主题更新至最新版本:
```bash
git submodule update --remote --merge
```
接着,前往 `hugo.toml` 并将默认主题更改为 `FixIt`
```diff
- theme = "LoveIt"
+ theme = "FixIt"
```
这样就完成了迁移工作,现在一切准备就绪 🎉
## 为什么选择 FixIt
FixIt 主题继承了 LoveIt 等主题的优秀功能,并在它们的基础上添加了新的功能与优化,详见 [特性](#特性)。除此之外,FixIt 主题还有以下优点:
- 完善的中英文官方文档
- 社区支持:主题官网、Discussions 和官方 QQ 群
- 持续积极地更新
- 不断收纳各方的建议和想法
- 高度开放主题可自定义部分
总之,如果你更偏好 FixIt 主题的设计语言和自由度,如果你和我一样喜欢个性化自定义主题,那么,FixIt 主题可能是更适合你。
- [hugo-fixit/hugo-fixit-start](https://github.com/hugo-fixit/hugo-fixit-start)
- [hugo-fixit/hugo-fixit-start1](https://github.com/hugo-fixit/hugo-fixit-start1)
- [hugo-fixit/docs](https://github.com/hugo-fixit/docs)
- [Lruihao/hugo-blog](https://github.com/Lruihao/hugo-blog)
## 谁在用 FixIt
@@ -166,7 +128,7 @@ FixIt 支持下列语言:
## 问题、想法、bugs 和 PRs
所有的反馈都是欢迎的!详见 [议题](https://github.com/hugo-fixit/FixIt/issues) 或者 [讨论](https://github.com/hugo-fixit/FixIt/discussions)。
所有的反馈都是欢迎的!详见 [议题](https://github.com/hugo-fixit/FixIt/issues) 或者 [讨论](https://github.com/hugo-fixit/FixIt/discussions) 或者加入 QQ 群:`814031017`
## 参与贡献
@@ -184,7 +146,7 @@ FixIt 支持下列语言:
## 致谢
<details open>
<details>
<summary>FixIt 主题中用到了以下项目,感谢它们的作者:</summary>
- [normalize.css](https://github.com/necolas/normalize.css)
@@ -224,7 +186,7 @@ FixIt 支持下列语言:
</details>
<details open>
<details>
<summary>FixIt 主题还借鉴了以下项目的部分功能,同样感谢它们的作者:</summary>
- [DoIt](https://github.com/HEIGE-PCloud/DoIt)
@@ -234,19 +196,22 @@ FixIt 支持下列语言:
## 许可协议
FixIt 根据 **MIT** 许可协议授权。 更多信息请查看 [LICENSE 文件](LICENSE)。
FixIt 根据 **MIT** 许可协议授权。更多信息请查看 [LICENSE 文件](LICENSE)。
## 作者
[Lruihao](https://github.com/Lruihao "在 GitHub 上关注我")
Follow [Lruihao](https://github.com/Lruihao "在 GitHub 上关注我")
## 赞助支持
给我一个 Star 🌟 已经是对我最大的鼓励和支持了。\
如果你喜爱这个主题,请考虑给我买杯咖啡 ☕️。
[![Open Source Love](https://badges.frapsoft.com/os/v1/open-source.svg?v=103)](https://github.com/hugo-fixit/FixIt)
如果你喜爱这个主题,请考虑给我买杯咖啡 ☕️,谢谢!
- [PayPal](https://paypal.me/Lruihao)
- [支付宝](images/alipay.jpg)
- [微信支付](images/wechatpay.jpg)
谢谢!❤️
如果你喜欢这个主题,别忘了留下一颗 ⭐️ 哦,谢谢!
[^1]: 主题名称趣谈:“leave it, keep itlove itfix it”。出现又离开,爱而不得。这像不像那该死的爱情和 BUG 呢?🤣
+2 -1
View File
@@ -97,7 +97,8 @@
.featured-image-preview {
width: 100%;
padding: 30% 0 0;
// use the same proportions as the cover image of https://dev.to/
aspect-ratio: auto 1000 / 420;
position: relative;
margin: 0.6rem auto;
@include transition(transform 0.4s ease);
+2 -2
View File
@@ -203,10 +203,10 @@
dl {
dt {
margin-bottom: 0.5em;
font-weight: bold;
}
dd {
margin-inline-start: 1.25em;
margin: 0.25em 0 1em;
}
}
+1 -1
View File
@@ -18,7 +18,7 @@ code {
}
// indented code
pre {
pre:not(.mermaid[data-processed='true']) {
margin: 0;
line-height: 1.45em;
padding: 0.5rem;
@@ -1,4 +1,8 @@
>#comments {
padding: 2rem 0;
@extend .print-d-none;
iframe {
width: 100%;
}
}
@@ -3,12 +3,8 @@
text-align: center;
margin-top: 3rem;
.fixit-encryptor-shortcode & {
margin-top: 1rem;
}
#fixit-decryptor-input,
.fixit-decryptor-input,
.fixit-decryptor-btn,
.fixit-encryptor-btn {
display: inline-block;
box-sizing: border-box;
@@ -40,9 +36,8 @@
}
}
#fixit-decryptor-input,
.fixit-decryptor-input {
width: clamp(50%, 400px, 100%);
width: calc(clamp(50%, 450px, 100%) - 100px);
height: 3rem;
padding-left: 1rem;
padding-right: 1rem;
@@ -53,10 +48,11 @@
}
}
.fixit-decryptor-btn,
.fixit-encryptor-btn {
cursor: pointer;
@include transition(all 0.1s ease-out);
padding: 0.6rem 1rem;
padding: 0.8rem 1rem;
background-color: $header-background-color;
@@ -66,6 +62,20 @@
}
}
.encrypted-hidden {
display: none;
// fixit-encryptor shortcodes
fixit-encryptor {
.fixit-decryptor-container {
margin-top: 1rem;
}
&.decrypted > .fixit-decryptor-container {
.fixit-decryptor-loading,
.fixit-decryptor-input,
.fixit-decryptor-btn {
display: none;
}
}
}
.encrypted-hidden {
display: none !important;
}
+3 -1
View File
@@ -1,5 +1,7 @@
.mermaid {
text-align: center;
&[data-processed='true'] {
text-align: center;
}
svg {
max-width: 100%;
+3 -6
View File
@@ -13,9 +13,9 @@ libFiles:
# aplayer@1.10.1 https://github.com/MoePlayer/APlayer
aplayerCSS: aplayer@1.10.1/dist/APlayer.min.css
aplayerJS: aplayer@1.10.1/dist/APlayer.min.js
# artalk@2.6.4 https://github.com/ArtalkJS/Artalk
artalkCSS: artalk@2.6.4/dist/Artalk.css
artalkJS: artalk@2.6.4/dist/Artalk.js
# artalk@latest https://github.com/ArtalkJS/Artalk
artalkCSS: artalk@latest/dist/Artalk.css
artalkJS: artalk@latest/dist/Artalk.js
# autocomplete-js@0.38.1 https://github.com/algolia/autocomplete
# TODO update autocompleteJS: '@algolia/autocomplete-js@1.7.1/dist/umd/index.production.js'
autocompleteJS: autocomplete.js@0.38.1/dist/autocomplete.min.js
@@ -57,9 +57,6 @@ libFiles:
# TODO update to 3.x
mapboxGLCSS: mapbox-gl@2.10.0/dist/mapbox-gl.css
mapboxGLJS: mapbox-gl@2.10.0/dist/mapbox-gl.js
# mermaid@9.4.3 https://github.com/mermaid-js/mermaid
# TODO bump Mermaid from 9.x to 10.x
mermaidJS: mermaid@9.4.3/dist/mermaid.min.js
# meting@2.0.1 https://github.com/metowolf/MetingJS
metingJS: meting@2.0.1/dist/Meting.min.js
# object-fit-images@3.2.4 https://github.com/fregante/object-fit-images
+3 -6
View File
@@ -13,9 +13,9 @@ libFiles:
# aplayer@1.10.1 https://github.com/MoePlayer/APlayer
aplayerCSS: aplayer@1.10.1/dist/APlayer.min.css
aplayerJS: aplayer@1.10.1/dist/APlayer.min.js
# artalk@2.6.4 https://github.com/ArtalkJS/Artalk
artalkCSS: artalk@2.6.4/dist/Artalk.css
artalkJS: artalk@2.6.4/dist/Artalk.js
# artalk@latest https://github.com/ArtalkJS/Artalk
artalkCSS: artalk@latest/dist/Artalk.css
artalkJS: artalk@latest/dist/Artalk.js
# autocomplete-js@0.38.1 https://github.com/algolia/autocomplete
# TODO update autocompleteJS: '@algolia/autocomplete-js@1.7.1/dist/umd/index.production.js'
autocompleteJS: autocomplete.js@0.38.1/dist/autocomplete.min.js
@@ -57,9 +57,6 @@ libFiles:
# TODO update to 3.x
mapboxGLCSS: mapbox-gl@2.10.0/dist/mapbox-gl.css
mapboxGLJS: mapbox-gl@2.10.0/dist/mapbox-gl.js
# mermaid@9.4.3 https://github.com/mermaid-js/mermaid
# TODO bump Mermaid from 9.x to 10.x
mermaidJS: mermaid@9.4.3/dist/mermaid.min.js
# meting@2.0.1 https://github.com/metowolf/MetingJS
metingJS: meting@2.0.1/dist/Meting.min.js
# object-fit-images@3.2.4 https://github.com/fregante/object-fit-images
+18 -18
View File
@@ -1,35 +1,35 @@
/**
* Custom javascript for FixIt site.
* Custom JavaScript for FixIt blog site.
* @author @Lruihao https://lruihao.cn
*/
const FixItCustom = new (function () {
class FixItBlog {
/**
* Hello World
* You can define your own functions below.
* @returns {FixItCustom}
* say hello
* you can define your own functions below
* @returns {FixItBlog}
*/
this.hello = () => {
console.log('FixItCustom echo: Hello FixIt!');
hello() {
console.log('custom.js: Hello FixIt!');
return this;
};
}
/**
* Initialize.
* @returns {FixItCustom}
* initialize
* @returns {FixItBlog}
*/
this.init = () => {
// Custom infos.
init() {
this.hello();
return this;
};
})();
}
}
/**
* Immediate.
* immediate execution
*/
(() => {
FixItCustom.init();
// It will be executed when the DOM tree is built.
window.fixitBlog = new FixItBlog();
// it will be executed when the DOM tree is built
document.addEventListener('DOMContentLoaded', () => {
// FixItCustom.init();
window.fixitBlog.init();
});
})();
+110 -83
View File
@@ -12,86 +12,125 @@ FixItDecryptor = function (options = {}) {
this.options = options || {};
this.options.duration = this.options.duration || 24 * 60 * 60; // default cache one day
this.decryptedEventSet = new Set();
this.partialDecryptedEventSet = new Set();
this.resetEventSet = new Set();
this.$el = document.querySelector('.fixit-decryptor-container');
/**
* decrypt content
* @param {String} base64EncodeContent encrypted content
* @param {Element} $content content element
* @param {String} salt salt string
* @param {Boolean} [isAll=true] whether to decrypt all content
*/
var _decryptContent = (base64EncodeContent) => {
var _decryptContent = ($content, salt, isAll=true) => {
try {
this.$el.querySelector('.fixit-decryptor-loading').classList.add('d-none');
this.$el.querySelector('#fixit-decryptor-input').classList.add('d-none');
this.$el.querySelector('.fixit-encryptor-btn').classList.remove('d-none');
document.querySelector('#content').insertAdjacentHTML(
if (isAll) {
// decrypt all content
this.$el.querySelector('.fixit-decryptor-loading').classList.add('d-none');
this.$el.querySelector('.fixit-decryptor-input').classList.add('d-none');
this.$el.querySelector('.fixit-decryptor-btn').classList.add('d-none');
this.$el.querySelector('.fixit-encryptor-btn').classList.remove('d-none');
} else {
// decrypt shortcode content
$content.parentElement.classList.add('decrypted');
}
$content.insertAdjacentHTML(
'afterbegin',
CryptoJS.enc.Base64.parse(base64EncodeContent).toString(CryptoJS.enc.Utf8)
CryptoJS.enc.Base64
.parse($content.getAttribute('data-content').replace(salt, ''))
.toString(CryptoJS.enc.Utf8)
);
} catch (err) {
return console.error(err);
}
// decrypted hook
console.log(this.decryptedEventSet)
for (const event of this.decryptedEventSet) {
event();
}
const eventSet = isAll ? this.decryptedEventSet : this.partialDecryptedEventSet;
for (const event of eventSet) {
event($content);
}
};
/**
* validate password
* @param {Element} $decryptor decryptor element
* @param {Element} $content content element
* @param {Function} callback callback function after password validation
* @returns
*/
var _validatePassword = ($decryptor, $content, callback) => {
const password = $content.getAttribute('data-password');
const inputEl = $decryptor.querySelector('.fixit-decryptor-input');
const input = inputEl.value.trim();
const inputMd5 = CryptoJS.MD5(input).toString();
const inputSha256 = CryptoJS.SHA256(input).toString();
const saltLen = input.length % 2 ? input.length : input.length + 1;
inputEl.value = '';
inputEl.blur();
if (!input) {
alert('Please enter the correct password!');
return console.warn('Please enter the correct password!');
}
if (inputMd5 !== password) {
alert(`Password error: ${input} not the correct password!`);
return console.warn(`Password error: ${input} not the correct password!`);
}
callback(inputMd5, inputSha256.slice(saltLen));
}
/**
* initialize FixIt decryptor
*/
_proto.init = () => {
this.addEventListener('decrypted', this.options?.decrypted);
this.addEventListener('partial-decrypted', this.options?.partialDecrypted);
this.addEventListener('reset', this.options?.reset);
this.validateCache();
const _decryptor = this;
this.$el.querySelector('#fixit-decryptor-input')?.addEventListener('keydown', function (e) {
if (e.key === 'Enter') {
e.preventDefault();
const $content = document.querySelector('#content');
const password = $content.getAttribute('data-password');
const input = this.value.trim();
const saltLen = input.length % 2 ? input.length : input.length + 1;
const inputMd5 = CryptoJS.MD5(input).toString();
const inputSha256 = CryptoJS.SHA256(input).toString();
this.value = '';
this.blur();
if (!input) {
alert('Please enter the correct password!');
return console.warn('Please enter the correct password!');
}
if (inputMd5 !== password) {
alert(`Password error: ${input} not the correct password!`);
return console.warn(`Password error: ${input} not the correct password!`);
}
const decryptorHandler = () => {
const $content = document.querySelector('#content');
_validatePassword(this.$el, $content, (password, salt) => {
// cache decryption statistics
window.localStorage?.setItem(
`fixit-decryptor/#${location.pathname}`,
JSON.stringify({
expiration: Math.ceil(Date.now() / 1000) + _decryptor.options.duration,
md5: inputMd5,
sha256: inputSha256.slice(saltLen)
expiration: Math.ceil(Date.now() / 1000) + this.options.duration,
password,
salt,
})
);
_decryptContent($content.getAttribute('data-content').replace(inputSha256.slice(saltLen), ''));
_decryptContent($content, salt);
});
};
// bind decryptor input enter keydown event
this.$el.querySelector('#fixit-decryptor-input')?.addEventListener('keydown', (e) => {
if (e.key === 'Enter') {
e.preventDefault();
decryptorHandler();
}
});
this.$el.querySelector('.fixit-encryptor-btn')?.addEventListener('click', function (e) {
// bind decryptor button click event
this.$el.querySelector('.fixit-decryptor-btn')?.addEventListener('click', (e) => {
e.preventDefault();
this.classList.add('d-none')
_decryptor.$el.querySelector('#fixit-decryptor-input').classList.remove('d-none');
decryptorHandler();
});
// bind encryptor button click event
this.$el.querySelector('.fixit-encryptor-btn')?.addEventListener('click', (e) => {
e.preventDefault();
e.target.classList.add('d-none')
this.$el.querySelector('.fixit-decryptor-input').classList.remove('d-none');
this.$el.querySelector('.fixit-decryptor-btn').classList.remove('d-none');
document.querySelector('#content').innerHTML = '';
document.querySelector('#content').insertAdjacentElement(
'afterbegin',
_decryptor.$el
this.$el
);
window.localStorage?.removeItem(`fixit-decryptor/#${location.pathname}`);
// reset hook
for (const event of _decryptor.resetEventSet) {
for (const event of this.resetEventSet) {
event();
}
});
@@ -101,50 +140,31 @@ FixItDecryptor = function (options = {}) {
* initialize fixit-encryptor shortcodes
*/
_proto.initShortcodes = () => {
// TODO TODO shortcode decrypted event
// this.addEventListener('decrypted', this.options?.decrypted);
const _decryptor = this;
const $shortcodes = document.querySelectorAll('fixit-encryptor:not(.decrypted)');
customElements.get('fixit-encryptor') || customElements.define('fixit-encryptor', class extends HTMLElement {});
const $shortcodes = document.querySelectorAll('fixit-encryptor:not(:has(.decrypted))');
$shortcodes.forEach($shortcode => {
const decryptorHandler = () => {
const $decryptor = $shortcode.querySelector('.fixit-decryptor-container');
const $content = $shortcode.querySelector('[data-password][data-content]');
_validatePassword($decryptor, $content, (password, salt) => {
_decryptContent($content, salt, false);
});
};
// bind decryptor input enter keydown event
$shortcode.querySelector('.fixit-decryptor-input')?.addEventListener('keydown', function (e) {
if (e.key === 'Enter') {
e.preventDefault();
const $decryptor = this.parentElement.parentElement;
const $content = $decryptor.nextElementSibling;
const password = $content.getAttribute('data-password');
const input = this.value.trim();
const saltLen = input.length % 2 ? input.length : input.length + 1;
const inputMd5 = CryptoJS.MD5(input).toString();
const inputSha256 = CryptoJS.SHA256(input).toString();
this.value = '';
this.blur();
if (!input) {
alert('Please enter the correct password!');
return console.warn('Please enter the correct password!');
}
if (inputMd5 !== password) {
alert(`Password error: ${input} not the correct password!`);
return console.warn(`Password error: ${input} not the correct password!`);
}
try {
const base64EncodeContent = $content.getAttribute('data-content').replace(inputSha256.slice(saltLen), '');
$decryptor.querySelector('.fixit-decryptor-input').classList.add('d-none');
$content.insertAdjacentHTML(
'afterbegin',
CryptoJS.enc.Base64.parse(base64EncodeContent).toString(CryptoJS.enc.Utf8)
);
$decryptor.parentElement.classList.add('decrypted');
} catch (err) {
return console.error(err);
}
// TODO shortcode decrypted hook
// for (const event of _decryptor.decryptedEventSet) {
// event();
// }
decryptorHandler();
}
});
// bind decryptor button click event
$shortcode.querySelector('.fixit-decryptor-btn')?.addEventListener('click', function (e) {
e.preventDefault();
decryptorHandler();
});
});
};
@@ -159,17 +179,18 @@ FixItDecryptor = function (options = {}) {
if (!cachedStat) {
this.$el.querySelector('.fixit-decryptor-loading').classList.add('d-none');
this.$el.querySelector('#fixit-decryptor-input').classList.remove('d-none');
this.$el.querySelector('.fixit-decryptor-input').classList.remove('d-none');
this.$el.querySelector('.fixit-decryptor-btn').classList.remove('d-none');
return this;
}
if (cachedStat?.md5 !== password || Number(cachedStat?.expiration) < Math.ceil(Date.now() / 1000)) {
if (cachedStat?.password !== password || Number(cachedStat?.expiration) < Math.ceil(Date.now() / 1000)) {
this.$el.querySelector('.fixit-decryptor-loading').classList.add('d-none');
this.$el.querySelector('#fixit-decryptor-input').classList.remove('d-none');
this.$el.querySelector('.fixit-decryptor-input').classList.remove('d-none');
window.localStorage?.removeItem(`fixit-decryptor/#${location.pathname}`);
console.warn('The password has expired, please re-enter!');
return this;
}
_decryptContent($content.getAttribute('data-content').replace(cachedStat.sha256, ''));
_decryptContent($content, cachedStat.salt);
return this;
};
@@ -187,6 +208,9 @@ FixItDecryptor = function (options = {}) {
case 'decrypted':
this.decryptedEventSet.add(listener);
break;
case 'partial-decrypted':
this.partialDecryptedEventSet.add(listener);
break;
case 'reset':
this.resetEventSet.add(listener);
break;
@@ -211,6 +235,9 @@ FixItDecryptor = function (options = {}) {
case 'decrypted':
this.decryptedEventSet.delete(listener);
break;
case 'partial-decrypted':
this.partialDecryptedEventSet.delete(listener);
break;
case 'reset':
this.resetEventSet.delete(listener);
break;
+113 -53
View File
@@ -3,7 +3,6 @@ import Util from './util';
class FixIt {
constructor() {
this.config = window.config;
this.data = this.config.data || [];
this.isDark = document.body.dataset.theme === 'dark';
this.util = new Util();
this.newScrollTop = this.util.getScrollTop();
@@ -49,8 +48,8 @@ class FixIt {
});
}
initTwemoji() {
this.config.twemoji && twemoji.parse(document.body);
initTwemoji(target = document.body) {
this.config.twemoji && twemoji.parse(target);
}
initMenu() {
@@ -94,7 +93,7 @@ class FixIt {
this.isDark = !this.isDark;
window.localStorage?.setItem('theme', this.isDark ? 'dark' : 'light');
for (let event of this.switchThemeEventSet) {
event();
event(this.isDark);
}
}, false);
});
@@ -234,7 +233,7 @@ class FixIt {
const results = {};
window._index.search(query).forEach(({ item, refIndex, matches }) => {
let title = item.title;
let content = item.content;
let content = item.content.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
matches.forEach(({ indices, value, key }) => {
if (key === 'content') {
let offset = 0;
@@ -334,8 +333,8 @@ class FixIt {
}
}
initDetails() {
this.util.forEach(document.getElementsByClassName('details'), ($details) => {
initDetails(target = document) {
this.util.forEach(target.getElementsByClassName('details'), ($details) => {
const $summary = $details.querySelector('.details-summary');
$summary.addEventListener('click', () => {
$details.classList.toggle('open');
@@ -345,7 +344,8 @@ class FixIt {
initLightGallery() {
if (this.config.lightgallery) {
lightGallery(document.getElementById('content'), {
this.lg && this.lg.destroy(true);
this.lg = lightGallery(document.getElementById('content'), {
plugins: [lgThumbnail, lgZoom],
selector: '.lightgallery',
speed: 400,
@@ -377,7 +377,7 @@ class FixIt {
$preChroma.parentElement.replaceChild($chroma, $preChroma);
$td.appendChild($preChroma);
});
this.util.forEach(document.querySelectorAll('.highlight > .chroma'), ($chroma) => {
this.util.forEach(document.querySelectorAll('.highlight > .chroma:not(:has(.code-header))'), ($chroma) => {
const $codeElements = $chroma.querySelectorAll('pre.chroma > code');
if ($codeElements.length) {
const $code = $codeElements[$codeElements.length - 1];
@@ -386,8 +386,13 @@ class FixIt {
// code title
const $title = document.createElement('span');
$title.classList.add('code-title');
const hlAttrs = this.data[$chroma.parentNode.id];
$title.insertAdjacentHTML('afterbegin', `<i class="arrow fa-solid fa-chevron-right fa-fw" aria-hidden="true"></i><span class="title-inner">${hlAttrs?.title ?? ''}</span>`);
// insert code title inner
$title.insertAdjacentHTML(
'afterbegin',
$chroma.parentNode.title
? `<i class="arrow fa-solid fa-chevron-right fa-fw" aria-hidden="true"></i><span class="title-inner">${$chroma.parentNode.title}</span>`
: '<i class="arrow fa-solid fa-chevron-right fa-fw" aria-hidden="true"></i>'
);
$title.addEventListener('click', () => {
$chroma.classList.toggle('open');
}, false);
@@ -451,8 +456,8 @@ class FixIt {
});
}
initTable() {
this.util.forEach(document.querySelectorAll('.content table'), ($table) => {
initTable(target = document) {
this.util.forEach(target.querySelectorAll('.content table'), ($table) => {
const $wrapper = document.createElement('div');
$wrapper.className = 'table-wrapper';
$table.parentElement.replaceChild($wrapper, $table);
@@ -544,30 +549,38 @@ class FixIt {
}, false);
}
initMath() {
initMath(target = document.body) {
if (this.config.math) {
renderMathInElement(document.body, this.config.math);
renderMathInElement(target, this.config.math);
}
}
switchMermaidTheme(theme) {
const $mermaidElements = document.getElementsByClassName('mermaid');
if ($mermaidElements.length) {
// TODO perf
const themes = this.config.mermaid.themes ?? ['default', 'dark', 'neutral'];
mermaid.initialize({ startOnLoad: false, theme: theme ?? (this.isDark ? themes[1] : themes[0]), securityLevel: 'loose' });
this.util.forEach($mermaidElements, $mermaid => {
mermaid.render('svg-' + $mermaid.id, this.data[$mermaid.id], svgCode => {
$mermaid.innerHTML = svgCode;
}, $mermaid);
});
}
};
initMermaid() {
this.switchMermaidTheme();
this.switchThemeEventSet.add(() => { this.switchMermaidTheme(); });
this.beforeprintEventSet.add(() => { this.switchMermaidTheme('neutral'); });
if (!window.mermaid?.initialize) {
return;
}
const _initializeAndRun = () => {
const themes = window.mermaid.themes ?? ['default', 'dark'];
window.mermaid.initialize({
securityLevel: 'loose',
startOnLoad: false,
theme: this.isDark ? themes[1] : themes[0],
});
window.mermaid.run()
}
_initializeAndRun()
this.switchThemeEventSet.add(() => {
// Reinitialize and run mermaid when theme changes.
this.util.forEach(document.querySelectorAll('.mermaid[data-processed]'), ($mermaid) => {
$mermaid.dataset.processed = ''
$mermaid.innerHTML = ''
$mermaid.appendChild($mermaid.nextElementSibling.content.cloneNode(true))
})
_initializeAndRun()
});
this.beforeprintEventSet.add(() => {
// Set the theme to neutral when printing.
});
}
initEcharts() {
@@ -582,11 +595,16 @@ class FixIt {
this._echartsArr[i].dispose();
}
this._echartsArr = [];
const stagingDOM = this.util.getStagingDOM()
this.util.forEach(document.getElementsByClassName('echarts'), ($echarts) => {
const chart = echarts.init($echarts, this.isDark ? 'dark' : 'light', { renderer: 'svg' });
chart.setOption(JSON.parse(this.data[$echarts.id]));
this._echartsArr.push(chart);
if ($echarts.nextElementSibling.tagName === 'TEMPLATE') {
const chart = echarts.init($echarts, this.isDark ? 'dark' : 'light', { renderer: 'svg' });
stagingDOM.stage($echarts.nextElementSibling.content.cloneNode(true));
chart.setOption(stagingDOM.contentAsJson());
this._echartsArr.push(chart);
}
});
stagingDOM.destroy();
});
this.switchThemeEventSet.add(this._echartsOnSwitchTheme);
this._echartsOnSwitchTheme();
@@ -600,11 +618,13 @@ class FixIt {
initMapbox() {
if (this.config.mapbox) {
mapboxgl.accessToken = this.config.mapbox.accessToken;
mapboxgl.setRTLTextPlugin(this.config.mapbox.RTLTextPlugin);
this._mapboxArr = this._mapboxArr || [];
this.util.forEach(document.getElementsByClassName('mapbox'), ($mapbox) => {
const { lng, lat, zoom, lightStyle, darkStyle, marked, navigation, geolocate, scale, fullscreen } = this.data[$mapbox.id];
if (!mapboxgl.accessToken) {
mapboxgl.accessToken = this.config.mapbox.accessToken;
mapboxgl.setRTLTextPlugin(this.config.mapbox.RTLTextPlugin);
this._mapboxArr = this._mapboxArr || [];
}
this.util.forEach(document.querySelectorAll('.mapbox:empty'), ($mapbox) => {
const { lng, lat, zoom, lightStyle, darkStyle, marked, navigation, geolocate, scale, fullscreen } = JSON.parse($mapbox.dataset.options);
const mapbox = new mapboxgl.Map({
container: $mapbox,
center: [lng, lat],
@@ -643,7 +663,7 @@ class FixIt {
this._mapboxOnSwitchTheme = this._mapboxOnSwitchTheme || (() => {
this.util.forEach(this._mapboxArr, (mapbox) => {
const $mapbox = mapbox.getContainer();
const { lightStyle, darkStyle } = this.data[$mapbox.id];
const { lightStyle, darkStyle } = JSON.parse($mapbox.dataset.options);
mapbox.setStyle(this.isDark ? darkStyle : lightStyle);
mapbox.addControl(new MapboxLanguage());
});
@@ -652,25 +672,45 @@ class FixIt {
}
}
initTypeit() {
initTypeit(target = document) {
if (this.config.typeit) {
const typeitConfig = this.config.typeit;
const speed = typeitConfig.speed || 100;
const cursorSpeed = typeitConfig.cursorSpeed || 1000;
const cursorChar = typeitConfig.cursorChar || '|';
const loop = typeitConfig.loop ?? false;
Object.values(typeitConfig.data).forEach((group) => {
// divide them into different groups according to the data-group attribute value of the element
// results in an object like {group1: [ele1, ele2], group2: [ele3, ele4]}
const typeitElements = target.querySelectorAll('.typeit')
const groupMap = Array.from(typeitElements).reduce((acc, ele) => {
const group = ele.dataset.group || ele.id || Math.random().toString(36).substring(2);
acc[group] = acc[group] || [];
acc[group].push(ele);
return acc;
}, {});
const stagingDOM = this.util.getStagingDOM()
Object.values(groupMap).forEach((group) => {
const typeone = (i) => {
const id = group[i];
const shortcodeLoop = document.querySelector(`#${id}`).parentElement.dataset.loop;
const instance = new TypeIt(`#${id}`, {
strings: this.data[id],
const typeitElement = group[i];
const singleLoop = typeitElement.dataset.loop;
stagingDOM.stage(typeitElement.querySelector('template').content.cloneNode(true));
// for shortcodes usage
let targetEle = typeitElement.firstElementChild
// for system elements usage
if (typeitElement.firstElementChild.tagName === 'TEMPLATE') {
typeitElement.innerHTML = '';
targetEle = typeitElement
}
// create a new instance of TypeIt for each element
const instance = new TypeIt(targetEle, {
strings: stagingDOM.$el.querySelector('pre')?.innerHTML || stagingDOM.contentAsHtml(),
speed: speed,
lifeLike: true,
cursorSpeed: cursorSpeed,
cursorChar: cursorChar,
waitUntilVisible: true,
loop: shortcodeLoop ? JSON.parse(shortcodeLoop) : loop,
loop: singleLoop ? JSON.parse(singleLoop) : loop,
afterComplete: () => {
if (i === group.length - 1) {
if (typeitConfig.duration >= 0) {
@@ -687,6 +727,7 @@ class FixIt {
};
typeone(0);
});
stagingDOM.destroy();
}
}
@@ -926,12 +967,28 @@ class FixIt {
this.initEcharts();
this.initTypeit();
this.initMapbox();
this.util.forEach(document.querySelectorAll('.encrypted-hidden'), ($element) => {
$element.classList.replace('encrypted-hidden', 'decrypted-shown');
});
this.initToc();
this.initTocListener();
this.initPangu();
this.util.forEach(document.querySelectorAll('.encrypted-hidden'), ($element) => {
$element.classList.replace('encrypted-hidden', 'decrypted-shown');
});
},
partialDecrypted: ($content) => {
this.initTwemoji($content);
this.initDetails($content);
this.initLightGallery();
this.initHighlight();
this.initTable($content);
this.initMath($content);
this.initMermaid();
this.initEcharts();
this.initTypeit($content);
this.initMapbox();
this.initPangu();
this.util.forEach($content.querySelectorAll('.encrypted-hidden'), ($element) => {
$element.classList.replace('encrypted-hidden', 'decrypted-shown');
});
},
reset: () => {
this.util.forEach(document.querySelectorAll('.decrypted-shown'), ($element) => {
@@ -943,6 +1000,9 @@ class FixIt {
this.decryptor.addEventListener('decrypted', () => {
this.decryptor.initShortcodes();
})
this.decryptor.addEventListener('partial-decrypted', () => {
this.decryptor.initShortcodes();
})
this.decryptor.initShortcodes();
}
this.config.encryption?.all && this.decryptor.init();
@@ -1101,7 +1161,6 @@ class FixIt {
event();
}
this.initToc();
this.switchMermaidTheme();
this.initSearch();
const isMobile = this.util.isMobile()
@@ -1142,7 +1201,8 @@ class FixIt {
try {
if (this.config.encryption) {
this.initFixItDecryptor();
} else if (!this.config.encryption?.all) {
}
if (!this.config.encryption?.all) {
this.initTwemoji();
this.initDetails();
this.initLightGallery();
+31
View File
@@ -55,4 +55,35 @@ export default class Util {
behavior: 'smooth'
});
}
/**
* get a hidden element for temporary use
* @returns {Object} { $el: Element, destroy: Function }
*/
getStagingDOM() {
const stagingElement = document.createElement('div')
stagingElement.style.display = 'none';
stagingElement.dataset.stagingId = Math.random().toString(36).slice(2);
document.body.appendChild(stagingElement);
return {
$el: stagingElement,
stage(dom) {
stagingElement.innerHTML = '';
stagingElement.appendChild(dom);
},
contentAsHtml() {
return stagingElement.innerHTML;
},
contentAsText() {
return stagingElement.innerText;
},
contentAsJson() {
return JSON.parse(stagingElement.innerHTML);
},
destroy() {
document.body.removeChild(stagingElement);
}
}
}
}
+1 -2
View File
@@ -1,7 +1,7 @@
algoliasearch@4.20.0 https://github.com/algolia/algoliasearch-client-javascript
animate.css@4.1.1 https://github.com/daneden/animate.css
aplayer@1.10.1 https://github.com/MoePlayer/APlayer
artalk@2.6.4 https://github.com/ArtalkJS/Artalk
artalk@latest https://github.com/ArtalkJS/Artalk
autocomplete-js@0.38.1 https://github.com/algolia/autocomplete
cell-watermark@1.0.3 https://github.com/Lruihao/watermark
cookieconsent@3.1.1 https://github.com/osano/cookieconsent
@@ -17,7 +17,6 @@ instant.page@5.2.0 https://github.com/instantpage/instant.page
katex@0.16.9 https://github.com/KaTeX/KaTeX
lightgallery@2.7.2 https://github.com/sachinchoolur/lightgallery
mapbox-gl@2.10.0 https://github.com/mapbox/mapbox-gl-js
mermaid@9.4.3 https://github.com/mermaid-js/mermaid
meting@2.0.1 https://github.com/metowolf/MetingJS
normalize.css@8.0.1 https://github.com/necolas/normalize.css
object-fit-images@3.2.4 https://github.com/fregante/object-fit-images [archived]
-1
View File
File diff suppressed because one or more lines are too long
-1
View File
File diff suppressed because one or more lines are too long
-1580
View File
File diff suppressed because one or more lines are too long
+7
View File
@@ -0,0 +1,7 @@
---
title: My First Post
date: 2023-02-20T20:14:22+08:00
draft: false
---
A blog (a truncation of "weblog") is an informational website published on the World Wide Web consisting of discrete, often informal diary-style text entries (posts). Posts are typically displayed in reverse chronological order so that the most recent post appears first, at the top of the web page. Until 2009, blogs were usually the work of a single individual,[citation needed] occasionally of a small group, and often covered a single subject or topic. In the 2010s, "multi-author blogs" (MABs) emerged, featuring the writing of multiple authors and sometimes professionally edited. MABs from newspapers, other media outlets, universities, think tanks, advocacy groups, and similar institutions account for an increasing quantity of blog traffic. The rise of Twitter and other "microblogging" systems helps integrate MABs and single-author blogs into the news media. Blog can also be used as a verb, meaning to maintain or add content to a blog.
+55
View File
@@ -0,0 +1,55 @@
# -------------------------------------------------------------------------------------
# The following is a necessary configuration for the FixIt theme.
# -------------------------------------------------------------------------------------
title = "My Hugo FixIt Site"
baseURL = "http://example.org/"
# Change the default theme to be use when building the site with Hugo
# theme = "FixIt"
[markup]
# Syntax Highlighting (https://gohugo.io/content-management/syntax-highlighting)
[markup.highlight]
########## necessary configurations ##########
# https://github.com/hugo-fixit/FixIt/issues/43
codeFences = true
lineNos = true
lineNumbersInTable = true
noClasses = false
########## necessary configurations ##########
guessSyntax = true
# Goldmark is from Hugo 0.60 the default library used for Markdown
[markup.goldmark]
[markup.goldmark.extensions]
definitionList = true
footnote = true
linkify = true
strikethrough = true
table = true
taskList = true
typographer = true
[markup.goldmark.renderer]
# whether to use HTML tags directly in the document
unsafe = true
# Table Of Contents settings
[markup.tableOfContents]
ordered = false
startLevel = 2
endLevel = 6
[outputs]
home = ["HTML", "RSS", "JSON", "archives"]
page = ["HTML", "MarkDown"]
section = ["HTML", "RSS"]
taxonomy = ["HTML"]
term = ["HTML", "RSS"]
# -------------------------------------------------------------------------------------
# Theme Core Configuration
# See: https://fixit.lruihao.cn/documentation/basics/#theme-configuration
# -------------------------------------------------------------------------------------
[params]
# FixIt theme version
version = "0.3.X" # e.g. "0.2.X", "0.2.15", "v0.2.15" etc.
# ...
Submodule docs deleted from 483d685a80
+3 -3
View File
@@ -3,11 +3,11 @@
"https://fixit.lruihao.cn",
"https://pre.fixit.lruihao.cn",
"https://hugofixit.vercel.app",
"https://fixit-x-cell.vercel.app"
"https://docs-cell-x.vercel.app"
],
"originsRegex": [
"https://fixit-git-([A-z0-9]|-)*x-cell\\.vercel\\.app",
"https://fixit-[A-z0-9]{9}-x-cell\\.vercel\\.app",
"https://docs-git-([A-z0-9]|-)*cell-x\\.vercel\\.app",
"https://docs-[A-z0-9]{9}-cell-x\\.vercel\\.app",
"http://localhost:[0-9]+"
],
"defaultCommentOrder": "oldest"
+15 -6
View File
@@ -1,6 +1,8 @@
# =====================================================================================
# It's recommended to use Alternate Theme Config to configure FixIt
# Modifying this file may result in merge conflict
# There are currently some restrictions to what a theme component can configure:
# params, menu, outputformats and mediatypes
# =====================================================================================
# -------------------------------------------------------------------------------------
@@ -13,7 +15,7 @@ title = ""
# Hostname (and path) to the root
baseURL = "http://localhost:1313"
# theme list
theme = ["FixIt"]
# theme = ["FixIt"] # enable in your site config file
# determines default content language ["en", "zh-cn", "fr", "pl", ...]
defaultContentLanguage = "en"
# language code ["en", "zh-CN", "fr", "pl", ...]
@@ -40,13 +42,14 @@ enableEmoji = true
[menu]
[[menu.main]]
identifier = "posts"
identifier = "archives"
parent = ""
# you can add extra information before the name (HTML format is supported), such as icons
pre = ""
# you can add extra information after the name (HTML format is supported), such as icons
post = ""
name = "Posts"
url = "/posts/"
name = "Archives"
url = "/archives/"
# title will be shown when you hover on this menu link
title = ""
weight = 1
@@ -62,6 +65,7 @@ enableEmoji = true
type = ""
[[menu.main]]
identifier = "categories"
parent = ""
pre = ""
post = ""
name = "Categories"
@@ -72,6 +76,7 @@ enableEmoji = true
icon = "fa-solid fa-folder-tree"
[[menu.main]]
identifier = "tags"
parent = ""
pre = ""
post = ""
name = "Tags"
@@ -260,7 +265,7 @@ enableEmoji = true
# taxonomy: ["HTML", "RSS"]
# term: ["HTML", "RSS"]
[outputs]
home = ["HTML", "RSS", "JSON", "archives", "offline"]
home = ["HTML", "RSS", "JSON", "archives"]
page = ["HTML", "MarkDown"]
section = ["HTML", "RSS"]
taxonomy = ["HTML"]
@@ -283,7 +288,7 @@ enableEmoji = true
[params]
# FixIt 0.2.15 | CHANGED FixIt theme version
version = "0.2.X" # e.g. "0.2.X", "0.2.15", "v0.2.15" etc.
version = "0.3.X" # e.g. "0.2.X", "0.2.15", "v0.2.15" etc.
# site description
description = ""
# site keywords
@@ -693,6 +698,8 @@ enableEmoji = true
[params.page.heading.number]
# whether to enable auto heading numbering
enable = false
# FixIt 0.3.3 | NEW only enable in main section pages (default is posts)
onlyMainSection = true
[params.page.heading.number.format]
h1 = "{title}"
h2 = "{h2} {title}"
@@ -795,6 +802,8 @@ enableEmoji = true
enable = false
server = "https://yourdomain"
site = "默认站点"
# FixIt 0.3.3 | NEW whether use backend configuration
useBackendConf = false
placeholder = ""
noComment = ""
sendBtn = ""
+1
View File
@@ -129,6 +129,7 @@ expirationReminder = "Dieser Artikel wurde zuletzt auf {{ .Date }} aktualisiert,
encryptedAbstract = ""
encryptedMessage = ""
password = "Passwort"
enterBtn = ""
encryptyAgain = ""
relatedContent = "Ähnliche Inhalte"
+1
View File
@@ -128,6 +128,7 @@ expirationReminder = "This article was last updated on {{ .Date }}, the content
encryptedAbstract = "This article has been encrypted, so its raw content is invisible!"
encryptedMessage = "Please enter the password"
password = "Password"
enterBtn = "Enter"
encryptyAgain = "Encrypt again"
relatedContent = "Related Content"
+1
View File
@@ -129,6 +129,7 @@ expirationReminder = "Este artículo se actualizó por última vez el {{ .Date }
encryptedAbstract = ""
encryptedMessage = ""
password = "Contraseña"
enterBtn = ""
encryptyAgain = ""
relatedContent = "Contenido relacionado"
+1
View File
@@ -128,6 +128,7 @@ expirationReminder = "Cet article a été mis à jour pour la dernière fois le
encryptedAbstract = "Cet article a été chiffré, son contenu n'est donc pas lisible!"
encryptedMessage = "Entrer le mot de passe"
password = "Mot de passe"
enterBtn = "Entrer"
encryptyAgain = "Chiffrer à nouveau"
relatedContent = "Contenu lié"
+197
View File
@@ -0,0 +1,197 @@
# Translations for Hindi
# हिंदी के लिए अनुवाद
# https://gohugo.io/content-management/multilingual/#translation-of-strings
# === init ===
[init]
configurationError = "कन्फ़िग्यरेशन त्रुटि \nआपने फिक्सइट संस्करण पैरामीटर को सही ढंग से कॉन्फ़िगर नहीं किया है।. यह देखें: https://fixit.lruihao.cn/documentation/basics/#theme-configuration"
compatibilityError = "संगतता त्रुटि ({{ .From }} -> {{ .To }}):\nआपके पास एक असंगत अपडेट है. यह देखें: https://github.com/hugo-fixit/FixIt/releases"
RCVersionWarn = "आप फिक्सइट के डिवेलपर संस्करण का उपयोग कर रहे हैं। कृपया एक स्थिर संस्करण का उपयोग करने पर विचार करें।\nयह देखें: https://github.com/hugo-fixit/FixIt/releases"
devEnvWarn = "वर्तमान परिवेश \"डिवेलप्मेंट\" का है। \"टिप्पणी प्रणाली\", \"सीडीएन\" और \"फ़िंगरप्रिंट\" अक्षम कर दिए जाएंगे। "
quicklyUpgrade = "शीघ्रता से अपग्रेड यह कमांड का उपयोग करें: "
# === init ===
# === baseof ===
[baseof]
backToTop = "वापस शीर्ष पर"
viewComments = "टिप्पणियाँ देखें"
noscript = "फिक्सइट थीम जावास्क्रिप्ट सक्षम होने पर सबसे अच्छा काम करता है।"
# === baseof ===
# === Taxonomy ===
[archives]
other = "अभिलेखागार"
[allSome]
other = "सभी {{ .Some }}"
[category]
other = "श्रेणी"
[categories]
other = "श्रेणियाँ"
[collection]
other = "संग्रह"
[collections]
other = "संग्रह"
[tag]
other = "टैग"
[tags]
other = "टैग "
[posts]
other = "पदों"
# === Taxonomy ===
# === Section ===
[section]
recentlyUpdated = "हाल ही में अपडेट किया गया"
[section.totalWordCount]
one = "कुल एक शब्द"
other = "कुल {{ .Count }} शब्द"
[section.archiveCounter]
one = "केवल एक लेख"
other = "कुल {{ .Count }} लेख"
# === Section ===
# === Pagination ===
[pagination]
more = "और देखें"
# === Pagination ===
# === partials/header.html ===
[header]
selectLanguage = "भाषा चुने"
noMoretTranslations = "कोई और अनुवाद नहीं"
switchTheme = "थीम बदलें"
# === partials/header.html ===
# === partials/footer.html ===
[footer]
poweredBySome = "{{ .Hugo }} के द्वारा संचालित | थीम - {{ .Theme }}"
siteUV = "कुल विज़िटर"
sitePV = "कुल विज़िट"
siteRunning = "वेबसाइट चल रही है ..."
# === partials/footer.html ===
# === partials/comment.html ===
[comment]
valineLang = "hi"
valinePlaceholder = "आपकी टिप्पणी ..."
facebookLanguageCode = "hi"
# === partials/comment.html ===
# === partials/assets.html ===
[assets]
search = "खोज"
searchPlaceholder = "शीर्षक या सामग्री खोजें ..."
clear = "साफ़ करें"
cancel = "रद्द करें"
noResultsFound = "कोई परिणाम नहीं मिला"
copyToClipboard = "क्लिपबोर्ड पर कॉपी करें"
editLockTitle = "संपादन योग्य कोड ब्लॉक को लॉक करें"
editUnLockTitle = "संपादन योग्य कोड ब्लॉक को अनलॉक करें"
cookieconsentMessage = "यह वेबसाइट आपके अनुभव को बेहतर बनाने के लिए कुकीज़ का उपयोग करती है।"
cookieconsentDismiss = "समझ गया!"
cookieconsentLink = "और अधिक जानें"
# === partials/assets.html ===
# === partials/plugin/share.html ===
[shareOn]
other = " शेयर करें"
# === partials/plugin/share.html ===
# === posts/single.html ===
[single]
contents = "सामग्री"
pin = "शीर्ष पर पिन करें"
repost = "दोबारा पोस्ट करें"
publishedOnDate = "{{ .Date }} पर प्रकाशित"
views = "दृश्य"
comments = "टिप्पणियाँ"
author = "रचयिता"
updatedOnDate = "{{ .Date }} पर अपडेट"
readMarkdown = "मार्कडाउन पढ़ें"
viewSource = "स्रोत देखें"
editThisPage = "इस पृष्ठ को संपादित करें"
reportIssue = "समस्या की रिपोर्ट करें"
back = "पीछे"
home = "घर"
readMore = "और पढ़ें"
expirationReminder = "यह लेख अंतिम बार {{ .Date }} पर अद्यतन किया गया था, सामग्री पुरानी हो सकती है."
encryptedAbstract = "यह लेख एन्क्रिप्ट किया गया है, इसलिए इसकी मूल सामग्री अदृश्य है!"
encryptedMessage = "कृपया पासवर्ड दर्ज करें"
password = "पासवर्ड"
enterBtn = "दर्ज करें"
encryptyAgain = "फिर से एन्क्रिप्ट करें"
relatedContent = "संबंधित सामग्री"
[single.includedIn]
categories = "{{ .Categories }} में शामिल"
collections = "{{ .Collections }} में शामिल"
both = "{{ .Categories }} और {{ .Collections }} में शामिल"
[single.wordCount]
one = "एक शब्द "
other = "{{ .Count }} शब्द "
[single.fuzzyWordCount]
other = "लगभग {{ .Count }} शब्द"
[single.readingTime]
one = "एक मिनट"
other = "{{ .Count }} मिनट"
[single.reward]
donate = "दान करें"
wechatpay = "वीचैट पे"
alipay = "अली पे"
paypal = "पेपैल"
bitcoin = "बिटकॉइन"
# === posts/single.html ===
# === 404.html ===
[pageNotFound]
other = "पृष्ठ नहीं मिला"
[pageNotFoundText]
other = "आप जिस पृष्ठ को खोज रहे हैं वह मौजूद नहीं है। क्षमा मांगना।"
# === 404.html ===
# === offline ===
[offlineTitle]
other = "ऑफलाइन"
[offlineText]
other = "आप इंटरनेट से कनेक्ट नहीं हैं, केवल कैश्ड पेज ही उपलब्ध होंगे।"
# === offline ===
# === shortcodes/admonition.html ===
[admonition]
note = "ध्यान दें"
abstract = "सारांश"
info = "जानकारी"
tip = "टिप"
success = "सफलता"
question = "प्रश्न"
warning = "चेतावनी"
failure = "असफलता"
danger = "खतरा"
bug = "बग"
example = "उदाहरण"
quote = "उद्धरण"
# === shortcodes/admonition.html ===
# === shortcodes/version.html ===
[version]
new = "नया"
changed = "बदला हुआ"
deleted = "हटाए गए"
# === shortcodes/version.html ===
+1
View File
@@ -129,6 +129,7 @@ expirationReminder = "Questo articolo è stato aggiornato l'ultima volta il {{ .
encryptedAbstract = ""
encryptedMessage = ""
password = "Password"
enterBtn = ""
encryptyAgain = ""
relatedContent = "Contenuti correlati"
+1
View File
@@ -129,6 +129,7 @@ expirationReminder = "Ten artykuł był ostatnio aktualizowany {{ .Date }}, jego
encryptedAbstract = ""
encryptedMessage = ""
password = "Hasło"
enterBtn = ""
encryptyAgain = ""
relatedContent = "Powiązane treści"
+1
View File
@@ -129,6 +129,7 @@ expirationReminder = "Este artigo foi atualizado pela última vez em {{ .Date }}
encryptedAbstract = ""
encryptedMessage = ""
password = "Contrasinha"
enterBtn = ""
encryptyAgain = ""
relatedContent = "Conteúdo relacionado"
+1
View File
@@ -129,6 +129,7 @@ expirationReminder = "Acest articol a fost actualizat ultima dată pe {{ .Date }
encryptedAbstract = ""
encryptedMessage = ""
password = "Parolă"
enterBtn = ""
encryptyAgain = ""
relatedContent = "Conținut înrudit"
+1
View File
@@ -129,6 +129,7 @@ expirationReminder = "Эта статья последний раз обновл
encryptedAbstract = ""
encryptedMessage = ""
password = "арготизм"
enterBtn = ""
encryptyAgain = ""
relatedContent = "Связанный контент"
+1
View File
@@ -129,6 +129,7 @@ expirationReminder = "Овај чланак је последњи пут ажу
encryptedAbstract = ""
encryptedMessage = ""
password = "Паролица"
enterBtn = ""
encryptyAgain = ""
relatedContent = "Повезани садржај"
+1
View File
@@ -128,6 +128,7 @@ expirationReminder = "Bài viết này được cập nhật lần cuối vào {
encryptedAbstract = ""
encryptedMessage = ""
password = "Mật khẩu"
enterBtn = ""
encryptyAgain = ""
relatedContent = "Nội dung liên quan"
+1
View File
@@ -126,6 +126,7 @@ expirationReminder = "本文最后更新于 {{ .Date }},文中内容可能已
encryptedAbstract = "本文已加密,因此其原始内容不可见!"
encryptedMessage = "请输入密码"
password = "密码"
enterBtn = "进入"
encryptyAgain = "重新加密"
relatedContent = "相关内容"
+1
View File
@@ -126,6 +126,7 @@ expirationReminder = "本文最後更新於 {{ .Date }},文中內容可能已
encryptedAbstract = "本文已加密,囙此其原始內容不可見!"
encryptedMessage = "請輸入密碼"
password = "密碼"
enterBtn = "進入"
encryptyAgain = "重新加密"
relatedContent = "相關內容"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

@@ -1,3 +1,5 @@
{{- $id := dict "Content" (trim (partial "function/dos2unix.html" .Inner) "\n") "Scratch" .Page.Scratch | partial "function/id.html" -}}
<div class="mermaid" id="{{ $id }}"></div>
{{- .Page.Scratch.SetInMap "this" "mermaid" true -}}
<pre class="mermaid">
{{- .Inner | safeHTML }}
</pre>
<template>{{- .Inner | safeHTML }}</template>
{{- .Page.Store.Set "hasMermaid" true -}}
@@ -1,3 +1,2 @@
{{- $id := dict "Content" .Attributes "Scratch" .Page.Scratch | partial "function/id.html" -}}
{{- $codeBlock := transform.Highlight .Inner .Type .Options -}}
{{- replace $codeBlock "<div class=\"highlight\">" (printf "<div class=\"highlight\" id=\"%v\">" $id) 1 | safeHTML -}}
{{- $result := transform.HighlightCodeBlock . -}}
{{- $result.Wrapped -}}
+5 -2
View File
@@ -1,5 +1,5 @@
{{- /* Read the config and format */ -}}
{{- $params := .Page.Scratch.Get "params" -}}
{{- $params := partial "function/params.html" -}}
{{- $h1Format := $params.heading.number.format.h1 | default "{title}" -}}
{{- $h2Format := $params.heading.number.format.h2 | default "{h2} {title}" -}}
{{- $h3Format := $params.heading.number.format.h3 | default "{h2}.{h3} {title}" -}}
@@ -15,7 +15,10 @@
<h{{ .Level }} id="{{ .Anchor | safeURL }}" class="heading-element">
<a href="#{{ .Anchor | safeURL }}" class="heading-mark"></a>
{{- if $params.heading.number.enable -}}
{{- /* Only enable in main section pages */ -}}
{{- $onlyMainSection := cond $params.heading.number.onlyMainSection (eq .Page.Type "posts") true -}}
{{- if $params.heading.number.enable | and $onlyMainSection -}}
{{- /* Add 1 to the current level */ -}}
{{- $headingMap := .Page.Scratch.Get "heading-counter" -}}
{{- $count := (string .Level) | index $headingMap | int | add 1 -}}
+4 -2
View File
@@ -1,11 +1,13 @@
{{- $params := .Page.Params | merge site.Params.page -}}
{{- if .Title | and .Text -}}
{{- $linked := ne $params.lightgallery false -}}
<figure>
{{- dict "Src" .Destination "Alt" .Text "Caption" .Text "Title" .Title "Linked" true "Responsive" true | partial "plugin/image.html" -}}
{{- dict "Src" .Destination "Alt" .Text "Caption" .Text "Title" .Title "Linked" $linked "Responsive" true | partial "plugin/image.html" -}}
<figcaption class="image-caption">
{{- .Text | safeHTML -}}
</figcaption>
</figure>
{{- else -}}
{{- $linked := (eq (.Page.Scratch.Get "params").lightgallery "force") | or (ne .Title "") -}}
{{- $linked := (eq $params.lightgallery "force") | or ($params.lightgallery | and (ne .Title "")) -}}
{{- dict "Src" .Destination "Alt" .Text "Title" .Title "Linked" $linked "Responsive" true | partial "plugin/image.html" -}}
{{- end -}}
+2 -2
View File
@@ -21,14 +21,14 @@
<script>(window.localStorage?.getItem('theme') ? localStorage.getItem('theme') === 'dark' : ('{{ $theme }}' === 'auto' ? window.matchMedia('(prefers-color-scheme: dark)').matches : '{{ $theme }}' === 'dark')) && document.body.setAttribute('data-theme', 'dark');</script>
{{- /* Body wrapper */ -}}
<div class="wrapper" data-page-style="{{ (.Scratch.Get `params`).pageStyle | default `normal` }}">
<div class="wrapper" data-page-style="{{ (partial `function/params.html`).pageStyle | default `normal` }}">
{{- partial "header.html" . -}}
{{- partial "breadcrumb.html" . -}}
{{- $toc := .Scratch.Get "toc" -}}
<main class="container{{ if (eq $toc.enable true) | and (eq $toc.position `left`) }} container-reverse{{ end }}">
{{- block "content" . }}{{ end -}}
</main>
{{- partial "footer.html" . -}}
{{- partialCached "footer.html" . -}}
</div>
{{- /* Theme widgets */ -}}
+1 -1
View File
@@ -4,7 +4,7 @@
{{- end -}}
{{- define "content" -}}
{{- $params := .Scratch.Get "params" -}}
{{- $params := partial "function/params.html" -}}
<article class="page single special">
<div class="header">
{{- /* Title */ -}}
+2 -2
View File
@@ -1,5 +1,5 @@
{{- $params := .Scratch.Get "params" -}}
{{- $author := .Scratch.Get "author" -}}
{{- $params := partial "function/params.html" -}}
{{- $author := .Store.Get "author" -}}
# {{ .Title }}
{{ if $params.password -}}
+1 -1
View File
@@ -7,7 +7,7 @@
{{ end -}}
{{- define "content" -}}
{{- $params := .Scratch.Get "params" -}}
{{- $params := partial "function/params.html" -}}
<article class="page single special friends">
<div class="header">
{{- /* Title */ -}}
+1 -1
View File
@@ -5,7 +5,7 @@
{{- define "content" -}}
{{- /* All Posts */ -}}
{{- $pages := where .Site.RegularPages "Type" "posts" -}}
{{- $pages := .Scratch.Get "mainSectionPages" -}}
<div class="page archive">
<div class="header">
+2 -2
View File
@@ -6,7 +6,7 @@
{{- end -}}
{{- define "content" -}}
{{- $params := .Scratch.Get "params" -}}
{{- $params := partial "function/params.html" -}}
{{- $profile := .Site.Params.home.profile -}}
{{- $posts := .Site.Params.home.posts -}}
@@ -28,7 +28,7 @@
{{- /* Posts */ -}}
{{- if ne $posts.enable false | and .Site.RegularPages -}}
{{- /* Paginate */ -}}
{{- $pages := where .Site.RegularPages "Type" "posts" -}}
{{- $pages := .Scratch.Get "mainSectionPages" -}}
{{- if .Site.Params.page.hiddenFromHomePage -}}
{{- $pages = where $pages "Params.hiddenfromhomepage" false -}}
{{- else -}}
+1 -1
View File
@@ -1,4 +1,4 @@
{{- if .Site.Params.search -}}
{{- if .Site.Params.search.enable -}}
{{- $index := slice -}}
{{- $pages := where .Site.RegularPages "Params.password" "eq" nil -}}
{{- if .Site.Params.page.hiddenFromSearch -}}
+2 -2
View File
@@ -1,11 +1,11 @@
# {{ .Site.Title }}
{{ $pages := where .Site.RegularPages "Type" "posts" -}}
{{ $pages := .Scratch.Get "mainSectionPages" -}}
{{- $pages = where $pages "Draft" "eq" false -}}
{{- T "section.archiveCounter" (len $pages) }}
{{ range $pages.GroupByPublishDate "2006" }}
{{- if ne .Key "0001" -}}
{{- printf "\n## %v\n\n" .Key -}}
{{- printf "\n## %v\n\n%v\n\n" .Key (T "section.archiveCounter" .Pages.Len) -}}
{{- range .Pages -}}
{{- printf "- %v [%v](%v \"%v\")\n" (.PublishDate.Format "01-02") .Title .Permalink (.PublishDate.Format "2006-01-02 15:04:05") -}}
{{- end -}}
+2 -2
View File
@@ -36,8 +36,8 @@
{{ with .OutputFormats.Get "RSS" }}
{{ printf "<atom:link href=%q rel=\"self\" type=%q />" .Permalink .MediaType | safeHTML }}
{{ end }}
{{- range where .Site.RegularPages "Type" "posts" | first (.Site.Params.home.rss | default 10) -}}
{{- $params := .Scratch.Get "params" -}}
{{- range .Scratch.Get "mainSectionPages" | first (.Site.Params.home.rss | default 10) -}}
{{- $params := partial "function/params.html" -}}
{{- if $params.password | or $params.hiddenFromRss }}{{ continue }}{{ end -}}
{{- dict "Page" . "Site" .Site | partial "rss/item.html" -}}
{{- end -}}
+1 -1
View File
@@ -4,7 +4,7 @@
{{- end -}}
{{- define "content" -}}
{{- $params := .Scratch.Get "params" -}}
{{- $params := partial "function/params.html" -}}
<article class="page single special friends">
<div class="header">
{{- /* Title */ -}}
+15 -13
View File
@@ -1,7 +1,8 @@
{{- $params := .Scratch.Get "params" -}}
{{- $params := partial "function/params.html" -}}
{{- $cdn := .Scratch.Get "cdn" | default dict -}}
{{- $fingerprint := .Scratch.Get "fingerprint" -}}
{{- $config := (.Scratch.Get "this").config -}}
{{- $config = dict "version" (.Scratch.Get "version") | merge $config -}}
{{- /* Search */ -}}
{{- if .Site.Params.search | and .Site.Params.search.enable -}}
@@ -70,11 +71,11 @@
{{- end -}}
{{- /* TypeIt */ -}}
{{- with (.Scratch.Get "this").typeitMap -}}
{{- $typeit := $.Site.Params.typeit -}}
{{- if .Store.Get "hasTyped" -}}
{{- $typeit := .Site.Params.typeit -}}
{{- $source := $cdn.typeitJS | default "lib/typeit/index.umd.js" -}}
{{- dict "Source" $source "Fingerprint" $fingerprint "Defer" true | dict "Scratch" $.Scratch "Data" | partial "scratch/script.html" -}}
{{- $config = dict "speed" $typeit.speed "cursorSpeed" $typeit.cursorSpeed "cursorChar" $typeit.cursorChar "duration" $typeit.duration "loop" $typeit.loop "data" . | dict "typeit" | merge $config -}}
{{- $config = dict "speed" $typeit.speed "cursorSpeed" $typeit.cursorSpeed "cursorChar" $typeit.cursorChar "duration" $typeit.duration "loop" $typeit.loop | dict "typeit" | merge $config -}}
{{- end -}}
{{- /* KaTeX */ -}}
@@ -114,15 +115,16 @@
{{- end -}}
{{- /* mermaid */ -}}
{{- if (.Scratch.Get "this").mermaid -}}
{{- $source := $cdn.mermaidJS | default "lib/mermaid/mermaid.min.js" -}}
{{- dict "Source" $source "Fingerprint" $fingerprint | dict "Scratch" .Scratch "Data" | partial "scratch/script.html" -}}
{{- $mermaid := .Site.Params.mermaid -}}
{{- $config = dict "themes" $mermaid.themes | dict "mermaid" | merge $config -}}
{{- if .Store.Get "hasMermaid" -}}
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
window.mermaid = mermaid;
window.mermaid.themes = {{ .Site.Params.mermaid.themes }};
</script>
{{- end -}}
{{- /* ECharts */ -}}
{{- if (.Scratch.Get "this").echarts -}}
{{- if .HasShortcode "echarts" -}}
{{- $source := $cdn.echartsJS | default "lib/echarts/echarts.min.js" -}}
{{- dict "Source" $source "Fingerprint" $fingerprint "Defer" true | dict "Scratch" .Scratch "Data" | partial "scratch/script.html" -}}
{{- $lightTheme := resources.Get "lib/echarts/theme/light.yml" | transform.Unmarshal -}}
@@ -131,7 +133,7 @@
{{- end -}}
{{- /* Mapbox GL */ -}}
{{- if (.Scratch.Get "this").mapbox -}}
{{- if .HasShortcode "mapbox" -}}
{{- $source := $cdn.mapboxGLCSS | default "lib/mapbox-gl/mapbox-gl.css" -}}
{{- dict "Source" $source "Minify" true "Fingerprint" $fingerprint "Preload" true | dict "Scratch" .Scratch "Data" | partial "scratch/style.html" -}}
{{- $source = $cdn.mapboxGLJS | default "lib/mapbox-gl/mapbox-gl.js" -}}
@@ -141,7 +143,7 @@
{{- end -}}
{{- /* Music */ -}}
{{- if (.Scratch.Get "this").music -}}
{{- if .HasShortcode "music" -}}
{{- /* APlayer */ -}}
{{- $source := $cdn.aplayerCSS | default "lib/aplayer/APlayer.min.css" -}}
{{- dict "Source" $source "Fingerprint" $fingerprint "Preload" true | dict "Scratch" .Scratch "Data" | partial "scratch/style.html" -}}
@@ -183,7 +185,7 @@
{{- end -}}
{{- /* Content Decryption */ -}}
{{- $encryptPartial := (.Scratch.Get "this").encryptPartial -}}
{{- $encryptPartial := .HasShortcode "fixit-encryptor" -}}
{{- if $params.password | or $encryptPartial -}}
{{- $cryptoCoreJS := $cdn.cryptoCoreJS | default "lib/crypto-js/core.js" -}}
{{- $cryptoEncBase64JS := $cdn.cryptoEncBase64JS | default "lib/crypto-js/enc-base64.js" -}}
@@ -0,0 +1,12 @@
{{- /* How to use */ -}}
{{- /* partial "function/format-number" (dict "PRECISION" 2 "NUMBER" 5201314 */ -}}
{{- $number := .NUMBER -}}
{{- $precision := .PRECISION | default 1 -}}
{{- with $number -}}
{{- if ge . 1000 -}}
{{- $number = printf "%vk" (lang.FormatNumberCustom $precision (div . 1000.0) "- .") -}}
{{ printf "%v" $number }}
{{- end -}}
{{- end -}}
{{- return $number -}}
@@ -0,0 +1,12 @@
{{- $response := dict -}}
{{- with resources.GetRemote .URL .OPTIONS -}}
{{- with .Err -}}
{{- erroridf "error-get-remote-json" "%s" . -}}
{{- else -}}
{{- $response = .Content | transform.Unmarshal -}}
{{- end -}}
{{- else -}}
{{- erroridf "error-get-remote-json" "Unable to get remote resource %q" .URL -}}
{{- end -}}
{{- return $response -}}
-3
View File
@@ -8,7 +8,4 @@
{{- $id = printf "id-%d" $count -}}
{{- $count | add 1 | $.Scratch.SetInMap "this" "count" -}}
{{- end -}}
{{- with .Content -}}
{{- dict $id . | dict "data" | dict "config" | merge ($.Scratch.Get "this") | $.Scratch.Set "this" -}}
{{- end -}}
{{- return $id -}}
+2
View File
@@ -0,0 +1,2 @@
{{- $params := page.Params | merge site.Params.page -}}
{{- return $params -}}
+1 -1
View File
@@ -1,4 +1,4 @@
{{- $params := .Scratch.Get "params" -}}
{{- $params := partial "function/params.html" -}}
<meta name="author" content="{{ .Site.Params.author.name }}">
<meta name="author-link" content="{{ .Site.Params.author.link }}">
+1 -1
View File
@@ -1,4 +1,4 @@
{{- $params := .Scratch.Get "params" -}}
{{- $params := partial "function/params.html" -}}
{{- with .Site.Params.verification.google -}}
<meta name="google-site-verification" content="{{ . }}" />
+9 -13
View File
@@ -14,9 +14,8 @@
<span class="header-title-pre">{{ . | safeHTML }}</span>
{{- end -}}
{{- if .typeit -}}
{{- $id := dict "Content" .name "Scratch" $.Scratch "Id" "typeit-header-desktop" | partial "function/id.html" -}}
<span id="{{ $id }}" class="typeit"></span>
{{- dict $id (slice $id) | dict "typeitMap" | merge ($.Scratch.Get "this") | $.Scratch.Set "this" -}}
{{- $.Store.Set "hasTyped" true -}}
<span class="typeit"><template>{{ .name | default $.Site.Title }}</template></span>
{{- else -}}
<span class="header-title-text">{{ .name | default $.Site.Title }}</span>
{{- end -}}
@@ -29,9 +28,8 @@
</a>
{{- with .Site.Params.header.subtitle -}}
{{- if .typeit -}}
{{- $id := dict "Content" .name "Scratch" $.Scratch "Id" "typeit-header-subtitle-desktop" | partial "function/id.html" -}}
<span id="{{ $id }}" class="typeit header-subtitle"></span>
{{- dict $id (slice $id) | dict "typeitMap" | merge ($.Scratch.Get "this") | $.Scratch.Set "this" -}}
{{- $.Store.Set "hasTyped" true -}}
<span class="typeit header-subtitle"><template>{{ .name }}</template></span>
{{- else -}}
<span class="header-subtitle">{{ .name }}</span>
{{- end -}}
@@ -125,7 +123,7 @@
</li>
{{- end -}}
{{- end -}}
{{- else if gt (len .AllTranslations) 1 -}}
{{- else if .IsTranslated -}}
{{- range .AllTranslations -}}
{{- if ne .Lang $.Lang -}}
<li class="menu-item">
@@ -164,9 +162,8 @@
<span class="header-title-pre">{{ . | safeHTML }}</span>
{{- end -}}
{{- if .typeit -}}
{{- $id := dict "Content" .name "Scratch" $.Scratch "Id" "typeit-header-title-mobile" | partial "function/id.html" -}}
<span id="{{ $id }}" class="typeit"></span>
{{- dict $id (slice $id) | dict "typeitMap" | merge ($.Scratch.Get "this") | $.Scratch.Set "this" -}}
{{- $.Store.Set "hasTyped" true -}}
<span class="typeit"><template>{{ .name | default $.Site.Title }}</template></span>
{{- else -}}
<span class="header-title-text">{{ .name | default $.Site.Title }}</span>
{{- end -}}
@@ -179,9 +176,8 @@
</a>
{{- with .Site.Params.header.subtitle -}}
{{- if .typeit -}}
{{- $id := dict "Content" .name "Scratch" $.Scratch "Id" "typeit-header-subtitle-mobile" | partial "function/id.html" -}}
<span id="{{ $id }}" class="typeit header-subtitle"></span>
{{- dict $id (slice $id) | dict "typeitMap" | merge ($.Scratch.Get "this") | $.Scratch.Set "this" -}}
{{- $.Store.Set "hasTyped" true -}}
<span class="typeit header-subtitle"><template>{{ .name }}</template></span>
{{- else -}}
<span class="header-subtitle">{{- .name -}}</span>
{{- end -}}
+2 -3
View File
@@ -45,10 +45,9 @@
{{- with $profile.subtitle -}}
<p class="home-subtitle">
{{- if $profile.typeit -}}
{{- $id := dict "Content" . "Scratch" $.Scratch "Id" "typeit-profile-subtitle" | partial "function/id.html" -}}
<span class="d-none">{{ . }}</span>
<span id="{{ $id }}" class="typeit"></span>
{{- dict $id (slice $id) | dict "typeitMap" | merge ($.Scratch.Get "this") | $.Scratch.Set "this" -}}
{{- $.Store.Set "hasTyped" true -}}
<span class="typeit"><template>{{ . }}</template></span>
{{- else -}}
{{- . -}}
{{- end -}}
+1 -1
View File
@@ -1,6 +1,6 @@
{{- /* FixIt theme environment detection */ -}}
{{- $params := .Scratch.Get "params" -}}
{{- $params := partial "function/params.html" -}}
{{- if hugo.IsProduction -}}
{{- $cdn := .Site.Params.cdn -}}
+3 -6
View File
@@ -4,12 +4,9 @@
{{- /* Check for updates */ -}}
{{- if $devOpts.c4u -}}
{{- /* Select the scope named "public_repo" to generate personal access token */ -}}
{{- $header := dict "Authorization" "" -}}
{{- with $devOpts.githubtoken -}}
{{- $header = dict "Authorization" (printf "token %v" .) -}}
{{- end -}}
{{- $latest = (getJSON "https://api.github.com/repos/hugo-fixit/FixIt/releases/latest" $header).tag_name -}}
{{- $url := "https://api.github.com/repos/hugo-fixit/FixIt/releases/latest" -}}
{{- $options := dict "headers" (.Scratch.Get "githubTokenHeader") -}}
{{- $latest = (partial "function/get-remote-json" (dict "URL" $url "OPTIONS" $options )).tag_name -}}
{{- end -}}
{{- /* FixIt theme version detection */ -}}
+11
View File
@@ -10,3 +10,14 @@
{{- $homeRelPermalink = strings.TrimSuffix "archives/" $homeRelPermalink -}}
{{- $homeRelPermalink = strings.TrimSuffix "offline/" $homeRelPermalink -}}
{{- .Scratch.Set "homeRelPermalink" $homeRelPermalink -}}
{{- /* Set pages of main section */ -}}
{{- $pages := where .Site.RegularPages "Type" "posts" -}}
{{- .Scratch.Set "mainSectionPages" $pages -}}
{{- /* Select the scope named "public_repo" to generate personal access token */ -}}
{{- $header := dict "Authorization" "" -}}
{{- with .Site.Params.dev.githubtoken -}}
{{- $header = dict "Authorization" (printf "token %v" .) -}}
{{- end -}}
{{- .Scratch.Set "githubTokenHeader" $header -}}
+1 -2
View File
@@ -1,5 +1,4 @@
{{- .Scratch.Set "version" "v0.3.0" -}}
{{- .Scratch.Set "params" (.Params | merge .Site.Params.page) -}}
{{- .Scratch.Set "version" "v0.3.4" -}}
{{- .Scratch.Set "this" dict -}}
{{- partial "init/detection-env.html" . -}}
+1 -31
View File
@@ -1,35 +1,5 @@
{{- /* FixIt theme patches */ -}}
{{- $params := .Scratch.Get "params" -}}
{{- /* Author data patch */ -}}
{{- $authorDefault := dict "name" "Anonymous" "link" "" "email" "" "avatar" "" -}}
{{- $author := .Site.Params.author | merge $authorDefault -}}
{{- $authorPost := dict -}}
{{- $gravatar := .Site.Params.gravatar -}}
{{- if reflect.IsMap $params.author -}}
{{- $authorPost = $params.author -}}
{{- else if isset $params "author" -}}
{{- $authorPost = dict "name" $params.author -}}
{{- end -}}
{{- if isset $authorPost "name" | and (ne $authorPost.name .Site.Params.author.name) -}}
{{- $author = $authorPost | merge $authorDefault | merge $author -}}
{{- else -}}
{{- with $authorPost.link -}}{{ $author = dict "link" . | merge $author }}{{- end -}}
{{- with $authorPost.email -}}{{ $author = dict "email" . | merge $author }}{{- end -}}
{{- with $authorPost.avatar -}}{{ $author = dict "avatar" . | merge $author }}{{- end -}}
{{- end -}}
{{- if $gravatar.enable | and $author.email -}}
{{- with $gravatar -}}
{{- $author = dict "avatar" (printf "https://%v/avatar/%v?s=32&d=%v"
(path.Clean .Host | default "www.gravatar.com")
(md5 $author.email)
(.Style | default ""))
| merge $author
-}}
{{- end -}}
{{- end -}}
{{- .Scratch.Set "author" $author -}}
{{- $params := partial "function/params.html" -}}
{{- /* Toc data patch */ -}}
{{- $toc := $params.toc -}}
+2 -2
View File
@@ -1,4 +1,4 @@
{{- $params := page.Scratch.Get "params" -}}
{{- $params := partial "function/params.html" -}}
{{- $class := .Class | default "" -}}
{{- $style := "" -}}
{{- $loading := .Loading | default "lazy" -}}
@@ -88,7 +88,7 @@
<a class="lightgallery" href="{{ $srcLarge | safeURL }}" data-thumbnail="{{ $srcSmall | safeURL }}"{{ with $caption }} data-sub-html="<h2>{{ . }}</h2>{{ with $.Title }}<p>{{ . }}</p>{{ end }}"{{ end }}{{ with .Rel }} rel="{{ . }}"{{ end }}>
{{- end -}}
<img loading="{{ $loading }}" src="{{ $src | safeURL }}" alt="{{ $alt }}"
{{- if .Responsive }} srcset="{{ $srcSmall | safeURL }}, {{ $srcMedium | safeURL }} 1.5x, {{ $srcLarge | safeURL }} 2x" sizes="auto"{{- end -}}
{{- if .Responsive }} srcset="{{ $srcSmall | safeURL }}, {{ $srcMedium | safeURL }} 1.5x, {{ $srcLarge | safeURL }} 2x"{{- end -}}
{{- if eq $loading "lazy" }} data-title="{{ .Title | default $alt }}"
{{- else }} title="{{ .Title | default $alt }}"{{- end -}}
{{- with .Width }} width="{{ . }}"{{- end -}}
+6 -2
View File
@@ -1,6 +1,6 @@
{{- $reward := .Reward -}}
{{- $id := .Id -}}
{{- $author := .Author -}}
{{- $author := .Author | default "" -}}
{{- if $reward.enable -}}
<div class="post-reward">
@@ -12,7 +12,11 @@
{{- with T (printf "single.reward.%v" $way) -}}{{ $way = . }}{{- end -}}
{{- if $image -}}
<div>
{{- dict "Src" $image "Alt" (printf "%v %v" $author $way) | partial "plugin/image.html" -}}
{{-
dict "Src" $image
"Alt" (strings.TrimPrefix " " (printf "%v %v" $author $way))
| partial "plugin/image.html"
-}}
<span{{ if $reward.animation }} data-animation{{ end }}>{{ $way }}</span>
</div>
{{- end -}}
+1 -1
View File
@@ -1,4 +1,4 @@
{{- $share := (.Scratch.Get "params").share | default dict -}}
{{- $share := (partial "function/params.html").share | default dict -}}
{{- if $share.enable -}}
{{- /* 001: Twitter */ -}}
+1 -1
View File
@@ -1,5 +1,5 @@
{{- /* Collection List */ -}}
{{- $params := .Scratch.Get "params" -}}
{{- $params := partial "function/params.html" -}}
{{- if .Params.collections | and $params.collectionList | and (not $params.password) -}}
{{- $collectionTerms := .GetTerms "collections" -}}
+1 -1
View File
@@ -1,5 +1,5 @@
{{- /* Collection Navigation */ -}}
{{- $params := .Scratch.Get "params" -}}
{{- $params := partial "function/params.html" -}}
{{- if .Params.collections | and $params.collectionNavigation | and (not $params.password) -}}
{{- $collectionTerms := .GetTerms "collections" -}}
+9 -5
View File
@@ -15,18 +15,22 @@
{{- $artalk := $comment.artalk | default dict -}}
{{- if $artalk.enable -}}
<div id="artalk" class="comment"></div>
{{- $source := $cdn.artalkCSS | default "lib/artalk/Artalk.css" -}}
{{- $source := $cdn.artalkCSS | default (add $artalk.server "/dist/Artalk.css") -}}
{{- dict "Source" $source "Minify" true "Fingerprint" $fingerprint | dict "Scratch" .Scratch "Data" | partial "scratch/style.html" -}}
{{- $source := $cdn.artalkJS | default "lib/artalk/Artalk.js" -}}
{{- $source := $cdn.artalkJS | default (add $artalk.server "/dist/Artalk.js") -}}
{{- dict "Source" $source "Fingerprint" $fingerprint | dict "Scratch" .Scratch "Data" | partial "scratch/script.html" -}}
{{- $commentConfig = dict "el" "#artalk" "pageKey" .Permalink "pageTitle" .Title "pvEl" "artalk-visitor-count" "countEl" "artalk-comment-count" | dict "artalk" | merge $commentConfig -}}
{{- if (eq $artalk.locale "") | and (eq $.Site.LanguageCode "en") -}}
{{- $artalk = dict "locale" "en-US" | merge $artalk -}}
{{- end -}}
{{- $commentConfig = dict "locale" ($artalk.locale | default $.Site.LanguageCode | default "auto") | dict "artalk" | merge $commentConfig -}}
{{- if eq $artalk.usebackendconf false -}}
{{- $commentConfig = dict "useBackendConf" false | dict "artalk" | merge $commentConfig -}}
{{- end -}}
{{- with .Site.Params.gravatar -}}
{{/* See https://artalk.js.org/guide/frontend/config.html#gravatar-params */}}
{{- $commentConfig = dict "mirror" .Host "params" (printf "d=%v&s=240" .Style) | dict "gravatar" | dict "artalk" | merge $commentConfig -}}
{{- $gravatarMirror := printf "https://%v/avatar/" .Host -}}
{{- $commentConfig = dict "mirror" $gravatarMirror "params" (printf "d=%v&s=240" .Style) | dict "gravatar" | dict "artalk" | merge $commentConfig -}}
{{- end -}}
{{- with $artalk.server -}}
{{- $commentConfig = dict "server" . | dict "artalk" | merge $commentConfig -}}
@@ -297,7 +301,7 @@
{{- with $giscus -}}
{{- $commentConfig = .lightTheme | default "light" | dict "lightTheme" | dict "giscus" | merge $commentConfig -}}
{{- $commentConfig = .darkTheme | default "dark" | dict "darkTheme" | dict "giscus" | merge $commentConfig -}}
<div id="giscus">
<div id="giscus" class="comment">
<script
src="https://giscus.app/client.js"
data-repo="{{ .Repo }}"
@@ -325,7 +329,7 @@
{{- end -}}
</div>
{{- /* lightgallery for Artalk and Twikoo */ -}}
{{- $params := .Scratch.Get "params" -}}
{{- $params := partial "function/params.html" -}}
{{- if not $params.lightgallery | and (($artalk.enable | and $artalk.lightgallery) | or ($twikoo.enable | and $twikoo.lightgallery)) -}}
{{- $source := $cdn.lightgalleryCSS | default "lib/lightgallery/css/lightgallery-bundle.min.css" -}}
{{- dict "Source" $source "Fingerprint" $fingerprint | dict "Scratch" .Scratch "Data" | partial "scratch/style.html" -}}
@@ -1,4 +1,4 @@
{{- $params := .Scratch.Get "params" -}}
{{- $params := partial "function/params.html" -}}
{{- $expirationReminder := $params.expirationReminder | default dict -}}
{{- if $expirationReminder.enable -}}
+6 -3
View File
@@ -1,13 +1,16 @@
{{- $params := .Scratch.Get "params" -}}
{{- $params := partial "function/params.html" -}}
{{- if $params.password -}}
{{- $msg := (.Scratch.Get "params").message | default (T "single.encryptedMessage") -}}
{{- $msg := $params.message | default (T "single.encryptedMessage") -}}
{{- $loading := resources.Get "images/loading.svg" | minify -}}
<div class="fixit-decryptor-container">
<img class="fixit-decryptor-loading" src="{{ $loading.RelPermalink }}" alt="decryptor loading" />
<label for="fixit-decryptor-input" title='{{ T "single.password" }}'>
<input type="password" id="fixit-decryptor-input" class="d-none" placeholder="🔑 {{ $msg }}" />
<input type="password" id="fixit-decryptor-input" class="fixit-decryptor-input d-none" placeholder="🔑 {{ $msg }}" />
</label>
<button class="fixit-decryptor-btn d-none">
{{- dict "Class" "fa-solid fa-unlock" | partial "plugin/icon.html" }} {{ T "single.enterBtn" -}}
</button>
<button class="fixit-encryptor-btn d-none">
{{- dict "Class" "fa-solid fa-lock" | partial "plugin/icon.html" }} {{ T "single.encryptyAgain" -}}
</button>
+8 -3
View File
@@ -1,4 +1,4 @@
{{- $params := .Scratch.Get "params" -}}
{{- $params := partial "function/params.html" -}}
{{- /* Git info */ -}}
{{- $gitRepo := "" -}}
@@ -98,8 +98,13 @@
</div>
<div class="post-nav">
{{- $prev := cond .Site.Params.navigationReverse .Next .Prev -}}
{{- $next := cond .Site.Params.navigationReverse .Prev .Next -}}
{{- $pages := .Scratch.Get "mainSectionPages" -}}
{{- $prev := $pages.Prev . -}}
{{- $next := $pages.Next . -}}
{{- if .Site.Params.navigationReverse -}}
{{- $prev = $pages.Next . -}}
{{- $next = $pages.Prev . -}}
{{- end -}}
{{- with $prev -}}
<a href="{{ .RelPermalink }}" class="post-nav-item" rel="prev" title="{{ .LinkTitle }}">
{{- dict "Class" "fa-solid fa-angle-left fa-fw" | partial "plugin/icon.html" -}}
+34 -4
View File
@@ -1,11 +1,41 @@
{{- $params := .Scratch.Get "params" -}}
{{- $author := .Scratch.Get "author" -}}
{{- $params := .Params | merge .Site.Params.page -}}
{{- /* Author data patch */ -}}
{{- $authorDefault := dict "name" "" "link" "" "email" "" "avatar" "" -}}
{{- $author := .Site.Params.author | merge $authorDefault -}}
{{- $authorPost := dict -}}
{{- if reflect.IsMap $params.author -}}
{{- $authorPost = $params.author -}}
{{- else if isset $params "author" -}}
{{- warnf "检测到你的 author 参数格式错误,请参考主题文档设置为正常的格式。" -}}
{{- $authorPost = dict "name" $params.author -}}
{{- end -}}
{{- if isset $authorPost "name" | and (ne $authorPost.name .Site.Params.author.name) -}}
{{- $author = $authorPost | merge $authorDefault | merge $author -}}
{{- else -}}
{{- with $authorPost.link -}}{{ $author = dict "link" . | merge $author }}{{- end -}}
{{- with $authorPost.email -}}{{ $author = dict "email" . | merge $author }}{{- end -}}
{{- with $authorPost.avatar -}}{{ $author = dict "avatar" . | merge $author }}{{- end -}}
{{- end -}}
{{- $gravatar := .Site.Params.gravatar -}}
{{- if $gravatar.enable | and $author.email -}}
{{- with $gravatar -}}
{{- $author = dict "avatar" (printf "https://%v/avatar/%v?s=32&d=%v"
(path.Clean .Host | default "www.gravatar.com")
(md5 $author.email)
(.Style | default ""))
| merge $author
-}}
{{- end -}}
{{- end -}}
{{- .Store.Set "author" $author -}}
<span class="post-author">
{{- $content := $author.name -}}
{{- $content := $author.name | default "Anonymous" -}}
{{- $icon := dict "Class" "fa-solid fa-user-circle" -}}
{{- if $author.avatar | and $params.authorAvatar -}}
{{- $content = printf "%v&nbsp;%v" (dict "Src" $author.avatar "Class" "avatar" "Alt" $author.name | partial "plugin/image.html") $author.name -}}
{{- $content = printf "%v&nbsp;%v" (dict "Src" $author.avatar "Class" "avatar" "Alt" $content | partial "plugin/image.html") $content -}}
{{- $icon = "" -}}
{{- end -}}
{{- if $author.link -}}
+2 -2
View File
@@ -1,9 +1,9 @@
{{- /* Related Content */ -}}
{{- /* https://gohugo.io/content-management/related/ */ -}}
{{- $params := .Scratch.Get "params" -}}
{{- $params := partial "function/params.html" -}}
{{- if $params.related.enable | and (not $params.password) -}}
{{- $posts := where .Site.RegularPages "Type" "posts" -}}
{{- $posts := .Scratch.Get "mainSectionPages" -}}
{{- if .Site.Params.page.hiddenFromRelated -}}
{{- $posts = where $posts "Params.hiddenfromrelated" false -}}
{{- else -}}
+1 -1
View File
@@ -1,4 +1,4 @@
{{- $reward := .Scratch.Get "reward" -}}
{{- $author := .Scratch.Get "author" -}}
{{- $author := .Store.Get "author" -}}
{{- $options := dict "Reward" $reward "Id" "fi-reward" "Author" $author.name -}}
{{- partial "plugin/reward.html" $options -}}
+1 -1
View File
@@ -4,7 +4,7 @@
{{- end -}}
{{- define "content" -}}
{{- $params := .Scratch.Get "params" -}}
{{- $params := partial "function/params.html" -}}
{{- $toc := .Scratch.Get "toc" -}}
{{- $tocEmpty := eq .TableOfContents `<nav id="TableOfContents"></nav>` -}}
+4 -3
View File
@@ -1,6 +1,7 @@
{{- $content := .Inner | transform.Unmarshal | jsonify -}}
{{- $id := dict "Content" $content "Scratch" .Page.Scratch | partial "function/id.html" -}}
{{- $width := cond .IsNamedParams (.Get "width") (.Get 0) | default "100%" -}}
{{- $height := cond .IsNamedParams (.Get "height") (.Get 1) | default "30rem" -}}
<div class="echarts" id="{{ $id }}" style="width: {{ $width }}; height: {{ $height }};"></div>
{{- .Page.Scratch.SetInMap "this" "echarts" true -}}
{{- $attrs := printf `style="width: %v; height: %v;"` $width $height -}}
<div class="echarts" {{ $attrs | safeHTMLAttr }}></div>
<template>{{ $content }}</template>
{{- /* EOF */ -}}
+3
View File
@@ -25,6 +25,9 @@
<label title='{{ T "single.password" }}'>
<input type="password" class="fixit-decryptor-input" placeholder="🔑 {{ $message }}" />
</label>
<button class="fixit-decryptor-btn">
{{- dict "Class" "fa-solid fa-unlock" | partial "plugin/icon.html" }} {{ T "single.enterBtn" -}}
</button>
</div>
<div data-password="{{ md5 $password }}" data-content="{{ $content }}"></div>
</fixit-encryptor>
+5 -4
View File
@@ -1,4 +1,4 @@
{{- $mapbox := (.Page.Scratch.Get "params").mapbox | default dict -}}
{{- $mapbox := (partial "function/params.html").mapbox | default dict -}}
{{- $lng := cond .IsNamedParams (.Get "lng") (.Get 0) -}}
{{- $lat := cond .IsNamedParams (.Get "lat") (.Get 1) -}}
@@ -28,6 +28,7 @@
{{- end -}}
{{- $darkStyle = $darkStyle | default $lightStyle -}}
{{- $options := dict "lng" $lng "lat" $lat "zoom" $zoom "marked" $marked "lightStyle" $lightStyle "darkStyle" $darkStyle "geolocate" $geolocate "navigation" $navigation "scale" $scale "fullscreen" $fullscreen -}}
{{- $id := dict "Content" $options "Scratch" .Page.Scratch | partial "function/id.html" -}}
<div class="mapbox" id="{{ $id }}" style="width: {{ $width }}; height: {{ $height }};"></div>
{{- .Page.Scratch.SetInMap "this" "mapbox" true -}}
{{- $attrs := printf `style="width: %v; height: %v;"` $width $height -}}
<div class="mapbox" data-options="{{ $options | jsonify }}" {{ $attrs | safeHTMLAttr }}></div>
{{- /* EOF */ -}}
+5 -3
View File
@@ -1,3 +1,5 @@
{{- $id := dict "Content" (trim (partial "function/dos2unix.html" .Inner) "\n") "Scratch" .Page.Scratch | partial "function/id.html" -}}
<div class="mermaid" id="{{ $id }}"></div>
{{- .Page.Scratch.SetInMap "this" "mermaid" true -}}
<pre class="mermaid">
{{- .Inner | safeHTML }}
</pre>
<template>{{- .Inner | safeHTML }}</template>
{{- .Page.Store.Set "hasMermaid" true -}}
-1
View File
@@ -47,4 +47,3 @@
{{- else -}}
<meting-js server="{{ .Get 0 }}" type="{{ .Get 1 }}" id="{{ .Get 2 }}" theme="{{ $theme }}"></meting-js>
{{- end -}}
{{- .Page.Scratch.SetInMap "this" "music" true -}}
+1 -1
View File
@@ -3,7 +3,7 @@
{{- $alipay := (.Get "alipay") | default (.Get 1) -}}
{{- $paypal := (.Get "paypal") | default (.Get 2) -}}
{{- $bitcoin := (.Get "bitcoin") | default (.Get 3) -}}
{{- $author := (.Get "author") | default (.Get 4) | default (.Page.Scratch.Get "author").name -}}
{{- $author := (.Get "author") | default (.Get 4) -}}
{{- $comment := (.Get "comment") | default (.Get 5) -}}
{{- $mode := (.Get "mode") | default (.Get 6) -}}
{{- $reward := dict "enable" true "comment" $comment "mode" $mode -}}
+17 -15
View File
@@ -1,3 +1,4 @@
{{- /* trim the newline */ -}}
{{- $content := trim (partial "function/dos2unix.html" .Inner) "\n" -}}
{{- $classList := slice -}}
{{- with .Get "class" -}}
@@ -15,25 +16,26 @@
{{- /* parsing code links */ -}}
{{- $content = replaceRE `(<span[^<>]*>)([^<>]*)\[([^<>]+)\]\(([^<>]+)\)([^<>]*)(</span>)` "$1$2$6<a href=\"$4\">$3</a>$1$5$6" $content -}}
{{- end -}}
{{- /* split multiline string */ -}}
{{- $content = split $content "\n" -}}
{{- $classList = $classList | append "highlight" -}}
{{- else -}}
{{- $content = $content | .Page.RenderString -}}
{{- end -}}
{{- /* trim the newline */ -}}
{{- $id := dict "Content" $content "Scratch" .Page.Scratch | partial "function/id.html" -}}
{{- $key := .Get "group" | string | default $id -}}
{{- $typeitMap := (.Page.Scratch.Get "this").typeitMap | default dict -}}
{{- $group := index $typeitMap $key -}}
{{- $group = $group | default slice | append $id -}}
{{- dict $key $group | merge $typeitMap | .Page.Scratch.SetInMap "this" "typeitMap" -}}
{{- $attrs := printf `id="%v"` $id -}}
{{- with $classList -}}
{{- $attrs = delimit $classList " " | printf `%v class="%v"` $attrs -}}
{{- $wrapperAttrs := `class="typeit"` -}}
{{- with (.Get "group" | string) -}}
{{- $wrapperAttrs = printf `%v data-group="%v"` $wrapperAttrs . -}}
{{- end -}}
{{- with $loop -}}
{{- $wrapperAttrs = printf `%v data-loop="true"` $wrapperAttrs -}}
{{- end -}}
<div class="typeit"{{ if ne $loop "" }} data-loop="{{ $loop }}"{{ end }}>{{ printf `<%v %v></%v>` $tag $attrs $tag | safeHTML }}</div>
{{- /* EOF */ -}}
{{- $innerAttrs := "" -}}
{{- with $classList -}}
{{- $innerAttrs = printf `class="%v"` (delimit $classList " ") -}}
{{- end -}}
<div {{ $wrapperAttrs | safeHTMLAttr }}>
{{- printf `<%v %v></%v>` $tag $innerAttrs $tag | safeHTML -}}
<template><pre>{{ printf "%v" $content | safeHTML }}</pre></template>
</div>
{{- .Page.Store.Set "hasTyped" true -}}
+6 -3
View File
@@ -19,12 +19,12 @@
{{- else -}}
{{- $termTitle = printf "%v - %v" (T $taxonomy | default $taxonomy) .Title -}}
{{- end -}}
<h2 class="single-title animate__animated animate__pulse animate__faster">
<h1 class="single-title animate__animated animate__pulse animate__faster">
{{- with $termIcon -}}
{{- dict "Class" (add . " fa-fw me-1") | partial "plugin/icon.html" -}}
{{- end -}}
{{- $termTitle }} <sup>{{ $pageCount }}</sup>
</h2>
</h1>
{{- /* Paginate */ -}}
{{- if .Pages -}}
@@ -35,7 +35,10 @@
{{- $pages = .Paginate $pages -}}
{{- end -}}
{{- range $pages.PageGroups -}}
<h3 class="group-title">{{ .Key }}</h3>
<h2 class="group-title">
{{- dict "Class" "fa-regular fa-calendar fa-fw me-1" | partial "plugin/icon.html" -}}
{{- .Key -}}
</h2>
{{- range .Pages -}}
<article class="archive-item">
<a href="{{ .RelPermalink }}" class="archive-item-link">
+2 -2
View File
@@ -16,12 +16,12 @@
{{- $termsIcon = "fa-solid fa-layer-group" -}}
{{- end -}}
{{- /* Title */ -}}
<h2 class="single-title animate__animated animate__pulse animate__faster">
<h1 class="single-title animate__animated animate__pulse animate__faster">
{{- with $termsIcon -}}
{{- dict "Class" (add . " fa-fw me-1") | partial "plugin/icon.html" -}}
{{- end -}}
{{- .Params.Title | default (T $taxonomies) | default $taxonomies | dict "Some" | T "allSome" }} <sup>{{ len .Data.Terms.ByCount }}</sup>
</h2>
</h1>
{{- /* Render miscellaneous terms */ -}}
{{- .Render (add "terms/" $taxonomies) -}}
</div>

Some files were not shown because too many files have changed in this diff Show More