diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 40b878d..0000000 --- a/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -node_modules/ \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index a554032..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "extends": [ - "hexo", - "plugin:react/recommended", - "plugin:json/recommended" - ], - "settings": { - "node": { - "tryExtensions": [ - ".js", - ".jsx", - ".json" - ] - }, - "react": { - "version": "16.0" - } - }, - "parserOptions": { - "ecmaFeatures": { - "jsx": true - }, - "sourceType": "module" - }, - "plugins": [ - "react" - ], - "rules": { - "react/jsx-uses-vars": "error", - "indent": [ - "error", - 4, - { - "SwitchCase": 1 - } - ], - "react/no-unknown-property": [ - "error", - { - "ignore": [ - "class", - "onclick", - "onload", - "onsubmit" - ] - } - ], - "react/react-in-jsx-scope": [ - "off" - ], - "react/prop-types": [ - "off" - ], - "react/display-name": [ - "off" - ], - "react/jsx-key": [ - "off" - ], - "react/jsx-no-target-blank": [ - "error", - { - "allowReferrer": true - } - ] - } -} \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index ee93322..0000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,4 +0,0 @@ -Please make sure you took care of the following things before you submit this issue. Thank you! - -- [ ] I have set up and configured my blog according to the [Hexo docs](https://hexo.io/) and the [Icarus docs](https://ppoffice.github.io/hexo-theme-icarus/); -- [ ] I have looked up [Github issues](https://github.com/ppoffice/hexo-theme-icarus/issues) and found no solutions to my problems. diff --git "a/.github/ISSUE_TEMPLATE/Bug\345\217\215\351\246\210.md" "b/.github/ISSUE_TEMPLATE/Bug\345\217\215\351\246\210.md" new file mode 100644 index 0000000..77b353a --- /dev/null +++ "b/.github/ISSUE_TEMPLATE/Bug\345\217\215\351\246\210.md" @@ -0,0 +1,39 @@ +--- +name: Bug反馈 +about: 请按照模板填写Bug反馈,否则你的Issue可能会被直接关闭。 +title: [Bug] 问题概述 +labels: '' +assignees: '' + +--- + +> 确保你在提交Bug反馈之前仔细阅读了[Hexo文档](https://hexo.io/zh-cn/),[Icarus用户指南](https://ppoffice.github.io/hexo-theme-icarus/tags/Icarus%E7%94%A8%E6%88%B7%E6%8C%87%E5%8D%97/),和[GitHub issues](https://github.com/ppoffice/hexo-theme-icarus/issues)来了解你的问题是否已经被他人提出过。 + +**Bug描述** +简洁清晰地描述你遇到的Bug是什么。 + +**系统与环境** +列出你的Hexo和Icarus的版本和配置。 + +- Hexo,操作系统,和Node.js的版本(使用`hexo version`命令来查看) +- 站点配置文件`_config.yml` +- 主题配置文件`_config.icarus.yml`或`themes/icarus/_config.yml` +- 其他额外的配置文件(文章front-matter,`_config.post.yml`,或`_config.page.yml`) +- 浏览器版本(如Firefox 70.0,Chrome Android 80.0) + +**复现方式** +列出复现这个Bug的步骤,如: + +1. 访问‘...’ +2. 点击’...‘ +3. 下拉到‘...’ +4. 出现‘...’的错误 + +**期望行为** +简洁清晰地描述没有这个情况下你期望得到的结果。 + +**截图** +如果可以的话,请附上几张截图来帮助说明你遇到的问题。 + +**额外上下文** +附上与问题有关的其他上下文信息。 diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..bc54ef0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,39 @@ +--- +name: Bug Report +about: Please follow this template if you are reporting a bug, or your issue may be closed without further notice. +title: [Bug] Bug summary +labels: '' +assignees: '' + +--- + +> Make sure you go through the [Hexo docs](https://hexo.io), [Icarus user manual](https://ppoffice.github.io/hexo-theme-icarus/tags/Icarus-User-Guide/), and [GitHub issues](https://github.com/ppoffice/hexo-theme-icarus/issues) to see if the bug you are reporting has been already addressed by others. + +**Describe the bug** +A clear and concise description of what the bug is. + +**System and Environment** +The version and configuration of Hexo and Icarus. + +- Hexo, OS, and node version (use `hexo version` command to view these information) +- Site configuration file `_config.yml` +- Theme configuration file `_config.icarus.yml` or `themes/icarus/_config.yml` +- Any additional theme configuration files (post front-matter, `_config.post.yml`, or `_config.page.yml`) +- Browser and version (e.g., Firefox 70.0, Chrome Android 80.0) + +**To Reproduce** +Steps to reproduce the behavior, such as: + +1. Go to '...' +2. Click on '...' +3. Scroll down to '...' +4. '...' error appears + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..8d97ac5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,20 @@ +blank_issues_enabled: false +contact_links: + - name: Gitter + url: https://gitter.im/hexo-theme-icarus/community + about: Redirect your Icarus usage questions to Gitter. + - name: Gitter + url: https://gitter.im/hexo-theme-icarus/community + about: 与Icarus使用相关的问题请转至这里。 + - name: Bug Report + url: https://github.com/ppoffice/hexo-theme-icarus/issues/new?template=bug_report.md + about: Please follow this template if you are reporting a bug, or your issue may be closed without further notice. + - name: Bug反馈 + url: https://github.com/ppoffice/hexo-theme-icarus/issues/new?template=Bug反馈.md + about: 请按照模板填写Bug反馈,否则你的Issue可能会被直接关闭。 + - name: Feature Request + url: https://github.com/ppoffice/hexo-theme-icarus/issues/new?template=feature_request.md + about: Please follow this template if you are requesting a new feature, or your issue may be closed without further notice. + - name: 功能建议 + url: https://github.com/ppoffice/hexo-theme-icarus/issues/new?template=功能建议.md + about: 请按照模板填写功能建议,否则你的Issue可能会被直接关闭。 \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..1202613 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,26 @@ +--- +name: Feature Request +about: Please follow this template if you are requesting a new feature, or your issue may be closed without further notice. +title: [FEAT] Feature request summary +labels: '' +assignees: '' + +--- + +> Make sure you go through the [Hexo docs](https://hexo.io), [Icarus user manual](https://ppoffice.github.io/hexo-theme-icarus/tags/Icarus-User-Guide/), and [GitHub issues](https://github.com/ppoffice/hexo-theme-icarus/issues) to see if the feature you are requesting has been already addressed by others. + +**Is your feature request related to a problem? Please describe.** + +A clear and concise description of what the problem is (e.g., I'm always frustrated when [...]). + +**Describe the solution you'd like** + +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** + +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** + +Add any other context or screenshots about the feature request here. diff --git "a/.github/ISSUE_TEMPLATE/\345\212\237\350\203\275\345\273\272\350\256\256.md" "b/.github/ISSUE_TEMPLATE/\345\212\237\350\203\275\345\273\272\350\256\256.md" new file mode 100644 index 0000000..afddc5c --- /dev/null +++ "b/.github/ISSUE_TEMPLATE/\345\212\237\350\203\275\345\273\272\350\256\256.md" @@ -0,0 +1,26 @@ +--- +name: 功能建议 +about: 请按照模板填写功能建议,否则你的Issue可能会被直接关闭。 +title: [FEAT] 功能建议概述 +labels: '' +assignees: '' + +--- + +> 确保你在提交功能建议之前仔细阅读了[Hexo文档](https://hexo.io/zh-cn/),[Icarus用户指南](https://ppoffice.github.io/hexo-theme-icarus/tags/Icarus%E7%94%A8%E6%88%B7%E6%8C%87%E5%8D%97/),和[GitHub issues](https://github.com/ppoffice/hexo-theme-icarus/issues)来了解你的建议是否已经被他人提出过。 + +**你的功能建议与某个使用问题相关么?请详述。** + +简洁清晰地描述你遇到的问题是什么(如:我在使用...的时候遇到了...)。 + +**描述你想要的解决方案** + +简洁清晰地描述你想要的解决方案可以达到的效果。 + +**描述你考虑过的替代办法** + +简洁清晰地描述你考虑过的替代解决方案或是新功能。 + +**额外上下文** + +附上与功能请求有关的其他上下文信息或者截图。 diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md new file mode 100644 index 0000000..427172b --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md @@ -0,0 +1,30 @@ +--- +name: Pull Request +about: Suggest a code change to this project. +title: '' +labels: '' +assignees: '' + +--- + +**Note 0** +Please review [the contributing guide](https://github.com/ppoffice/hexo-theme-icarus/blob/master/CONTRIBUTING.md) before making this pull request. + +**Note 1** + +Please break up your pull request into multiple smaller requests if it contains multiple bug fixes +or new features. +Each pull request should have one bug fix or new feature only for better code maintainability. + +**Note 2** + +Many components of this theme, including core functions, some Hexo extensions, widgets and plugins, +have been moved to [ppoffice/hexo-component-inferno](https://github.com/ppoffice/hexo-component-inferno). +Please make a pull request to that repository instead of this one if your changes are related to +the above components. + +**Detailed description** + +> Please use the [Icarus issue template](https://github.com/ppoffice/hexo-theme-icarus/blob/master/.github/ISSUE_TEMPLATE/bug_report.md) if it is a bug fix. + +> Please use the [Icarus feature request template](https://github.com/ppoffice/hexo-theme-icarus/blob/master/.github/ISSUE_TEMPLATE/feature_request.md) if it is a bug fix. diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..122534f --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: 'npm' + directory: '/' + schedule: + interval: 'daily' diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 0000000..7926e31 --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,32 @@ +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 14 +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 7 +# Issues with these labels will never be considered stale +exemptLabels: + - bug:core + - bug:extension + - bug:general + - feature:core + - feature:extension + - feature:general + - tutorial:v1 + - tutorial:v2 + - tutorial:v3 + - tutorial:v4 + - tutorial:v5 + - tutorial:v6 + - tutorial:v7 + - tutorial:v8 + - tutorial:v9 + - Gitalk + - utterances +# Label to use when marking an issue as stale +staleLabel: wontfix +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. +# Comment to post when closing a stale issue. Set to `false` to disable +closeComment: false \ No newline at end of file diff --git a/.github/workflows/github-release.yml b/.github/workflows/github-release.yml new file mode 100644 index 0000000..54336dc --- /dev/null +++ b/.github/workflows/github-release.yml @@ -0,0 +1,20 @@ +name: GitHub Release + +on: + push: + tags: + - "*" + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.ref }} + release_name: ${{ github.ref }} + draft: true + prerelease: false diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..a84a340 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,15 @@ +name: Code Linting + +on: [push, pull_request] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v1 + - run: npm install + - run: > + npm install $(node -e "const deps=require('./package.json').peerDependencies; + console.log(Object.keys(deps).map(key=>key+'@'+deps[key]).join(' '));") + - run: npm run lint diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml new file mode 100644 index 0000000..3867f39 --- /dev/null +++ b/.github/workflows/npm-publish.yml @@ -0,0 +1,18 @@ +name: Node.js Package + +on: + release: + types: [published] + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v1 + with: + node-version: 12 + registry-url: https://registry.npmjs.org/ + - run: npm publish + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..fc974bc --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,39 @@ +name: Test + +on: [push, pull_request] + +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [10, 14] + fail-fast: false + steps: + - uses: actions/checkout@v2 + with: + repository: hexojs/hexo-starter + - uses: actions/checkout@v2 + with: + path: themes/icarus + - uses: actions/checkout@v2 + with: + repository: SukkaLab/hexo-many-posts + path: source/_posts/hexo-many-posts + - uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - uses: actions/cache@v1 + with: + path: node_modules + key: npm-cache + restore-keys: npm-cache + - run: npm install + - run: > + npm install $(node -e "const deps=require('./themes/icarus/package.json').dependencies; + console.log(Object.keys(deps).map(key=>key+'@'+deps[key]).join(' '));") + - run: > + npm install $(node -e "const deps=require('./themes/icarus/package.json').peerDependencies; + console.log(Object.keys(deps).map(key=>key+'@'+deps[key]).join(' '));") + - run: npx hexo config theme icarus + - run: time NODE_ENV=production npx hexo g -b diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..77bc0b4 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,40 @@ +# Contributing Guidelines + +## Code styles + +Please refer to the [.eslintrc.json](https://github.com/ppoffice/hexo-theme-icarus/blob/master/.eslintrc.json). +You can also use `npm run lint` or `yarn lint` to fix code style issues. + +## Project versioning + +We use [SemVer](http://semver.org/) for versioning. +Any changes to the code base should not be released using an existing version. + +## Commit message format + +The commit message should follow the [Bluejava commit message format](https://github.com/bluejava/git-commit-guide). +The supported scopes are: + +- **core** for changes related to Hexo extensions and theme-specific functions +- **comment** for comment plugin layout, schema, style, or script changes +- **share** for share plugin layout, schema, style, or script changes +- **donate** for donation plugin layout, schema, style, or script changes +- **search** for search plugin layout, schema, style, or script changes +- **widget** for widget layout, schema, style, or script changes +- **plugin** for other plugin layout, schema, style, or script changes +- **i18n** for adding or updating translations +- **test** for testing or linting-related commits +- **build** for build scripts, CI, other development or deployment related commits +- use __\*__ or leave empty to refer to commits that do not have a clear scope + +## Submit changes + +1. Fork this repository, make changes to it, and run it against some actual Hexo sites to see if +anything is broken. +You should also run `npm run lint` or `yarn lint` to find and fix any code formatting issue. +2. Submit a pull request to our repository. Please make sure you followed the instructions +above. +3. We will review the pull request regularly and inform you of our questions and any changes +that need to be made before we can merge your pull request. +4. We expect your response within two weeks, after which your pull request may be closed if +no activity is shown. diff --git a/LICENSE b/LICENSE index 98d68da..fc77245 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2015 PPOffice +Copyright (c) 2020 PPOffice Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/_config.yml b/_config.yml index e48ebaf..da6b6db 100644 --- a/_config.yml +++ b/_config.yml @@ -1,13 +1,13 @@ # Version of the configuration file -version: 3.0.0 +version: 4.0.0 +# Icarus theme variant, can be "default" or "cyberpunk" +variant: default # Path or URL to the website's logo -logo: /img/logo.png #https://cdn.jsdelivr.net/gh/removeif/blog_image/img/2019/20191121115040.png +logo: https://cdn.jsdelivr.net/gh/removeif/removeif-demo@latest/img/logo.png #/img/logo.svg # Page metadata configurations head: # URL or path to the website's icon - favicon: /img/favicon.png - # Canonical URL of the current page - canonical_url: + favicon: https://cdn.jsdelivr.net/gh/removeif/removeif-demo@latest/img/favicon.png #/img/favicon.svg # Open Graph metadata # https://hexo.io/docs/helpers.html#open-graph open_graph: @@ -20,9 +20,9 @@ head: # Page URL (og:url) (optional) # You should leave this blank for most of the time url: https://removeif.github.io/ - # Page cover (og:image) (optional) Default to the Open Graph image or thumbnail of the page + # Page cover (og:image) (optional) # You should leave this blank for most of the time - image: /img/avatar.png + image: https://cdn.jsdelivr.net/gh/removeif/removeif-demo@latest/img/avatar.png # Site name (og:site_name) (optional) # You should leave this blank for most of the time site_name: 辣椒の酱 @@ -31,63 +31,67 @@ head: author: removeif # Page description (og:description) (optional) # You should leave this blank for most of the time - description: java,技术分享,后端开发,支付框架,数据接口,算法,leetcode + description: # Twitter card type (twitter:card) - twitter_card: + twitter_card: # Twitter ID (twitter:creator) - twitter_id: - # Twitter ID (twitter:creator) - twitter_site: + twitter_id: + # Twitter Site (twitter:site) + twitter_site: # Google+ profile link (deprecated) - google_plus: + google_plus: # Facebook admin ID - fb_admins: + fb_admins: # Facebook App ID - fb_app_id: + fb_app_id: # Structured data of the page # https://developers.google.com/search/docs/guides/intro-structured-data structured_data: # Page title (optional) # You should leave this blank for most of the time - title: 辣椒の酱 + title: # Page description (optional) # You should leave this blank for most of the time - description: java,技术分享,后端开发,支付框架,数据接口,算法,leetcode + description: # Page URL (optional) # You should leave this blank for most of the time - url: https://removeif.github.io/ + url: # Page author (article:author) (optional) # You should leave this blank for most of the time - author: removeif - # Page images (optional) Default to the Open Graph image or thumbnail of the page + author: + # Page images (optional) # You should leave this blank for most of the time - image: /img/avatar.png + image: # Additional HTML meta tags in an array meta: # Meta tag specified in = style # E.g., name=theme-color;content=#123456 => - '' # URL or path to the website's RSS atom.xml - rss: /atom.xml + rss: # Page top navigation bar configurations navbar: # Naviagtion menu items menu: - 首页: / - 归档: /archives - 分类: /categories - 标签: /tags - 影音: /media - 相册: /album - 友链: /friend - 碎碎念: /self-talking - 留言: /message - 关于: /about + Home: / + Archives: /archives + Categories: /categories + Tags: /tags + About: /about + Album: /album + Friend: /friend + Message: /message + Self-talking: /self-talking + Music: /music + Media: /media # Links to be shown on the right of the navigation bar links: + Join Gitter: + icon: fab fa-gitter + url: 'https://gitter.im/hexo-theme-amazing/community' Download on GitHub: icon: fab fa-github - url: 'https://github.com/removeif' + url: 'https://github.com/removeif/hexo-theme-amazing' # Page footer configurations footer: # Links to be shown on the right of the footer section @@ -100,30 +104,59 @@ footer: url: 'https://creativecommons.org/licenses/by/4.0/' Download on GitHub: icon: fab fa-github - url: 'https://github.com/removeif' + url: 'https://github.com/removeif/hexo-theme-amazing' # Article related configurations article: # Code highlight settings highlight: # Code highlight themes # https://github.com/highlightjs/highlight.js/tree/master/src/styles - theme: atom-one-dark + theme: atom-one-light # Show copy code button clipboard: true # Default folding status of the code blocks. Can be "", "folded", "unfolded" fold: unfolded - # Whether to show thumbnail image for every article - thumbnail: true # Whether to show estimated article reading time readtime: true + # Article licensing block + licenses: + Creative Commons: + icon: fab fa-creative-commons + url: 'https://creativecommons.org/' + Attribution: + icon: fab fa-creative-commons-by + url: 'https://creativecommons.org/licenses/by/4.0/' + Noncommercial: + icon: fab fa-creative-commons-nc + url: 'https://creativecommons.org/licenses/by-nc/4.0/' # Search plugin configurations # https://ppoffice.github.io/hexo-theme-icarus/categories/Plugins/Search/ search: type: insight - +# Comment plugin configurations +# https://ppoffice.github.io/hexo-theme-icarus/categories/Plugins/Comment/ +#comment: +# type: disqus +# # Disqus shortname +# shortname: '' +# Comment plugin configurations +# https://ppoffice.github.io/hexo-theme-icarus/categories/Plugins/Comment/ +comment: + type: gitalk + language: zh-CN #zh-CN #Localization language key, en, zh-CN and zh-TW are currently available. + owner: removeif # (required) GitHub user name + repo: blog_comment # (required) GitHub repository name + client_id: 46a9f3481b46ea0129d8 # (required) OAuth application client id + client_secret: 79c7c9cb847e141757d7864453bcbf89f0655b24 # (required) OAuth application client secret + admin: ['removeif'] + create_issue_manually: true + distraction_free_mode: false + has_hot_recommend: true # 是否有热门推荐 + has_latest_comment: true #是否有最新评论 # Donate plugin configurations -donate: - # Alipay donate button configurations +# https://ppoffice.github.io/hexo-theme-icarus/categories/Plugins/Donation/ +donates: + # Alipay donate button configurations - # Donation entry name type: alipay @@ -134,7 +167,12 @@ donate: type: wechat # Qrcode image URL qrcode: 'https://raw.githubusercontent.com/removeif/blog_image/master/img/2019/20190802135550.png' + # "Buy me a coffee" donate button configurations # - +# type: buymeacoffee +# # URL to the "Buy me a coffee" page +# url: '' +# # Patreon donate button configurations # - # type: patreon # # URL to the Patreon page @@ -170,12 +208,14 @@ sidebar: sticky: false # Sidebar widget configurations # http://ppoffice.github.io/hexo-theme-icarus/categories/Widgets/ -# 注释对应的节点,包括”-“一起注释掉,相应的widget不显示 widgets: + # Table of contents widget configurations - # Where should the widget be placed, left sidebar or right sidebar position: left type: toc + # Select show index + index: false # Profile widget configurations - # Where should the widget be placed, left sidebar or right sidebar @@ -183,18 +223,18 @@ widgets: type: profile # Author name author: 辣椒の酱 - # Title of the author to be shown in the profile widget + # Author title author_title: 尚未执佩剑,转眼即江湖 - # Author's current location to be shown in the profile widget + # Author's current location location: 阿尔及利亚 - # Path or URL to the avatar to be shown in the profile widget - avatar: /img/avatar.png + # URL or path to the avatar image + avatar: https://cdn.jsdelivr.net/gh/removeif/removeif-demo@latest/img/avatar.png # Whether show the rounded avatar image avatar_rounded: true # Email address for the Gravatar - gravatar: + gravatar: # URL or path for the follow button - follow_link: 'https://weibo.com/u/3050419984' + follow_link: 'https://github.com/ppoffice' # Links to be shown on the bottom of the profile widget social_links: Github: @@ -202,7 +242,7 @@ widgets: url: 'https://github.com/removeif' Weibo: icon: fab fa-weibo - url: 'https://weibo.com/u/3050419984' + url: 'https://weibo.com/removeif' Email: icon: fa fa-envelope url: 'mailto:removeif@163.com' @@ -212,21 +252,21 @@ widgets: RSS: icon: fas fa-rss url: /atom.xml - has_hitokoto: true #左边一言开关,true-开,false-关 - + has_hitokoto: true # Recommendation links widget configurations - # Table of contents widget configurations - + # Where should the widget be placed, left sidebar or right sidebar + position: left + type: links + # Names and URLs of the sites + links: + Hexo: 'https://hexo.io' + Bulma: 'https://bulma.io' + # Latest comment widget configurations + - + # Where should the widget be placed, left sidebar or right sidebar position: right type: latest_comment -# - -# # Where should the widget be placed, left sidebar or right sidebar -# position: left -# type: links -# # Names and URLs of the sites -# links: -# Hexo: 'https://hexo.io' -# Bulma: 'https://bulma.io' # Recent posts widget configurations - # Where should the widget be placed, left sidebar or right sidebar @@ -253,26 +293,28 @@ widgets: position: right type: subscribe_email # Hint text under the email input - description: 输入邮箱开始订阅,更博后邮件通知! + description: # Feedburner ID - feedburner_id: removeifFeedsId + feedburner_id: '' # Google AdSense unit configurations -# - -# # Where should the widget be placed, left sidebar or right sidebar -# position: left -# type: adsense -# # AdSense client ID -# client_id: '' -# # AdSense AD unit ID -# slot_id: '' -# - - # position: right - # type: notice - # contents: - # 1: 2019.8.15 主题开源 - # 2: 2020.5.20 添加公告widget - # 3: 2020.5.21 公告测试 + - + # Where should the widget be placed, left sidebar or right sidebar + position: right + type: adsense + +# AdSense client ID +adsense_client_id: #'ca-pub-6343805421927634' +# AdSense AD unit ID +adsense_slot_id: '5134765588' +# article head ad +article_head_has_ad: true +# comment head ad +comment_head_has_ad: true +# other ad +index_zero_position_ad: true +index_ad_positions: 2,5,9 #首页adsense放置广告的位置,尽量少配置些,多了有可能不显示。一位的时候,加个逗号,如1,或者1,5,9 # Plugin configurations +# https://ppoffice.github.io/hexo-theme-icarus/categories/Plugins/ plugins: # Enable page startup animations animejs: true @@ -282,23 +324,29 @@ plugins: # https://tongji.baidu.com baidu_analytics: # Baidu Analytics tracking ID - tracking_id: + tracking_id: # BuSuanZi site/page view counter # https://busuanzi.ibruce.info busuanzi: true + # CNZZ statistics + # https://www.umeng.com/web + cnzz: + # CNZZ tracker id + id: + # CNZZ website id + web_id: # Enable the lightGallery and Justified Gallery plugins - # https://ppoffice.github.io/hexo-theme-icarus/Plugins/General/gallery-plugin/ gallery: true # Google Analytics plugin settings # https://analytics.google.com google_analytics: # Google Analytics tracking ID - tracking_id: + tracking_id: # Hotjar user feedback plugin # https://www.hotjar.com/ hotjar: # Hotjar site id - site_id: + site_id: # Enable the KaTeX math typesetting supprot # https://katex.org/ katex: false @@ -320,69 +368,12 @@ providers: # Name or URL of the fontawesome icon font CDN provider iconcdn: loli # https://cdn.jsdelivr.net/gh/removeif/removeif.github.io@v1.0.6/json_data/record.json, cdn前缀,对于hexo new page 页面中引用的资源文件不生效,需要手动改,如friend友链页中引用的资源 - my_cdn_pre: #https://cdn.jsdelivr.net/gh/removeif/removeif.github.io@v2.2.1 - -# Comment plugin configurations -# https://ppoffice.github.io/hexo-theme-icarus/categories/Plugins/Comment/ -comment: - type: gitalk - language: zh-CN #zh-CN #Localization language key, en, zh-CN and zh-TW are currently available. - owner: removeif # (required) GitHub user name - repo: blog_comment # (required) GitHub repository name - client_id: 46a9f3481b46ea0129d8 # (required) OAuth application client id - client_secret: 79c7c9cb847e141757d7864453bcbf89f0655b24 # (required) OAuth application client secret - admin: ['removeif'] - create_issue_manually: true - distraction_free_mode: false - has_hot_recommend: true # 是否有热门推荐 - has_latest_comment: true #是否有最新评论 - -# comment: -# type: valine -# app_id: rOtVIhvG3kd7QkMKe3naSU9R-gzGzoHsz -# app_key: F2sNV0CkqvbPat45di3DEn3z -# notify: false -# verify: false -# avatar: 'mp' -# placeholder: '留下您的高见!' -# has_latest_comment: true #是否有最新评论 true-有,false-无 -# owner: 辣椒の酱 #博主名 最新评论标注[博主] -# required_fields: ['nick', 'mail', 'link'] -# lang: en #zh-CN zh-TW en ja - - -# utteranc site: https://utteranc.es/ -# comment: -# type: utteranc -# repo: removeif/utteranc_comment # (required) GitHub userName & repository name -# issue_term: pathname -# issue_number: -# label: -# theme: github-light - -global_gray: false #true 全局灰色,特定时期可以开启,false-不开启 - -has_banner: false #首页是否有banner,true-是,false-否,如果配置了热门推荐显示热门推荐,banner配置数据在json_data/banner.json里按照配置格式配置好,至少三条 - -has_latest_modify_time: true #是否显示最后修改时间 true开启,false-关闭 - -busuanzi_only_count: false #当上面plugins中busuanzi: true时,此配置busuanzi_only_count为true时,网站不显示不蒜子统计数据,但是会每次统计。false时显示统计数据。 - -has_copyright: true # 文中是否显示copyright true开启,false-关闭 + # my_cdn_pre: https://cdn.jsdelivr.net/gh/removeif/removeif-demo@v1.0.8/ #https://cdn.jsdelivr.net/gh/removeif/removeif.github.io@v2.2.1 -# http://sachinchoolur.github.io/lightGallery/docs/api.html -lightgallery_is_full: true #图片灯箱是否显示完整的插件(包括放大,分享等),true-显示,false-显示简洁版 website_start_time: 2018/11/11 00:00:00 #网站运行开始时间,不填不显示 - -footer_registered_no: #川ICP备88888888号-8 #备案号 - -footer_copyright_dsec: © 版权说明:[本网站所有内容均收集于互联网或自己创作,
    方便于网友与自己学习交流,如有侵权,请留言,立即处理]
#footer 版权说明 可自由配置 - -has_live_2D_switch: true #live2D开关 true-开 false-关 - +footer_registered_no: 川ICP备88888888号-8(测试) #备案号 side_music_netease_id: 2364053447 #侧边栏网易云歌单id - -use_pjax: false #是否开启pjax,false-不开启,true-开启,开启后局部更新网页信息,切换页面背景音乐不间断等特性 - -index_show_tags_cateories: true #首页文章item面板是否显示tag和categories +busuanzi_only_count: false #当上面plugins中busuanzi: true时,此配置busuanzi_only_count为true时,网站不显示不蒜子统计数据,但是会每次统计。false时显示统计数据。 +has_live_2D_switch: true #live2D开关 true-开 false-关 +use_pjax: true #是否pjax \ No newline at end of file diff --git a/ex_pages/scaffolds/post.md b/ex_pages/scaffolds/post.md index 692de3b..02d38f3 100644 --- a/ex_pages/scaffolds/post.md +++ b/ex_pages/scaffolds/post.md @@ -3,7 +3,11 @@ thumbnail: title: {{ title }} date: {{ date }} tags: +-test1 +-test2 categories: +-test3 +-test4 toc: true recommend: 1 keywords: categories-java diff --git a/ex_pages/source/about/index.md b/ex_pages/source/about/index.md index 96a413a..6271fdd 100644 --- a/ex_pages/source/about/index.md +++ b/ex_pages/source/about/index.md @@ -7,7 +7,7 @@ comments: false #### 个人简介 --- -分享很喜欢的**[老罗](https://baike.baidu.com/item/%E7%BD%97%E6%B0%B8%E6%B5%A9/26814?fr=aladdin)**的一段话: +分享很喜欢的[老罗](https://baike.baidu.com/item/%E7%BD%97%E6%B0%B8%E6%B5%A9/26814?fr=aladdin)的一段话: >"***每一个生命来到世间都注定改变世界,别无选择。要么变得好一点,要么变得坏一点。你如果走进社会为了生存为了什么不要脸的理由,变成了一个恶心的成年人社会中的一员,那你就把这个世界变得恶心了一点点。如果你一生刚正不阿,如果你一生耿直,没有做任何恶心的事情,没做对别人有害的事情,一辈子拼了老命勉强把自己身边的几个人照顾好了,没有成名没有发财,没有成就伟大的事业,然后耿着脖子一生正直,到了七八十岁耿着脖子去世了。你这一生是不是没有改变世界?你还是改变世界了,你把这个世界变得美好了一点点。因为世界上又多了一个好人。***" @@ -33,6 +33,7 @@ comments: false + 在Icarus主题之上进行了部分修改。 ***更新日志:*** +--*2020.09.20:icarus4.0适配* --*2020.01.18:icarus3.0适配* --*2019.11.17:增加深色主题开关* --*2019.10.30:去图,精简卡片* diff --git a/ex_pages/source/music/index.md b/ex_pages/source/music/index.md index 1ca0ff2..868ff92 100644 --- a/ex_pages/source/music/index.md +++ b/ex_pages/source/music/index.md @@ -20,5 +20,5 @@ date: 2019-07-30 10:43:45 list-max-height="800px" > ---- +

温馨提示:选择喜欢的音乐双击播放,由于版权原因部分不能播放。如果喜欢歌单收藏一下,去网易云都能播放哟!

\ No newline at end of file diff --git a/include/config.js b/include/config.js index e5c7092..6b77147 100644 --- a/include/config.js +++ b/include/config.js @@ -4,69 +4,104 @@ const path = require('path'); const util = require('util'); const crypto = require('crypto'); const logger = require('hexo-log')(); +const yaml = require('hexo-component-inferno/lib/util/yaml'); +const { Migrator } = require('hexo-component-inferno/lib/core/migrate'); +const { SchemaLoader } = require('hexo-component-inferno/lib/core/schema'); +const { yellow } = require('./util/console'); -module.exports = hexo => { +function loadThemeConfig(hexo, cfgPaths) { + const configs = cfgPaths.map(cfgPath => fs.readFileSync(cfgPath)) + .map(cfgPath => yaml.parse(cfgPath)); + return Object.assign({}, ...configs, hexo.config.theme_config); +} + +function generateThemeConfigFile(schema, cfgPath) { + const defaultValue = schema.getDefaultValue(); + fs.writeFileSync(cfgPath, defaultValue.toYaml()); +} + +function hashConfigFile(cfgPath) { + const content = fs.readFileSync(cfgPath); + return crypto.createHash('md5').update(content).digest('hex'); +} + +function checkConfig(hexo) { if (!process.argv.includes('--icarus-dont-check-config')) { - const SCHEMA_ROOT = path.join(hexo.theme_dir, 'include/schema/'); - const CONFIG_PATH = path.join(hexo.theme_dir, '_config.yml'); + logger.info('=== Checking theme configurations ==='); - const yaml = require('../include/util/yaml'); - const { SchemaLoader } = require('../include/util/schema'); - const loader = SchemaLoader.load(require(path.join(SCHEMA_ROOT, 'config.json')), SCHEMA_ROOT); + const siteCfgFile = path.join(hexo.base_dir, '_config.yml'); + const themeSiteCfg = path.join(hexo.base_dir, '_config.amazing.yml'); + const themeDirCfg = path.join(hexo.theme_dir, '_config.yml'); + const themeCfgPaths = [themeDirCfg, themeSiteCfg].filter(cfgPath => fs.existsSync(cfgPath)); + const themeSiteCfgExample = themeSiteCfg + '.example'; + + const schemaDir = path.join(hexo.theme_dir, 'include/schema/'); + const loader = SchemaLoader.load(require(path.join(schemaDir, 'config.json')), schemaDir); const schema = loader.getSchema('/config.json'); - logger.info('=== Checking the configuration file ==='); - // Generate config file if not exist if (!process.argv.includes('--icarus-dont-generate-config')) { - if (!fs.existsSync(CONFIG_PATH)) { - logger.warn(`${CONFIG_PATH} is not found. We are creating one for you...`); - logger.info('You may add \'--icarus-dont-generate-config\' to prevent creating the configuration file.'); - const defaultValue = schema.getDefaultValue(); - fs.writeFileSync(CONFIG_PATH, defaultValue.toYaml()); - logger.info(`${CONFIG_PATH} created successfully.`); + if (!themeCfgPaths.length) { + logger.warn('None of the following configuration files is found:'); + logger.warn(`- ${yellow(themeSiteCfg)}`); + logger.warn(`- ${yellow(themeDirCfg)}`); + logger.info('Generating theme configuration file...'); + generateThemeConfigFile(schema, themeSiteCfg); + themeCfgPaths.push(themeSiteCfg); + logger.info(`${yellow(themeSiteCfg)} created successfully.`); + logger.info('To skip configuration generation, use "--icarus-dont-generate-config".'); } } - try { - const cfgStr = fs.readFileSync(CONFIG_PATH); - let cfg = yaml.parse(cfgStr); - // Check config version - if (!process.argv.includes('--icarus-dont-upgrade-config')) { - const migrator = new(require('../include/util/migrate'))(path.join(hexo.theme_dir, 'include/migration')); - // Upgrade config - if (migrator.isOudated(cfg.version)) { - logger.info(`Your configuration file is outdated (${cfg.version} < ${migrator.getLatestVersion()}). ` - + 'Trying to upgrade it...'); - // Backup old config - const hash = crypto.createHash('sha256').update(cfgStr).digest('hex'); - const backupPath = CONFIG_PATH + '.' + hash.substring(0, 16); - fs.writeFileSync(backupPath, cfgStr); - logger.info(`Current configurations are written up to ${backupPath}`); - // Migrate config - cfg = migrator.migrate(cfg); - // Save config - fs.writeFileSync(CONFIG_PATH, yaml.stringify(cfg)); - logger.info(`${CONFIG_PATH} upgraded successfully.`); - const defaultValue = schema.getDefaultValue(); - fs.writeFileSync(CONFIG_PATH + '.example', defaultValue.toYaml()); - logger.info(`We also created an example at ${CONFIG_PATH + '.example'} for your reference.`); + let cfg = loadThemeConfig(hexo, themeCfgPaths); + + if (!process.argv.includes('--icarus-dont-upgrade-config')) { + const migrator = new Migrator(require(path.join(hexo.theme_dir, 'include/migration/head'))); + if (cfg.version && migrator.isOudated(cfg.version)) { + logger.warn(`Your theme configuration is outdated (${cfg.version} < ${migrator.getLatestVersion()}).`); + logger.info('To skip the configuration upgrade, use "--icarus-dont-upgrade-config".'); + + logger.info('Backing up theme configuration files...'); + for (const cfgPath of themeCfgPaths) { + const backupPath = cfgPath + '.' + hashConfigFile(cfgPath); + const relCfgPath = path.relative(hexo.base_dir, cfgPath); + const relBackupPath = path.relative(hexo.base_dir, backupPath); + fs.renameSync(cfgPath, backupPath); + logger.info(`${yellow(relCfgPath)} => ${yellow(relBackupPath)}`); } - } - // Check config file against schemas - const result = schema.validate(cfg); - if (result !== true) { - logger.warn('Configuration file failed one or more checks.'); - logger.warn('Icarus may still run, but you will encounter excepted results.'); - logger.warn('Here is some information for you to correct the configuration file.'); - logger.warn(util.inspect(result)); + logger.info('Upgrading theme configurations...'); + cfg = migrator.migrate(cfg); + fs.writeFileSync(themeSiteCfg, yaml.stringify(cfg)); + logger.info(`Theme configurations are written to ${yellow(themeSiteCfg)}.`); + + generateThemeConfigFile(schema, themeSiteCfgExample); + logger.info(`Example configurations is at ${yellow(themeSiteCfgExample)}.`); } - } catch (e) { - logger.error(e); - logger.error(`Failed to load the configuration file ${CONFIG_PATH}.`); - logger.error('Please add \'--icarus-dont-check-config\' to your Hexo command if you'); - logger.error('wish to skip the config file checking.'); - process.exit(-1); } + + const validation = schema.validate(cfg); + if (validation !== true) { + logger.warn('Theme configurations failed one or more checks.'); + logger.warn('Icarus may still run, but you will encounter unexcepted results.'); + logger.warn('Here is some information for you to correct the configuration file.'); + logger.warn(util.inspect(validation)); + } + + const rootCfg = yaml.parse(fs.readFileSync(siteCfgFile)); + if (rootCfg.theme_config) { + logger.warn(`"theme_config" found in ${yellow(siteCfgFile)}.`); + logger.warn(`Please remove theme configurations from ${yellow(siteCfgFile)}.`); + } + } +} + +module.exports = hexo => { + try { + checkConfig(hexo); + } catch (e) { + logger.error(e); + logger.error('Theme configuration checking failed.'); + logger.info('You may use \'--icarus-dont-check-config\' to skip configuration checking.'); + process.exit(-1); } }; diff --git a/include/dependency.js b/include/dependency.js index 4e77910..1a797f8 100644 --- a/include/dependency.js +++ b/include/dependency.js @@ -21,11 +21,14 @@ module.exports = hexo => { } logger.info('=== Checking package dependencies ==='); - const missingDeps = Object.keys(packageInfo.peerDependencies) - .filter(name => !checkDependency(name, packageInfo.peerDependencies[name])); + const dependencies = Object.assign({}, packageInfo.peerDependencies, packageInfo.dependencies); + const missingDeps = Object.keys(dependencies) + .filter(name => !checkDependency(name, dependencies[name])); if (missingDeps && missingDeps.length) { logger.error('Please install the missing dependencies your Hexo site root directory:'); - logger.error(green('npm install --save ' + missingDeps.map(name => `${name}@${packageInfo.peerDependencies[name]}`).join(' '))); + logger.error(green('npm install --save ' + missingDeps.map(name => `${name}@${dependencies[name]}`).join(' '))); + logger.error('or:'); + logger.error(green('yarn add ' + missingDeps.map(name => `${name}@${dependencies[name]}`).join(' '))); process.exit(-1); } }; diff --git a/include/filter/locals.js b/include/filter/locals.js deleted file mode 100644 index b2413e5..0000000 --- a/include/filter/locals.js +++ /dev/null @@ -1,66 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const yaml = require('js-yaml'); - -module.exports = hexo => { - const RESERVED_KEYS = { - post: Object.keys(require('hexo/lib/models/post')(hexo).paths), - page: Object.keys(require('hexo/lib/models/page')(hexo).paths) - }; - - function getThemeConfig(extension) { - if (fs.existsSync(path.join(hexo.theme_dir, '_config' + extension + '.yml'))) { - return yaml.safeLoad(fs.readFileSync(path.join(hexo.theme_dir, '_config' + extension + '.yml'))); - } - return null; - } - - const ALTERNATIVE_CONFIG = { - post: getThemeConfig('.post'), - page: getThemeConfig('.page') - }; - - function getExtraConfig(source, reservedKeys) { - const result = {}; - for (const key in source) { - if (!key.startsWith('_') && !reservedKeys.includes(key) && typeof source[key] !== 'function') { - result[key] = source[key]; - } - } - return result; - } - - hexo.extend.filter.register('template_locals', locals => { - // inject helper functions - locals.helper = {}; - const helpers = hexo.extend.helper.list(); - for (const name in helpers) { - locals.helper[name] = helpers[name].bind(locals); - } - if (typeof locals.__ === 'function') { - locals.helper.__ = locals.__; - } - if (typeof locals._p === 'function') { - locals.helper._p = locals._p; - } - - const page = locals.page; - if (page) { - if ((page.layout !== 'page' || page.layout !== 'post') && ALTERNATIVE_CONFIG[page.layout]) { - // load alternative config if exists - locals.config = Object.assign({}, Object.getPrototypeOf(locals).theme || locals.theme, ALTERNATIVE_CONFIG[page.layout]); - } else { - // site config already merged into theme config in hexo/lib/hexo/index.js#Hexo.prototype._generateLocals() - locals.config = Object.assign({}, Object.getPrototypeOf(locals).theme || locals.theme); - } - // merge page configs - if (page.__post === true) { - Object.assign(locals.config, getExtraConfig(page, RESERVED_KEYS.page)); - } else if (page.__page === true) { - Object.assign(locals.config, getExtraConfig(page, RESERVED_KEYS.page)); - } - } - - return locals; - }); -}; diff --git a/include/generator/categories.js b/include/generator/categories.js deleted file mode 100644 index e208ad4..0000000 --- a/include/generator/categories.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Category list page generator - */ -module.exports = function(hexo) { - hexo.extend.generator.register('categories', locals => { - return { - path: 'categories/', - layout: ['categories'], - data: Object.assign({}, locals, { - __categories: true - }) - }; - }); -}; diff --git a/include/generator/category.js b/include/generator/category.js deleted file mode 100644 index d047cdd..0000000 --- a/include/generator/category.js +++ /dev/null @@ -1,34 +0,0 @@ -const pagination = require('hexo-pagination'); - -module.exports = function(hexo) { - // ATTENTION: This will override the default category generator! - hexo.extend.generator.register('category', function(locals) { - const config = this.config; - const perPage = config.category_generator.per_page; - const paginationDir = config.pagination_dir || 'page'; - - function findParent(category) { - let parents = []; - if (typeof category === 'object' && 'parent' in category) { - const parent = locals.categories.filter(cat => cat._id === category.parent).first(); - parents = [parent].concat(findParent(parent)); - } - return parents; - } - - return locals.categories.reduce((result, category) => { - const posts = category.posts.sort('-date'); - const data = pagination(category.path, posts, { - perPage: perPage, - layout: ['category', 'archive', 'index'], - format: paginationDir + '/%d/', - data: { - category: category.name, - parents: findParent(category) - } - }); - - return result.concat(data); - }, []); - }); -}; diff --git a/include/generator/insight.js b/include/generator/insight.js deleted file mode 100644 index afe0275..0000000 --- a/include/generator/insight.js +++ /dev/null @@ -1,43 +0,0 @@ -const util = require('hexo-util'); - -/** - * Insight search content.json generator. - */ -module.exports = function(hexo) { - hexo.extend.generator.register('insight', function(locals) { - const url_for = hexo.extend.helper.get('url_for').bind(this); - function minify(str) { - return util.stripHTML(str).trim().replace(/\n/g, ' ').replace(/\s+/g, ' ') - .replace(/&#x([\da-fA-F]+);/g, (match, hex) => { - return String.fromCharCode(parseInt(hex, 16)); - }) - .replace(/&#([\d]+);/g, (match, dec) => { - return String.fromCharCode(dec); - }); - } - function postMapper(post) { - return { - title: post.title, - text: minify(post.content), - link: url_for(post.path) - }; - } - function tagMapper(tag) { - return { - name: tag.name, - slug: tag.slug, - link: url_for(tag.path) - }; - } - const site = { - pages: locals.pages.map(postMapper), - posts: locals.posts.map(postMapper), - tags: locals.tags.map(tagMapper), - categories: locals.categories.map(tagMapper) - }; - return { - path: '/content.json', - data: JSON.stringify(site) - }; - }); -}; diff --git a/include/generator/tags.js b/include/generator/tags.js deleted file mode 100644 index 87b9c7b..0000000 --- a/include/generator/tags.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Tag list page generator - */ -module.exports = function(hexo) { - hexo.extend.generator.register('tags', locals => { - return { - path: 'tags/', - layout: ['tags'], - data: Object.assign({}, locals, { - __tags: true - }) - }; - }); -}; diff --git a/include/helper/cdn.js b/include/helper/cdn.js deleted file mode 100644 index 0ddbcc1..0000000 --- a/include/helper/cdn.js +++ /dev/null @@ -1,122 +0,0 @@ -/** - * CDN static file resolvers. - * - * @example - * <%- cdn(package, version, filename) %> - * <%- fontcdn(fontName) %> - * <%- iconcdn() %> - */ - -const PROVIDERS = { - LIBRARY: { - cdnjs: '[cdnjs]https://cdnjs.cloudflare.com/ajax/libs/${ package }/${ version }/${ filename }', - loli: '[cdnjs]https://cdnjs.loli.net/ajax/libs/${ package }/${ version }/${ filename }', - jsdelivr: 'https://cdn.jsdelivr.net/npm/${ package }@${ version }/${ filename }', - unpkg: 'https://unpkg.com/${ package }@${ version }/${ filename }' - }, - FONT: { - google: 'https://fonts.googleapis.com/${ type }?family=${ fontname }', - loli: 'https://fonts.loli.net/${ type }?family=${ fontname }' - }, - ICON: { - loli: 'https://cdnjs.loli.net/ajax/libs/font-awesome/5.12.0/css/all.min.css', - fontawesome: 'https://use.fontawesome.com/releases/v5.12.0/css/all.css' - } -}; - -/** - * Convert npm library path to CDN.js path - */ -const CDNJS_FIXTURES = { - 'moment': (ver, fname) => [ - 'moment.js', ver, fname.startsWith('min/') ? fname.substr(4) : fname - ], - 'outdatedbrowser': (ver, fname) => [ - 'outdated-browser', ver, fname.startsWith('outdatedbrowser/') ? fname.substr(16) : fname - ], - 'highlight.js': (ver, fname) => [ - 'highlight.js', ver, fname.endsWith('.css') && fname.indexOf('.min.') === -1 - ? fname.substr(0, fname.length - 4) + '.min.css' : fname - ], - 'mathjax': (ver, fname) => [ - 'mathjax', ver, fname.startsWith('unpacked/') ? fname.substr(9) : fname - ], - 'katex': (ver, fname) => [ - 'KaTeX', ver, fname - ], - 'pace-js': (ver, fname) => [ - 'pace', ver, fname - ], - 'clipboard': (ver, fname) => [ - 'clipboard.js', ver, fname - ], - // disqusjs is not hosted on CDN.js - 'disqusjs': (ver, fname) => [] -}; - -module.exports = function (hexo) { - hexo.extend.helper.register('cdn', function (_package, version, filename) { - let { cdn = 'jsdelivr' } = typeof this.config.providers === 'object' ? this.config.providers : {}; - if (cdn in PROVIDERS.LIBRARY) { - cdn = PROVIDERS.LIBRARY[cdn]; - } - // cdn.js does not follow a GitHub npm style like jsdeliver and unpkg do. Patch it! - if (cdn === 'cdnjs' || cdn.startsWith('[cdnjs]')) { - if (cdn.startsWith('[cdnjs]')) { - cdn = cdn.substr(7); - } - if (filename.startsWith('dist/')) { - filename = filename.substr(5); - } - if (Object.prototype.hasOwnProperty.call(CDNJS_FIXTURES, _package)) { - [_package, version, filename] = CDNJS_FIXTURES[_package](version, filename); - // package is not hosted on CDN.js - if (!_package) { - cdn = 'jsdelivr'; - } - } - } - return cdn.replace(/\${\s*package\s*}/gi, _package) - .replace(/\${\s*version\s*}/gi, version) - .replace(/\${\s*filename\s*}/gi, filename); - }); - - // filename resource abs url - hexo.extend.helper.register('my_cdn', function (filename) { - - // https://cdn.jsdelivr.net/gh/removeif/removeif.github.io@v1.0.6/json_data/record.json - // full url,return - if (filename.startsWith("https://cdn.jsdelivr.net")) { - return filename; - } else { - const myCdnPre = this.config.providers.my_cdn_pre; - if (myCdnPre != undefined && myCdnPre != "") { - if (filename.endsWith(".css") && !filename.endsWith(".min.css") && myCdnPre.indexOf("cdn.jsdelivr.net") > -1) { - filename = filename.replace(".css", ".min.css"); - } else if (filename.endsWith(".js") && !filename.endsWith(".min.js") && myCdnPre.indexOf("cdn.jsdelivr.net") > -1) { - filename = filename.replace(".js", ".min.js"); - } - return this.config.providers.my_cdn_pre + filename; - } else { - return filename; - } - } - }); - - hexo.extend.helper.register('fontcdn', function (fontName, type = 'css') { - let { fontcdn = 'google' } = typeof this.config.providers === 'object' ? this.config.providers : {}; - if (fontcdn in PROVIDERS.FONT) { - fontcdn = PROVIDERS.FONT[fontcdn]; - } - return fontcdn.replace(/\${\s*fontname\s*}/gi, fontName) - .replace(/\${\s*type\s*}/gi, type); - }); - - hexo.extend.helper.register('iconcdn', function () { - let { iconcdn = 'fontawesome' } = typeof this.config.providers === 'object' ? this.config.providers : {}; - if (iconcdn in PROVIDERS.ICON) { - iconcdn = PROVIDERS.ICON[iconcdn]; - } - return iconcdn; - }); -}; diff --git a/include/helper/thumbnail.js b/include/helper/thumbnail.js deleted file mode 100644 index 98f9a51..0000000 --- a/include/helper/thumbnail.js +++ /dev/null @@ -1,24 +0,0 @@ -/** -* Helper functions for post thumbnail. -* -* @example -* <%- has_thumbnail(post) %> -* <%- get_thumbnail(post) %> -*/ -module.exports = function(hexo) { - hexo.extend.helper.register('has_thumbnail', function(post) { - const { article } = this.config; - if (typeof post !== 'object') { - return false; - } - if (article && article.thumbnail === false) { - return false; - } - return 'thumbnail' in post && post.thumbnail; - }); - - hexo.extend.helper.register('get_thumbnail', function(post) { - const { url_for, has_thumbnail } = this.helper; - return url_for(has_thumbnail.call(this, post) ? post.thumbnail : '/img/thumbnail.svg'); - }); -}; diff --git a/include/migration/head.js b/include/migration/head.js index 63f0634..e1807e4 100644 --- a/include/migration/head.js +++ b/include/migration/head.js @@ -1 +1 @@ -module.exports = require('./v2_v3'); +module.exports = require('./v3_v4'); diff --git a/include/migration/v2_v3.js b/include/migration/v2_v3.js index 78b9550..67cbff5 100644 --- a/include/migration/v2_v3.js +++ b/include/migration/v2_v3.js @@ -1,13 +1,13 @@ const logger = require('hexo-log')(); const deepmerge = require('deepmerge'); -const Migration = require('../util/migrate').Migration; +const Migration = require('hexo-component-inferno/lib/core/migrate').Migration; module.exports = class extends Migration { constructor() { super('3.0.0', null); } - doMigrate(config) { + upgrade(config) { const result = deepmerge({}, config); result.head = { favicon: config.favicon || null, @@ -47,6 +47,11 @@ module.exports = class extends Migration { } } + if (Array.isArray(result.donate) && result.donate.length) { + result.donates = result.donate; + delete result.donate; + } + if (Array.isArray(result.widgets) && result.widgets.length) { for (const widget of result.widgets) { if (Object.prototype.hasOwnProperty.call(widget, 'type')) { diff --git a/include/migration/v3_v4.js b/include/migration/v3_v4.js new file mode 100644 index 0000000..6fe2d76 --- /dev/null +++ b/include/migration/v3_v4.js @@ -0,0 +1,14 @@ +const Migration = require('hexo-component-inferno/lib/core/migrate').Migration; + +module.exports = class extends Migration { + constructor() { + super('4.0.0', null); + } + + upgrade(config) { + if (typeof config.article === 'object') { + delete config.article.thumbnail; + } + return config; + } +}; diff --git a/include/helper/page.js b/include/myhelper/myhelper.js similarity index 56% rename from include/helper/page.js rename to include/myhelper/myhelper.js index 1e80e76..c84b337 100644 --- a/include/helper/page.js +++ b/include/myhelper/myhelper.js @@ -1,21 +1,10 @@ +const crypto = require('crypto'); /** -* Helper functions for page/post. -* -* @example -* <%- is_categories(page) %> -* <%- is_tags(page) %> -*/ + * some global method + */ module.exports = function (hexo) { - hexo.extend.helper.register('is_categories', function (page = null) { - return (page === null ? this.page : page).__categories === true; - }); - - hexo.extend.helper.register('is_tags', function (page = null) { - return (page === null ? this.page : page).__tags === true; - }); - // 获取路劲中最后一个字符串,针对于后面调整分类和链接格式时,id不受影响 - hexo.extend.helper.register('get_path_end_str', function (path, unique, title) { + hexo.extend.helper.register('_get_path_end_str', function (path, unique, title) { // 原格式 2020-02-06 02:29:04/"test1".html -> 20200206022904/test1.html if (unique != undefined && unique != '') { @@ -30,7 +19,7 @@ module.exports = function (hexo) { return unique; } } else { - // 对于短连接模式,原来有issue评论的,使用title关联,如果有最新评论以及热门推荐的需要 更爱相应issue中的文章url + // 对于短连接模式,原来有issue评论的,使用title关联,如果有最新评论以及热门推荐的需要 更爱相应issue中的文章url // 对于page 有可能是 有title的情况需要排除 if (title != undefined && title != "" && path.indexOf("/index.html") < 0) { title += ".html"; @@ -47,5 +36,37 @@ module.exports = function (hexo) { } else { return pathArr[pathArrEndIndex].toLocaleLowerCase(); } - }) -}; + }); + + hexo.extend.helper.register('_get_md5', function (str) { + return crypto.createHash('md5').update(str).digest('hex'); + }); + + // filename resource abs url + hexo.extend.helper.register('my_cdn', function (filename) { + + // https://cdn.jsdelivr.net/gh/removeif/removeif.github.io@v1.0.6/json_data/record.json + // full url,return + if (filename.startsWith("https://cdn.jsdelivr.net")) { + return filename; + } else { + + const myCdnPre = this.config.providers.my_cdn_pre; + if (myCdnPre != undefined && myCdnPre != "") { + + if (filename.startsWith(this.config.root)) { + filename = filename.replace(this.config.root, ""); + } + + if (filename.endsWith(".css") && !filename.endsWith(".min.css") && myCdnPre.indexOf("cdn.jsdelivr.net") > -1) { + filename = filename.replace(".css", ".min.css"); + } else if (filename.endsWith(".js") && !filename.endsWith(".min.js") && myCdnPre.indexOf("cdn.jsdelivr.net") > -1) { + filename = filename.replace(".js", ".min.js"); + } + return this.config.providers.my_cdn_pre + filename; + } else { + return filename; + } + } + }); +}; \ No newline at end of file diff --git a/include/register.js b/include/register.js index 39bffd0..c87165d 100644 --- a/include/register.js +++ b/include/register.js @@ -1,27 +1,15 @@ const logger = require('hexo-log')(); module.exports = hexo => { - logger.info('=== Patching Hexo ==='); - require('../include/generator/categories')(hexo); - require('../include/generator/category')(hexo); - require('../include/generator/tags')(hexo); - require('../include/generator/insight')(hexo); - require('../include/filter/locals')(hexo); - require('../include/helper/cdn')(hexo); - require('../include/helper/page')(hexo); - require('../include/helper/thumbnail')(hexo); - - const hooks = [ - 'after_render:html', - 'after_post_render' - ]; - const filters = [ - 'hexoMetaGeneratorInject', - 'externalLinkFilter' - ]; - hooks.forEach(hook => { - hexo.extend.filter.list()[hook] - .filter(filter => filters.includes(filter.name)) - .forEach(filter => hexo.extend.filter.unregister(hook, filter)); - }); + logger.info('=== Registering Hexo extensions ==='); + require('hexo-component-inferno/lib/hexo/filter/locals')(hexo); + require('hexo-component-inferno/lib/hexo/generator/assets')(hexo); + require('hexo-component-inferno/lib/hexo/generator/insight')(hexo); + require('hexo-component-inferno/lib/hexo/generator/categories')(hexo); + require('hexo-component-inferno/lib/hexo/generator/category')(hexo); + require('hexo-component-inferno/lib/hexo/generator/tags')(hexo); + require('hexo-component-inferno/lib/hexo/helper/cdn')(hexo); + require('hexo-component-inferno/lib/hexo/helper/page')(hexo); + require('hexo-component-inferno/lib/core/view').init(hexo); + require('./myhelper/myhelper')(hexo) }; diff --git a/include/schema/comment/.gitkeep b/include/schema/comment/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/include/schema/comment/changyan.json b/include/schema/comment/changyan.json deleted file mode 100644 index b27efc6..0000000 --- a/include/schema/comment/changyan.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/comment/changyan.json", - "description": "Changyan comment plugin configurations", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "changyan" - }, - "app_id": { - "type": "string", - "description": "Changyan app ID" - }, - "conf": { - "type": "string", - "description": "Changyan configuration ID" - } - }, - "required": [ - "type", - "app_id", - "conf" - ] -} \ No newline at end of file diff --git a/include/schema/comment/disqus.json b/include/schema/comment/disqus.json deleted file mode 100644 index 1e8c07a..0000000 --- a/include/schema/comment/disqus.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/comment/disqus.json", - "description": "Disqus comment plugin configurations", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "disqus" - }, - "shortname": { - "type": "string", - "description": "Disqus shortname" - } - }, - "required": [ - "type", - "shortname" - ] -} \ No newline at end of file diff --git a/include/schema/comment/disqusjs.json b/include/schema/comment/disqusjs.json deleted file mode 100644 index cc53d01..0000000 --- a/include/schema/comment/disqusjs.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/comment/disqusjs.json", - "description": "DisqusJS comment plugin configurations", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "disqusjs" - }, - "shortname": { - "type": "string", - "description": "Disqus shortname" - }, - "api_key": { - "description": "Disqus application API key", - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": [ - { - "type": "string" - } - ] - } - ] - }, - "api": { - "type": "string", - "description": "Disqus API endpoint" - }, - "admin": { - "type": "string", - "description": "Disqus moderator username", - "nullable": true - }, - "admin_label": { - "type": "string", - "description": "Disqus moderator badge text", - "default": false, - "nullable": true - }, - "nesting": { - "type": "integer", - "description": "Maximum number of comment nesting level", - "default": 4, - "nullable": true - } - }, - "required": [ - "type", - "shortname", - "api_key" - ] -} \ No newline at end of file diff --git a/include/schema/comment/facebook.json b/include/schema/comment/facebook.json deleted file mode 100644 index 11ceb02..0000000 --- a/include/schema/comment/facebook.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/comment/facebook.json", - "description": "Facebook comment plugin configurations", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "facebook" - } - }, - "required": [ - "type" - ] -} \ No newline at end of file diff --git a/include/schema/comment/gitalk.json b/include/schema/comment/gitalk.json deleted file mode 100644 index 231cd5b..0000000 --- a/include/schema/comment/gitalk.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/comment/gitalk.json", - "description": "Gitalk comment plugin configurations", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "gitalk" - }, - "client_id": { - "type": "string", - "description": "GitHub application client ID" - }, - "client_secret": { - "type": "string", - "description": "GitHub application client secret" - }, - "repo": { - "type": "string", - "description": "GitHub repository" - }, - "owner": { - "type": "string", - "description": "GitHub repository owner. Can be personal user or organization" - }, - "admin": { - "type": "array", - "description": "GitHub repository owner and collaborators. (Users who having write access to this repository)", - "items": { - "type": "string" - } - }, - "per_page": { - "type": "number", - "description": "Pagination size, with maximum 100", - "default": 10, - "nullable": true - }, - "distraction_free_mode": { - "type": "boolean", - "description": "Facebook-like distraction free mode", - "default": false, - "nullable": true - }, - "pager_direction": { - "type": "string", - "description": "Comment sorting direction, available values are `last` and `first`", - "default": "last", - "nullable": true - }, - "create_issue_manually": { - "type": "boolean", - "description": "Create GitHub issues manually for each page", - "default": false, - "nullable": true - }, - "proxy": { - "type": "string", - "description": "GitHub oauth request reverse proxy for CORS", - "nullable": true - }, - "flip_move_options": { - "type": "object", - "description": "Comment list animation", - "nullable": true - }, - "enable_hotkey": { - "type": "boolean", - "description": "Enable hot key (cmd|ctrl + enter) submit comment", - "default": true, - "nullable": true - } - }, - "required": [ - "type", - "client_id", - "client_secret", - "repo", - "owner", - "admin" - ] -} \ No newline at end of file diff --git a/include/schema/comment/gitment.json b/include/schema/comment/gitment.json deleted file mode 100644 index c9fd071..0000000 --- a/include/schema/comment/gitment.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/comment/gitment.json", - "description": "Gitment comment plugin configurations", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "gitment" - }, - "owner": { - "type": "string", - "description": "Your GitHub ID" - }, - "repo": { - "type": "string", - "description": "The repository to store your comments. Make sure you're repo's owner" - }, - "client_id": { - "type": "string", - "description": "GitHub client ID" - }, - "client_secret": { - "type": "string", - "description": "GitHub client secret" - }, - "theme": { - "type": "string", - "description": "An optional Gitment theme object", - "default": "gitment.defaultTheme", - "nullable": true - }, - "per_page": { - "type": "number", - "description": "An optional number to which comments will be paginated", - "default": 20, - "nullable": true - }, - "max_comment_height": { - "type": "number", - "description": "An optional number to limit comments' max height, over which comments will be folded", - "default": 250, - "nullable": true - } - }, - "required": [ - "type", - "owner", - "repo", - "client_id", - "client_secret" - ] -} \ No newline at end of file diff --git a/include/schema/comment/isso.json b/include/schema/comment/isso.json deleted file mode 100644 index 6ad0825..0000000 --- a/include/schema/comment/isso.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/comment/isso.json", - "description": "Isso comment plugin configurations", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "isso" - }, - "url": { - "type": "string", - "description": "URL to your Isso comment service" - } - }, - "required": [ - "type", - "url" - ] -} \ No newline at end of file diff --git a/include/schema/comment/livere.json b/include/schema/comment/livere.json deleted file mode 100644 index 1459882..0000000 --- a/include/schema/comment/livere.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/comment/livere.json", - "description": "Livere comment plugin configurations", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "livere" - }, - "uid": { - "type": "string", - "description": "LiveRe comment service UID" - } - }, - "required": [ - "type", - "uid" - ] -} \ No newline at end of file diff --git a/include/schema/comment/utteranc.json b/include/schema/comment/utteranc.json deleted file mode 100644 index 7419c18..0000000 --- a/include/schema/comment/utteranc.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/comment/utteranc.json", - "description": "Utterances comment plugin configurations", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "utteranc" - }, - "repo": { - "type": "string", - "description": "GitHub repository to which Utterances connects" - }, - "label": { - "type": "string", - "description": "Label assigned to issues created by Utterances", - "nullable": true - }, - "theme": { - "type": "string", - "description": "Utterances look and feel", - "enum": [ - "github-light", - "github-dark", - "github-dark-orange", - "icy-dark", - "dark-blue", - "photon-dark" - ], - "default": "github-light", - "nullable": true - } - }, - "required": [ - "type", - "repo" - ], - "oneOf": [ - { - "type": "object", - "properties": { - "issue_term": { - "type": "string", - "description": "The mapping between blog posts and GitHub issues", - "default": "pathname" - } - }, - "required": [ - "issue_term" - ] - }, - { - "type": "object", - "properties": { - "issue_number": { - "type": "integer", - "description": "Configure Utterances to load a specific issue by number" - } - }, - "required": [ - "issue_number" - ] - } - ] -} \ No newline at end of file diff --git a/include/schema/comment/valine.json b/include/schema/comment/valine.json deleted file mode 100644 index 0ae4ea9..0000000 --- a/include/schema/comment/valine.json +++ /dev/null @@ -1,102 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/comment/valine.json", - "description": "Valine comment plugin configurations", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "valine" - }, - "app_id": { - "type": "string", - "description": "Application from Leancloud" - }, - "app_key": { - "type": "string", - "description": "Application from Leancloud" - }, - "placeholder": { - "type": "string", - "description": "Comment box placeholders", - "nullable": true - }, - "notify": { - "type": "boolean", - "description": "Enable email notification when someone comments", - "default": false, - "nullable": true - }, - "verify": { - "type": "boolean", - "description": "Enable verification code service", - "default": false, - "nullable": true - }, - "avatar": { - "type": "string", - "description": "Gravatar type", - "enum": [ - "", - "mp", - "identicon", - "monsterid", - "wavatar", - "robohash", - "retro", - "hide", - "mm" - ], - "default": "mm", - "nullable": true - }, - "avatar_force": { - "type": "boolean", - "description": "Pull the latest avatar upon page visit", - "default": false, - "nullable": true - }, - "meta": { - "type": "array", - "description": "Reviewer attributes", - "items": { - "type": "string" - }, - "default": [ - "nick", - "mail", - "link" - ], - "nullable": true - }, - "page_size": { - "type": "integer", - "description": "Number of comments per page", - "default": 10, - "nullable": true - }, - "visitor": { - "type": "boolean", - "description": "Show visitor count", - "default": false, - "nullable": true - }, - "highlight": { - "type": "boolean", - "description": "Enable code highlighting", - "default": true, - "nullable": true - }, - "record_ip": { - "type": "boolean", - "description": "Record reviewer IP address", - "default": false, - "nullable": true - } - }, - "required": [ - "type", - "app_id", - "app_key" - ] -} \ No newline at end of file diff --git a/include/schema/common/article.json b/include/schema/common/article.json index 140857a..8794662 100644 --- a/include/schema/common/article.json +++ b/include/schema/common/article.json @@ -34,17 +34,31 @@ }, "nullable": true }, - "thumbnail": { - "type": "boolean", - "description": "Whether to show thumbnail image for every article", - "default": true, - "nullable": true - }, "readtime": { "type": "boolean", "description": "Whether to show estimated article reading time", "default": true, "nullable": true + }, + "licenses": { + "$ref": "/misc/poly_links.json", + "description": "Article licensing block", + "examples": [ + { + "Creative Commons": { + "icon": "fab fa-creative-commons", + "url": "https://creativecommons.org/" + }, + "Attribution": { + "icon": "fab fa-creative-commons-by", + "url": "https://creativecommons.org/licenses/by/4.0/" + }, + "Noncommercial": { + "icon": "fab fa-creative-commons-nc", + "url": "https://creativecommons.org/licenses/by-nc/4.0/" + } + } + ] } } } \ No newline at end of file diff --git a/include/schema/common/comment.json b/include/schema/common/comment.json index b6923a8..a5e8cbd 100644 --- a/include/schema/common/comment.json +++ b/include/schema/common/comment.json @@ -29,10 +29,10 @@ "$ref": "/comment/livere.json" }, { - "$ref": "/comment/valine.json" + "$ref": "/comment/utterances.json" }, { - "$ref": "/comment/utteranc.json" + "$ref": "/comment/valine.json" } ] } \ No newline at end of file diff --git a/include/schema/common/donates.json b/include/schema/common/donates.json index 9ee9c2a..f1d23ab 100644 --- a/include/schema/common/donates.json +++ b/include/schema/common/donates.json @@ -1,10 +1,14 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "$id": "/common/donates.json", - "description": "Donate plugin configurations", + "description": "Donate plugin configurations\nhttps://ppoffice.github.io/hexo-theme-icarus/categories/Plugins/Donation/", "type": "array", "items": { + "type": "object", "oneOf": [ + { + "$ref": "/donate/afdian.json" + }, { "$ref": "/donate/alipay.json" }, diff --git a/include/schema/common/head.json b/include/schema/common/head.json index 3269314..3e62d22 100644 --- a/include/schema/common/head.json +++ b/include/schema/common/head.json @@ -10,11 +10,6 @@ "default": "/img/favicon.svg", "nullable": true }, - "canonical_url": { - "type": "string", - "description": "Canonical URL of the current page", - "nullable": true - }, "open_graph": { "$ref": "/misc/open_graph.json" }, diff --git a/include/schema/common/plugins.json b/include/schema/common/plugins.json index 2482ae1..a3d85c6 100644 --- a/include/schema/common/plugins.json +++ b/include/schema/common/plugins.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "$id": "/common/plugins.json", - "description": "Plugin configurations", + "description": "Plugin configurations\nhttps://ppoffice.github.io/hexo-theme-icarus/categories/Plugins/", "type": "object", "properties": { "animejs": { @@ -16,6 +16,9 @@ "busuanzi": { "$ref": "/plugin/busuanzi.json" }, + "cnzz": { + "$ref": "/plugin/cnzz.json" + }, "gallery": { "$ref": "/plugin/gallery.json" }, diff --git a/include/schema/common/search.json b/include/schema/common/search.json index d4f851c..4e48d43 100644 --- a/include/schema/common/search.json +++ b/include/schema/common/search.json @@ -12,6 +12,9 @@ }, { "$ref": "/search/google_cse.json" + }, + { + "$ref": "/search/algolia.json" } ] } \ No newline at end of file diff --git a/include/schema/common/widgets.json b/include/schema/common/widgets.json index c606f22..890cae2 100644 --- a/include/schema/common/widgets.json +++ b/include/schema/common/widgets.json @@ -28,12 +28,6 @@ { "$ref": "/widget/recent_posts.json" }, - { - "$ref": "/widget/latest_comment.json" - }, - { - "$ref": "/widget/hot_recommend.json" - }, { "$ref": "/widget/archives.json" }, @@ -47,7 +41,16 @@ "$ref": "/widget/adsense.json" }, { - "$ref": "/widget/notice.json" + "$ref": "/widget/ads_x.json" + }, + { + "$ref": "/widget/hot_recommend.json" + }, + { + "$ref": "/widget/latest_comment.json" + }, + { + "$ref": "/widget/recommend_post.json" } ], "required": [ diff --git a/include/schema/config.json b/include/schema/config.json index e6268cd..a9767b9 100644 --- a/include/schema/config.json +++ b/include/schema/config.json @@ -7,7 +7,16 @@ "version": { "type": "string", "description": "Version of the configuration file", - "default": "3.0.0" + "default": "4.0.0" + }, + "variant": { + "type": "string", + "description": "Icarus theme variant, can be \"default\" or \"cyberpunk\"", + "enum": [ + "default", + "cyberpunk" + ], + "default": "default" }, "logo": { "type": [ diff --git a/include/schema/donate/.gitkeep b/include/schema/donate/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/include/schema/donate/alipay.json b/include/schema/donate/alipay.json deleted file mode 100644 index 3ba2aa2..0000000 --- a/include/schema/donate/alipay.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/donate/alipay.json", - "description": "Alipay donate button configurations", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "alipay" - }, - "qrcode": { - "type": "string", - "description": "Alipay qrcode image URL" - } - }, - "required": [ - "type", - "qrcode" - ] -} \ No newline at end of file diff --git a/include/schema/donate/buymeacoffee.json b/include/schema/donate/buymeacoffee.json deleted file mode 100644 index c51a0f7..0000000 --- a/include/schema/donate/buymeacoffee.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/donate/buymeacoffee.json", - "description": "\"Buy me a coffee\" donate button configurations", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "buymeacoffee" - }, - "url": { - "type": "string", - "description": "URL to the \"Buy me a coffee\" page" - } - }, - "required": [ - "type", - "url" - ] -} \ No newline at end of file diff --git a/include/schema/donate/patreon.json b/include/schema/donate/patreon.json deleted file mode 100644 index f3c2c9c..0000000 --- a/include/schema/donate/patreon.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/donate/patreon.json", - "description": "Patreon donate button configurations", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "patreon" - }, - "url": { - "type": "string", - "description": "URL to the Patreon page" - } - }, - "required": [ - "type", - "url" - ] -} \ No newline at end of file diff --git a/include/schema/donate/paypal.json b/include/schema/donate/paypal.json deleted file mode 100644 index d19a421..0000000 --- a/include/schema/donate/paypal.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/donate/paypal.json", - "description": "Paypal donate button configurations", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "paypal" - }, - "business": { - "type": "string", - "description": "Paypal business ID or email address" - }, - "currency_code": { - "type": "string", - "description": "Currency code", - "examples": [ - "USD" - ] - } - }, - "required": [ - "type", - "business", - "currency_code" - ] -} \ No newline at end of file diff --git a/include/schema/donate/wechat.json b/include/schema/donate/wechat.json deleted file mode 100644 index a50cfc0..0000000 --- a/include/schema/donate/wechat.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/donate/wechat.json", - "description": "Wechat donate button configurations", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "wechat" - }, - "qrcode": { - "type": "string", - "description": "Wechat qrcode image URL" - } - }, - "required": [ - "type", - "qrcode" - ] -} \ No newline at end of file diff --git a/include/schema/misc/.gitkeep b/include/schema/misc/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/include/schema/misc/meta.json b/include/schema/misc/meta.json deleted file mode 100644 index ba24a0d..0000000 --- a/include/schema/misc/meta.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/misc/meta.json", - "description": "Additional HTML meta tags in an array", - "type": "array", - "items": { - "type": "string", - "description": "Meta tag specified in = style\nE.g., name=theme-color;content=#123456 => " - }, - "nullable": true -} \ No newline at end of file diff --git a/include/schema/misc/open_graph.json b/include/schema/misc/open_graph.json deleted file mode 100644 index 28b51d5..0000000 --- a/include/schema/misc/open_graph.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/misc/open_graph.json", - "description": "Open Graph metadata\nhttps://hexo.io/docs/helpers.html#open-graph", - "type": "object", - "properties": { - "title": { - "type": "string", - "description": "Page title (og:title) (optional)\nYou should leave this blank for most of the time", - "nullable": true - }, - "type": { - "type": "string", - "description": "Page type (og:type) (optional)\nYou should leave this blank for most of the time", - "default": "blog", - "nullable": true - }, - "url": { - "type": "string", - "description": "Page URL (og:url) (optional)\nYou should leave this blank for most of the time", - "nullable": true - }, - "image": { - "type": [ - "string", - "array" - ], - "description": "Page cover (og:image) (optional) Default to the Open Graph image or thumbnail of the page\nYou should leave this blank for most of the time", - "items": { - "type": "string" - }, - "nullable": true - }, - "site_name": { - "type": "string", - "description": "Site name (og:site_name) (optional)\nYou should leave this blank for most of the time", - "nullable": true - }, - "author": { - "type": "string", - "description": "Page author (article:author) (optional)\nYou should leave this blank for most of the time", - "nullable": true - }, - "description": { - "type": "string", - "description": "Page description (og:description) (optional)\nYou should leave this blank for most of the time", - "nullable": true - }, - "twitter_card": { - "type": "string", - "description": "Twitter card type (twitter:card)", - "nullable": true - }, - "twitter_id": { - "type": "string", - "description": "Twitter ID (twitter:creator)", - "nullable": true - }, - "twitter_site": { - "type": "string", - "description": "Twitter ID (twitter:creator)", - "nullable": true - }, - "google_plus": { - "type": "string", - "description": "Google+ profile link (deprecated)", - "nullable": true - }, - "fb_admins": { - "type": "string", - "description": "Facebook admin ID", - "nullable": true - }, - "fb_app_id": { - "type": "string", - "description": "Facebook App ID", - "nullable": true - } - }, - "nullable": true -} \ No newline at end of file diff --git a/include/schema/misc/poly_links.json b/include/schema/misc/poly_links.json deleted file mode 100644 index 0ad425a..0000000 --- a/include/schema/misc/poly_links.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/misc/poly_links.json", - "description": "A polymorphic link", - "type": "object", - "patternProperties": { - ".+": { - "type": [ - "string", - "object" - ], - "description": "URL or path of the link, with/without the icon element class name", - "properties": { - "url": { - "type": "string", - "description": "URL or path of the link" - }, - "icon": { - "type": "string", - "description": "Icon element class name" - } - }, - "required": [ - "url", - "icon" - ] - } - }, - "examples": [ - { - "My GitHub Page": "https://github.com/ppoffice" - }, - { - "My GitHub Page": { - "url": "https://github.com/ppoffice", - "icon": "fab fa-github" - } - } - ], - "nullable": true -} \ No newline at end of file diff --git a/include/schema/misc/structured_data.json b/include/schema/misc/structured_data.json deleted file mode 100644 index 9ea8334..0000000 --- a/include/schema/misc/structured_data.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/misc/structured_data.json", - "description": "Structured data of the page\nhttps://developers.google.com/search/docs/guides/intro-structured-data", - "type": "object", - "properties": { - "title": { - "type": "string", - "description": "Page title (optional)\nYou should leave this blank for most of the time", - "nullable": true - }, - "description": { - "type": "string", - "description": "Page description (optional)\nYou should leave this blank for most of the time", - "nullable": true - }, - "url": { - "type": "string", - "description": "Page URL (optional)\nYou should leave this blank for most of the time", - "nullable": true - }, - "author": { - "type": "string", - "description": "Page author (article:author) (optional)\nYou should leave this blank for most of the time", - "nullable": true - }, - "image": { - "type": [ - "string", - "array" - ], - "description": "Page images (optional) Default to the Open Graph image or thumbnail of the page\nYou should leave this blank for most of the time", - "items": { - "type": "string" - }, - "nullable": true - } - }, - "nullable": true -} \ No newline at end of file diff --git a/include/schema/plugin/baidu_analytics.json b/include/schema/plugin/baidu_analytics.json deleted file mode 100644 index 543577f..0000000 --- a/include/schema/plugin/baidu_analytics.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/plugin/baidu_analytics.json", - "description": "Baidu Analytics plugin settings\nhttps://tongji.baidu.com", - "type": "object", - "properties": { - "tracking_id": { - "type": "string", - "description": "Baidu Analytics tracking ID", - "nullable": true - } - }, - "required": [ - "tracking_id" - ] -} \ No newline at end of file diff --git a/include/schema/plugin/busuanzi.json b/include/schema/plugin/busuanzi.json deleted file mode 100644 index a9f4d27..0000000 --- a/include/schema/plugin/busuanzi.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/plugin/busuanzi.json", - "description": "BuSuanZi site/page view counter\nhttps://busuanzi.ibruce.info", - "type": "boolean", - "default": false -} \ No newline at end of file diff --git a/include/schema/plugin/gallery.json b/include/schema/plugin/gallery.json deleted file mode 100644 index b8aa3c0..0000000 --- a/include/schema/plugin/gallery.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/plugin/gallery.json", - "description": "Enable the lightGallery and Justified Gallery plugins\nhttps://ppoffice.github.io/hexo-theme-icarus/Plugins/General/gallery-plugin/", - "type": "boolean", - "default": true -} \ No newline at end of file diff --git a/include/schema/plugin/google_analytics.json b/include/schema/plugin/google_analytics.json deleted file mode 100644 index 9846152..0000000 --- a/include/schema/plugin/google_analytics.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/plugin/google_analytics.json", - "description": "Google Analytics plugin settings\nhttps://analytics.google.com", - "type": "object", - "properties": { - "tracking_id": { - "type": "string", - "description": "Google Analytics tracking ID", - "nullable": true - } - }, - "required": [ - "tracking_id" - ] -} \ No newline at end of file diff --git a/include/schema/plugin/hotjar.json b/include/schema/plugin/hotjar.json deleted file mode 100644 index 1ec6d0e..0000000 --- a/include/schema/plugin/hotjar.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/plugin/hotjar.json", - "description": "Hotjar user feedback plugin\nhttps://www.hotjar.com/", - "type": "object", - "properties": { - "site_id": { - "type": [ - "string", - "number" - ], - "description": "Hotjar site id", - "nullable": true - } - }, - "required": [ - "site_id" - ] -} \ No newline at end of file diff --git a/include/schema/plugin/katex.json b/include/schema/plugin/katex.json deleted file mode 100644 index 2991b62..0000000 --- a/include/schema/plugin/katex.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/plugin/katex.json", - "description": "Enable the KaTeX math typesetting supprot\nhttps://katex.org/", - "type": "boolean", - "default": false -} \ No newline at end of file diff --git a/include/schema/plugin/mathjax.json b/include/schema/plugin/mathjax.json deleted file mode 100644 index 26387e8..0000000 --- a/include/schema/plugin/mathjax.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/plugin/mathjax.json", - "description": "Enable the MathJax math typesetting support\nhttps://www.mathjax.org/", - "type": "boolean", - "default": false -} \ No newline at end of file diff --git a/include/schema/plugin/outdated_browser.json b/include/schema/plugin/outdated_browser.json deleted file mode 100644 index 31efbc4..0000000 --- a/include/schema/plugin/outdated_browser.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/plugin/outdated_browser.json", - "description": "Enable the Outdated Browser plugin\nhttp://outdatedbrowser.com/", - "type": "boolean", - "default": false -} \ No newline at end of file diff --git a/include/schema/plugin/progressbar.json b/include/schema/plugin/progressbar.json deleted file mode 100644 index 6ad74d1..0000000 --- a/include/schema/plugin/progressbar.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/plugin/progressbar.json", - "description": "Show a progress bar at top of the page on page loading", - "type": "boolean", - "default": true -} \ No newline at end of file diff --git a/include/schema/search/.gitkeep b/include/schema/search/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/include/schema/search/google_cse.json b/include/schema/search/google_cse.json deleted file mode 100644 index a2afe12..0000000 --- a/include/schema/search/google_cse.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/search/google_cse.json", - "description": "Enable Google CSE\nhttps://cse.google.com/cse/create/new", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "google_cse" - }, - "cx": { - "type": "string", - "description": "Google CSE cx value" - } - }, - "required": [ - "type", - "cx" - ] -} \ No newline at end of file diff --git a/include/schema/search/insight.json b/include/schema/search/insight.json deleted file mode 100644 index 45ebf7b..0000000 --- a/include/schema/search/insight.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/search/insight.json", - "description": "Enable Insight search\nhttps://ppoffice.github.io/hexo-theme-icarus/Plugins/Search/insight-search-plugin/", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "insight" - } - }, - "required": [ - "type" - ] -} \ No newline at end of file diff --git a/include/schema/share/.gitkeep b/include/schema/share/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/include/schema/share/addthis.json b/include/schema/share/addthis.json deleted file mode 100644 index 603866e..0000000 --- a/include/schema/share/addthis.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/share/addthis.json", - "description": "Enable AddThis share buttons\nhttps://www.addthis.com/", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "addthis" - }, - "install_url": { - "type": "string", - "description": "URL to the AddThis share plugin script" - } - }, - "required": [ - "type", - "install_url" - ] -} \ No newline at end of file diff --git a/include/schema/share/addtoany.json b/include/schema/share/addtoany.json deleted file mode 100644 index 2ed9af7..0000000 --- a/include/schema/share/addtoany.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/share/addtoany.json", - "description": "Enable AddToAny share buttons\nhttps://www.addtoany.com/", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "addtoany" - } - }, - "required": [ - "type" - ] -} \ No newline at end of file diff --git a/include/schema/share/bdshare.json b/include/schema/share/bdshare.json deleted file mode 100644 index 4e310d5..0000000 --- a/include/schema/share/bdshare.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/share/bdshare.json", - "description": "Enable Baidu share buttons", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "bdshare" - } - }, - "required": [ - "type" - ] -} \ No newline at end of file diff --git a/include/schema/share/sharejs.json b/include/schema/share/sharejs.json deleted file mode 100644 index 9b4d330..0000000 --- a/include/schema/share/sharejs.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/share/sharejs.json", - "description": "Enable Share.js share buttons\nhttps://github.com/overtrue/share.js/", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "sharejs" - } - }, - "required": [ - "type" - ] -} \ No newline at end of file diff --git a/include/schema/share/sharethis.json b/include/schema/share/sharethis.json deleted file mode 100644 index 6fc6c51..0000000 --- a/include/schema/share/sharethis.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/share/sharethis.json", - "description": "Enable ShareThis share buttons\nhttps://sharethis.com/", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "sharethis" - }, - "install_url": { - "type": "string", - "description": "URL to the ShareThis share plugin script" - } - }, - "required": [ - "type", - "install_url" - ] -} \ No newline at end of file diff --git a/include/schema/search/baidu.json b/include/schema/widget/ads_x.json similarity index 66% rename from include/schema/search/baidu.json rename to include/schema/widget/ads_x.json index 7b390cd..67185db 100644 --- a/include/schema/search/baidu.json +++ b/include/schema/widget/ads_x.json @@ -1,12 +1,12 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/search/baidu.json", - "description": "Enable Baidu search", + "$id": "/widget/ads_x.json", + "description": "Adsense X Widget", "type": "object", "properties": { "type": { "type": "string", - "const": "baidu" + "const": "ads_x" } }, "required": [ diff --git a/include/schema/widget/adsense.json b/include/schema/widget/adsense.json index ed3815a..c3d5c2c 100644 --- a/include/schema/widget/adsense.json +++ b/include/schema/widget/adsense.json @@ -1,25 +1,13 @@ { - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/widget/adsense.json", - "description": "Google AdSense unit configurations", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "adsense" - }, - "client_id": { - "type": "string", - "description": "AdSense client ID" - }, - "slot_id": { - "type": "string", - "description": "AdSense AD unit ID" - } - }, - "required": [ - "type", - "client_id", - "slot_id" - ] -} \ No newline at end of file + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/widget/adsense.json", + "description": "Google AdSense unit configurations", + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "adsense" + } + }, + "required": ["type"] +} diff --git a/include/schema/widget/categories.json b/include/schema/widget/categories.json deleted file mode 100644 index 7fc2ec4..0000000 --- a/include/schema/widget/categories.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/widget/categories.json", - "description": "Categories widget configurations", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "categories" - } - }, - "required": [ - "type" - ] -} \ No newline at end of file diff --git a/include/schema/widget/links.json b/include/schema/widget/links.json deleted file mode 100644 index 2088018..0000000 --- a/include/schema/widget/links.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/widget/links.json", - "description": "Recommendation links widget configurations", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "links" - }, - "links": { - "type": "object", - "description": "Names and URLs of the sites", - "patternProperties": { - ".+": { - "type": "string", - "description": "URL of the site" - } - }, - "examples": [ - { - "Hexo": "https://hexo.io", - "Bulma": "https://bulma.io" - } - ], - "nullable": true - } - }, - "required": [ - "type" - ] -} \ No newline at end of file diff --git a/include/schema/widget/notice.json b/include/schema/widget/notice.json deleted file mode 100644 index a42eba5..0000000 --- a/include/schema/widget/notice.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/widget/notice.json", - "description": "Notice links widget configurations", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "notice" - }, - "contents": { - "type": "object", - "description": "notic contents", - "patternProperties": { - ".+": { - "type": "string", - "description": "URL of the site" - } - }, - "examples": [ - { - "1": "2019.05.23 建站" - } - ], - "nullable": true - } - }, - "required": [ - "type" - ] -} \ No newline at end of file diff --git a/include/schema/widget/recent_posts.json b/include/schema/widget/recent_posts.json deleted file mode 100644 index e19cf11..0000000 --- a/include/schema/widget/recent_posts.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/widget/recent_posts.json", - "description": "Recent posts widget configurations", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "recent_posts" - } - }, - "required": [ - "type" - ] -} \ No newline at end of file diff --git a/include/schema/widget/archives.json b/include/schema/widget/recommend_post.json similarity index 59% rename from include/schema/widget/archives.json rename to include/schema/widget/recommend_post.json index 35d9244..98c5505 100644 --- a/include/schema/widget/archives.json +++ b/include/schema/widget/recommend_post.json @@ -1,12 +1,12 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/widget/archives.json", - "description": "Archives widget configurations", + "$id": "/widget/recommend_post.json", + "description": "Latest Comment widget configurations", "type": "object", "properties": { "type": { "type": "string", - "const": "archives" + "const": "recommend_post" } }, "required": [ diff --git a/include/schema/widget/subscribe_email.json b/include/schema/widget/subscribe_email.json deleted file mode 100644 index 43b2c8a..0000000 --- a/include/schema/widget/subscribe_email.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/widget/subscribe_email.json", - "description": "Google FeedBurner email subscription widget configurations", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "subscribe_email" - }, - "description": { - "type": "string", - "description": "Hint text under the email input", - "nullable": true - }, - "feedburner_id": { - "type": "string", - "description": "Feedburner ID" - } - }, - "required": [ - "type", - "feedburner_id" - ] -} \ No newline at end of file diff --git a/include/schema/widget/tags.json b/include/schema/widget/tags.json deleted file mode 100644 index 4cb438a..0000000 --- a/include/schema/widget/tags.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/widget/tags.json", - "description": "Tags widget configurations", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "tags" - } - }, - "required": [ - "type" - ] -} \ No newline at end of file diff --git a/include/schema/widget/toc.json b/include/schema/widget/toc.json deleted file mode 100644 index 911023e..0000000 --- a/include/schema/widget/toc.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "/widget/toc.json", - "description": "Table of contents widget configurations", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "toc" - } - }, - "required": [ - "type" - ] -} \ No newline at end of file diff --git a/include/style/article.styl b/include/style/article.styl new file mode 100644 index 0000000..4ea7a22 --- /dev/null +++ b/include/style/article.styl @@ -0,0 +1,164 @@ +/* --------------------------------- + * Article Summary and Content + * --------------------------------- */ +$article-font-size ?= 1.1rem + +article + &.media + .media-content + color: $text-light + + .title + margin: 0 + line-height: inherit + + &.article + .article-meta, .article-tags + color: $text-light + + .article-meta + overflow-x: auto + margin-bottom: .5rem + + .article-more + @extend .button.is-light + + .content + word-wrap: break-word + font-size: $article-font-size + + h1 + font-size: 1.75em + + h2 + font-size: 1.5em + + h3 + font-size: 1.25em + + h4 + font-size: 1.125em + + h5 + font-size: 1em + + pre + font-size: .85em + + code + padding: 0 + background: transparent + overflow-wrap: break-word + + blockquote + &.pullquote + float: right + max-width: 50% + font-size: 1.15rem + position: relative + + footer + strong + cite + margin-left: .5em + + .message.message-immersive + border-radius: 0 + margin: 0 0-($card-content-padding) $card-content-padding 0-($card-content-padding) + .message-body + border: none + +.rtl + direction: rtl + + .level + &, &.is-mobile + .level-item:not(:last-child) + margin-left: .75rem + margin-right: 0 + +// Overflow table +.table-overflow + overflow-x: auto + + table + width: auto !important + + th + word-break: keep-all + +// Video container +.video-container + position: relative + padding-bottom: 56.25% + padding-top: 25px + height: 0 + + iframe + position: absolute + top: 0 + left: 0 + width: 100% + height: 100% + +.article-licensing + position: relative + z-index: 1 + box-shadow: none + background: $white-ter + border-radius: $radius + overflow: hidden + + &:after + position: absolute + z-index: -1 + right: -50px + top: -87.87px + content: '\f25e' + font-size: 200px + font-family: 'Font Awesome 5 Brands' + opacity: 0.1 + + .level-left + flex-wrap: wrap + max-width: 100% + + .licensing-title + @extend .mb-3 + line-height: 1.2 + + p:not(:last-child) + @extend .mb-1 + + a + @extend .size-small, .has-text-grey + + .licensing-meta + .level-item + @extend .mr-4 + + .icon + @extend .mr-1 + width: 1.2em + height: 1.2em + font-size: 1.2em + vertical-align: bottom + + h6 + @extend .size-small + + a + color: inherit + +a + &.article-nav-prev + span + text-align: left + flex-shrink: 1 + word-wrap: break-word + white-space: normal + &.article-nav-next + span + text-align: right + flex-shrink: 1 + word-wrap: break-word + white-space: normal \ No newline at end of file diff --git a/include/style/base.styl b/include/style/base.styl new file mode 100644 index 0000000..c0093a7 --- /dev/null +++ b/include/style/base.styl @@ -0,0 +1,96 @@ +bulma-stylus-root = '../../../../node_modules/bulma-stylus/stylus' + +/* --------------------------------- + * Override Bulma CSS Framework + * --------------------------------- */ +$body-size ?= 14px +$body-background-color ?= #f7f7f7 + +$family-sans-serif ?= Ubuntu, Roboto, 'Open Sans', 'Microsoft YaHei', sans-serif +$family-code ?= 'Source Code Pro', monospace, 'Microsoft YaHei' + +$primary ?= $blue +$custom-colors ?= { + grey-lightest: { + '1': $grey-lightest + '2': $grey-darker + } +} + +$navbar-item-active-color ?= $primary +$footer-background-color ?= $scheme-main + +$gap ?= 64px +$tablet ?= 769px +$desktop ?= 1088px +$widescreen ?= 1280px +$fullhd ?= 1472px + +$shadow ?= 0 4px 10px rgba(0, 0, 0, 0.05) + +$title-weight ?= $weight-normal + +$control-height ?= 2.25em +$button-padding-vertical ?= calc(0.375em - 1px) + +$card-radius ?= $radius +$card-media-margin ?= 0.75rem +$card-shadow ?= $shadow, 0 0 1px rgba(0, 0, 0, 0.1) + +$menu-item-active-color ?= $link +$menu-item-active-background-color ?= hsl(219, 70%, 96%) + +$content-heading-weight ?= $weight-normal + + +$logo-height ?= 1.75rem + +// FIXME: https://github.com/groenroos/bulma-stylus/issues/11 +@import bulma-stylus-root + '/utilities/initial-variables' +@import bulma-stylus-root + '/utilities/functions' +@import bulma-stylus-root + '/utilities/derived-variables' + +$colors = merge($colors, $custom-colors) + +@import bulma-stylus-root + '/utilities/animations' +@import bulma-stylus-root + '/utilities/mixins' +@import bulma-stylus-root + '/utilities/controls' +@import bulma-stylus-root + '/base/_all' +@import bulma-stylus-root + '/components/_all' +@import bulma-stylus-root + '/elements/_all' +@import bulma-stylus-root + '/form/_all' +@import bulma-stylus-root + '/grid/_all' +@import bulma-stylus-root + '/layout/_all' + +html + height: 100% + -webkit-text-size-adjust: 100% + -moz-text-size-adjust: 100% + -ms-text-size-adjust: 100% + text-size-adjust: 100% + +body + min-height: 100% + display: flex + flex-direction: column + +body > .section + flex-grow: 1 + ++desktop() + ::-webkit-scrollbar + width: 8px + height: 8px + + ::-webkit-scrollbar-track + border-radius: 3px + background: rgba(0,0,0,0.06) + box-shadow: inset 0 0 5px rgba(0,0,0,0.1) + + ::-webkit-scrollbar-thumb + border-radius: 3px + background: rgba(0,0,0,0.12) + box-shadow: inset 0 0 10px rgba(0,0,0,0.2) + + ::-webkit-scrollbar-thumb:hover + background: rgba(0,0,0,0.24) diff --git a/include/style/button.styl b/include/style/button.styl new file mode 100644 index 0000000..b9f6c30 --- /dev/null +++ b/include/style/button.styl @@ -0,0 +1,8 @@ +/* --------------------------------- + * Buttons + * --------------------------------- */ +.button + &.is-transparent + color: inherit + background: transparent + border-color: transparent diff --git a/include/style/card.styl b/include/style/card.styl new file mode 100644 index 0000000..db5f46f --- /dev/null +++ b/include/style/card.styl @@ -0,0 +1,18 @@ +/* --------------------------------- + * Card + * --------------------------------- */ +.card + overflow: visible + border-radius: $card-radius + + & + .card, & + .column-right-shadow + margin-top: 1.5rem + + .card-image + overflow: hidden + border-top-left-radius: $card-radius + border-top-right-radius: $card-radius + + .media + .media + border: none + margin-top: 0 diff --git a/include/style/codeblock.styl b/include/style/codeblock.styl new file mode 100644 index 0000000..0cae04f --- /dev/null +++ b/include/style/codeblock.styl @@ -0,0 +1,105 @@ +/* --------------------------------- + * Code Highlight + * --------------------------------- */ +$codeblock-caption-bg ?= rgba(200, 200, 200, .15) + +figure.highlight + padding: 0 + width: 100% + position: relative + margin: 1em 0 1em !important + border-radius: $radius + + &.folded + .highlight-body + height: 0 + + .copy + opacity: .7 + + pre, table tr:hover + color: inherit + background: transparent + + table + width: auto + + tr td + border: none + + tr:not(:first-child) td + padding-top: 0 + + tr:not(:last-child) td + padding-bottom: 0 + + pre + padding: 0 + overflow: visible + + .line, code .hljs + line-height: 1.5rem + + figcaption, .gutter + background: $codeblock-caption-bg + + figcaption + margin: 0 !important + padding: .3em 0em .3em .75em + font-style: normal + font-size: .8em + + * + color: inherit + + span + font-weight: 500 + font-family: $family-code + + .level-left *:not(:last-child) + margin-right: .5em + + .level-right *:not(:first-child) + margin-left: .5em + + .fold + cursor: pointer + + &.level + overflow: auto + + .level-right + a + padding: 0em .75em + + .highlight-body + overflow: auto + + .gutter + text-align: right + + .tag, .title, .number, .section + display: inherit + font: inherit + margin: inherit + padding: inherit + background: inherit + height: inherit + text-align: inherit + vertical-align: inherit + min-width: inherit + border-radius: inherit + +/* --------------------------------- + * Fix Gist Snippet + * --------------------------------- */ +.gist + table + tr:hover + background: transparent + + td + border: none + + .file + all: initial diff --git a/include/style/donate.styl b/include/style/donate.styl new file mode 100644 index 0000000..82499fa --- /dev/null +++ b/include/style/donate.styl @@ -0,0 +1,34 @@ +/* --------------------------------- + * Donate Buttons + * --------------------------------- */ +$donate-qrcode-max-width ?= 280px +$donate-qrcode-shadow ?= $card-shadow +$donate-qrcode-box-radius ?= $card-radius + +.donate + position: relative + + .qrcode + display: none + position: absolute + z-index: 99 + bottom: 2.5em + line-height: 0 + overflow: hidden + box-shadow: $donate-qrcode-shadow + border-radius: $donate-qrcode-box-radius + + img + max-width: $donate-qrcode-max-width + + &:hover + .qrcode + display: block + + &:first-child:not(:last-child) + .qrcode + left: -.75rem + + &:last-child:not(:first-child) + .qrcode + right: -.75rem diff --git a/include/style/footer.styl b/include/style/footer.styl new file mode 100644 index 0000000..c58431b --- /dev/null +++ b/include/style/footer.styl @@ -0,0 +1,20 @@ +/* --------------------------------- + * Page Footer + * --------------------------------- */ +footer.footer + .level-start + +mobile() + text-align: center + + .level-end + .field + flex-wrap: wrap + align-items: center + + +mobile() + justify-content: center + margin-top: 1rem + +.footer-logo + img + max-height: $logo-height diff --git a/source/css/helper.styl b/include/style/helper.styl similarity index 87% rename from source/css/helper.styl rename to include/style/helper.styl index 7a0c93c..dbc74ff 100644 --- a/source/css/helper.styl +++ b/include/style/helper.styl @@ -4,92 +4,122 @@ $spacer ?= 1rem $spacers ?= 0, $spacer * .25, $spacer * .5, $spacer, $spacer * 1.5, $spacer * 3 -for n in (0..5) +for n in (0 .. 5) .ml-{n} margin-left: $spacers[n] !important + .mr-{n} margin-right: $spacers[n] !important + .mx-{n} @extend .ml-{n}, .mr-{n} + .ml-n{n} margin-left: - $spacers[n] !important + .mr-n{n} margin-right: - $spacers[n] !important + .mx-n{n} @extend .ml-n{n}, .mr-n{n} + .mt-{n} margin-top: $spacers[n] !important + .mb-{n} margin-bottom: $spacers[n] !important + .my-{n} @extend .mt-{n}, .mb-{n} + .mt-n{n} margin-top: - $spacers[n] !important + .mb-n{n} margin-bottom: - $spacers[n] !important + .my-n{n} @extend .mt-n{n}, .mb-n{n} .pl-{n} padding-left: $spacers[n] !important + .pr-{n} padding-right: $spacers[n] !important + .px-{n} @extend .pl-{n}, .pr-{n} + .pl-n{n} padding-left: - $spacers[n] !important + .pr-n{n} padding-right: - $spacers[n] !important + .px-n{n} @extend .pl-n{n}, .pr-n{n} + .pt-{n} padding-top: $spacers[n] !important + .pb-{n} padding-bottom: $spacers[n] !important + .py-{n} @extend .pt-{n}, .pb-{n} + .pt-n{n} padding-top: - $spacers[n] !important + .pb-n{n} padding-bottom: - $spacers[n] !important + .py-n{n} @extend .pt-n{n}, .pb-n{n} .ml-auto margin-left: auto !important + .mr-auto margin-right: auto !important + .mx-auto @extend .ml-auto, .mr-auto + .mt-auto margin-top: auto !important + .mb-auto margin-bottom: auto !important + .my-auto @extend .mt-auto, .mb-auto .pl-auto margin-left: auto !important + .pr-auto margin-right: auto !important + .px-auto @extend .pl-auto, .pr-auto + .pt-auto margin-top: auto !important + .pb-auto margin-bottom: auto !important + .py-auto @extend .pt-auto, .pb-auto - /* --------------------------------- * Flex helpers * --------------------------------- */ -for n in (0..5) +for n in (0 .. 5) .order-{n} order: n !important - .justify-content-start justify-content: start !important @@ -99,16 +129,15 @@ for n in (0..5) .flex-shrink-1 flex-shrink: 1 !important - /* --------------------------------- * Color helpers * --------------------------------- */ .link-muted color: inherit + &:hover color: $primary !important - /* --------------------------------- * Font helpers * --------------------------------- */ @@ -118,15 +147,25 @@ for n in (0..5) .line-height-inherit line-height: inherit !important - /* --------------------------------- * Image helpers * --------------------------------- */ -.image.is-7by3 - padding-top: 42.8% - img - bottom: 0 - left: 0 - position: absolute - right: 0 - top: 0 \ No newline at end of file +.image + &.is-7by3 + padding-top: 42.8% + + img + bottom: 0 + left: 0 + position: absolute + right: 0 + top: 0 + + .avatar + height: 100% + object-fit: cover + + .fill + object-fit: cover + width: 100% !important + height: 100% !important \ No newline at end of file diff --git a/include/style/mystyle/article.styl b/include/style/mystyle/article.styl new file mode 100644 index 0000000..2167e26 --- /dev/null +++ b/include/style/mystyle/article.styl @@ -0,0 +1,56 @@ +/* --------------------------------- + * Article Summary and Content + * --------------------------------- */ +.display-none-class { + display: none; +} + +.index-category-tag { + margin-bottom: 1rem; +} + +.index-category-tag .level-item { + display: unset; +} + +article.article .pin-icon { + color: #3273dc; + font-size: 1.6rem; + margin-right: 20px; + transform: rotate(30deg); + -ms-transform: rotate(30deg); + -moz-transform: rotate(30deg); + -webkit-transform: rotate(30deg); + -o-transform: rotate(30deg); +} + +article.article .article-meta { + height: 41px; +} + +.index-category-tag hr { + background-color: #f5f5f5; + margin-top: .3rem; + margin-bottom: .5rem; + box-shadow: unset; +} + +.index-category-tag .button.is-small { + border-radius: 2px; + margin-bottom: 4px; + background-color: unset; +} + +.index-categories, .index-tags { + padding: 2px; +} + +.recommend-post { + margin: 0 0 1.5rem 0; +} + +.recommend-area { + background: #f5f5f5; + padding: .5rem .5rem; + margin: .5rem 0rem; +} \ No newline at end of file diff --git a/include/style/mystyle/base.styl b/include/style/mystyle/base.styl new file mode 100644 index 0000000..2bb01d3 --- /dev/null +++ b/include/style/mystyle/base.styl @@ -0,0 +1,398 @@ +$family-code ?= "Source Code Pro", monospace, "Microsoft YaHei" +$family-sans-serif1 ?= 'Monda', "PingFang SC", "Microsoft YaHei", sans-serif + +body, button, input, select, textarea { + font-family: $family-sans-serif1 +} + +// 自定义图片样式 +.img-x { + position: relative; + overflow-y: hidden; + height: 100%; + white-space: nowrap; + a { + box-sizing: border-box; + text-align: center; + position: relative; + display: inline-block; + padding: 10px 10px; + vertical-align: top; + height: 100%; + width: 40%; + } +} + +.img-y { + position: relative; + overflow-y: hidden; + height: 100%; + white-space: nowrap; + a { + box-sizing: border-box; + text-align: center; + position: relative; + display: inline-block; + padding: 10px 10px; + vertical-align: top; + height: 100%; + width: 30%; + } +} + +.article hr { + background-color: #6190e8; + margin-top: -0.8rem; + margin-bottom: 1rem; + box-shadow: 1px 2px 8px #000; +} + +.index-category-tag hr { + background-color: #f5f5f5; + margin-top: .3rem; + margin-bottom: .5rem; + box-shadow: unset; +} + +.friend-title-item { + font-weight: bold; + text-align: center; +} + +// 友链 +.friend-card-item { + width: 32%; + border-radius: 2px; + color: #4a4a4a; + padding: 0.5rem; + display: inline-block; + margin: 5px; + margin-top: 15px; + .text-desc { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + .ava { + width: 5rem !important; + height: 5rem !important; + margin: 0 !important; + margin-right: 0.2em !important; + border-radius: 40px; + } + img { + float: left; + transition: all 0.5s ease-in; + -webkit-transition: all 0.5s ease-in; + -moz-transition: all 0.5s ease-in; + -o-transition: all 0.5s ease-in; + } + img:hover { + transform: rotate(360deg); + -webkit-transform: rotate(360deg); + -moz-transform: rotate(360deg); + -o-transform: rotate(360deg); + -ms-transform: rotate(360deg); + } + &:hover { + transform: scale(0.995); + box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.12), 0 0 6px 0 rgba(0, 0, 0, 0.04); + } +} + +.content blockquote { + background-color: #f5f5f5; + border-left: 3px solid #6190e8; + padding: 1em 1em; + overflow: auto; +} + +// about timeline +.time-axis-main { + width: 90%; + margin: 30px auto; + .time-axis { + margin: 0; + padding: 0; + position: relative; + } + + .time-axis:before { + content: ''; + position: absolute; + left: 93px; + top: 15px; + width: 1px; + height: 100%; + background-color: #E4E4E4; + } + + .time-axis-item { + list-style: none; + padding-left: 150px; + position: relative; + line-height: 45px; + font-size: 14px; + color: #141414; + } + + .time-axis-date { + position: absolute; + left: -1.9%; + top: 0; + color: #3273dc; + font-style: italic; + font-weight: bold; + } + + .time-axis-title { + background-color: whitesmoke; + border-left: 3px solid #6190e8; + padding: 0.8em 1.0em; + font-weight: bold; + line-height: 25px; + } + + .time-axis-achievement { + background-color: whitesmoke; + border-left: 3px solid #e89b44; + padding: 0em 1.0em; + font-style: italic; + margin-bottom: 30px; + } + + .time-axis-date span { + position: absolute; + right: -25px; + top: 35%; + display: block; + width: 13px; + height: 13px; + border: 1px solid #ccc; + border-radius: 100%; + background-color: #fff; + } + + .time-axis-date span:after { + content: ''; + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + width: 7px; + height: 7px; + margin: auto; + background-color: #ccc; + border: 1px solid #ccc; + border-radius: 100%; + } + + .time-axis-item:first-child .time-axis-date span { + border-color: #48BEB2; + } + + .time-axis-item:first-child .time-axis-date span:after { + background-color: #48BEB2; + border-color: #48BEB2; + } +} + +.music-container { + .video-player .fa-video-camera:before { + content: "\f03d"; + } + + .video-player .fa-music:before { + content: "\f001"; + } + #musicarea { + margin: 20px auto; + width: 500px; + } + .music-player { + .d-title { + margin-bottom: 20px; + font-size: 2rem; + font-weight: 700; + text-align: center; + } + } +} + +.video-player { + + .d-title { + margin-bottom: 20px; + font-size: 2rem; + font-weight: 700; + text-align: center; + } + + .fa { + display: inline-block; + font: normal normal normal 14px / 1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + } + + .hits { + text-align: center; + font-size: 13px; + color: #cd0411 + } + + #video-list { + overflow-y: auto; + height: 300px; + blockquote { + font-size: 13px; + text-align: center; + border-right: 3px solid #6190e8; + } + } +} + +.text-center { + text-align: center; +} + +.markdown-body { + font-family: $family-sans-serif !important; + img { + max-width: 30% !important; + } +} + +#hitokoto { + text-align: center; + cursor: pointer; + padding: 1rem; +} + +.text-tips { + text-align center; + font-size: 0.875em; +} + +.social-share { + text-align: center; +} + +// 头像翻转 +.level img { + border-radius: 100px; + transition: all 0.5s ease-in; + -webkit-transition: all 0.5s ease-in; + -moz-transition: all 0.5s ease-in; + -o-transition: all 0.5s ease-in; +} + +.level figure img:hover { + transform: rotate(360deg); + -webkit-transform: rotate(360deg); + -moz-transform: rotate(360deg); + -o-transform: rotate(360deg); + -ms-transform: rotate(360deg); +} + +.content .gt-container .gt-comment-edit { + margin-right: 2%; +} + +.content { + a { + img { + margin: auto; + display: block; + } + } +} + +.content .gt-container .gt-comment-admin .gt-comment-content { + border: 0.01em solid #deeafb; +} + +// ============self-talking start +.content .gt-container .gt-comment-header { + font-size: 0.875em; + position: relative; + display: inline-block; + left: -6%; + margin-bottom: 10px; + padding: 0 10% 0 32px; + height: 32px; + line-height: 32px; + border-radius: 0 3px 3px 0; + background-color: #deeafb; +} + +.content .gt-container .gt-comment-content:hover { + -webkit-box-shadow: unset; + box-shadow: unset +} + +.content .gt-container .gt-comment-body { + padding-left: 2%; +} + +.self-talking .gt-comment-reply .gt-ico-reply { + display: none; +} + +.content .gt-container .gt-avatar { + display: none !important; +} + +.article .content .markdown-body a img { + margin-right: 1%; + margin-top: 1%; + display: unset; +} + +.gt-container .gt-comment-content:hover { + -webkit-box-shadow: unset !important; + box-shadow: unset !important; +} + +.toc-scroll { + max-height: 500px; + overflow: auto; +} + +.navbar-highlight { + background-color #fff !important; +} + +.gt-container .gt-comment-owner { + padding: 0.2em 0.2em !important; + margin: 0 0.5em 0 0.5em !important; +} + +hr { + margin: .0rem 0; +} + +.level:not(:last-child) { + margin-bottom: .5rem; +} + +.post-navigation .level { + margin-bottom: 1rem; +} + +.text-right { + text-align: right; +} + +.text-left { + text-align: left; +} + +.font1_1 { + font-size 1.1rem; +} + +// ============self-talking end \ No newline at end of file diff --git a/include/style/mystyle/footer.styl b/include/style/mystyle/footer.styl new file mode 100644 index 0000000..1688a6c --- /dev/null +++ b/include/style/mystyle/footer.styl @@ -0,0 +1,20 @@ +/* --------------------------------- + * Page Footer + * --------------------------------- */ +.aplayer-narrow{ + -webkit-transform: translateX(-100%); + transform: translateX(-100%); +} + +.aplayer-narrow:hover { + -webkit-transform: translateX(0); + transform: translateX(0); +} + +.aplayer{ + transition: all .5s ease-out; +} + +.aplayer .aplayer-miniswitcher { + background: white !important; +} \ No newline at end of file diff --git a/include/style/mystyle/navbar.styl b/include/style/mystyle/navbar.styl new file mode 100644 index 0000000..015e1c6 --- /dev/null +++ b/include/style/mystyle/navbar.styl @@ -0,0 +1,10 @@ +/* --------------------------------- + * Top Navigation + * --------------------------------- */ +.navbar.is-fixed-top { + top: 0; +} + +.navbar.is-fixed-bottom, .navbar.is-fixed-top { + z-index: 100; +} \ No newline at end of file diff --git a/include/style/mystyle/night.styl b/include/style/mystyle/night.styl new file mode 100644 index 0000000..6923cf1 --- /dev/null +++ b/include/style/mystyle/night.styl @@ -0,0 +1,413 @@ +/* --------------------------------- + * Night + * --------------------------------- */ + +// night Mode +// author by removef +// https://removeif.github.io/ +night-color = #151313 +night-color-hover = #7a7a7a +night-link = #3273dc + +.night { + + color: silver !important; + background-color black; + + .aplayer .aplayer-miniswitcher { + background: #c0c0c0 !important; + } + + .navbar-highlight { + background-color night-color !important; + } + .content blockquote { + background-color: night-color + } + .button.is-light { + background-color: night-color; + } + .tag:not(body) { + background-color: night-color; + } + + strong { + color: white; + } + + .time-axis-achievement { + background-color: night-color; + color: white + } + + .time-axis-title { + background-color: night-color; + color: white + } + + .pagination .pagination-link:not(.is-current), .pagination .pagination-previous, .pagination .pagination-next { + background-color: night-color; + } + + .button.is-white { + color: white; + } + + .button.is-light { + color silver + } + + a:hover { + //background-color night-color-hover + color white + } + + hr { + background-color: night-color; + } + + .menu-list a:hover { + background-color: night-color-hover; + color night-link + } + .menu-list a { + color silver + } + + .level a:hover { + //background-color: night-color-hover; + color night-link !important + } + + .level .is-rounded:hover { + color white !important + } + + .level .level-item.is-marginless:hover { + background-color: night-color; + color night-link + } + + .level .level-item.is-link:hover { + color white + } + + //.level .level-item .is-size-7:hover { + // background-color: black; + // color white + //} + + .navbar-menu a:hover { + color: night-link + } + + .post-copyright { + background-color: night-color; + } + + #back-to-top:hover { + color night-link + } + + .tags.has-addons .tag:hover { + color night-link + } + + input { + background-color black + color white + } + + .card { + color silver + } + + .has-text-grey { + color silver !important + } + .has-link-black-ter { + color night-link !important + } + .has-link-grey.-link { + color silver + } + .has-link-grey, .has-link-black-ter { + color silver !important; + } + + .menu-label { + color silver !important; + } + + .tag:not(body) { + color silver + } + + #body_hot_comment .comment-content .item { + color silver + } + + .has-text-black-ter { + color silver !important; + } + + .has-text-black-ter:hover { + color night-link !important + } + + .navbar-item, .navbar-link { + color silver + } + + .title { + color silver + } + + .level-item.tag.is-danger { + background-color night-link !important + color silver + } + + .friend-title-item { + color silver + } + + .music-container #musiclist { + background night-color + } + + .meplayer-container { + background-color night-color + } + + // --removeif + .navbar { + background-color night-color + } + .card { + background-color night-color + } + .footer { + background-color night-color + } + .button.is-white { + background-color night-color + } + .cardm { + background-color night-color + } + .waifu-tips { + background-color night-color + color silver + } + // -- + + .has-link-grey.-link:hover { + color night-link !important + } + .has-link-black-ter:hover { + color night-link !important + } + + .timeline .media:last-child:after { + background-color night-color + } + + .level-item.tag.is-danger, + .button:not(.is-white), #index_hot_div, + #post-calendar canvas, + .waifu canvas, + .is-current, + .button.is-marginless .fab, .fas, + .button.is-large, + .gt-btn, + .gt-comment-body pre, + .time-axis-main, + .meplayer-control-play, + .social-share, + .g-emoji, + .fa-envelope + input, + img { + filter: brightness(.6) !important + } + + figure { + filter: brightness(.7) !important + } + + strong { + filter: brightness(.8) !important; + } + + .content blockquote { + border-left: 3px solid #1e4584; + } + + .timeline { + border-left: 1px solid #dbdbdb70; + .media:before { + background: #dbdbdb70; + } + } + + .post-copyright { + border-left: 3px solid #ff170070; + } + + .button.is-light { + filter: brightness(1) !important; + } + + .breadcrumb li.is-active a { + color silver + } + + .menu-list li ul { + border-left: 1px solid #dbdbdb70; + } + + // comment start + + .markdown-body blockquote { + border-left: 0.25em solid #dfe2e590; + } + + .gt-container .gt-comment-content { + background-color black !important + color silver !important + } + + .gt-container .gt-comment-body { + color silver !important + } + + .gt-container .gt-comment-content:hover { + -webkit-box-shadow: 0 0.625em 3.75em 0 #f4f4f4; + box-shadow: 0 0.625em 3.75em 0 black; + } + + textarea { + background-color night-color; + color white; + } + + .gt-container .gt-header-textarea:hover { + background-color: black; + } + + .gt-container .gt-header-textarea { + background-color: black; + } + .ins-section-container { + background-color: night-color; + color: silver; + } + .searchbox .searchbox-input-wrapper .searchbox-input { + background-color: night-color; + } + .cardm { + color: unset; + } + .g-ads-x { + filter: brightness(0.6) !important; + } + .g-ads-y { + filter: brightness(0.6) !important; + } + .google-auto-placed { + filter: brightness(0.6) !important; + } + + .pagination-previous, .pagination-next, .pagination-link { + color: silver; + } + .pagination .pagination-link a, .pagination .pagination-ellipsis a, .pagination .pagination-previous a, .pagination .pagination-next a { + color: silver; + } + + .content .gt-container .gt-comment-header { + background-color: #151313; + } + .content .gt-container .gt-comment-admin .gt-comment-content { + border: 2px solid #151313; + } + + #post-calendar { + background-color: #626161; + //border-radius: 20rem; + } + .button.is-white, .button.is-transparent { + color: silver; + } + + hr, .index-category-tag hr { + background-color: #989898; + } + + .navbar-menu { + background-color: unset; + } + #index_hot_div { + color: silver; + } + #index_hot_div { + filter: unset !important; + .item { + filter: brightness(0.6) !important; + } + } + .gt-container .gt-meta { + border-bottom: 2px solid #989898; + } + + figure.highlight figcaption * { + color: unset; + } + + figure.highlight figcaption.level .level-right a { + color: silver; + } + + .menu-list .is-current { + color: #3273dc; + background: #7a7a7a; + filter: unset !important; + } + + .friend-card-item { + color: unset; + } + + .g-ads-x, .g-ads-y, .google-auto-placed { + filter: brightness(0.6) !important; + } + .index-category-tag { + .button.is-small { + color: silver; + filter: unset !important; + } + .article-more:hover { + background-color: unset !important; + } + } + + a.navbar-item:focus, .navbar-link:focus, a.navbar-item:focus-within, .navbar-link:focus-within, a.navbar-item:hover, .navbar-link:hover, a.navbar-item.is-active, .navbar-link.is-active { + background-color: unset; + color: #3273dc; + } + + .menu-list a.is-active { + background-color: #7a7a7a; + color: #3273dc; + } + + .recommend-area, .article-licensing { + background: #000; + } + + .article-licensing .licensing-title a { + color: #3273dc !important; + } + +} \ No newline at end of file diff --git a/include/style/mystyle/responsive.styl b/include/style/mystyle/responsive.styl new file mode 100644 index 0000000..f4fd3b0 --- /dev/null +++ b/include/style/mystyle/responsive.styl @@ -0,0 +1,66 @@ +/* --------------------------------- + * Responsive Layout + * --------------------------------- */ ++widescreen() + .is-1-column .container + .is-2-column .container + .is-3-column .container { + /* 关闭评论图片 后调节 原94%*/ + max-width: 85%; /*screen-widescreen + 2 * extend-width - 2 * gap*/ + width: 85%; + } + max-width: $desktop - 2 * $gap + width: $desktop - 2 * $gap + .column.is-3-widescreen { + flex: none; + width: 24%; + } + .column.is-6-widescreen { + width: 52%; + } + .column.is-4-widescreen { + flex: none; + width: 24%; + } + .column.is-8-widescreen { + width: 76%; + } + .column.is-9-widescreen { + width: 76%; + } + //screen-widescreen + 2 * extend-width - 2 * gap + .navbar > .container .navbar-brand, .container > .navbar .navbar-brand { + margin-left: 0%; + } + + .navbar > .container .navbar-menu, .container > .navbar .navbar-menu { + margin-right: 0.5%; + } + + .level-end { + margin-right: -1.5%; + } + ++fullhd() + .is-2-column .container + max-width: $widescreen - 2 * $gap + width: $widescreen - 2 * $gap + + .is-1-column .container + max-width: $desktop - 2 * $gap + width: $desktop - 2 * $gap + ++tablet() + //参考自 https://github.com/ppoffice/hexo-theme-icarus/pull/616/files + .has-navbar-fixed-top + .column-main, + .column-left, + .column-right, + .column-right-shadow + .widget + &.is-sticky + top: 5.5rem; + ++mobile() + .section + padding: 6.5rem 1.5rem diff --git a/include/style/mystyle/widget.styl b/include/style/mystyle/widget.styl new file mode 100644 index 0000000..8f4edeb --- /dev/null +++ b/include/style/mystyle/widget.styl @@ -0,0 +1,142 @@ +/* --------------------------------- + * Widget + * --------------------------------- */ + +.level-item .subtitle, .level-item .title { + margin-bottom: 0; +} + +#hitokoto { + text-align: center; + cursor: pointer; + padding: 1rem; +} + +.level:not(:last-child) { + margin-bottom: .5rem; +} + +hr { + margin: 0 0; +} + +.donate .qrcode img { + max-width: 140px; +} + +// 最新评论CSS +.body_hot_comment .comment-content { + font-size: 0.75em; + letter-spacing: 0.1em; + .card-comment-item { + display: inline-block; + margin-top: 10px; + width: 100%; + .ava { + height: 3rem !important; + margin-right: 0.2em !important; + border-radius: 40px; + } + img { + float: left; + transition: all 0.5s ease-in; + -webkit-transition: all 0.5s ease-in; + -moz-transition: all 0.5s ease-in; + -o-transition: all 0.5s ease-in; + } + + img:hover { + transform: rotate(360deg); + -webkit-transform: rotate(360deg); + -moz-transform: rotate(360deg); + -o-transform: rotate(360deg); + -ms-transform: rotate(360deg); + } + } + :first-child { + margin-top: unset; + } + .item-header-text { + padding-left: 0.75em; + font-size: 0.75rem; + line-height: 1.5; + -webkit-line-clamp: 1; + overflow: hidden; + -webkit-box-orient: vertical; + display: -webkit-box; + + } + .item-text { + padding-left: 0.75em; + font-size: 0.75rem; + line-height: 1.5; + -webkit-line-clamp: 2; + text-overflow: ellipsis; + overflow: hidden; + height: auto; + -webkit-box-orient: vertical; + word-break: break-all; + display: -webkit-box; + white-space: normal; + } +} + +.level0 { + background-color: #d9e6fd; + color: #4a4a4a; +} + +.level1 { + background-color: #8fb8fb; + color: #4a4a4a; +} + +.level2 { + background-color: #5593f7; + color: white; +} + +.level3 { + background-color: #3273dc; + color: white; +} + +#index_hot_div { + margin-top: 10px; + display: flex; + flex-wrap: wrap; + .item { + align-items: center; + border-radius: 4px; + display: inline-flex; + font-size: 0.75rem; + height: 2.1rem; + justify-content: center; + line-height: 1.5; + padding-left: 0.5rem; + padding-right: 0.5rem; + white-space: nowrap; + margin-bottom: 0.75rem; + box-shadow: 0px 0px 2px 1px #b5b5b5; + } + +} + +// 归档 +.post-calendar-pre { + overflow-x: auto; + justify-content: center; + max-width: 100%; +} + +#post-calendar { + display: flex; + justify-context: center; + align-items: center; + left: 0px; + top: 0px; + width: 100%; + height: 200px; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + margin-bottom: 2rem; +} diff --git a/include/style/navbar.styl b/include/style/navbar.styl new file mode 100644 index 0000000..a11191c --- /dev/null +++ b/include/style/navbar.styl @@ -0,0 +1,53 @@ +/* --------------------------------- + * Top Navigation + * --------------------------------- */ +$navbar-item-padding-v ?= 1.25rem +$navbar-item-padding-h ?= .75rem +$navbar-item-margin-v ?= 0 +$navbar-item-margin-h ?= 0 + +.navbar-main + box-shadow: $shadow + + .navbar-menu, .navbar-start, .navbar-end + align-items: stretch + display: flex + padding: 0 + flex-shrink: 0 + + .navbar-menu + flex-grow: 1 + flex-shrink: 0 + overflow-x: auto + + .navbar-start + justify-content: flex-start + margin-right: auto + + .navbar-end + justify-content: flex-end + margin-left: auto + + .navbar-item + display: flex + align-items: center + padding: $navbar-item-padding-v $navbar-item-padding-h + margin: $navbar-item-margin-v $navbar-item-margin-h + + &.is-active + background-color: transparent + + +until($navbar-breakpoint) + .navbar-menu + justify-content: center + box-shadow: none + + .navbar-start + margin-right: 0 + + .navbar-end + margin-left: 0 + +.navbar-logo + img + max-height: $logo-height \ No newline at end of file diff --git a/include/style/pagination.styl b/include/style/pagination.styl new file mode 100644 index 0000000..28428c7 --- /dev/null +++ b/include/style/pagination.styl @@ -0,0 +1,29 @@ +/* --------------------------------- + * Pagination and Post Navigation + * --------------------------------- */ +$pagination-box-shadow ?= $card-shadow +$pagination-background-color ?= $button-background-color +$post-navigation-fg ?= $grey + +.pagination + .pagination-link, + .pagination-ellipsis, + .pagination-previous, + .pagination-next + a + color: $pagination-color + .pagination-link, + .pagination-previous, + .pagination-next + border: none + background: $pagination-background-color + box-shadow: $pagination-box-shadow + .pagination-link.is-current + background: $pagination-current-background-color + +.post-navigation + color: $post-navigation-fg + flex-wrap: wrap + justify-content: space-around + .level-item + margin-bottom: 0 diff --git a/include/style/plugin.styl b/include/style/plugin.styl new file mode 100644 index 0000000..47c59ac --- /dev/null +++ b/include/style/plugin.styl @@ -0,0 +1,111 @@ +/* --------------------------------- + * Back to Top Button + * --------------------------------- */ +#back-to-top + position: fixed + opacity: 0 + outline: none + padding: 8px 0 + line-height: 24px + border-radius: $card-radius + transform: translateY(120px) + transition: .4s ease opacity, .4s ease width, .4s ease transform, .4s ease border-radius + + &.is-rounded + border-radius: 50% + + &.fade-in + opacity: 1 + + &.rise-up + transform: translateY(0) + +/* --------------------------------- + * Gallery Plugin + * --------------------------------- */ +.gallery-item + .caption + color: $grey + +/* --------------------------------- + * Table of Content Widget + * --------------------------------- */ ++mobile() + #toc + display: none + position: fixed + margin: 1rem + left: 0 + right: 0 + bottom: 0 + z-index: 100 + max-height: calc(100vh - 2rem) + overflow-y: auto + + #toc-mask + display: none + position: fixed + top: 0 + left: 0 + right: 0 + bottom: 0 + z-index: 99 + background: rgba(0, 0, 0, .7) + + #toc, #toc-mask + &.is-active + display: block + +/* --------------------------------- + * Page Loading Progressbar + * --------------------------------- */ +.pace + user-select: none + pointer-events: none + + .pace-progress + top: 0 + right: 100% + width: 100% + height: 2px + z-index: 2000 + position: fixed + background: $primary + +.pace-inactive + display: none + +/* --------------------------------- + * Fix FontAwesome Icons + * --------------------------------- */ +.fa, .fab, .fal, .far, .fas + line-height: inherit + +/* --------------------------------- + * MathJax and KaTeX + * --------------------------------- */ +.MathJax, .katex-display + overflow-x: auto + overflow-y: hidden + +.katex + white-space: nowrap + +.katex-display + margin-top: -1em !important + +.katex-html + padding-top: 1em + .tag + align-items: unset + background-color: unset + border-radius: unset + color: unset + display: unset + font-size: unset + height: unset + justify-content: unset + line-height: unset + padding-left: unset + padding-right: unset + white-space: unset \ No newline at end of file diff --git a/include/style/responsive.styl b/include/style/responsive.styl new file mode 100644 index 0000000..ad6be4d --- /dev/null +++ b/include/style/responsive.styl @@ -0,0 +1,32 @@ +/* --------------------------------- + * Responsive Layout + * --------------------------------- */ ++widescreen() + .is-1-column .container, .is-2-column .container + max-width: $desktop - 2 * $gap + width: $desktop - 2 * $gap + ++fullhd() + .is-2-column .container + max-width: $widescreen - 2 * $gap + width: $widescreen - 2 * $gap + + .is-1-column .container + max-width: $desktop - 2 * $gap + width: $desktop - 2 * $gap + ++tablet() + .is-sticky + position: -webkit-sticky + position: sticky + top: 1.5rem + z-index: 99 + + .column-main, .column-left, .column-right, .column-right-shadow + &.is-sticky + top: .75rem + align-self: flex-start + ++mobile() + .section + padding: 1.5rem 1rem diff --git a/include/style/search.styl b/include/style/search.styl new file mode 100644 index 0000000..0cdedd9 --- /dev/null +++ b/include/style/search.styl @@ -0,0 +1,204 @@ +/* --------------------------------- + * Search Box + * --------------------------------- */ +// container sizes +$searchbox-container-width ?= 540px +$searchbox-container-margin ?= 100px +$searchbox-breakpoint-width ?= 559px +$searchbox-breakpoint-height ?= 479px +// overlay and container styles +$searchbox-box-shadow ?= $card-shadow +$searchbox-border-radius ?= $radius +$searchbox-bg-overlay ?= $modal-background-background-color +$searchbox-bg-container ?= $white-ter +$searchbox-border ?= $border +// header styles +$searchbox-bg-input ?= $white +$searchbox-bg-close-hover ?= $searchbox-bg-container +$searchbox-bg-close-active ?= $grey-lighter +// body styles +$searchbox-fg-result-header ?= $grey-light +$searchbox-fg-result-item-secondary ?= $grey-light +$searchbox-bg-result-item-hover ?= $searchbox-bg-input +$searchbox-fg-result-item-active ?= findColorInvert($primary) +$searchbox-bg-result-item-active ?= $primary +$searchbox-bg-result-item-highlight ?= $yellow +// footer styles +$searchbox-bg-pagination-item ?= $searchbox-bg-input +$searchbox-bg-pagination-item-hover ?= $searchbox-bg-container +$searchbox-fg-pagination-item-active ?= findColorInvert($primary) +$searchbox-bg-pagination-item-active ?= $primary +$searchbox-bg-pagination-item-disabled ?= $searchbox-bg-container + +.searchbox + display: none + top: 0 + left: 0 + width: 100% + height: 100% + z-index: 100 + font-size: 1rem + line-height: 0 + background: $searchbox-bg-overlay + + &.show + display: flex + + a, a:hover + color: inherit + text-decoration: none + + input + font-size: 1rem + border: none + outline: none + box-shadow: none + border-radius: 0 + + &, .searchbox-container + position: fixed + align-items: center + flex-direction: column + line-height: 1.25em + + .searchbox-container + z-index: 101 + display: flex + overflow: hidden + box-shadow: $searchbox-box-shadow + border-radius: $searchbox-border-radius + background-color: $searchbox-bg-container + width: $searchbox-container-width + top: $searchbox-container-margin + bottom: $searchbox-container-margin + + .searchbox-header, .searchbox-body, .searchbox-footer + width: 100% + + .searchbox-header + display: flex + flex-direction: row + line-height: 1.5em + font-weight: normal + background-color: $searchbox-bg-input + // fix Chrome 71 height issue + // https://github.com/ppoffice/hexo-theme-icarus/issues/719 + min-height: 3rem + + .searchbox-input-container + display: flex + flex-grow: 1 + + .searchbox-input + flex-grow: 1 + color: inherit + box-sizing: border-box + padding: .75em 0 .75em 1.25em + background: $searchbox-bg-input + + .searchbox-close + display: inline-block + font-size: 1.5em + padding: .5em .75em + cursor: pointer + + &:hover + background: $searchbox-bg-close-hover + + &:active + background: $searchbox-bg-close-active + + .searchbox-body + flex-grow: 1 + overflow-y: auto + border-top: 1px solid $searchbox-border + + .searchbox-result-section header, .searchbox-result-item + padding: .75em 1em + + .searchbox-result-section + border-bottom: 1px solid $searchbox-border + + header + color: $searchbox-fg-result-header + + .searchbox-result-item + display: flex + flex-direction: row + + &:not(.disabled):not(.active):not(:active):hover + background-color: $searchbox-bg-result-item-hover + + &:active, &.active + color: $searchbox-fg-result-item-active + background-color: $searchbox-bg-result-item-active + + em + font-style: normal + background: $searchbox-bg-result-item-highlight + + .searchbox-result-icon + margin-right: 1em + + .searchbox-result-content + overflow: hidden + + .searchbox-result-title, .searchbox-result-preview + display: block + overflow: hidden + white-space: nowrap + text-overflow: ellipsis + + .searchbox-result-title-secondary + color: $searchbox-fg-result-item-secondary + + .searchbox-result-preview + margin-top: .25em + + .searchbox-result-item:not(:active):not(.active) + .searchbox-result-preview + color: $searchbox-fg-result-item-secondary + + .searchbox-footer + padding: .5em 1em + + .searchbox-pagination + margin: 0 + padding: 0 + list-style: none + text-align: center + + .searchbox-pagination-item + margin: 0 .25rem + + .searchbox-pagination-item, .searchbox-pagination-link + display: inline-block + + .searchbox-pagination-link + overflow: hidden + padding: .5em .8em + box-shadow: $searchbox-box-shadow + border-radius: $searchbox-border-radius + background-color: $searchbox-bg-pagination-item + + .searchbox-pagination-item.active + .searchbox-pagination-link + color: $searchbox-fg-pagination-item-active + background-color: $searchbox-bg-pagination-item-active + + .searchbox-pagination-item.disabled + .searchbox-pagination-link + cursor: not-allowed + background-color: $searchbox-bg-pagination-item-disabled + + .searchbox-pagination-item:not(.active):not(.disabled) + .searchbox-pagination-link:hover + background-color: $searchbox-bg-pagination-item-hover + +@media screen and (max-width: $searchbox-breakpoint-width), screen and (max-height: $searchbox-breakpoint-height) + .searchbox .searchbox-container + top: 0 + left: 0 + width: 100% + height: 100% + border-radius: 0 diff --git a/include/style/timeline.styl b/include/style/timeline.styl new file mode 100644 index 0000000..1d00f94 --- /dev/null +++ b/include/style/timeline.styl @@ -0,0 +1,38 @@ +/* --------------------------------- + * Archive Timeline + * --------------------------------- */ +$timeline-fg-line ?= $grey-lighter +$timeline-bg-line ?= $card-background-color + +.timeline + margin-left: 1rem + padding: 1rem 0 0 1.5rem + border-left: 1px solid $timeline-fg-line + + .media + position: relative + + &:before, &:last-child:after + content: '' + display: block + position: absolute + left: calc(-.375rem - 1.5rem - .25px) + + &:before + width: .75rem + height: .75rem + top: calc(1rem + 1.5 * .85rem / 2 - .75rem / 2) + background: $timeline-fg-line + border-radius: 50% + + &:first-child:before + top: calc(1.5 * .85rem / 2 - .75rem / 2) + + &:last-child:after + width: .75rem + top: calc(1rem + 1.5 * .85rem / 2 + .75rem / 2) + bottom: 0 + background: $timeline-bg-line + + &:first-child:last-child:after + top: calc(1.5 * .85rem / 2 + .75rem / 2) diff --git a/include/util/migrate.js b/include/util/migrate.js deleted file mode 100644 index d19e6a6..0000000 --- a/include/util/migrate.js +++ /dev/null @@ -1,110 +0,0 @@ -const path = require('path'); -const logger = require('hexo-log')(); - -class Version { - constructor(version) { - const ver = version.split('.').map(i => parseInt(i, 10)); - if (ver.length !== 3) { - throw new Error('Malformed version number ' + version); - } - this.major = ver[0]; - this.minor = ver[1]; - this.patch = ver[2]; - } - - toString() { - return `${this.major}.${this.minor}.${this.patch}`; - } -} - -Version.compare = function(a, b) { - if (!(a instanceof Version) || !(b instanceof Version)) { - throw new Error('Cannot compare non-Versions'); - } - if (a.major !== b.major) { - return a.major - b.major; - } - if (a.minor !== b.minor) { - return a.minor - b.minor; - } - if (a.patch !== b.patch) { - return a.patch - b.patch; - } - return 0; -}; - -class Migration { - - /** - * @param {string} version Target version - * @param {string} head File name of the previous migration - */ - constructor(version, head) { - this.version = new Version(version); - this.head = head; - } - - doMigrate(config) { - throw new Error('Not implemented!'); - } - - migrate(config) { - logger.info(`Updating configurations from ${config.version} to ${this.version.toString()}...`); - const result = this.doMigrate(config); - result.version = this.version.toString(); - return result; - } -} - - -class Migrator { - constructor(root) { - this.versions = []; - this.migrations = {}; - - let head = 'head'; - while (head) { - const migration = new(require(path.join(root, head)))(); - if (!(migration instanceof Migration)) { - throw new Error(`Migration ${head} is not a Migration class.`); - } - this.versions.push(migration.version); - this.migrations[migration.version.toString()] = migration; - head = migration.head; - } - - this.versions.sort(Version.compare); - } - - isOudated(version) { - if (!this.versions.length) { - return false; - } - return Version.compare(new Version(version), this.getLatestVersion()) < 0; - } - - getLatestVersion() { - if (!this.versions.length) { - return null; - } - return this.versions[this.versions.length - 1]; - } - - migrate(config, toVersion = null) { - const fVer = new Version(config.version); - const tVer = toVersion ? new Version(toVersion) : this.getLatestVersion(); - // find all migrations whose version is larger than fromVer, smaller or equal to toVer - // and run migrations on the config one by one - return this.versions.filter(ver => Version.compare(ver, fVer) > 0 && Version.compare(ver, tVer) <= 0) - .sort(Version.compare) - .reduce((cfg, ver) => { - const migration = this.migrations[ver.toString()]; - return migration.migrate(cfg); - }, config); - } -} - -Migrator.Version = Version; -Migrator.Migration = Migration; - -module.exports = Migrator; diff --git a/include/util/schema.js b/include/util/schema.js deleted file mode 100644 index 4028b6f..0000000 --- a/include/util/schema.js +++ /dev/null @@ -1,520 +0,0 @@ -/** - * Configuration and validation. - * @module core/schema - */ -const Ajv = require('ajv'); -const path = require('path'); -const yaml = require('../util/yaml'); - -/** - * A magic string for reformating comment lines in the YAML output. - */ -const MAGIC = 'c823d4d4'; - -/** - * Default value for the primitive types. - * @access private - */ -const PRIMITIVE_DEFAULTS = { - 'null': null, - 'boolean': false, - 'number': 0, - 'integer': 0, - 'string': '', - 'array': [], - 'object': {} -}; - -const typeOf = value => { - return value === undefined - ? 'undefined' - : Object.prototype.toString.call(value) - .replace(/^\[object\s+([a-z]+)\]$/i, '$1') - .toLowerCase(); -}; - -const hasOwnProperty = (obj, prop) => { - return obj === null || typeOf(obj) === 'undefined' - ? false - : Object.prototype.hasOwnProperty.call(obj, prop); -}; - -function traverseObj(obj, targetKey, handler) { - if (typeOf(obj) === 'array') { - for (const child of obj) { - traverseObj(child, targetKey, handler); - } - } else if (typeOf(obj) === 'object') { - for (const key in obj) { - if (key === targetKey) { - handler(obj[key]); - } else { - traverseObj(obj[key], targetKey, handler); - } - } - } -} - -/** - * The default value wrapper class. - */ -class DefaultValue { - - /** - * @param {any} value The wrapped default value. - * @param {string} description A description of the contained value. Used to produce - * the comment string. - */ - constructor(value, description) { - this.value = value; - this.description = description; - } - - /** - * Duplicate the current default value. - *

- * Wrapped value will be shallow copied. - * - * @returns {module:core/schema~DefaultValue} A new instance of the current default value. - */ - clone() { - const result = new DefaultValue(this.value, this.description); - if (result.value instanceof DefaultValue) { - result.value = result.value.clone(); - } else if (typeOf(result.value) === 'array') { - result.value = [].concat(result.value); - } else if (typeOf(result.value) === 'object') { - result.value = Object.assign({}, result.value); - } - return result; - } - - /** - * Unwrap current {module:core/schema~DefaultValue} if its wrapped value is also a - * {module:core/schema~DefaultValue}. - *

- * The description will also be replaced with wrapped value description, if exists. - */ - flatten() { - if (this.value instanceof DefaultValue) { - this.value.flatten(); - if (hasOwnProperty(this.value, 'description') && this.value.description) { - this.description = this.value.description; - } - this.value = this.value.value; - } - } - - /** - * Merge current default value with another default value. - * - * @param {module:core/schema~DefaultValue} source The input object to be merged with. Should have the - * same wrapped value type as current wrapped default value. - */ - merge(source) { - if (hasOwnProperty(source, 'value') && source.value !== null) { - this.flatten(); - if (source.value instanceof DefaultValue) { - source = source.clone(); - source.flatten(); - } - if (typeOf(source.value) === typeOf(this.value)) { - if (typeOf(this.value) === 'array') { - this.value = this.value.concat(source.value); - } else if (typeOf(this.value) === 'object') { - Object.keys(source.value).forEach(key => { this.value[key] = source.value[key]; }); - } else { - this.value = source.value; - } - } else if (typeOf(this.value) === 'undefined' || typeOf(this.value) === 'null') { - this.value = source.value; - } - } - if (hasOwnProperty(source, 'description') && source.description) { - this.description = source.description; - } - } - - /** - * Create a new array with comments inserted as new elements right before each child element. - *

- * If current wrapped value is an array and some of its elements are instances of - * {@link module:core/schema~DefaultValue}, the element's description will be inserted as a new child - * right before the element. - * The element itself will also be converted into its commented version using the toCommented - * method. - * - * @returns {Array} A new array with comments and the original elements in the commented form. - */ - toCommentedArray() { - return [].concat(...this.value.map(item => { - if (item instanceof DefaultValue) { - if (typeOf(item.description) !== 'string' || !item.description.trim()) { - return [item.toCommented()]; - } - return item.description.split('\n').map((line, i) => { - return MAGIC + i + ': ' + line; - }).concat(item.toCommented()); - } else if (typeOf(item) === 'array' || typeOf(item) === 'object') { - return new DefaultValue(item).toCommented(); - } - return [item]; - })); - } - - /** - * Create a new object with comments inserted as new properties right before every original properties. - *

- * Works similar to {@link module:core/schema~DefaultValue#toCommentedArray}. - * - * @returns {Object} A new object with comments and the original property values in the commented form. - */ - toCommentedObject() { - if (this.value instanceof DefaultValue) { - return this.value.toCommented(); - } - const result = {}; - for (const key in this.value) { - const item = this.value[key]; - if (item instanceof DefaultValue) { - if (typeOf(item.description) === 'string' && item.description.trim()) { - item.description.split('\n').forEach((line, i) => { - result[MAGIC + key + i] = line; - }); - } - result[key] = item.toCommented(); - } else if (typeOf(item) === 'array' || typeOf(item) === 'object') { - result[key] = new DefaultValue(item).toCommented(); - } else { - result[key] = item; - } - } - return result; - } - - /** - * Call {@link module:core/schema~DefaultValue#toCommentedArray} or - * {@link module:core/schema~DefaultValue#toCommentedObject} based on the type of the wrapped value. - *

- * If neither applies, directly return the wrapped value. - * - * @returns {any} The commented object/array, or the original wrapped value. - */ - toCommented() { - if (typeOf(this.value) === 'array') { - return this.toCommentedArray(); - } else if (typeOf(this.value) === 'object') { - return this.toCommentedObject(); - } - return this.value; - } - - /** - * Create the YAML string with all the comments from current default value. - * - * @returns {string} The formatted YAML string. - */ - toYaml() { - const regex = new RegExp('^(\\s*)(?:-\\s*\\\')?' + MAGIC + '.*?:\\s*\\\'?(.*?)\\\'*$', 'mg'); - return yaml.stringify(this.toCommented()).replace(regex, '$1# $2');// restore comments - } -} - -/* eslint-disable no-use-before-define */ -/** - * A class that can resolving referenced JSON schemas and create {@link module:core/schema~DefaultValue}s. - */ -class Schema { - - /** - * @param {module:core/schema~SchemaLoader} loader JSON schema loader. - * @param {Object} def The JSON schema definition. - */ - constructor(loader, def) { - if (!(loader instanceof SchemaLoader)) { - throw new Error('loader must be an instance of SchemaLoader'); - } - if (typeOf(def) !== 'object') { - throw new Error('schema definition must be an object'); - } - this.loader = loader; - this.def = def; - this.compiledSchema = null; - } - - /** - * Validate an object against the JSON schema. - * - * @param {any} obj Object to be validated. - * @returns {boolean|Object} True if Object is valid, or validation errors. - */ - validate(obj) { - if (!this.compiledSchema) { - this.compiledSchema = this.loader.compileValidator(this.def.$id); - } - return this.compiledSchema(obj) ? true : this.compiledSchema.errors; - } - - /** - * Create the {@link module:core/schema~DefaultValue} for an array-typed JSON schema. - *

- * Each possible type of the array elements defined in oneOf will be processed and a - * {@link module:core/schema~DefaultValue} will be added to the result array. - * - * @param {Object} def JSON schema definition of the array. - * @returns {@link module:core/schema~DefaultValue} The {@link module:core/schema~DefaultValue} for the - * array definition. - */ - getArrayDefaultValue(def) { - const defaultValue = new DefaultValue(null, def.description); - // all array elements have the same type, return the default value for that type - if (typeOf(def.items) === 'object') { - const items = Object.assign({}, def.items); - delete items.oneOf; - let value = this.getDefaultValue(items); - // additionally, if each array element can be in one of the provided types in oneOf - if (typeOf(def.items.oneOf) === 'array') { - // for each oneOf element, return a {@link module:core/schema~DefaultValue} - defaultValue.value = def.items.oneOf.map(one => { - // if the items definition also exists, merge it with the oneOf - // {@link module:core/schema~DefaultValue} - const clone = value.clone(); - clone.merge(this.getDefaultValue(one)); - return clone; - }); - } else { - if (typeOf(value) !== 'array') { - value = [value]; - } - defaultValue.value = value; - } - } - return defaultValue; - } - - /** - * Create the {@link module:core/schema~DefaultValue} for an object-typed JSON schema. - *

- * The first possible type of the object element defined in oneOf will be processed and its - * {@link module:core/schema~DefaultValue} will be merged with the {@link module:core/schema~DefaultValue} - * created from the properties definition. - * - * @param {Object} def JSON schema definition of the object. - * @returns {@link module:core/schema~DefaultValue} The {@link module:core/schema~DefaultValue} for the - * object definition. - */ - getObjectDefaultValue(def) { - const value = {}; - if (typeOf(def.properties) === 'object') { - for (const property in def.properties) { - value[property] = this.getDefaultValue(def.properties[property]); - } - } - const defaultValue = new DefaultValue(value, def.description); - // only the first one of the possible types will be merged with {@link module:core/schema~DefaultValue} - // for the properties definition. - if (typeOf(def.oneOf) === 'array' && def.oneOf.length) { - defaultValue.merge(this.getDefaultValue(def.oneOf[0])); - defaultValue.description = def.description; - } - return defaultValue; - } - - /** - * Create the {@link module:core/schema~DefaultValue} for any typed JSON schema that is not purely defined - * by its $ref. - *

- * If the definition also contains a $ref, the {@link module:core/schema~DefaultValue} for the - * $ref definition will be merged to the {@link module:core/schema~DefaultValue} of the current - * definition. - *

- * If type of the JSON schema is of primitive types, and the nullable is set to - * false in the schema definition, primitive default values will be set insided the result - * {@link module:core/schema~DefaultValue}. - * - * @param {Object} def JSON schema definition. - * @returns {@link module:core/schema~DefaultValue} The {@link module:core/schema~DefaultValue} for the - * definition. - * @throws {Error} If type is undefined or it is 'array', 'object', or primitive types. - */ - getTypedDefaultValue(def) { - let defaultValue; - const type = typeOf(def.type) === 'array' ? def.type[0] : def.type; - if (type === 'array') { - defaultValue = this.getArrayDefaultValue(def); - } else if (type === 'object') { - defaultValue = this.getObjectDefaultValue(def); - } else if (hasOwnProperty(PRIMITIVE_DEFAULTS, type)) { - if (hasOwnProperty(def, 'nullable') && def.nullable) { - defaultValue = new DefaultValue(null, def.description); - } else { - defaultValue = new DefaultValue(PRIMITIVE_DEFAULTS[type], def.description); - } - } else { - throw new Error(`Cannot get default value for type ${type}`); - } - // referred default value always get overwritten by its parent default value - if (hasOwnProperty(def, '$ref') && def.$ref) { - const refDefaultValue = this.getReferredDefaultValue(def); - refDefaultValue.merge(defaultValue); - defaultValue = refDefaultValue; - } - return defaultValue; - } - - /** - * Create the {@link module:core/schema~DefaultValue} for any JSON schema that is purely defined by its - * $ref. - * - * @param {Object} def JSON schema definition. - * @returns {@link module:core/schema~DefaultValue} The {@link module:core/schema~DefaultValue} for the - * definition. - */ - getReferredDefaultValue(def) { - const schema = this.loader.getSchema(def.$ref); - if (!schema) { - throw new Error(`Schema ${def.$ref} is not loaded`); - } - const defaultValue = this.getDefaultValue(schema.def); - defaultValue.merge({ description: def.description }); - return defaultValue; - } - - /** - * Create the {@link module:core/schema~DefaultValue} for any JSON schema. - * - * @param {Object} def JSON schema definition. - * @returns {@link module:core/schema~DefaultValue} The {@link module:core/schema~DefaultValue} for the - * definition. - */ - getDefaultValue(def = null) { - if (!def) { - def = this.def; - } - if (hasOwnProperty(def, 'const')) { - return new DefaultValue(def.const, def.description); - } - if (hasOwnProperty(def, 'default')) { - return new DefaultValue(def.default, def.description); - } - if (hasOwnProperty(def, 'examples') && typeOf(def.examples) === 'array' && def.examples.length) { - return new DefaultValue(def.examples[0], def.description); - } - if (hasOwnProperty(def, 'type') && def.type) { - return this.getTypedDefaultValue(def); - } - // $ref only schemas - if (hasOwnProperty(def, '$ref') && def.$ref) { - return this.getReferredDefaultValue(def); - } - throw new Error('The following schema definition must have at least one of the ' - + '["const", "default", "examples", "type", "$ref"] fields:\n' - + JSON.stringify(def, null, 2)); - } -} - -/** - * Class for loading JSON schema files from filesystems and creating validator. - */ -class SchemaLoader { - constructor() { - this.schemas = {}; - this.ajv = new Ajv({ nullable: true }); - } - - /** - * Get JSON schema definition by its $id. - * - * @param {string} $id JSON schema $id. - * @returns {Object} JSON schema definition. - */ - getSchema($id) { - return this.schemas[$id]; - } - - /** - * Add a JSON schema definition to the collection. - * - * @param {Object} JSON schema definition. - * @throws {Error} If JSON schema definition does not have an $id. - */ - addSchema(def) { - if (!hasOwnProperty(def, '$id')) { - throw new Error('The schema definition does not have an $id field'); - } - this.ajv.addSchema(def); - this.schemas[def.$id] = new Schema(this, def); - } - - /** - * Remove a JSON schema definition to the collection. - * - * @param {string} $id JSON schema $id. - */ - removeSchema($id) { - this.ajv.removeSchema($id); - delete this.schemas[$id]; - } - - /** - * Create a JSON schema validation function for a given schema identified by its $id. - * - * @param {*} $id $id JSON schema $id. - * @returns {Function} JSON schema validation function. - */ - compileValidator($id) { - return this.ajv.compile(this.getSchema($id).def); - } -} - -/** - * Create a {@link module:core/schema~SchemaLoader} and load all referred JSON schema from the resolve - * directories. - * - * @param {Object} rootSchemaDef The root JSON schema definition. - * @param {Array} resolveDirs Additional directories for resolving referred JSON schemas besides the - * lib/schema folder in this library. Directory order matters. - * @returns {@link module:core/schema~SchemaLoader} The schema loader with all referred schemas loaded. - * @throws {Error} Referred schema not found in any of the resolve directories. - */ -SchemaLoader.load = (rootSchemaDef, resolveDirs = []) => { - if (typeOf(resolveDirs) !== 'array') { - resolveDirs = [resolveDirs]; - } - resolveDirs.push(path.join(__dirname, '../schema/')); - - const loader = new SchemaLoader(); - loader.addSchema(rootSchemaDef); - - function handler($ref) { - if (loader.getSchema($ref)) { - return; - } - for (const dir of resolveDirs) { - let def; - try { - def = require(path.join(dir, $ref)); - } catch (e) { - continue; - } - if (typeOf(def) !== 'object' || def.$id !== $ref) { - continue; - } - loader.addSchema(def); - traverseObj(def, '$ref', handler); - return; - } - throw new Error('Cannot find schema definition ' + $ref + '.\n' - + 'Please check if the file exists and its $id is correct'); - } - - traverseObj(rootSchemaDef, '$ref', handler); - return loader; -}; - -module.exports = { - MAGIC, - Schema, - SchemaLoader, - DefaultValue -}; \ No newline at end of file diff --git a/include/util/yaml.js b/include/util/yaml.js deleted file mode 100644 index 8a7050c..0000000 --- a/include/util/yaml.js +++ /dev/null @@ -1,43 +0,0 @@ -const yaml = require('js-yaml'); -const YamlType = require('js-yaml/lib/js-yaml/type'); -const YamlSchema = require('js-yaml/lib/js-yaml/schema'); - -// output null as empty in yaml -const YAML_SCHEMA = new YamlSchema({ - include: [ - require('js-yaml/lib/js-yaml/schema/default_full') - ], - implicit: [ - new YamlType('tag:yaml.org,2002:null', { - kind: 'scalar', - resolve(data) { - if (data === null) { - return true; - } - const max = data.length; - return (max === 1 && data === '~') - || (max === 4 && (data === 'null' || data === 'Null' || data === 'NULL')); - }, - construct: () => null, - predicate: object => object === null, - represent: { - empty: () => '' - }, - defaultStyle: 'empty' - }) - ] -}); - -module.exports = { - parse(str) { - return yaml.safeLoad(str); - }, - - stringify(object) { - return yaml.safeDump(object, { - indent: 4, - lineWidth: 1024, - schema: YAML_SCHEMA - }); - } -}; diff --git a/languages/de.yml b/languages/de.yml index ce20b1b..09aecfb 100644 --- a/languages/de.yml +++ b/languages/de.yml @@ -9,42 +9,50 @@ common: one: 'Tag' other: 'Tags' post: - one: 'Post' - other: 'Posts' + one: 'Seite' + other: 'Seiten' + page: + one: 'Page' + other: 'Pages' prev: 'Zurück' next: 'Weiter' widget: follow: 'Folgen' recents: 'Letzte Einträge' links: 'Links' - tag_cloud: 'Tag Cloud' catalogue: 'Katalog' - email: - title: 'Abonnieren (Email)' - button: 'Abonnieren' + subscribe_email: 'Abonnieren Sie Updates' + subscribe: 'Abonnieren' + adsense: 'Werbung' article: + created_at: 'Gepostet vor %s' + updated_at: 'Aktualisiert vor %s' more: 'Mehr lesen' comments: 'Kommentare' - read: 'lesen' - about: 'Über' - words: 'Worte' + read_time: '%s lesen' + word_count: + one: 'Über %d Wort' + other: 'Über %d Wörter' + licensing: + author: 'Author' + created_at: 'Posted on' + updated_at: 'Updated on' + licensed_under: 'Licensed under' donate: title: 'Gefällt Ihnen der Artikel? Unterstützen Sie den Autor mit' + afdian: 'Afdian.net' alipay: 'Alipay' wechat: 'Wechat' paypal: 'Paypal' patreon: 'Patreon' + buymeacoffee: 'Kauf mir einen Kaffee' plugin: backtotop: 'Zurück nach oben' - visit: '%s Besuche' - visitor: 'Von %s Nutzern besucht' + visit_count: '%s Besuche' + visitor_count: 'Von %s Nutzern besucht' search: search: 'Suche' hint: 'Tippen Sie etwas...' -insight: - hint: 'Tippen Sie etwas...' - posts: 'Posts' - pages: 'Seiten' - categories: 'Kategorien' - tags: 'Tags' - untitled: '(Unbenannt)' + no_result: 'Keine Ergebnisse für' + untitled: '(Ohne Titel)' + empty_preview: '(Keine Vorschau)' diff --git a/languages/en.yml b/languages/en.yml index 2c9cbc4..ea75052 100644 --- a/languages/en.yml +++ b/languages/en.yml @@ -11,15 +11,17 @@ common: post: one: 'Post' other: 'Posts' + page: + one: 'Page' + other: 'Pages' prev: 'Previous' next: 'Next' widget: follow: 'Follow' - recents: 'Recent' + recents: 'Recents' links: 'Links' - tag_cloud: 'Tag Cloud' catalogue: 'Catalogue' - subscribe_email: 'Subscribe to Updates' + subscribe_email: 'Subscribe for updates' subscribe: 'Subscribe' adsense: 'Advertisement' recommend_posts: 'Recommend Post' @@ -31,31 +33,35 @@ widget: hitokoto_from: 'From' hitokoto_provider: 'Provider' notice: 'Notice' - article: - more: 'Read More' + created_at: 'Posted %s' + updated_at: 'Updated %s' + more: 'Read more>>' comments: 'Comments' + read_time: '%s read' + last_modified: 'Last Modified:' comments_closed: 'This page’s comment has closed,it’s can’t comment.' comments_language: 'en' - read: 'read' - about: 'About' - words: 'words' - last_modified: 'Last Modified:' - copyright: - title: 'Post Title: ' - author: 'Post Author: ' - link: 'Post Link: ' - copyright_title: 'Copyright Notice: ' - copyright_content: 'All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.' + word_count: + one: 'About %d word' + other: 'About %d words' + licensing: + author: 'Author' + created_at: 'Posted on' + updated_at: 'Updated on' + licensed_under: 'Licensed under' donate: title: 'Like this article? Support the author with' + afdian: 'Afdian.net' alipay: 'Alipay' wechat: 'Wechat' paypal: 'Paypal' patreon: 'Patreon' buymeacoffee: 'Buy me a coffee' plugin: - backtotop: 'Back to Top' + backtotop: 'Back to top' + visit_count: '%s visits' + visitor_count: 'Visited by %s users' visit: '%s visits' visitor: 'Visited by %s users' footer_visitor: '❤️Thx %s users %s visited!❤️' @@ -63,10 +69,6 @@ plugin: search: search: 'Search' hint: 'Type something...' -insight: - hint: 'Type something...' - posts: 'Posts' - pages: 'Pages' - categories: 'Categories' - tags: 'Tags' + no_result: 'No results for' untitled: '(Untitled)' + empty_preview: '(No preview)' diff --git a/languages/es.yml b/languages/es.yml index f30c570..984357b 100644 --- a/languages/es.yml +++ b/languages/es.yml @@ -12,27 +12,48 @@ common: post: one: 'Entrada' other: 'Entradas' + page: + one: 'Página' + other: 'Páginas' prev: 'Anterior' next: 'Siguiente' widget: follow: 'SEGUIR' recents: 'Recientes' links: 'Enlaces' - tag_cloud: 'Nube de etiquetas' catalogue: 'Catálogo' + subscribe_email: 'Suscríbete para recibir actualizaciones' + subscribe: 'Suscribir' + adsense: 'Anuncio' article: + created_at: 'Publicado hace %s' + updated_at: 'Actualizado hace %s' more: 'Leer más' comments: 'Comentarios' - read: 'leer' - about: 'Acerca de' - words: 'palabras' + read_time: '%s de lectura' + word_count: + one: 'Aproximadamente %d palabra' + other: 'Aproximadamente %d palabras' + licensing: + author: 'Author' + created_at: 'Posted on' + updated_at: 'Updated on' + licensed_under: 'Licensed under' +donate: + title: '¿Te gusta este artículo? Apoya al autor con' + afdian: 'Afdian.net' + alipay: 'Alipay' + wechat: 'Wechat' + paypal: 'Paypal' + patreon: 'Patreon' + buymeacoffee: 'Cómprame un café' +plugin: + backtotop: 'Volver arriba' + visit_count: '%s visitas' + visitor_count: 'Visitado por %s usuarios' search: search: 'Buscar' hint: 'Teclea algo...' -insight: - hint: 'Teclea algo...' - posts: 'Entradas' - pages: 'Páginas' - categories: 'Categorías' - tags: 'Etiquetas' + no_result: 'No hay resultados para' untitled: '(Sin título)' + empty_preview: '(Sin vista previa)' diff --git a/languages/fr.yml b/languages/fr.yml index 9bfdbeb..6c33bf1 100644 --- a/languages/fr.yml +++ b/languages/fr.yml @@ -11,27 +11,48 @@ common: post: one: 'Article' other: 'Articles' + page: + one: 'Page' + other: 'Pages' prev: 'Préc' next: 'Suiv' widget: - follow: 'SUIVRE' + follow: 'Suivre' recents: 'Récents' links: 'Liens' - tag_cloud: 'Nuage de tags' catalogue: 'Catalogue' + subscribe_email: 'Abonnez-vous aux mises à jour' + subscribe: 'Abonnez-vous' + adsense: 'Annonce' article: - more: 'Read More' + created_at: 'Publié il y a %s' + updated_at: 'Mis à jour il y a %s' + more: 'Lire la suite' comments: 'Commentaires' - read: 'read' - about: 'About' - words: 'words' + read_time: '%s de lecture' + word_count: + one: 'Environ %d mot' + other: 'Environ %d mots' + licensing: + author: 'Author' + created_at: 'Posted on' + updated_at: 'Updated on' + licensed_under: 'Licensed under' +donate: + title: "Vous aimez cet article? Soutenez l'auteur avec" + afdian: 'Afdian.net' + alipay: 'Alipay' + wechat: 'Wechat' + paypal: 'Paypal' + patreon: 'Patreon' + buymeacoffee: 'Achetez-moi un café' +plugin: + backtotop: 'Retour au sommet' + visit_count: '%s visites' + visitor_count: 'Visité par %s utilisateurs' search: search: 'Search' hint: 'Type something...' -insight: - hint: 'Type something...' - posts: 'Articles' - pages: 'Pages' - categories: 'Catégories' - tags: 'Tags' - untitled: '(Untitled)' + no_result: 'Aucun résultat pour' + untitled: '(Sans titre)' + empty_preview: '(Pas de prévisualisation)' diff --git a/languages/id.yml b/languages/id.yml index ab3d036..97c99d9 100644 --- a/languages/id.yml +++ b/languages/id.yml @@ -11,35 +11,48 @@ common: post: one: 'Artikel' other: 'Artikel' + page: + one: 'Halaman' + other: 'Halaman' prev: 'Sebelumnya' next: 'Berikutnya' widget: follow: 'IKUTI' recents: 'Terbaru' links: 'Tautan' - tag_cloud: 'Awan tag' catalogue: 'Katalog' + subscribe_email: 'Berlangganan untuk pembaruan' + subscribe: 'Berlangganan' + adsense: 'Iklan' article: + created_at: 'Diposting %s' + updated_at: 'Diperbarui %s' more: 'Selengkapnya' comments: 'Komentar' - read: 'membaca' - about: 'Sekitar' - words: 'kata' -search: - search: 'Pencarian' - hint: 'Tulis Sesuatu..' -insight: - hint: 'Tulis Sesuatu..' - posts: 'Artikel' - pages: 'Halaman' - categories: 'Kategori' - tags: 'Tag' - untitled: 'Tanpa Judul' + read_time: '%s membaca' + word_count: + one: 'Sekitar %d kata' + other: 'Sekitar %d kata' + licensing: + author: 'Author' + created_at: 'Posted on' + updated_at: 'Updated on' + licensed_under: 'Licensed under' donate: title: 'Suka dengan artikel ini? Bantu penulis dengan donasi melalui' + afdian: 'Afdian.net' alipay: 'Alipay' wechat: 'Wechat' paypal: 'Paypal' patreon: 'Patreon' + buymeacoffee: 'Belikan aku kopi' plugin: backtotop: 'Kembali ke atas' + visit_count: '%s kunjungan' + visitor_count: 'Dikunjungi oleh %s pengguna' +search: + search: 'Pencarian' + hint: 'Tulis Sesuatu..' + no_result: 'Tidak ada hasil untuk' + untitled: '(Tanpa judul)' + empty_preview: '(Tidak ada preview)' diff --git a/languages/ja.yml b/languages/ja.yml index 00928c7..aa286ea 100644 --- a/languages/ja.yml +++ b/languages/ja.yml @@ -11,27 +11,48 @@ common: post: one: '投稿' other: '投稿' + page: + one: 'ページ' + other: 'ページ' prev: '前' next: '次' widget: follow: 'フォローする' recents: '最近の記事' links: 'リンク' - tag_cloud: 'タグクラウド' catalogue: 'カタログ' + subscribe_email: '更新を購読する' + subscribe: '購読する' + adsense: '広告' article: - more: 'Read More' + created_at: '%sに投稿' + updated_at: '%sに更新' + more: '続きを読む' comments: 'コメント' - read: 'read' - about: 'About' - words: 'words' + read_time: '%sで読む' + word_count: + one: '約%d語' + other: '約%d語' + licensing: + author: 'Author' + created_at: 'Posted on' + updated_at: 'Updated on' + licensed_under: 'Licensed under' +donate: + title: 'この記事は気に入りましたか? 著者をサポートする' + afdian: 'Afdian.net' + alipay: 'Alipay' + wechat: 'Wechat' + paypal: 'Paypal' + patreon: 'Patreon' + buymeacoffee: 'コーヒーを買って' +plugin: + backtotop: 'トップに戻る' + visit_count: '%s回の訪問' + visitor_count: '%s人のユーザーがアクセス' search: - search: 'Search' - hint: 'Type something...' -insight: - hint: 'Type something...' - posts: '投稿' - pages: 'Pages' - categories: 'カテゴリ' - tags: 'タグ' - untitled: '(Untitled)' + search: '検索' + hint: '何かを入力してください...' + no_result: 'の結果はありません' + untitled: '(無題)' + empty_preview: '(プレビューなし)' diff --git a/languages/ko.yml b/languages/ko.yml index 3ea0e68..5ce8653 100644 --- a/languages/ko.yml +++ b/languages/ko.yml @@ -11,27 +11,48 @@ common: post: one: '포스트' other: '포스트' + page: + one: '페이지' + other: '페이지' prev: '이전' next: '다음' widget: follow: '팔로우' recents: '최근 글' links: '링크' - tag_cloud: '태그 클라우드' catalogue: '카탈로그' + subscribe_email: '업데이트 구독' + subscribe: '구독' + adsense: '광고' article: + created_at: '%s게시 됨' + updated_at: '%s업데이트 됨' more: '자세히 보기' comments: '댓글' - read: '읽기' - about: '대략' - words: '단어' + read_time: '%s안에 읽기' + word_count: + one: '약 %d 단어' + other: '약 %d 단어' + licensing: + author: 'Author' + created_at: 'Posted on' + updated_at: 'Updated on' + licensed_under: 'Licensed under' +donate: + title: '이 기사처럼? 저자 지원' + afdian: 'Afdian.net' + alipay: 'Alipay' + wechat: 'Wechat' + paypal: 'Paypal' + patreon: 'Patreon' + buymeacoffee: '나에게 커피 사줘' +plugin: + backtotop: '맨 위로' + visit_count: '%s회 방문' + visitor_count: '%s명의 사용자가 방문 함' search: search: '검색' hint: '입력 하세요...' -insight: - hint: '입력 하세요...' - posts: '포스트' - pages: '페이지' - categories: '카테고리' - tags: '태그' + no_result: '에 대한 결과 없음' untitled: '(제목없음)' + empty_preview: '(미리보기 없음)' diff --git a/languages/pl.yml b/languages/pl.yml index 8b6cd2f..67a7db6 100644 --- a/languages/pl.yml +++ b/languages/pl.yml @@ -11,27 +11,48 @@ common: post: one: 'Artykuł' other: 'Artykuły' + page: + one: 'Strona' + other: 'Strony' prev: 'Poprzedni' next: 'Następny' widget: follow: 'SUBSKRYBUJ' recents: 'Najnowsze wpisy' links: 'Linki' - tag_cloud: 'Chmura tagòw' catalogue: 'Spis treści' + subscribe_email: 'Zapisz się, aby otrzymywać aktualizacje' + subscribe: 'Subskrybuj' + adsense: 'Reklama' article: + created_at: 'Opublikowano %s' + updated_at: 'Zaktualizowano %s' more: 'Czytaj dalej' comments: 'Komentarze' - read: 'Czytaj' - about: 'O mnie' - words: 'słowa' + read_time: '%s czytania' + word_count: + one: 'Około %d słowa' + other: 'Około %d słów' + licensing: + author: 'Author' + created_at: 'Posted on' + updated_at: 'Updated on' + licensed_under: 'Licensed under' +donate: + title: 'Podoba Ci się ten artykuł? Wesprzyj autora za pomocą' + afdian: 'Afdian.net' + alipay: 'Alipay' + wechat: 'Wechat' + paypal: 'Paypal' + patreon: 'Patreon' + buymeacoffee: 'Kup mi kawę' +plugin: + backtotop: 'Powrót do góry' + visit_count: '%s wizyty' + visitor_count: 'Odwiedzone przez %s użytkowników' search: search: 'szukaj' hint: 'Wpisz coś...' -insight: - hint: 'Wpisz coś...' - posts: 'Artykuły' - pages: 'Strony' - categories: 'Kategorie' - tags: 'Tagi' + no_result: 'Brak wyników dla' untitled: '(Bez tytułu)' + empty_preview: '(Brak podglądu)' diff --git a/languages/pt-BR.yml b/languages/pt-BR.yml index 5c1a164..5dbb2bf 100644 --- a/languages/pt-BR.yml +++ b/languages/pt-BR.yml @@ -11,27 +11,48 @@ common: post: one: 'Artigo' other: 'Artigos' + page: + one: 'Página' + other: 'Páginas' prev: 'Anterior' next: 'Próximo' widget: - follow: 'SEGUIR' + follow: 'Seguir' recents: 'Recentes' links: 'Links' - tag_cloud: 'Nuvem de tags' catalogue: 'Catálogo' + subscribe_email: 'Subscrição de atualizações' + subscribe: 'Se inscrever' + adsense: 'Anúncio' article: + created_at: 'Postado %s' + updated_at: 'Atualizado %s' more: 'Ler Mais' comments: 'Comentarios' - read: 'read' - about: 'About' - words: 'words' + read_time: '%s lidos' + word_count: + one: 'Cerca de %d palavra' + other: 'Cerca de %d palavras' + licensing: + author: 'Author' + created_at: 'Posted on' + updated_at: 'Updated on' + licensed_under: 'Licensed under' +donate: + title: 'Gostou deste artigo? Apoie o autor com' + afdian: 'Afdian.net' + alipay: 'Alipay' + wechat: 'Wechat' + paypal: 'Paypal' + patreon: 'Patreon' + buymeacoffee: 'Me compra um café' +plugin: + backtotop: 'De volta ao topo' + visit_count: '%s visitas' + visitor_count: 'Visitado por %s usuários' search: - search: 'Search' + search: 'Procurar' hint: 'Digite alguma coisa...' -insight: - hint: 'Digite alguma coisa...' - posts: 'Artigos' - pages: 'Paginas' - categories: 'Categorias' - tags: 'Tags' - untitled: '(Untitled)' + no_result: 'Sem resultados para' + untitled: '(Sem título)' + empty_preview: '(Não há visualização)' diff --git a/languages/ru.yml b/languages/ru.yml index 475f5e5..dc88909 100644 --- a/languages/ru.yml +++ b/languages/ru.yml @@ -11,27 +11,48 @@ common: post: one: 'пост' other: 'посты' + page: + one: 'страница' + other: 'страницы' prev: 'Назад' next: 'Далее' widget: follow: 'Подписаться' recents: 'недавние' links: 'ссылки' - tag_cloud: 'облако тегов' catalogue: 'Каталог' + subscribe_email: 'Подпишитесь на обновления' + subscribe: 'Подписывайся' + adsense: 'Рекламное объявление' article: + created_at: 'Опубликовано %s' + updated_at: 'Обновлено %s' more: 'Читать дальше' comments: 'Комментарии' - read: 'read' - about: 'About' - words: 'words' + read_time: '%s на чтение' + word_count: + one: 'Около %d слова' + other: 'Примерно %d слова' + licensing: + author: 'Author' + created_at: 'Posted on' + updated_at: 'Updated on' + licensed_under: 'Licensed under' +donate: + title: 'Понравилась эта статья? Поддержите автора' + afdian: 'Afdian.net' + alipay: 'Alipay' + wechat: 'Wechat' + paypal: 'Paypal' + patreon: 'Patreon' + buymeacoffee: 'Купи мне кофе' +plugin: + backtotop: 'Вернуться наверх' + visit_count: '%s посещения' + visitor_count: 'Посетили %s пользователя' search: - search: 'Search' + search: 'Поиск' hint: 'Введите что-нибудь...' -insight: - hint: 'Введите что-нибудь...' - posts: 'посты' - pages: 'страницы' - categories: 'категории' - tags: 'теги' + no_result: 'Нет результатов по запросу' untitled: '(Без названия)' + empty_preview: '(Нет предварительного просмотра)' diff --git a/languages/tr.yml b/languages/tr.yml index 8a7ba87..68a2898 100644 --- a/languages/tr.yml +++ b/languages/tr.yml @@ -11,27 +11,48 @@ common: post: one: 'Gönderi' other: 'Gönderiler' + page: + one: 'Sayfa' + other: 'Sayfalar' prev: 'Önceki' next: 'Sonraki' widget: follow: 'TAKİP ET' recents: 'Son' links: 'Linkler' - tag_cloud: 'Etiket bulutu' catalogue: 'Katalog' + subscribe_email: 'Güncellemeler için abone olun' + subscribe: 'Abone ol' + adsense: 'İlan' article: + created_at: '%s yayınlandı' + updated_at: '%s güncellendi' more: 'Daha fazla oku' comments: 'Yorumlar' - read: 'read' - about: 'About' - words: 'words' + read_time: '%s okundu' + word_count: + one: 'Yaklaşık %d kelime' + other: 'Yaklaşık %d kelime' + licensing: + author: 'Author' + created_at: 'Posted on' + updated_at: 'Updated on' + licensed_under: 'Licensed under' +donate: + title: 'Bu makaleyi beğendiniz mi? Yazarı şununla destekleyin' + afdian: 'Afdian.net' + alipay: 'Alipay' + wechat: 'Wechat' + paypal: 'Paypal' + patreon: 'Patreon' + buymeacoffee: 'Bana bir kahve al' +plugin: + backtotop: 'Başa dönüş' + visit_count: '%s ziyaret' + visitor_count: '%s kullanıcı tarafından ziyaret edildi' search: search: 'Search' hint: 'Bir şeyler yaz...' -insight: - hint: 'Bir şeyler yaz...' - posts: 'Gönderiler' - pages: 'Sayfalar' - categories: 'Kategoriler' - tags: 'Etiketler' + no_result: 'İçin sonuç yok' untitled: '(Başlıksız)' + empty_preview: '(Önizleme yok)' diff --git a/languages/vn.yml b/languages/vn.yml index 6138b0b..d72027e 100644 --- a/languages/vn.yml +++ b/languages/vn.yml @@ -1,47 +1,58 @@ common: archive: - one: 'Archive' - other: 'Archives' + one: 'Lưu trữ' + other: 'Lưu trữ' category: - one: 'Category' - other: 'Categories' + one: 'Thể loại' + other: 'Thể loại' tag: - one: 'Tag' - other: 'Tags' + one: 'Nhãn' + other: 'Nhãn' post: one: 'Bài viết' other: 'Bài viết' + page: + one: 'Trang' + other: 'Trang' prev: 'Trước' next: 'Sau' widget: follow: 'Theo dõi' recents: 'Gần đây' links: 'Link' - tag_cloud: 'Tag Cloud' catalogue: 'Mục lục' + subscribe_email: 'Theo dõi các bản cập nhật' + subscribe: 'Theo dõi' + adsense: 'Quảng cáo' article: + created_at: 'Đã đăng %s' + updated_at: 'Đã cập nhật %s' more: 'Đọc thêm' comments: 'Bình luận' - read: 'đọc' - about: 'Giới thiệu' - words: 'từ' + read_time: '%s đọc' + word_count: + one: 'Khoảng %d từ' + other: 'Khoảng %d từ' + licensing: + author: 'Author' + created_at: 'Posted on' + updated_at: 'Updated on' + licensed_under: 'Licensed under' donate: title: 'Bạn đọc có thể ủng hộ blog qua' + afdian: 'Afdian.net' alipay: 'Alipay' wechat: 'Wechat' paypal: 'Paypal' patreon: 'Patreon' + buymeacoffee: 'Mua cho tôi một ly cà phê' plugin: backtotop: 'Trở lai đầu trang' - visit: '%s Bạn đọc' - visitor: 'Thăm bởi %s bạn đọc' + visit_count: '%s Bạn đọc' + visitor_count: 'Thăm bởi %s bạn đọc' search: search: 'Tìm kiếm' hint: 'Gõ gì đó...' -insight: - hint: 'Gõ gì đó...' - posts: 'Bài viết' - pages: 'Trang' - categories: 'Thể loại' - tags: 'Thẻ' - untitled: '(Untitled)' + no_result: 'Không có kết quả cho' + untitled: '(Không có tiêu đề)' + empty_preview: '(Không có xem trước)' diff --git a/languages/zh-CN.yml b/languages/zh-CN.yml index 53f9855..6a071b2 100644 --- a/languages/zh-CN.yml +++ b/languages/zh-CN.yml @@ -11,13 +11,15 @@ common: post: one: '文章' other: '文章' + page: + one: '页面' + other: '页面' prev: '上一页' next: '下一页' widget: follow: '关注我' recents: '最新文章' links: '链接' - tag_cloud: '标签云' catalogue: '目录' subscribe_email: '订阅更新' subscribe: '订阅' @@ -32,27 +34,34 @@ widget: hitokoto_provider: '提供者' notice: '通知' article: - more: '阅读更多' + created_at: '%s发表' + updated_at: '%s更新' + more: '阅读更多>>' comments: '评论' comments_closed: '此处评论已关,暂不支持评论。' comments_language: 'zh-CN' - read: '读完' - about: '大约' - words: '个字' last_modified: '最后修改:' - copyright: - title: '本文标题:' - author: '本文作者:' - link: '本文链接:' - copyright_title: '版权声明:' - copyright_content: '本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!' + read_time: '%s读完' + word_count: + one: '大约%d个字' + other: '大约%d个字' + licensing: + author: '作者' + created_at: '发布于' + updated_at: '更新于' + licensed_under: '许可协议' donate: title: '喜欢这篇文章?打赏一下作者吧' + afdian: '爱发电' alipay: '支付宝' wechat: '微信' + paypal: 'Paypal' + patreon: 'Patreon' buymeacoffee: '送我杯咖啡' plugin: backtotop: '回到顶端' + visit_count: '%s次访问' + visitor_count: '共%s个访客' visit: '%s次访问' visitor: '共%s个访客' footer_visitor: '❤️感谢 %s 小伙伴的 %s 次光临!❤️' @@ -60,10 +69,6 @@ plugin: search: search: '搜索' hint: '想要查找什么...' -insight: - hint: '想要查找什么...' - posts: '文章' - pages: '页面' - categories: '分类' - tags: '标签' + no_result: '未找到搜索结果' untitled: '(无标题)' + empty_preview: '(无内容预览)' diff --git a/languages/zh-TW.yml b/languages/zh-TW.yml index 007e14c..555a4cb 100644 --- a/languages/zh-TW.yml +++ b/languages/zh-TW.yml @@ -11,37 +11,48 @@ common: post: one: '文章' other: '文章' + page: + one: '頁面' + other: '頁面' prev: '上一頁' next: '下一頁' widget: follow: '追蹤' recents: '最新文章' links: '連結' - tag_cloud: '標籤雲' catalogue: '文章目錄' subscribe_email: '訂閱 Email' subscribe: '訂閱' + adsense: '廣告' article: + created_at: '%s發表' + updated_at: '%s更新' more: '繼續閱讀' comments: '評論' - read: '閱讀文' - about: '大約' - words: '個字' + read_time: '%s讀完' + word_count: + one: '大約%d個字' + other: '大約%d個字' + licensing: + author: '作者' + created_at: '發表於' + updated_at: '更新於' + licensed_under: '許可協議' donate: title: '喜歡這篇文章嗎? 贊助一下作者吧!' + afdian: '愛發電' alipay: '支付寶' wechat: 'WeChat' paypal: 'PayPal' patreon: 'Patreon' + buymeacoffee: '送我杯咖啡' plugin: backtotop: '回到頁首' + visit_count: '%s次訪問' + visitor_count: '共%s個訪客' search: search: '搜尋' hint: '請輸入關鍵字...' -insight: - hint: '請輸入關鍵字...' - posts: '文章' - pages: '頁面' - categories: '分類' - tags: '標籤' + no_result: '未找到搜索結果' untitled: '(無標題)' + empty_preview: '(無內容預覽)' diff --git a/layout/archive.jsx b/layout/archive.jsx index 8cc0f95..b0621bb 100644 --- a/layout/archive.jsx +++ b/layout/archive.jsx @@ -1,12 +1,12 @@ const moment = require('moment'); const { Component, Fragment } = require('inferno'); -const Paginator = require('./misc/paginator'); -const ArticleMedia = require('./common/article-media'); +const Paginator = require('hexo-component-inferno/lib/view/misc/paginator'); +const ArticleMedia = require('hexo-component-inferno/lib/view/common/article_media'); module.exports = class extends Component { render() { - const { config, page,site, helper } = this.props; - const { url_for, my_cdn, __, has_thumbnail, get_thumbnail, date_xml, date } = helper; + const { config, page, site, helper } = this.props; + const { url_for, my_cdn, __, date_xml, date } = helper; const language = page.lang || page.language || config.language; @@ -50,15 +50,15 @@ module.exports = class extends Component { name: category.name })); return ; + categories={categories} + thumbnail={post.thumbnail ? url_for(post.thumbnail) : null} />; })} -
+
; } @@ -151,13 +151,13 @@ module.exports = class extends Component { } return -

-
+
+
- + {articleList}
diff --git a/layout/categories.jsx b/layout/categories.jsx index f439c49..7c1ceb1 100644 --- a/layout/categories.jsx +++ b/layout/categories.jsx @@ -1,10 +1,10 @@ const { Component } = require('inferno'); -const Categories = require('./widget/categories'); +const Categories = require('hexo-component-inferno/lib/view/widget/categories'); module.exports = class extends Component { render() { const { site, page, helper } = this.props; - return ; + return ; } }; diff --git a/layout/comment/.gitkeep b/layout/comment/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/layout/comment/changyan.jsx b/layout/comment/changyan.jsx deleted file mode 100644 index c8f212d..0000000 --- a/layout/comment/changyan.jsx +++ /dev/null @@ -1,30 +0,0 @@ -const { Component, Fragment } = require('inferno'); -const { cacheComponent } = require('../util/cache'); - -class ChangeYan extends Component { - render() { - const { appId, conf, path } = this.props; - if (!appId || !conf) { - return
- You forgot to set the app_id or conf for Changyan. - Please set it in _config.yml. -
; - } - const js = `window.changyan.api.config({appid: '${appId}',conf: '${conf}'});`; - return -
- - -
; - } -} - -module.exports = cacheComponent(ChangeYan, 'comment.changyan', props => { - const { comment, page } = props; - - return { - appId: comment.app_id, - conf: comment.conf, - path: page.path - }; -}); diff --git a/layout/comment/disqus.jsx b/layout/comment/disqus.jsx deleted file mode 100644 index dd3d302..0000000 --- a/layout/comment/disqus.jsx +++ /dev/null @@ -1,41 +0,0 @@ -const { Component, Fragment } = require('inferno'); -const { cacheComponent } = require('../util/cache'); - -class Disqus extends Component { - render() { - const { shortname, disqusId, path, permalink } = this.props; - if (!shortname) { - return
- You forgot to set the shortname for Disqus. - Please set it in _config.yml. -
; - } - const js = `var disqus_config = function () { - this.page.url = '${permalink}'; - this.page.identifier = '${disqusId || path}'; - }; - (function() { - var d = document, s = d.createElement('script'); - s.src = '//' + '${shortname}' + '.disqus.com/embed.js'; - s.setAttribute('data-timestamp', +new Date()); - (d.head || d.body).appendChild(s); - })();`; - return -
- -
- -
; - } -} - -module.exports = cacheComponent(Disqus, 'comment.disqus', props => { - const { comment, page } = props; - - return { - path: page.path, - shortname: comment.shortname, - disqusId: page.disqusId, - permalink: page.permalink - }; -}); diff --git a/layout/comment/disqusjs.jsx b/layout/comment/disqusjs.jsx deleted file mode 100644 index fb22307..0000000 --- a/layout/comment/disqusjs.jsx +++ /dev/null @@ -1,68 +0,0 @@ -const { Component, Fragment } = require('inferno'); -const { cacheComponent } = require('../util/cache'); - -class DisqusJs extends Component { - render() { - const { - shortname, - apiKey, - api, - admin, - adminLabel = false, - nesting = 4, - disqusId, - path, - permalink, - pageTitle, - siteTitle, - jsUrl, - cssUrl - } = this.props; - if (!shortname) { - return
- You forgot to set the shortname or api_key for Disqus. - Please set it in _config.yml. -
; - } - const js = `new DisqusJS({ - shortname: '${shortname}', - apikey: '${JSON.stringify(apiKey)}', - siteName: '${siteTitle}', - identifier: '${disqusId || path}', - url: '${permalink || path}', - title: '${pageTitle}', - api: '${api}', - admin: '${admin}', - adminLabel: '${adminLabel}', - nesting: ${nesting} - });`; - return - -
- -
- - -
; - } -} - -module.exports = cacheComponent(DisqusJs, 'comment.disqusjs', props => { - const { config, page, helper, comment } = props; - - return { - path: page.path, - shortname: comment.shortname, - apiKey: comment.api_key, - api: comment.api, - admin: comment.admin, - adminLabel: comment.admin_label, - nesting: comment.nesting, - disqusId: page.disqusId, - permalink: page.permalink, - pageTitle: page.title, - siteTitle: config.title, - jsUrl: helper.cdn('disqusjs', '1.2.5', 'dist/disqus.js'), - cssUrl: helper.cdn('disqusjs', '1.2.5', 'dist/disqusjs.css') - }; -}); diff --git a/layout/comment/facebook.jsx b/layout/comment/facebook.jsx deleted file mode 100644 index 2148d3b..0000000 --- a/layout/comment/facebook.jsx +++ /dev/null @@ -1,28 +0,0 @@ -const { Component, Fragment } = require('inferno'); -const { cacheComponent } = require('../util/cache'); - -class Facebook extends Component { - render() { - const { language, permalink } = this.props; - const js = `(function(d, s, id) { - var js, fjs = d.getElementsByTagName(s)[0]; - if (d.getElementById(id)) return; - js = d.createElement(s); js.id = id; - js.src = "//connect.facebook.net/${language.split('-').join('_')}/sdk.js#xfbml=1&version=v2.8"; - fjs.parentNode.insertBefore(js, fjs); - }(document, 'script', 'facebook-jssdk'));`; - return -
- -
; - } -} - -module.exports = cacheComponent(Facebook, 'comment.facebook', props => { - const { config, page } = props; - - return { - language: page.lang || page.language || config.language || 'en', - permalink: page.permalink - }; -}); diff --git a/layout/comment/gitalk.jsx b/layout/comment/gitalk.jsx index 50cd6fc..258c98a 100644 --- a/layout/comment/gitalk.jsx +++ b/layout/comment/gitalk.jsx @@ -1,6 +1,6 @@ const crypto = require('crypto'); -const { Component, Fragment } = require('inferno'); -const { cacheComponent } = require('../util/cache'); +const {Component, Fragment} = require('inferno'); +const {cacheComponent} = require('hexo-component-inferno/lib/util/cache'); class Gitalk extends Component { render() { @@ -52,18 +52,18 @@ class Gitalk extends Component { gitalk.render('comment-container')});`; return
- - + +
; } } -module.exports = cacheComponent(Gitalk, 'comment.gitalk', props => { - const { helper, comment } = props; - const { my_cdn, url_for, __ } = helper; +module.exports = Gitalk.Cacheable = cacheComponent(Gitalk, 'comment.gitalk', props => { + const {helper, comment} = props; + const {my_cdn, url_for, __, _get_md5, _get_path_end_str} = helper; // FIXME: config name change - const id = crypto.createHash('md5').update(helper.get_path_end_str(props.page.path, props.page.uniqueId, props.page.title)).digest('hex'); + const id = _get_md5(_get_path_end_str(props.page.path, props.page.uniqueId, props.page.title)); let canComments = props.page.comments; diff --git a/layout/comment/gitment.jsx b/layout/comment/gitment.jsx deleted file mode 100644 index faf3061..0000000 --- a/layout/comment/gitment.jsx +++ /dev/null @@ -1,58 +0,0 @@ -const crypto = require('crypto'); -const { Component, Fragment } = require('inferno'); -const { cacheComponent } = require('../util/cache'); - -class Gitment extends Component { - render() { - const { - id, - repo, - owner, - clientId, - clientSecret, - perPage = 20, - maxCommentHeight = 250 - } = this.props; - - if (!id || !repo || !owner || !clientId || !clientSecret) { - return
- You forgot to set the owner, repo, clientId, - or clientSecret for Gitment. - Please set it in _config.yml. -
; - } - const js = `var gitment = new Gitment({ - id: '${id}', - repo: '${repo}', - owner: '${owner}', - oauth: { - client_id: '${clientId}', - client_secret: '${clientSecret}', - }, - perPage: ${perPage}, - maxCommentHeight: ${maxCommentHeight} - }) - gitment.render('comment-container')`; - return -
- - - -
; - } -} - -module.exports = cacheComponent(Gitment, 'comment.gitment', props => { - const { comment } = props; - - const id = crypto.createHash('md5').update(props.page.path).digest('hex'); - return { - id, - repo: comment.repo, - owner: comment.owner, - clientId: comment.client_id, - clientSecret: comment.client_secret, - perPage: comment.per_page, - maxCommentHeight: comment.max_comment_height - }; -}); diff --git a/layout/comment/isso.jsx b/layout/comment/isso.jsx deleted file mode 100644 index eef9965..0000000 --- a/layout/comment/isso.jsx +++ /dev/null @@ -1,26 +0,0 @@ -const { Component, Fragment } = require('inferno'); -const { cacheComponent } = require('../util/cache'); - -class Isso extends Component { - render() { - const { url } = this.props; - if (!url) { - return
- You forgot to set the url for Isso. - Please set it in _config.yml. -
; - } - return -
- -
; - } -} - -module.exports = cacheComponent(Isso, 'comment.isso', props => { - const { comment } = props; - - return { - url: comment.url - }; -}); diff --git a/layout/comment/livere.jsx b/layout/comment/livere.jsx deleted file mode 100644 index 36c554c..0000000 --- a/layout/comment/livere.jsx +++ /dev/null @@ -1,37 +0,0 @@ -const { Component } = require('inferno'); -const { cacheComponent } = require('../util/cache'); - -class LiveRe extends Component { - render() { - const { uid } = this.props; - if (!uid) { - return
- You forgot to set the uid for LiveRe. - Please set it in _config.yml. -
; - } - const js = `(function(d, s) { - var j, e = d.getElementsByTagName(s)[0]; - - if (typeof LivereTower === 'function') { return; } - - j = d.createElement(s); - j.src = 'https://cdn-city.livere.com/js/embed.dist.js'; - j.async = true; - - e.parentNode.insertBefore(j, e); - })(document, 'script');`; - return
- - -
; - } -} - -module.exports = cacheComponent(LiveRe, 'comment.livere', props => { - const { comment } = props; - - return { - uid: comment.uid - }; -}); diff --git a/layout/comment/utteranc.jsx b/layout/comment/utteranc.jsx index 600cd9c..8795ab9 100644 --- a/layout/comment/utteranc.jsx +++ b/layout/comment/utteranc.jsx @@ -3,8 +3,7 @@ * @module view/comment/utterances */ const { Component } = require('inferno'); -const { cacheComponent } = require('../util/cache'); - +const { cacheComponent } = require('hexo-component-inferno/lib/util/cache'); /** * Utterances comment JSX component. * diff --git a/layout/comment/valine.jsx b/layout/comment/valine.jsx index 9962dc2..fd65943 100644 --- a/layout/comment/valine.jsx +++ b/layout/comment/valine.jsx @@ -1,6 +1,5 @@ const { Component, Fragment } = require('inferno'); -const { cacheComponent } = require('../util/cache'); - +const { cacheComponent } = require('hexo-component-inferno/lib/util/cache'); class Valine extends Component { render() { const { @@ -20,7 +19,6 @@ class Valine extends Component { lang, enableQQ = true, requiredFields, - use_pjax } = this.props; if (!appId || !appKey) { return
@@ -28,7 +26,6 @@ class Valine extends Component { Please set it in _config.yml.
; } - const usePjax = use_pjax != undefined && use_pjax; const js = `var valine = new Valine({ el: '#comment-container' , notify: ${notify}, @@ -55,8 +52,8 @@ class Valine extends Component { } } -module.exports = cacheComponent(Valine, 'comment.valine', props => { - const { comment, page, use_pjax } = props; +module.exports = Valine.Cacheable = cacheComponent(Valine, 'comment.valine', props => { + const { comment, page } = props; return { appId: comment.app_id, @@ -74,6 +71,5 @@ module.exports = cacheComponent(Valine, 'comment.valine', props => { path: "/" + page.path, lang: comment.lang || __('article.comments_language'), requiredFields: comment.required_fields, - use_pjax }; }); diff --git a/layout/common/article-media.jsx b/layout/common/article-media.jsx deleted file mode 100644 index b59b7d9..0000000 --- a/layout/common/article-media.jsx +++ /dev/null @@ -1,32 +0,0 @@ -const { Component } = require('inferno'); - -module.exports = class extends Component { - render() { - const { thumbnail, url, title, date, dateXml, categories } = this.props; - - const categoryTags = []; - - if(categories.length > 0){ - categoryTags.push( ) - } - categories.forEach((category, i) => { - categoryTags.push({category.name}); - if (i < categories.length - 1) { - categoryTags.push(' / '); - } - }); - - return
- {thumbnail ? -

- {title} -

-
: null} -
-

-

{title}

-

{categoryTags.length ? categoryTags : null}

-
-
; - } -}; diff --git a/layout/common/article.jsx b/layout/common/article.jsx index 7404195..5b9fe89 100644 --- a/layout/common/article.jsx +++ b/layout/common/article.jsx @@ -3,14 +3,16 @@ const { Component, Fragment } = require('inferno'); const Share = require('./share'); const Donates = require('./donates'); const Comment = require('./comment'); -const crypto = require('crypto'); +const ArticleLicensing = require('hexo-component-inferno/lib/view/misc/article_licensing'); const RecommendPosts = require('../widget/recommend_post'); - - +const AdsenseX = require('../widget/ads_x'); /** * Get the word count of text. */ function getWordCount(content) { + if (typeof content === 'undefined') { + return 0; + } content = content.replace(/<\/?[a-z][^>]*>/gi, ''); content = content.trim(); return content ? (content.match(/[\u00ff-\uffff]|[a-zA-Z]+/g) || []).length : 0; @@ -18,67 +20,93 @@ function getWordCount(content) { module.exports = class extends Component { render() { + const { config, helper, page, index, mysite, indexAt } = this.props; + const { article, plugins, index_show_tags_categories,comment,comment_head_has_ad,article_head_has_ad,index_zero_position_ad,index_ad_positions } = config; + const { url_for, date, date_xml, __, _p, _get_md5, _get_path_end_str } = helper; - const { config, helper, page, index, site } = this.props; - const { article, plugins, comment, has_latest_modify_time, has_copyright, busuanzi_only_count, index_show_tags_cateories } = config; - const { has_thumbnail, my_cdn, get_thumbnail, url_for, date, date_xml, __, _p } = helper; const language = page.lang || page.language || config.language || 'en'; - var id = crypto.createHash('md5').update(helper.get_path_end_str(page.path, page.uniqueId, page.title)).digest('hex'); - const myPermalink = config.url + config.root + page.path; - var hasLatestTime = has_latest_modify_time == undefined || has_latest_modify_time; - var hasCopyright = has_copyright == undefined || has_copyright; - var showBusuanziVisitor = plugins && plugins.busuanzi === true && (busuanzi_only_count != undefined && !busuanzi_only_count); - var indexShowTagsCat = index_show_tags_cateories == undefined || index_show_tags_cateories; - var isGitalk = comment !== undefined && comment.type !== undefined && comment.type == 'gitalk'; - var showComment = comment !== undefined && comment.type !== undefined && (comment.type == 'gitalk' || comment.type == 'valine'); - var md5Id = id; - if (!isGitalk) { - id = "/" + page.path; - md5Id = crypto.createHash('md5').update(id).digest('hex'); - } - - var lastModified = __('article.last_modified'); - var copyrightTitle = __('article.copyright.title'); - var copyrightAuthor = __('article.copyright.author'); - var copyrightLink = __('article.copyright.link'); - var copyrightCopyrightContent = __('article.copyright.copyright_content'); - var copyrightCopyrightTitle = __('article.copyright.copyright_title'); + const cover = page.thumbnail ? page.thumbnail : null; const words = getWordCount(page._content); const time = moment.duration((words / 150.0) * 60, 'seconds'); const timeStr = time.locale(language).humanize().replace('a few seconds', 'fast').replace('hours', 'h').replace('minutes', 'm').replace('seconds', 's').replace('days', 'd'); const wordsCount = (words / 1000.0).toFixed(1); + const indexShowTagsCat = index_show_tags_categories == undefined || index_show_tags_categories; + const lastModified = __('article.last_modified'); + + const isPost = page.layout == 'post'; + + const isGitalk = comment !== undefined && comment.type !== undefined && comment.type == 'gitalk'; + const showComment = true;//comment !== undefined && comment.type !== undefined && (comment.type == 'gitalk' || comment.type == 'valine'); + var id = _get_md5(_get_path_end_str(page.path, page.uniqueId, page.title)); + var md5Id = id; + if (!isGitalk) { + id = "/" + page.path; + md5Id = _get_md5(id); + } + return + {(indexAt != undefined & indexAt == 0) ? : null} + {!index ? : null} {/* Main content */}
{/* Thumbnail */} - {has_thumbnail(page) ?
+ {cover ?
{index ? - {page.title + {page.title : - {page.title - } + {page.title + }
: null} {/* Metadata */}
{page.layout !== 'page' ? : null} @@ -119,41 +147,45 @@ module.exports = class extends Component { return tags; })()}
: null} -
+
: null} - {/* "Read more" button ・ */} + {/* Licensing block */} + {!index && isPost && article && article.licenses && Object.keys(article.licenses) + ? : null} + {/* Tags */} + {/*{!index && page.tags && page.tags.length ? : null}*/} + {/* "Read more" button */} {index && page.excerpt ? -
-
-
- {__('article.more')}>> +
+ - {hasLatestTime && page.updated && page.updated > page.date ? -
-
- -
-
: null - } -
: null} - {/*copyright*/} - {hasCopyright && !index && page.layout == 'post' ? - : null} - {!index && page.layout == 'post' ? : null} + {/*lastModified updated*/} + {page.updated && page.updated > page.date ? +
+
+ +
+
: null + } +
: null} + {/*Recommend & Relation post*/} + {!index && page.layout == 'post' && mysite !==undefined ? : null} {/* Share button */} {!index ? : null}
+ {index && (index_ad_positions.indexOf(indexAt) > -1) ? : null} {/* Donate button */} {!index ? : null} {/* Post navigation */} @@ -171,6 +203,7 @@ module.exports = class extends Component {
: null} : null} + {!index ? : null} {/* Comment */} {!index ? : null}
; diff --git a/layout/common/comment.jsx b/layout/common/comment.jsx index 2ae6105..e14a7f1 100644 --- a/layout/common/comment.jsx +++ b/layout/common/comment.jsx @@ -1,26 +1,28 @@ const logger = require('hexo-log')(); -const { Component } = require('inferno'); +const {Component} = require('inferno'); +const view = require('hexo-component-inferno/lib/core/view'); module.exports = class extends Component { render() { - const { config, page, helper } = this.props; - const { __ } = helper; - const { comment } = config; + const {config, page, helper} = this.props; + const {__} = helper; + const {comment} = config; if (!comment || typeof comment.type !== 'string') { return null; } const isGitalk = comment.type == 'gitalk'; const commentColsed = !page.comments; - + return
{!commentColsed ?
{__('article.comments')}
: null} {(() => { try { if (isGitalk || !commentColsed) { - const Comment = require('../comment/' + comment.type); - return ; + let Comment = view.require('comment/' + comment.type); + Comment = Comment.Cacheable ? Comment.Cacheable : Comment; + return ; } else { return
diff --git a/layout/common/donates.jsx b/layout/common/donates.jsx index 91e944b..bafe9d4 100644 --- a/layout/common/donates.jsx +++ b/layout/common/donates.jsx @@ -1,23 +1,25 @@ const logger = require('hexo-log')(); const { Component } = require('inferno'); +const view = require('hexo-component-inferno/lib/core/view'); module.exports = class extends Component { render() { const { config, helper } = this.props; const { __ } = helper; - const { donate = [] } = config; - if (!Array.isArray(donate) || !donate.length) { + const { donates = [] } = config; + if (!Array.isArray(donates) || !donates.length) { return null; } return
- {donate.map(service => { + {donates.map(service => { const type = service.type; if (typeof type === 'string') { try { - const Donate = require('../donate/' + type); + let Donate = view.require('donate/' + type); + Donate = Donate.Cacheable ? Donate.Cacheable : Donate; return ; } catch (e) { logger.w(`Icarus cannot load donate button "${type}"`); diff --git a/layout/common/footer.jsx b/layout/common/footer.jsx index ca56f31..4b6ded1 100644 --- a/layout/common/footer.jsx +++ b/layout/common/footer.jsx @@ -1,5 +1,5 @@ const { Component } = require('inferno'); -const { cacheComponent } = require('../util/cache'); +const { cacheComponent } = require('hexo-component-inferno/lib/util/cache'); class Footer extends Component { render() { @@ -10,9 +10,9 @@ class Footer extends Component { siteTitle, siteYear, author, - visitorCounterTitle, links, showVisitorCounter, + visitorCounterTitle, url_for, my_cdn, side_music_netease_id, @@ -21,6 +21,18 @@ class Footer extends Component { registeredNo, footerWebsiteTime } = this.props; + + let footerLogo = ''; + if (logo) { + if (logo.text) { + footerLogo = logo.text; + } else { + footerLogo = {siteTitle}; + } + } else { + footerLogo = siteTitle; + } + var footerWebsiteTimeTemp = footerWebsiteTime+""; var timeArr = footerWebsiteTimeTemp.split("|"); var timeJs = `function createTime(time) { @@ -45,7 +57,7 @@ class Footer extends Component {

diff --git a/layout/common/head.jsx b/layout/common/head.jsx index 160be34..8b33ff1 100644 --- a/layout/common/head.jsx +++ b/layout/common/head.jsx @@ -1,9 +1,8 @@ const { Component } = require('inferno'); -const MetaTags = require('../misc/meta'); -const OpenGraph = require('../misc/open_graph'); -const StructuredData = require('../misc/structured_data'); +const MetaTags = require('hexo-component-inferno/lib/view/misc/meta'); +const OpenGraph = require('hexo-component-inferno/lib/view/misc/open_graph'); +const StructuredData = require('hexo-component-inferno/lib/view/misc/structured_data'); const Plugins = require('./plugins'); -const { stripHTML } = require('hexo-util'); function getPageTitle(page, siteTitle, helper) { let title = page.title; @@ -30,14 +29,15 @@ function getPageTitle(page, siteTitle, helper) { module.exports = class extends Component { render() { - const { env, site, config, helper, page } = this.props; - const { url_for, cdn, my_cdn, iconcdn, fontcdn, is_post } = helper; + const { site, config, helper, page } = this.props; + const { url_for, cdn, fontcdn, iconcdn, is_post, my_cdn } = helper; const { url, - meta_generator = true, head = {}, article, highlight, + variant = 'default', + adsense_client_id, has_live_2D_switch, global_gray, comment @@ -46,12 +46,17 @@ module.exports = class extends Component { meta = [], open_graph = {}, structured_data = {}, - canonical_url, + canonical_url = page.permalink, rss, favicon } = head; const language = page.lang || page.language || config.language; + const fontCssUrl = { + default: fontcdn('Ubuntu:wght@400;600&family=Source+Code+Pro', 'css2'), + cyberpunk: fontcdn('Oxanium:wght@300;400;600&family=Roboto+Mono', 'css2') + }; + let hlTheme, images; if (highlight && highlight.enable === false) { hlTheme = null; @@ -63,8 +68,10 @@ module.exports = class extends Component { if (typeof page.og_image === 'string') { images = [page.og_image]; - } else if (helper.has_thumbnail(page)) { - images = [helper.get_thumbnail(page)]; + } else if (typeof page.cover === 'string') { + images = [url_for(page.cover)]; + } else if (typeof page.thumbnail === 'string') { + images = [url_for(page.thumbnail)]; } else if (article && typeof article.og_image === 'string') { images = [article.og_image]; } else if (page.content && page.content.includes(' widget.type === 'adsense'); - if (widget) { - adsenseClientId = widget.client_id; - } + if (adsense_client_id) { + adsenseClientId = adsense_client_id; } let openGraphImages = images; - if ((Array.isArray(open_graph.image) && open_graph.image.length > 0) || typeof open_graph.image === 'string') { + if ((typeof open_graph === 'object' && open_graph !== null) + && ((Array.isArray(open_graph.image) && open_graph.image.length > 0) || typeof open_graph.image === 'string')) { openGraphImages = open_graph.image; } else if ((Array.isArray(page.photos) && page.photos.length > 0) || typeof page.photos === 'string') { openGraphImages = page.photos; } let structuredImages = images; - if ((Array.isArray(structured_data.image) && structured_data.image.length > 0) || typeof structured_data.image === 'string') { + if ((typeof structured_data === 'object' && structured_data !== null) + && ((Array.isArray(structured_data.image) && structured_data.image.length > 0) || typeof structured_data.image === 'string')) { structuredImages = structured_data.image; } else if ((Array.isArray(page.photos) && page.photos.length > 0) || typeof page.photos === 'string') { structuredImages = page.photos; } - const keywordsCon = (page.keywords || (page.tags && page.tags.length ? page.tags : undefined) || config.keywords); - const descCon = (page.description || stripHTML(page.excerpt) || open_graph.description || page.content || config.description); - const authorCon = (page.author || open_graph.author || config.author) - // head meta data - meta.push("name=keywords;content=" + keywordsCon); - meta.push("name=description;content=" + descCon); - meta.push("name=author;content=" + authorCon); - var hasLive2D = has_live_2D_switch == undefined || has_live_2D_switch; var globalGray = global_gray != undefined && global_gray; const isValineComment = comment != undefined && comment.type != undefined && comment.type == 'valine'; + return - {meta_generator ? : null} - + {meta && meta.length ? : null} {getPageTitle(page, config.title, helper)} - {typeof open_graph === 'object' ? : null} - {typeof structured_data === 'object' ? : null} {canonical_url ? : null} - {rss ? : null} + {rss ? : null} {favicon ? : null} - {hlTheme ? : null} - - - + + + {/*icon*/} + + {globalGray ? : null} + + {adsenseClientId ? : null} + src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js" async> : null} {hasLive2D ? : null} {hasLive2D ? : null} {isValineComment ? : null} diff --git a/layout/common/navbar.jsx b/layout/common/navbar.jsx index a4cc6a2..6f6ed74 100644 --- a/layout/common/navbar.jsx +++ b/layout/common/navbar.jsx @@ -1,6 +1,6 @@ const { Component, Fragment } = require('inferno'); -const { cacheComponent } = require('../util/cache'); -const classname = require('../util/classname'); +const { cacheComponent } = require('hexo-component-inferno/lib/util/cache'); +const classname = require('hexo-component-inferno/lib/util/classname'); function isSameLink(a, b) { function santize(url) { @@ -28,11 +28,22 @@ class Navbar extends Component { searchTitle } = this.props; + let navbarLogo = ''; + if (logo) { + if (logo.text) { + navbarLogo = logo.text; + } else { + navbarLogo = {siteTitle}; + } + } else { + navbarLogo = siteTitle; + } + return

diff --git a/layout/misc/.gitkeep b/layout/misc/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/layout/misc/meta.jsx b/layout/misc/meta.jsx deleted file mode 100644 index a6e6073..0000000 --- a/layout/misc/meta.jsx +++ /dev/null @@ -1,41 +0,0 @@ -const { Component, Fragment } = require('inferno'); - -function trim(str) { - return str.trim().replace(/^"(.*)"$/, '$1').replace(/^'(.*)'$/, '$1'); -} - -function split(str, sep) { - const result = []; - let matched = null; - while ((matched = sep.exec(str)) !== null) { - result.push(matched[0]); - } - return result; -} - -module.exports = class extends Component { - render() { - let { meta = [] } = this.props; - if (!Array.isArray(meta)) { - meta = [meta]; - } - const tags = meta.filter(entry => typeof entry === 'string') - .map(entry => { - const props = split(entry, /(?:[^\\;]+|\\.)+/g) - .map(property => { - const entry = split(property, /(?:[^\\=]+|\\.)+/g); - if (entry.length < 2) { - return null; - } - return { [trim(entry[0])]: trim(entry[1]) }; - }).filter(property => { - return property !== null; - }).reduce((prev, current) => { - return Object.assign(prev, current); - }, {}); - return ; - }); - - return {tags}; - } -}; diff --git a/layout/misc/open_graph.jsx b/layout/misc/open_graph.jsx deleted file mode 100644 index 977e3c2..0000000 --- a/layout/misc/open_graph.jsx +++ /dev/null @@ -1,145 +0,0 @@ -// adapted from hexo/lib/plugins/helper/open_graph.js -const urlFn = require('url'); -const moment = require('moment'); -const { Component, Fragment } = require('inferno'); -const { encodeURL, stripHTML, escapeHTML } = require('hexo-util'); -const localeMap = { - 'en': 'en_US', - 'de': 'de_DE', - 'es': 'es_ES', - 'fr': 'fr_FR', - 'hu': 'hu_HU', - 'id': 'id_ID', - 'it': 'it_IT', - 'ja': 'ja_JP', - 'ko': 'ko_KR', - 'nl': 'nl_NL', - 'ru': 'ru_RU', - 'th': 'th_TH', - 'tr': 'tr_TR', - 'vi': 'vi_VN' -}; -const localeRegex = new RegExp(Object.keys(localeMap).join('|'), 'i'); - -module.exports = class extends Component { - render() { - const { - type, - title, - date, - updated, - author, - url, - siteName, - twitterCard, - twitterSite, - googlePlus, - facebookAdmins, - facebookAppId - } = this.props; - let { - description, - language, - images, - keywords, - twitterId - } = this.props; - - const htmlTags = []; - - if (description) { - description = escapeHTML(stripHTML(description).substring(0, 200).trim()) - .replace(/\n/g, ' '); - htmlTags.push(); - } - - htmlTags.push(); - htmlTags.push(); - htmlTags.push(); - htmlTags.push(); - - if (description) { - htmlTags.push(); - } - - if (language) { - if (language.length === 2) { - language = language.replace(localeRegex, str => localeMap[str]); - htmlTags.push(); - } else if (language.length === 5) { - const territory = language.slice(-2); - const territoryRegex = new RegExp(territory.concat('$')); - language = language.replace('-', '_').replace(territoryRegex, territory.toUpperCase()); - htmlTags.push(); - } - } - - if (!Array.isArray(images)) { - images = [images]; - } - images = images.map(path => { - if (!urlFn.parse(path).host) { - // resolve `path`'s absolute path relative to current page's url - // `path` can be both absolute (starts with `/`) or relative. - return urlFn.resolve(url, path); - } - htmlTags.push(); - return path; - }); - - if (date && (moment.isMoment(date) || moment.isDate(date)) && !isNaN(date.valueOf())) { - htmlTags.push(); - } - - if (updated && (moment.isMoment(updated) || moment.isDate(updated)) && !isNaN(updated.valueOf())) { - htmlTags.push(); - } - - if (author) { - htmlTags.push(); - } - - if (keywords) { - if (typeof keywords === 'string') { - keywords = keywords.split(','); - } - - keywords.map(tag => { - return tag.name ? tag.name : tag; - }).filter(Boolean).forEach(keyword => { - htmlTags.push(); - }); - } - - htmlTags.push(); - - if (images.length) { - htmlTags.push(); - } - - if (twitterId) { - if (twitterId[0] !== '@') { - twitterId = `@${twitterId}`; - } - htmlTags.push(); - } - - if (twitterSite) { - htmlTags.push(); - } - - if (googlePlus) { - htmlTags.push(); - } - - if (facebookAdmins) { - htmlTags.push(); - } - - if (facebookAppId) { - htmlTags.push(); - } - - return {htmlTags}; - } -}; diff --git a/layout/misc/paginator.jsx b/layout/misc/paginator.jsx deleted file mode 100644 index 7bb2df5..0000000 --- a/layout/misc/paginator.jsx +++ /dev/null @@ -1,53 +0,0 @@ -const { Component } = require('inferno'); - -module.exports = class extends Component { - render() { - const { current, total, baseUrl, path, urlFor, prevTitle, nextTitle } = this.props; - - function getPageUrl(i) { - return urlFor(i === 1 ? baseUrl : baseUrl + path + '/' + i + '/'); - } - - function pagination(c, m) { - const current = c; - const last = m; - const delta = 1; - const left = current - delta; - const right = current + delta + 1; - const range = []; - const elements = []; - let l; - - for (let i = 1; i <= last; i++) { - if (i === 1 || i === last || (i >= left && i < right)) { - range.push(i); - } - } - - for (const i of range) { - if (l) { - if (i - l === 2) { - elements.push(
  • {l + 1}
  • ); - } else if (i - l !== 1) { - elements.push(
  • ); - } - } - elements.push(
  • {i}
  • ); - l = i; - } - return elements; - } - - return ; - } -}; diff --git a/layout/misc/structured_data.jsx b/layout/misc/structured_data.jsx deleted file mode 100644 index bff8de3..0000000 --- a/layout/misc/structured_data.jsx +++ /dev/null @@ -1,56 +0,0 @@ -const urlFn = require('url'); -const moment = require('moment'); -const { Component } = require('inferno'); -const { stripHTML, escapeHTML } = require('hexo-util'); - -module.exports = class extends Component { - render() { - const { title, url, author } = this.props; - let { description, images, date, updated } = this.props; - - if (description) { - description = escapeHTML(stripHTML(description).substring(0, 200).trim()) - .replace(/\n/g, ' '); - } - - if (!Array.isArray(images)) { - images = [images]; - } - images = images.map(path => { - if (!urlFn.parse(path).host) { - // resolve `path`'s absolute path relative to current page's url - // `path` can be both absolute (starts with `/`) or relative. - return urlFn.resolve(url, path); - } - return path; - }).filter(url => url.endsWith('.jpg') || url.endsWith('.png') || url.endsWith('.gif')); - - if (date && (moment.isMoment(date) || moment.isDate(date)) && !isNaN(date.valueOf())) { - date = date.toISOString(); - } - - if (updated && (moment.isMoment(updated) || moment.isDate(updated)) && !isNaN(updated.valueOf())) { - updated = updated.toISOString(); - } - - const data = { - '@context': 'https://schema.org', - '@type': 'BlogPosting', - 'mainEntityOfPage': { - '@type': 'WebPage', - '@id': url - }, - 'headline': title, - 'image': images, - 'datePublished': date, - 'dateModified': updated, - 'author': { - '@type': 'Person', - 'name': author - }, - 'description': description - }; - - return ; - } -}; diff --git a/layout/plugin/animejs.jsx b/layout/plugin/animejs.jsx index e97adc3..4a41c07 100644 --- a/layout/plugin/animejs.jsx +++ b/layout/plugin/animejs.jsx @@ -1,5 +1,5 @@ const { Component } = require('inferno'); -const { cacheComponent } = require('../util/cache'); +const { cacheComponent } = require('hexo-component-inferno/lib/util/cache'); class AnimeJs extends Component { render() { @@ -11,11 +11,12 @@ class AnimeJs extends Component { } } -module.exports = cacheComponent(AnimeJs, 'plugin.animejs', props => { +AnimeJs.Cacheable = cacheComponent(AnimeJs, 'plugin.animejs', props => { const { helper, head } = props; - const { url_for, my_cdn } = helper; return { head, - jsUrl: my_cdn(url_for('/js/animation.js')) + jsUrl: helper.url_for('/js/animation.js') }; }); + +module.exports = AnimeJs; diff --git a/layout/plugin/back_to_top.jsx b/layout/plugin/back_to_top.jsx index f951b26..c3b6e8d 100644 --- a/layout/plugin/back_to_top.jsx +++ b/layout/plugin/back_to_top.jsx @@ -1,5 +1,5 @@ const { Component, Fragment } = require('inferno'); -const { cacheComponent } = require('../util/cache'); +const { cacheComponent } = require('hexo-component-inferno/lib/util/cache'); class BackToTop extends Component { render() { @@ -9,20 +9,21 @@ class BackToTop extends Component { - + ; } } -module.exports = cacheComponent(BackToTop, 'plugin.backtotop', props => { +BackToTop.Cacheable = cacheComponent(BackToTop, 'plugin.backtotop', props => { const { helper, head } = props; - const { url_for, my_cdn } = helper; if (head) { return null; } return { title: helper.__('plugin.backtotop'), - jsUrl: my_cdn(url_for('/js/back-to-top.js')) + jsUrl: helper.url_for('/js/back_to_top.js') }; }); + +module.exports = BackToTop; diff --git a/layout/plugin/baidu_analytics.jsx b/layout/plugin/baidu_analytics.jsx deleted file mode 100644 index b747bac..0000000 --- a/layout/plugin/baidu_analytics.jsx +++ /dev/null @@ -1,28 +0,0 @@ -const { Component } = require('inferno'); -const { cacheComponent } = require('../util/cache'); - -class BaiduAnalytics extends Component { - render() { - const { trackingId } = this.props; - - const js = `var _hmt = _hmt || []; - (function() { - var hm = document.createElement("script"); - hm.src = "//hm.baidu.com/hm.js?${trackingId}"; - var s = document.getElementsByTagName("script")[0]; - s.parentNode.insertBefore(hm, s); - })();`; - - return ; - } -} - -module.exports = cacheComponent(BaiduAnalytics, 'plugin.baiduanalytics', props => { - const { head, plugin } = props; - if (!head || !plugin.tracking_id) { - return null; - } - return { - trackingId: plugin.tracking_id - }; -}); diff --git a/layout/plugin/busuanzi.jsx b/layout/plugin/busuanzi.jsx deleted file mode 100644 index 90bc3fa..0000000 --- a/layout/plugin/busuanzi.jsx +++ /dev/null @@ -1,15 +0,0 @@ -const { Component } = require('inferno'); -const { cacheComponent } = require('../util/cache'); - -class Busuanzi extends Component { - render() { - return ; - } -} - -module.exports = cacheComponent(Busuanzi, 'plugin.busuanzi', props => { - if (!props.head) { - return null; - } - return {}; -}); diff --git a/layout/plugin/gallery.jsx b/layout/plugin/gallery.jsx deleted file mode 100644 index 180ed69..0000000 --- a/layout/plugin/gallery.jsx +++ /dev/null @@ -1,37 +0,0 @@ -const { Component, Fragment } = require('inferno'); -const { cacheComponent } = require('../util/cache'); - -class Gallery extends Component { - render() { - const { head, jsUrl, lightGallery, justifiedGallery } = this.props; - if (head) { - return - - - ; - } - return - - - ; - - } -} - -module.exports = cacheComponent(Gallery, 'plugin.gallery', props => { - const { head, helper, config } = props; - const { url_for, my_cdn } = helper; - const { lightgallery_is_full } = config; - const galleryJsUrl = (lightgallery_is_full != undefined && lightgallery_is_full) ? 'dist/js/lightgallery-all.min.js' : 'dist/js/lightgallery.min.js'; - return { - head, - lightGallery: { - jsUrl: helper.cdn('lightgallery', '1.6.12', `${ galleryJsUrl }`), - cssUrl: helper.cdn('lightgallery', '1.6.12', 'dist/css/lightgallery.min.css') - }, - justifiedGallery: { - jsUrl: helper.cdn('justifiedGallery', '3.7.0', 'dist/js/jquery.justifiedGallery.min.js'), - cssUrl: helper.cdn('justifiedGallery', '3.7.0', 'dist/css/justifiedGallery.min.css') - } - }; -}); diff --git a/layout/plugin/google_analytics.jsx b/layout/plugin/google_analytics.jsx deleted file mode 100644 index 22e70ec..0000000 --- a/layout/plugin/google_analytics.jsx +++ /dev/null @@ -1,29 +0,0 @@ -const { Component, Fragment } = require('inferno'); -const { cacheComponent } = require('../util/cache'); - -class GoogleAnalytics extends Component { - render() { - const { trackingId } = this.props; - - const js = `window.dataLayer = window.dataLayer || []; - function gtag(){dataLayer.push(arguments);} - gtag('js', new Date()); - - gtag('config', '${trackingId}');`; - - return - - - ; - } -} - -module.exports = cacheComponent(GoogleAnalytics, 'plugin.googleanalytics', props => { - const { head, plugin } = props; - if (!head || !plugin.tracking_id) { - return null; - } - return { - trackingId: plugin.tracking_id - }; -}); diff --git a/layout/plugin/hotjar.jsx b/layout/plugin/hotjar.jsx deleted file mode 100644 index b52873d..0000000 --- a/layout/plugin/hotjar.jsx +++ /dev/null @@ -1,31 +0,0 @@ -const { Component, Fragment } = require('inferno'); -const { cacheComponent } = require('../util/cache'); - -class Hotjar extends Component { - render() { - const { siteId } = this.props; - - const js = `(function(h,o,t,j,a,r){ - h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)}; - h._hjSettings={hjid:${siteId},hjsv:6}; - a=o.getElementsByTagName('head')[0]; - r=o.createElement('script');r.async=1; - r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv; - a.appendChild(r); - })(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');`; - - return - - ; - } -} - -module.exports = cacheComponent(Hotjar, 'plugin.hotjar', props => { - const { head, plugin } = props; - if (!head || !plugin.site_id) { - return null; - } - return { - siteId: plugin.site_id - }; -}); diff --git a/layout/plugin/katex.jsx b/layout/plugin/katex.jsx deleted file mode 100644 index a251be4..0000000 --- a/layout/plugin/katex.jsx +++ /dev/null @@ -1,33 +0,0 @@ -const { Component, Fragment } = require('inferno'); -const { cacheComponent } = require('../util/cache'); - -class KaTeX extends Component { - render() { - const { cssUrl, jsUrl, autoRenderUrl } = this.props; - - const js = `document.addEventListener("DOMContentLoaded", function() { - document.querySelectorAll('[role="article"] > .content').forEach(function(element) { - renderMathInElement(element); - }); - });`; - - return - - - - - ; - } -} - -module.exports = cacheComponent(KaTeX, 'plugin.katex', props => { - const { head, helper } = props; - if (head) { - return null; - } - return { - jsUrl: helper.cdn('katex', '0.11.1', 'dist/katex.min.js'), - cssUrl: helper.cdn('katex', '0.11.1', 'dist/katex.min.css'), - autoRenderUrl: helper.cdn('katex', '0.11.1', 'dist/contrib/auto-render.min.js') - }; -}); diff --git a/layout/plugin/mathjax.jsx b/layout/plugin/mathjax.jsx deleted file mode 100644 index ba606b1..0000000 --- a/layout/plugin/mathjax.jsx +++ /dev/null @@ -1,44 +0,0 @@ -const { Component, Fragment } = require('inferno'); -const { cacheComponent } = require('../util/cache'); - -class Mathjax extends Component { - render() { - const { jsUrl } = this.props; - - const js = `document.addEventListener('DOMContentLoaded', function () { - MathJax.Hub.Config({ - 'HTML-CSS': { - matchFontHeight: false - }, - SVG: { - matchFontHeight: false - }, - CommonHTML: { - matchFontHeight: false - }, - tex2jax: { - inlineMath: [ - ['$','$'], - ['\\\\(','\\\\)'] - ] - } - }); - });`; - - return - - - ; - } -} - -module.exports = cacheComponent(Mathjax, 'plugin.mathjax', props => { - const { head, helper, page } = props; - var mathJax = page.mathJax != undefined && page.mathJax; - if (head || !mathJax) { - return null; - } - return { - jsUrl: helper.cdn('mathjax', '2.7.5', 'unpacked/MathJax.js?config=TeX-MML-AM_CHTML') - }; -}); diff --git a/layout/plugin/outdated_browser.jsx b/layout/plugin/outdated_browser.jsx deleted file mode 100644 index b2ba55d..0000000 --- a/layout/plugin/outdated_browser.jsx +++ /dev/null @@ -1,42 +0,0 @@ -const { Component, Fragment } = require('inferno'); -const { cacheComponent } = require('../util/cache'); - -class OutdatedBrowser extends Component { - render() { - const { head, jsUrl, cssUrl } = this.props; - - const js = `document.addEventListener("DOMContentLoaded", function () { - outdatedBrowser({ - bgColor: '#f25648', - color: '#ffffff', - lowerThan: 'object-fit' // display on IE11 or below - }); - });`; - - if (head) { - return ; - } - return -
    -
    Your browser is out-of-date!
    -

    - Update your browser to view this website correctly.&npsb; - Update my browser now -

    -

    ×

    -
    - - -
    ; - - } -} - -module.exports = cacheComponent(OutdatedBrowser, 'plugin.outdatedbrowser', props => { - const { head, helper } = props; - return { - head, - cssUrl: helper.cdn('outdatedbrowser', '1.1.5', 'outdatedbrowser/outdatedbrowser.min.css'), - jsUrl: helper.cdn('outdatedbrowser', '1.1.5', 'outdatedbrowser/outdatedbrowser.min.js') - }; -}); diff --git a/layout/plugin/progressbar.jsx b/layout/plugin/progressbar.jsx deleted file mode 100644 index da0aed3..0000000 --- a/layout/plugin/progressbar.jsx +++ /dev/null @@ -1,20 +0,0 @@ -const { Component } = require('inferno'); -const { cacheComponent } = require('../util/cache'); - -class ProgressBar extends Component { - render() { - const { jsUrl } = this.props; - - return ; - } -} - -module.exports = cacheComponent(ProgressBar, 'plugin.progressbar', props => { - const { head, helper } = props; - if (!head) { - return null; - } - return { - jsUrl: helper.cdn('pace-js', '1.0.2', 'pace.min.js') - }; -}); diff --git a/layout/post.jsx b/layout/post.jsx index 39facb5..b0566bf 100644 --- a/layout/post.jsx +++ b/layout/post.jsx @@ -3,8 +3,8 @@ const Article = require('./common/article'); module.exports = class extends Component { render() { - const { config, page, helper ,site } = this.props; + const { config, page, helper,site } = this.props; - return
    ; + return
    ; } }; diff --git a/layout/search/.gitkeep b/layout/search/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/layout/search/baidu.jsx b/layout/search/baidu.jsx deleted file mode 100644 index 3bfdfb7..0000000 --- a/layout/search/baidu.jsx +++ /dev/null @@ -1,48 +0,0 @@ -const { Component, Fragment } = require('inferno'); -const { cacheComponent } = require('../util/cache'); - -class Baidu extends Component { - render() { - const { url, hint } = this.props; - - const js = `(function ($) { - $('.search-form').on('submit', function (e) { - var keyword = $('.searchbox-input[name="wd"]').val(); - window.location = 'https://www.baidu.com/s?wd=site:${url.replace(/http(s)*:\/\//, '')} ' + keyword; - return false; - }); - })(jQuery); - (function (document, $) { - $(document).on('click', '.navbar-main .search', function () { - $('.searchbox').toggleClass('show'); - }).on('click', '.searchbox .searchbox-mask', function () { - $('.searchbox').removeClass('show'); - }).on('click', '.searchbox-close', function () { - $('.searchbox').removeClass('show'); - }); - })(document, jQuery);`; - - return - - - ; - } -} - -module.exports = cacheComponent(Baidu, 'search.baidu', props => { - const { config, helper } = props; - - return { - url: config.url, - hint: helper.__('search.hint') - }; -}); diff --git a/layout/search/google_cse.jsx b/layout/search/google_cse.jsx deleted file mode 100644 index 65fc973..0000000 --- a/layout/search/google_cse.jsx +++ /dev/null @@ -1,86 +0,0 @@ -const { Component, Fragment } = require('inferno'); -const { cacheComponent } = require('../util/cache'); - -class Google extends Component { - render() { - const { cx, hint } = this.props; - - const js1 = `(function() { - var cx = '${cx}'; - var gcse = document.createElement('script'); - gcse.type = 'text/javascript'; - gcse.async = true; - gcse.src = 'https://cse.google.com/cse.js?cx=' + cx; - var s = document.getElementsByTagName('script')[0]; - s.parentNode.insertBefore(gcse, s); - })();`; - - const js2 = `(function (document, $) { - function debounce(func, wait, immediate) { - var timeout; - return function() { - var context = this, args = arguments; - var later = function() { - timeout = null; - if (!immediate) func.apply(context, args); - }; - var callNow = immediate && !timeout; - clearTimeout(timeout); - timeout = setTimeout(later, wait); - if (callNow) func.apply(context, args); - }; - }; - - $(document).on('click', '.navbar-main .search', function () { - $('.searchbox').toggleClass('show'); - }).on('click', '.searchbox .searchbox-mask', function () { - $('.searchbox').removeClass('show'); - }).on('click', '.searchbox-close', function () { - $('.searchbox').removeClass('show'); - }).on('keydown', '.searchbox-input', debounce(function () { - var value = $(this).val(); - try { - var element = google.search.cse.element.getElement('searchresults-only0'); - if (value.trim() === '') { - element.clearAllResults(); - } else { - element.execute(value); - } - } catch (e) {} - }, 300)); - })(document, jQuery);`; - - return - - - ; - } -} - -module.exports = cacheComponent(Google, 'search.google', props => { - const { helper, search } = props; - - return { - cx: search.cx, - hint: helper.__('search.hint') - }; -}); diff --git a/layout/search/insight.jsx b/layout/search/insight.jsx deleted file mode 100644 index bb34977..0000000 --- a/layout/search/insight.jsx +++ /dev/null @@ -1,58 +0,0 @@ -const { Component, Fragment } = require('inferno'); -const { cacheComponent } = require('../util/cache'); - -class Insight extends Component { - render() { - const { hint, translation, contentUrl, jsUrl, cssUrl } = this.props; - - const js = `(function (window) { - var INSIGHT_CONFIG = { - TRANSLATION: { - POSTS: '${translation.posts}', - PAGES: '${translation.pages}', - CATEGORIES: '${translation.categories}', - TAGS: '${translation.tags}', - UNTITLED: '${translation.untitled}', - }, - CONTENT_URL: '${contentUrl}', - }; - window.INSIGHT_CONFIG = INSIGHT_CONFIG; - })(window);`; - - return - - - - - ; - } -} - -module.exports = cacheComponent(Insight, 'search.insight', props => { - const { helper } = props; - const { url_for, my_cdn } = helper; - - return { - hint: helper.__('search.hint'), - translation: { - posts: helper.__('insight.posts'), - pages: helper.__('insight.pages'), - categories: helper.__('insight.categories'), - tags: helper.__('insight.tags'), - untitled: helper.__('insight.untitled') - }, - contentUrl: my_cdn(url_for('/content.json')), - jsUrl: my_cdn(url_for('/js/insight.js')), - cssUrl: my_cdn(url_for('/css/insight.css')) - }; -}); diff --git a/layout/share/.gitkeep b/layout/share/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/layout/share/addthis.jsx b/layout/share/addthis.jsx deleted file mode 100644 index 95c3d71..0000000 --- a/layout/share/addthis.jsx +++ /dev/null @@ -1,26 +0,0 @@ -const { Component, Fragment } = require('inferno'); -const { cacheComponent } = require('../util/cache'); - -class AddThis extends Component { - render() { - const { installUrl } = this.props; - if (!installUrl) { - return
    - You need to set install_url to use AddThis. - Please set it in _config.yml. -
    ; - } - return -
    - -
    ; - } -} - -module.exports = cacheComponent(AddThis, 'share.addthis', props => { - const { share } = props; - - return { - installUrl: share.install_url - }; -}); diff --git a/layout/share/addtoany.jsx b/layout/share/addtoany.jsx deleted file mode 100644 index e87b5ad..0000000 --- a/layout/share/addtoany.jsx +++ /dev/null @@ -1,22 +0,0 @@ -const { Component, Fragment } = require('inferno'); -const { cacheComponent } = require('../util/cache'); - -class AddToAny extends Component { - render() { - return -
    - - - - - - -
    - -
    ; - } -} - -module.exports = cacheComponent(AddToAny, 'share.addtoany', props => { - return {}; -}); diff --git a/layout/share/bdshare.jsx b/layout/share/bdshare.jsx deleted file mode 100644 index fcadd93..0000000 --- a/layout/share/bdshare.jsx +++ /dev/null @@ -1,23 +0,0 @@ -const { Component, Fragment } = require('inferno'); -const { cacheComponent } = require('../util/cache'); - -class BdShare extends Component { - render() { - const js = 'window._bd_share_config = { "common": { "bdSnsKey": {}, "bdText": "", "bdMini": "2", "bdPic": "", "bdStyle": "0", "bdSize": "16" }, "share": {} }; with (document) 0[(getElementsByTagName(\'head\')[0] || body).appendChild(createElement(\'script\')).src = \'http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion=\' + ~(-new Date() / 36e5)];'; - return -
    - - - - - - -
    - -
    ; - } -} - -module.exports = cacheComponent(BdShare, 'share.bdshare', props => { - return {}; -}); diff --git a/layout/share/sharejs.jsx b/layout/share/sharejs.jsx deleted file mode 100644 index 80b3657..0000000 --- a/layout/share/sharejs.jsx +++ /dev/null @@ -1,22 +0,0 @@ -const { Component, Fragment } = require('inferno'); -const { cacheComponent } = require('../util/cache'); - -class ShareJs extends Component { - render() { - const { cssUrl, jsUrl } = this.props; - return - - - - ; - } -} - -module.exports = cacheComponent(ShareJs, 'share.sharejs', props => { - const { helper } = props; - - return { - cssUrl: helper.cdn('social-share.js', '1.0.16', 'dist/css/share.min.css'), - jsUrl: helper.cdn('social-share.js', '1.0.16', 'dist/js/social-share.min.js') - }; -}); diff --git a/layout/share/sharethis.jsx b/layout/share/sharethis.jsx deleted file mode 100644 index 60a04f9..0000000 --- a/layout/share/sharethis.jsx +++ /dev/null @@ -1,26 +0,0 @@ -const { Component, Fragment } = require('inferno'); -const { cacheComponent } = require('../util/cache'); - -class ShareThis extends Component { - render() { - const { installUrl } = this.props; - if (!installUrl) { - return
    - You need to set install_url to use ShareThis. - Please set it in _config.yml. -
    ; - } - return -
    - -
    ; - } -} - -module.exports = cacheComponent(ShareThis, 'share.sharethis', props => { - const { share } = props; - - return { - installUrl: share.install_url - }; -}); diff --git a/layout/tags.jsx b/layout/tags.jsx index 2464ebd..e8c5a38 100644 --- a/layout/tags.jsx +++ b/layout/tags.jsx @@ -1,10 +1,10 @@ const { Component } = require('inferno'); -const Tags = require('./widget/tags'); +const Tags = require('hexo-component-inferno/lib/view/widget/tags'); module.exports = class extends Component { render() { const { site, helper } = this.props; - return ; + return ; } }; diff --git a/layout/util/cache.jsx b/layout/util/cache.jsx deleted file mode 100644 index b37d6a3..0000000 --- a/layout/util/cache.jsx +++ /dev/null @@ -1,48 +0,0 @@ -const crypto = require('crypto'); -const { Component } = require('inferno'); // eslint-disable-line no-unused-vars -const { createElement } = require('inferno-create-element'); - -const cache = {}; - -function computeHash(props) { - return crypto.createHash('md5').update(JSON.stringify(props)).digest('hex'); -} - -module.exports = { - - /** - * Create cached component from a given component class. - * The cache ID is caculated from the input props. - * - * @param {Component} type JSX component class - * @param {string} prefix Cache ID prefix - * @param {Function} transform Transform the input props to target props and - * its result is used to compute cache ID - * @returns A cache-enabled component. - * It returns cached JSX element when called if cache ID is found. - * It returns null if the props transform result is empty, which means the props - * passed to the createElement() indicates the element does not need to be created. - * Otherwise, it creates a new element and caches it if the transform function is provided. - * The original component can be accessed from the `_type` property of the return value. - * The props transform function can be accessed from the `_transform` property of the return value. - */ - cacheComponent(type, prefix, transform) { - const component = props => { - const targetProps = transform(props); - if (!targetProps) { - return null; - } - const cacheId = prefix + '-' + computeHash(targetProps); - if (!cacheId) { - return createElement(type, targetProps); - } - if (!cache[cacheId]) { - cache[cacheId] = createElement(type, targetProps); - } - return cache[cacheId]; - }; - component._type = type; - component._transform = transform; - return component; - } -}; diff --git a/layout/util/classname.jsx b/layout/util/classname.jsx deleted file mode 100644 index 3277c2d..0000000 --- a/layout/util/classname.jsx +++ /dev/null @@ -1,12 +0,0 @@ -module.exports = function(classname) { - if (typeof classname === 'string') { - return classname; - } - if (Array.isArray(classname)) { - return classname.join(' '); - } - if (typeof classname === 'object') { - return Object.keys(classname).filter(key => !!classname[key]).join(' '); - } - throw new Error('Cannot process class name' + JSON.stringify(classname)); -}; diff --git a/layout/widget/ads_x.jsx b/layout/widget/ads_x.jsx new file mode 100644 index 0000000..0f0dc16 --- /dev/null +++ b/layout/widget/ads_x.jsx @@ -0,0 +1,41 @@ +const {Component} = require('inferno'); +const {cacheComponent} = require('hexo-component-inferno/lib/util/cache'); + +class AdSenseX extends Component { + render() { + const {clientId, slotId} = this.props; + return
    +
    +
    + {/* +
    */} + + + +
    +
    +
    + } +} + +module.exports = cacheComponent(AdSenseX, 'widget.adsense_x', props => { + const {config, display} = props; + const {adsense_client_id, adsense_slot_id} = config; + if (!adsense_client_id || !adsense_slot_id || !display) { + return null; + } + return { + clientId: adsense_client_id, + slotId: adsense_slot_id + }; +}); diff --git a/layout/widget/adsense.jsx b/layout/widget/adsense.jsx index 18ba7ab..f03b275 100644 --- a/layout/widget/adsense.jsx +++ b/layout/widget/adsense.jsx @@ -1,44 +1,43 @@ -const { Component } = require('inferno'); -const { cacheComponent } = require('../util/cache'); +const {Component} = require('inferno'); +const {cacheComponent} = require('hexo-component-inferno/lib/util/cache'); class AdSense extends Component { render() { - const { title, clientId, slotId } = this.props; - if (!clientId || !slotId) { - return
    + const {title, clientId, slotId} = this.props; + return
    +
    -
    - You need to set client_id and slot_id to show this AD unit. - Please set it in _config.yml. + -
    -
    ; - } - return
    -
    -
    -
    ; +
    } } -module.exports = cacheComponent(AdSense, 'widget.adsense', props => { - const { widget, helper } = props; - const { client_id, slot_id } = widget; - +module.exports = AdSense.Cacheable = cacheComponent(AdSense, 'widget.adsense', props => { + const {helper, config} = props; + const {adsense_client_id, adsense_slot_id} = config; + if (!adsense_client_id || !adsense_slot_id) { + return null; + } return { title: helper.__('widget.adsense'), - clientId: client_id, - slotId: slot_id + clientId: adsense_client_id, + slotId: adsense_slot_id }; }); diff --git a/layout/widget/archives.jsx b/layout/widget/archives.jsx index 7c72747..a54448e 100644 --- a/layout/widget/archives.jsx +++ b/layout/widget/archives.jsx @@ -1,5 +1,5 @@ const { Component } = require('inferno'); -const { cacheComponent } = require('../util/cache'); +const { cacheComponent } = require('hexo-component-inferno/lib/util/cache'); class Archives extends Component { render() { @@ -43,7 +43,7 @@ class Archives extends Component { } } -module.exports = cacheComponent(Archives, 'widget.archives', props => { +module.exports = Archives.Cacheable = cacheComponent(Archives, 'widget.archives', props => { // adapted from hexo/lib/plugins/helper/list_archives.js const { site, diff --git a/layout/widget/categories.jsx b/layout/widget/categories.jsx index 90067e8..ea43b92 100644 --- a/layout/widget/categories.jsx +++ b/layout/widget/categories.jsx @@ -1,5 +1,6 @@ const { Component } = require('inferno'); -const { cacheComponent } = require('../util/cache'); +const { cacheComponent } = require('hexo-component-inferno/lib/util/cache'); +const AdsenseX = require('./ads_x'); class Categories extends Component { @@ -28,27 +29,31 @@ class Categories extends Component { } = this.props; var count={n: 0}; - return
    -
    - ; +
    + {isPage ? : null} + } } -module.exports = cacheComponent(Categories, 'widget.categories', props => { +module.exports = Categories.Cacheable = cacheComponent(Categories, 'widget.categories', props => { // adapted from hexo/lib/plugins/helper/list_categories.js const { page, diff --git a/layout/widget/hot_recommend.jsx b/layout/widget/hot_recommend.jsx index 4b61c04..02870f9 100644 --- a/layout/widget/hot_recommend.jsx +++ b/layout/widget/hot_recommend.jsx @@ -1,5 +1,5 @@ const { Component } = require('inferno'); -const { cacheComponent } = require('../util/cache'); +const { cacheComponent } = require('hexo-component-inferno/lib/util/cache'); class HotRecommend extends Component { render() { diff --git a/layout/widget/latest_comment.jsx b/layout/widget/latest_comment.jsx index 3accca0..d2072c2 100644 --- a/layout/widget/latest_comment.jsx +++ b/layout/widget/latest_comment.jsx @@ -1,5 +1,5 @@ const { Component } = require('inferno'); -const { cacheComponent } = require('../util/cache'); +const { cacheComponent } = require('hexo-component-inferno/lib/util/cache'); class LatestComment extends Component { render() { diff --git a/layout/widget/links.jsx b/layout/widget/links.jsx deleted file mode 100644 index 35891ef..0000000 --- a/layout/widget/links.jsx +++ /dev/null @@ -1,45 +0,0 @@ -const { URL } = require('url'); -const { Component } = require('inferno'); -const { cacheComponent } = require('../util/cache'); - -class Links extends Component { - render() { - const { title, links } = this.props; - return
    -
    - -
    -
    ; - } -} - -module.exports = cacheComponent(Links, 'widget.links', props => { - const { helper, widget } = props; - if (!Object.keys(widget.links).length) { - return null; - } - return { - title: helper.__('widget.links'), - links: widget.links - }; -}); diff --git a/layout/widget/notice.jsx b/layout/widget/notice.jsx deleted file mode 100644 index 555d52f..0000000 --- a/layout/widget/notice.jsx +++ /dev/null @@ -1,36 +0,0 @@ -const { URL } = require('url'); -const { Component } = require('inferno'); -const { cacheComponent } = require('../util/cache'); - -class Links extends Component { - render() { - const { title, contents } = this.props; - return
    -
    - -
    -
    ; - } -} - -module.exports = cacheComponent(Links, 'widget.links', props => { - const { helper, widget } = props; - if (!Object.keys(widget.contents).length) { - return null; - } - return { - title: helper.__('widget.notice'), - contents: widget.contents - }; -}); diff --git a/layout/widget/profile.jsx b/layout/widget/profile.jsx index 87d486f..95e34ef 100644 --- a/layout/widget/profile.jsx +++ b/layout/widget/profile.jsx @@ -1,6 +1,6 @@ const { Component } = require('inferno'); const gravatrHelper = require('hexo-util').gravatar; -const { cacheComponent } = require('../util/cache'); +const { cacheComponent } = require('hexo-component-inferno/lib/util/cache'); class Profile extends Component { renderSocialLinks(links) { @@ -48,7 +48,7 @@ class Profile extends Component {
    - {author} + {author}
    {author ?

    {author}

    : null} {authorTitle ?

    {authorTitle}

    : null} @@ -88,7 +88,7 @@ class Profile extends Component { {followLink ? : null} - {this.renderSocialLinks(socialLinks)} + {socialLinks ? this.renderSocialLinks(socialLinks) : null} {hasHitokoto == undefined || hasHitokoto ?

    :D 一言句子获取中...

    @@ -100,7 +100,7 @@ class Profile extends Component { } } -module.exports = cacheComponent(Profile, 'widget.profile', props => { +Profile.Cacheable = cacheComponent(Profile, 'widget.profile', props => { const { site, helper, widget } = props; const { avatar, @@ -129,7 +129,7 @@ module.exports = cacheComponent(Profile, 'widget.profile', props => { const categoryCount = site.categories.filter(category => category.length).length; const tagCount = site.tags.filter(tag => tag.length).length; - const socialLinks = Object.keys(social_links).map(name => { + const socialLinks = social_links ? Object.keys(social_links).map(name => { const link = social_links[name]; if (typeof link === 'string') { return { @@ -142,7 +142,7 @@ module.exports = cacheComponent(Profile, 'widget.profile', props => { url: url_for(link.url), icon: link.icon }; - }); + }) : null; return { avatar: getAvatar(), @@ -169,9 +169,11 @@ module.exports = cacheComponent(Profile, 'widget.profile', props => { }, followLink: url_for(follow_link), followTitle: __('widget.follow'), + socialLinks, hitokotoFrom: __('widget.hitokoto_from'), hitokotoProvider: __('widget.hitokoto_provider'), - socialLinks, hasHitokoto: has_hitokoto }; }); + +module.exports = Profile; diff --git a/layout/widget/recent_posts.jsx b/layout/widget/recent_posts.jsx index 7921126..21efbe5 100644 --- a/layout/widget/recent_posts.jsx +++ b/layout/widget/recent_posts.jsx @@ -1,6 +1,6 @@ const { Component } = require('inferno'); -const { cacheComponent } = require('../util/cache'); -const ArticleMedia = require('../common/article-media'); +const {cacheComponent} = require('hexo-component-inferno/lib/util/cache'); +const ArticleMedia = require('hexo-component-inferno/lib/view/common/article_media'); class RecentPosts extends Component { render() { @@ -23,9 +23,9 @@ class RecentPosts extends Component { } } -module.exports = cacheComponent(RecentPosts, 'widget.recentposts', props => { +module.exports = RecentPosts.Cacheable = cacheComponent(RecentPosts, 'widget.recentposts', props => { const { site, helper } = props; - const { has_thumbnail, get_thumbnail, url_for, __, date_xml, date } = helper; + const { url_for, __, date_xml, date } = helper; if (!site.posts.length) { return null; } @@ -34,7 +34,7 @@ module.exports = cacheComponent(RecentPosts, 'widget.recentposts', props => { title: post.title, date: date(post.date), dateXml: date_xml(post.date), - thumbnail: has_thumbnail(post) ? get_thumbnail(post) : null, + thumbnail: post.thumbnail ? post.thumbnail : null, categories: post.categories.map(category => ({ name: category.name, url: url_for(category.path) diff --git a/layout/widget/recommend_post.jsx b/layout/widget/recommend_post.jsx index edb3a28..5a75a0b 100644 --- a/layout/widget/recommend_post.jsx +++ b/layout/widget/recommend_post.jsx @@ -1,29 +1,31 @@ -const { Component } = require('inferno'); -const { cacheComponent } = require('../util/cache'); +const {Component} = require('inferno'); +const {cacheComponent} = require('hexo-component-inferno/lib/util/cache'); class RecommendPosts extends Component { render() { - const { recommendPost, relatePost, recommend_title, related_title } = this.props; + const {recommendPost, relatePost, recommend_title, related_title} = this.props; var i = 0, j = 0; - return
    + return
    {relatePost.length > 0 ?
    # {related_title} -
    +
    {relatePost.map(post => { j++; - return   {j}.{post.title}
    + return   {j}.{post.title}
    })}
    : null} {recommendPost.length > 0 ?
    # {recommend_title} -
    +
    {recommendPost.map(post => { i++; - return   {i}.{post.title}
    + return   {i}.{post.title}
    })}
    : null} @@ -31,10 +33,10 @@ class RecommendPosts extends Component { } } -module.exports = cacheComponent(RecommendPosts, 'widget.recommendposts', props => { - const { site, helper, curPost } = props; - const { url_for, __ } = helper; - if (!site.posts.length) { +RecommendPosts.Cacheable = cacheComponent(RecommendPosts, 'widget.recommendposts', props => { + const {mysite, helper, curPost} = props; + const {url_for, __} = helper; + if (!mysite.posts.length) { return null; } var relatePost = []; @@ -52,12 +54,12 @@ module.exports = cacheComponent(RecommendPosts, 'widget.recommendposts', props = return cur == post; } - relatePost = site.posts.filter(post => isRelatePost(curPost.categories, post.categories) && curPost.permalink != post.permalink).sort('date', -1).limit(8).map(post => ({ + relatePost = mysite.posts.filter(post => isRelatePost(curPost.categories, post.categories) && curPost.permalink != post.permalink).sort('date', -1).limit(8).map(post => ({ url: url_for(post.link || post.path), title: post.title })); - recommendPost = site.posts.filter((item, index, arr) => item.encrypt != true && item.recommend != undefined && item.recommend > 0).sort('recommend', -1).sort('recommend', -1).limit(6).map(post => ({ + recommendPost = mysite.posts.filter((item, index, arr) => item.encrypt != true && item.recommend != undefined && item.recommend > 0).sort('recommend', -1).sort('recommend', -1).limit(6).map(post => ({ url: url_for(post.link || post.path), title: post.title })); @@ -69,3 +71,5 @@ module.exports = cacheComponent(RecommendPosts, 'widget.recommendposts', props = related_title: __('widget.related_posts') }; }); + +module.exports = RecommendPosts; \ No newline at end of file diff --git a/layout/widget/subscribe_email.jsx b/layout/widget/subscribe_email.jsx deleted file mode 100644 index 3ae8c2c..0000000 --- a/layout/widget/subscribe_email.jsx +++ /dev/null @@ -1,45 +0,0 @@ -const { Component } = require('inferno'); -const { cacheComponent } = require('../util/cache'); - -class SubscribeEmail extends Component { - render() { - const { title, description, feedburnerId, buttonTitle } = this.props; - - return
    -
    - -
    -
    ; - } -} - -module.exports = cacheComponent(SubscribeEmail, 'widget.subscribeemail', props => { - const { helper, widget } = props; - const { feedburner_id, description } = widget; - - return { - description, - feedburnerId: feedburner_id, - title: helper.__('widget.subscribe_email'), - buttonTitle: helper.__('widget.subscribe') - }; -}); diff --git a/layout/widget/tags.jsx b/layout/widget/tags.jsx index 20bcd4f..ea28bc8 100644 --- a/layout/widget/tags.jsx +++ b/layout/widget/tags.jsx @@ -1,5 +1,6 @@ const { Component } = require('inferno'); -const { cacheComponent } = require('../util/cache'); +const { cacheComponent } = require('hexo-component-inferno/lib/util/cache'); +const AdsenseX = require('./ads_x'); class Tags extends Component { render() { @@ -12,7 +13,9 @@ class Tags extends Component { } = this.props; var count = 0; - return
    + return + {isPage ? : null} +
    -
    ; +
    + {isPage ? : null} + } } -module.exports = cacheComponent(Tags, 'widget.tags', props => { +module.exports = Tags.Cacheable = cacheComponent(Tags, 'widget.tags', props => { // adapted from hexo/lib/plugins/helper/list_tags.js const { helper, diff --git a/layout/widget/toc.jsx b/layout/widget/toc.jsx index 0969510..b3601be 100644 --- a/layout/widget/toc.jsx +++ b/layout/widget/toc.jsx @@ -1,44 +1,53 @@ -const { tocObj: getTocObj } = require('hexo-util'); -const { Component } = require('inferno'); -const { cacheComponent } = require('../util/cache'); +const {tocObj: getTocObj, unescapeHTML} = require('hexo-util'); +const {Component} = require('inferno'); +const {cacheComponent} = require('hexo-component-inferno/lib/util/cache'); + +/** + * Table of contents widget JSX component. + * @module view/widget/toc + */ + /** * Export a tree of headings of an article - * { - * "1": { - * "id": "How-to-enable-table-of-content-for-a-post", - * "text": "How to enable table of content for a post", - * "index": "1" - * }, - * "2": { - * "1": { - * "1": { - * "id": "Third-level-title", - * "text": "Third level title", - * "index": "2.1.1" - * }, - * "id": "Second-level-title", - * "text": "Second level title", - * "index": "2.1" - * }, - * "2": { - * "id": "Another-second-level-title", - * "text": "Another second level title", - * "index": "2.2" - * }, - * "id": "First-level-title", - * "text": "First level title", - * "index": "2" - * } - * } + * @private + * @example + * getToc('HTML content...'); + * // { + * // "1": { + * // "id": "How-to-enable-table-of-content-for-a-post", + * // "text": "How to enable table of content for a post", + * // "index": "1" + * // }, + * // "2": { + * // "1": { + * // "1": { + * // "id": "Third-level-title", + * // "text": "Third level title", + * // "index": "2.1.1" + * // }, + * // "id": "Second-level-title", + * // "text": "Second level title", + * // "index": "2.1" + * // }, + * // "2": { + * // "id": "Another-second-level-title", + * // "text": "Another second level title", + * // "index": "2.2" + * // }, + * // "id": "First-level-title", + * // "text": "First level title", + * // "index": "2" + * // } + * // } */ function getToc(content) { const toc = {}; const levels = [0, 0, 0]; - const tocObj = getTocObj(content, { min_depth: 1, max_depth: 6 }); - const minLevel = Math.min(...tocObj.map(item => item.level)); - tocObj.forEach(item => { - const { text, id } = item; + const tocObj = getTocObj(content, {min_depth: 1, max_depth: 6}); + const minLevel = Math.min(...tocObj.map((item) => item.level)); + tocObj.forEach((item) => { + const {text, id} = item; const level = item.level - minLevel; for (let i = 0; i < levels.length; i++) { @@ -68,105 +77,98 @@ function getToc(content) { return toc; } +/** + * Table of contents widget JSX component. + * + * @example + * + */ class Toc extends Component { - renderToc(toc) { + renderToc(toc, showIndex = true) { let result; const keys = Object.keys(toc) - .filter(key => !['id', 'index', 'text'].includes(key)) - .map(key => parseInt(key, 10)) + .filter((key) => !['id', 'index', 'text'].includes(key)) + .map((key) => parseInt(key, 10)) .sort((a, b) => a - b); if (keys.length > 0) { - result = ; + result = ; } if ('id' in toc && 'index' in toc && 'text' in toc) { - result =
  • - - {/*{toc.index}*/} - {toc.text} - - {result} -
  • ; + result = ( +
  • + + {showIndex && {toc.index}} + {unescapeHTML(toc.text)} + + {result} +
  • + ); } return result; } render() { + const {showIndex} = this.props; const toc = getToc(this.props.content); - //toc highlight - const js = ` - $(document).ready(function () { //参考自 https://github.com/ppoffice/hexo-theme-icarus/pull/616/files - var observerTopMargin; - var scrollObserver; - var headerElems = $(".headerlink"); - var activeTocItem; - - function initIntersectionObserver(docHeight) { - observerTopMargin = docHeight; - scrollObserver = new IntersectionObserver(scrollCallBack, - { - root: null, // viewpoint - rootMargin: docHeight + "px 0px -80% 0px" // cover top 30% of viewport to the top of document - }) - } - - function scrollCallBack(entries, observer) { - if ($(window).scrollTop() > observerTopMargin * 0.7) { - // User somehow scroll to 70% of observerTopMargin (which is inited as 200% document height) - // Observer top margin need to extend to cover all the space to the top of the document - initIntersectionObserver(observerTopMargin * 2) - observer.disconnect(); - return; - } - let toActive; - if (entries[0].intersectionRatio == 1) { // enter viewed area - let entry = entries.reduce((u, v) => (u.target.toc_id > v.target.toc_id ? u : v)); // get the lowest item - toActive = $("#toc-item-" + $(entry.target).attr("href").substr(1)); - } else { - let entry = entries.reduce((u, v) => (u.target.toc_id < v.target.toc_id ? u : v)); // get the highest item - let idx = Math.max(entry.target.toc_id - 1, 0); - toActive = $("#toc-item-" + $(headerElems[idx]).attr("href").substr(1)); - } - if (activeTocItem) activeTocItem.removeClass("is-current"); - activeTocItem = toActive - activeTocItem.addClass("is-current"); - } - - initIntersectionObserver($(document).height() * 2); - headerElems.each(function (index, obj) { - obj.toc_id = index; - scrollObserver.observe(obj); - }) - });`; if (!Object.keys(toc).length) { return null; } - return
    -
    - ; + ); } } -module.exports = cacheComponent(Toc, 'widget.toc', props => { - const { config, page, helper } = props; - const { layout, content } = page; +/** + * Cacheable table of contents widget JSX component. + *

    + * This class is supposed to be used in combination with the locals hexo filter + * ({@link module:hexo/filter/locals}). + * + * @see module:util/cache.cacheComponent + * @example + * /> + */ +Toc.Cacheable = cacheComponent(Toc, 'widget.toc', (props) => { + const {config, page, widget, helper} = props; + const {layout, content, encrypt, origin} = page; + const {index} = widget; - if (config.toc !== true || (layout !== 'page' && layout !== 'post')) { + if (config.toc !== true || (layout !== 'page' && layout !== 'post') || encrypt) { return null; } return { title: helper._p('widget.catalogue', Infinity), - content + showIndex: index !== false, + content: encrypt ? origin : content, + jsUrl: helper.url_for('/js/toc.js'), }; }); + +module.exports = Toc; \ No newline at end of file diff --git a/package.json b/package.json index 4ab3b02..1c337c7 100644 --- a/package.json +++ b/package.json @@ -1,41 +1,85 @@ { - "name": "hexo-theme-amazing", - "version": "3.0.0", - "private": true, - "engines": { - "node": ">=8.3.0" + "_from": "hexo-theme-amazing@^2.0.0", + "_id": "hexo-theme-amazing@2.0.0", + "_inBundle": false, + "_integrity": "sha512-8u6l4FCVR4/Yo6066nuHPec5TmkuD9G1Pgyu3Djhi+T6/T5bEIgiAUwIjyD3xXgqQY3i8CKSB7AdISOFVosOzA==", + "_location": "/hexo-theme-amazing", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "hexo-theme-amazing@^2.0.0", + "name": "hexo-theme-amazing", + "escapedName": "hexo-theme-amazing", + "rawSpec": "^2.0.0", + "saveSpec": null, + "fetchSpec": "^2.0.0" }, - "description": "A simple, delicate, and modern theme for Hexo", - "repository": "https://github.com/ppoffice/hexo-theme-amazing.git", - "author": "removeif ", - "license": "MIT", - "scripts": { - "lint": "eslint --ext .js --ext .jsx --ext .json .", - "test": "mocha test/index.js", - "postpublish": "PACKAGE_VERSION=$(cat package.json | grep \\\"version\\\" | head -1 | awk -F: '{ print $2 }' | sed 's/[\",]//g' | tr -d '[[:space:]]') && git tag $PACKAGE_VERSION && git push --tags" + "_requiredBy": [ + "#USER", + "/" + ], + "_resolved": "https://registry.npmjs.org/hexo-theme-amazing/-/hexo-theme-amazing-2.0.0.tgz", + "_shasum": "9f96ee5c948ab11f77dfe420464e08229184eb35", + "_spec": "hexo-theme-amazing@^2.0.0", + "_where": "/opt/blog/blog5", + "author": { + "name": "removeif", + "email": "removeif@users.noreply.github.com" + }, + "bugs": { + "url": "https://github.com/removeif/hexo-theme-amazing/issues" + }, + "bundleDependencies": false, + "dependencies": { + "deepmerge": "^4.2.2", + "hexo-component-inferno": "^0.8.2", + "inferno": "^7.3.3", + "inferno-create-element": "^7.3.3", + "moment": "^2.22.2", + "semver": ">=5.0.0" }, + "deprecated": false, + "description": "A simple, delicate, and modern theme for Hexo", "devDependencies": { - "chai": "^4.2.0", - "eslint": "^6.8.0", + "bulma-stylus": "0.8.0", + "eslint": "^7.6.0", "eslint-config-hexo": "^4.1.0", "eslint-plugin-json": "^2.0.1", "eslint-plugin-react": "^7.17.0", - "mocha": "^6.2.2" + "hexo": "^5.0.2", + "hexo-log": "^2.0.0", + "hexo-pagination": "^1.0.0", + "hexo-renderer-inferno": "^0.1.3", + "hexo-renderer-stylus": "^2.0.0", + "hexo-util": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" }, + "homepage": "https://github.com/removeif/hexo-theme-amazing", + "keywords": [ + "hexo", + "theme", + "icarus" + ], + "license": "MIT", + "name": "hexo-theme-amazing", "peerDependencies": { - "ajv": "^6.10.2", "bulma-stylus": "0.8.0", - "deepmerge": "^4.2.2", - "hexo": "^4.2.0", - "hexo-log": "^1.0.0", + "hexo": "^5.0.2", + "hexo-log": "^2.0.0", "hexo-pagination": "^1.0.0", - "hexo-renderer-inferno": "^0.1.1", - "hexo-renderer-stylus": "^1.1.0", - "hexo-util": "^1.8.0", - "inferno": "^7.3.3", - "inferno-create-element": "^7.3.3", - "js-yaml": "^3.13.1", - "moment": "^2.22.2", - "semver": ">=5.0.0" - } -} \ No newline at end of file + "hexo-renderer-inferno": "^0.1.3", + "hexo-renderer-stylus": "^2.0.0", + "hexo-util": "^2.2.0" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/removeif/hexo-theme-amazing.git" + }, + "scripts": { + "lint": "eslint --ext .js --ext .jsx --ext .json ." + }, + "version": "2.0.0" +} diff --git a/source/css/base.styl b/source/css/base.styl deleted file mode 100644 index 8407452..0000000 --- a/source/css/base.styl +++ /dev/null @@ -1,1824 +0,0 @@ -bulma-stylus-root = "../../../../node_modules/bulma-stylus/stylus" - -/* --------------------------------- - * Override Bulma CSS Framework - * --------------------------------- */ -$body-size ?= 14px -$body-background-color ?= #f7f7f7 - -//$family-sans-serif ?= Ubuntu, Roboto, "Open Sans", "Microsoft YaHei", sans-serif -$family-code ?= "Source Code Pro", monospace, "Microsoft YaHei" -$family-sans-serif ?= 'Monda', "PingFang SC", "Microsoft YaHei", sans-serif -//$family-sans-serif ?= 'Itim', 'Monda', 'PingFang SC', 'Microsoft YaHei', sans-serif; - -$primary ?= $blue -$custom-colors ?= { - grey-lightest: { - '1': $grey-lightest - '2': $grey-darker - } -} - -$gap ?= 64px -$tablet ?= 769px -$desktop ?= 1088px -$widescreen ?= 1280px -$fullhd ?= 1472px - -$shadow ?= 0 4px 10px rgba(0, 0, 0, 0.05) - -$title-weight ?= $weight-normal - -$control-height ?= 2.25em -$button-padding-vertical ?= calc(0.375em - 1px) - -$card-radius ?= $radius -$card-media-margin ?= 0.75rem -$card-shadow ?= $shadow, 0 0 1px rgba(0,0,0,0.1) - -$content-heading-weight ?= $weight-normal - -$article-size ?= 1.1rem - -// FIXME: https://github.com/groenroos/bulma-stylus/issues/11 -@import bulma-stylus-root + "/utilities/initial-variables" -@import bulma-stylus-root + "/utilities/functions" -@import bulma-stylus-root + "/utilities/derived-variables" - -$colors = merge($colors, $custom-colors) - -@import bulma-stylus-root + "/utilities/animations" -@import bulma-stylus-root + "/utilities/mixins" -@import bulma-stylus-root + "/utilities/controls" -@import bulma-stylus-root + "/base/_all" -@import bulma-stylus-root + "/components/_all" -@import bulma-stylus-root + "/elements/_all" -@import bulma-stylus-root + "/form/_all" -@import bulma-stylus-root + "/grid/_all" -@import bulma-stylus-root + "/layout/_all" - -/* --------------------------------- - * Custom Layout - * --------------------------------- */ -+widescreen() - .is-1-column .container - .is-2-column .container - .is-3-column .container { - /* 关闭评论图片 后调节 原94%*/ - max-width: 85%; /*screen-widescreen + 2 * extend-width - 2 * gap*/ - width: 85%; - } - max-width: $desktop - 2 * $gap - width: $desktop - 2 * $gap - .column.is-3-widescreen { - flex: none; - width: 24%; - } - .column.is-6-widescreen { - width: 52%; - } - .column.is-4-widescreen { - flex: none; - width: 24%; - } - .column.is-8-widescreen { - width: 76%; - } - .column.is-9-widescreen { - width: 76%; - } - //screen-widescreen + 2 * extend-width - 2 * gap - .navbar > .container .navbar-brand, .container > .navbar .navbar-brand { - margin-left: 0%; - } - - .navbar > .container .navbar-menu, .container > .navbar .navbar-menu { - margin-right: 0.5%; - } - - .level-end { - margin-right: -1.5%; - } - -+fullhd() - .is-2-column .container - max-width: $widescreen - 2 * $gap - width: $widescreen - 2 * $gap - .is-1-column .container - max-width: $desktop - 2 * $gap - width: $desktop - 2 * $gap - .is-1-column .container - .is-2-column .container - .is-3-column .container { - max-width: 80%; - width: 80%; - } - -+tablet() - .column-main, - .column-left, - .column-right, - .column-right-shadow - .widget - &.is-sticky - align-self: flex-start - position: -webkit-sticky - position: sticky - top: .75rem - .column-right-shadow - &.is-sticky - top: 1.5rem - //参考自 https://github.com/ppoffice/hexo-theme-icarus/pull/616/files - .has-navbar-fixed-top - .column-main, - .column-left, - .column-right, - .column-right-shadow - .widget - &.is-sticky - top: 5.5rem; - -.section - padding: 3rem 1.5rem; - -+mobile() - .section - padding: 7rem 1.5rem; - .friend-card-item - width: 100% !important; - .content .gt-container .gt-comment-header { - width: 100%; - } - -.navbar-main - box-shadow: $shadow - .navbar-menu, - .navbar-start, - .navbar-end - align-items: stretch - display: flex - padding: 0 - flex-shrink: 0 - .navbar-menu - flex-grow: 1 - flex-shrink: 0 - overflow-x: auto - .navbar-start - justify-content: flex-start - margin-right: auto - .navbar-end - justify-content: flex-end - margin-left: auto - .navbar-item - display: flex - align-items: center - padding: 1.25rem 0.75rem - &.is-active - color: $primary - background-color: transparent - +until($navbar-breakpoint) - .navbar-menu - justify-content: center - box-shadow: none - .navbar-start - margin-right: 0 - .navbar-end - margin-left: 0 - -.title - color: $black-ter - -.card - border-radius: $card-radius - & + .card, - & + .column-right-shadow - margin-top: 1.5rem - .card-image - overflow: hidden - border-top-left-radius: $card-radius - border-top-right-radius: $card-radius - .media + .media - border: none - margin-top: 0 - -.content - h1 - font-size: 1.75em - h2 - font-size: 1.5em - h3 - font-size: 1.25em - h4 - font-size: 1.125em - h5 - font-size: 1em - pre - font-size: 0.85em - code - padding: 0 - background: transparent - blockquote - footer - strong + cite - margin-left: 0.5em - - -/* --------------------------------- - * Font icon fixes - * --------------------------------- */ -.fa, .fab, .fal, .far, .fas - line-height: inherit - - -/* --------------------------------- - * Fix Gist Snippet - * --------------------------------- */ -.gist - table - tr:hover - background: transparent - td - border: none - .file - all: initial - - -/* --------------------------------- - * Fix code highlight - * --------------------------------- */ -figure.highlight - padding: 0 - width: 100% - position: relative - margin: 1em 0 1em !important - &.folded - .highlight-body - height: 0 - - pre, - table tr:hover - color: inherit - background: transparent - - table - width: auto - - tr td - border: none - tr:not(:first-child) td - padding-top: 0 - tr:not(:last-child) td - padding-bottom: 0 - - pre - padding: 0 - overflow: visible - - .line, - code .hljs - line-height: 1.5rem - - figcaption, - .gutter - background: rgba(200, 200, 200, 0.15) - - figcaption - margin: 0 !important - padding: .3em .0em .3em .75em - font-style: normal - font-size: .8em - - * - color: $grey - - span - font-weight: 500 - font-family: $family-code - - .level-left *:not(:last-child) - margin-right: .5em - - .level-right *:not(:first-child) - margin-left: .5em - - .fold - cursor: pointer - - &.level - overflow : auto - .level-right - a - padding: .0em 0.75em - - - .highlight-body - overflow: auto - - .gutter - text-align: right - - .tag, - .title, - .number, - .section - display: inherit - font: inherit - margin: inherit - padding: inherit - background: inherit - height: inherit - text-align: inherit - vertical-align: inherit - min-width: inherit - border-radius: inherit - - -/* --------------------------------- - * Custom Element/Component styles - * --------------------------------- */ -.button.is-transparent - @extend .button.is-white - background: transparent !important - -article - &.media - .media-content - color: $grey - .title - margin: 0 - line-height: inherit - &.article - .article-meta, - .article-tags - color: $grey - .article-meta - overflow-x: auto - margin-bottom: 0.5rem - .article-more - @extend .button.is-light - .content - font-size: $article-size - blockquote.pullquote - float: right - max-width: 50% - font-size: 1.15rem - position: relative - a - word-wrap: break-word - .pin-icon - color: #3273dc; - font-size: 1.6rem; - margin-right: 20px; - transform: rotate(30deg); - -ms-transform: rotate(30deg); - -moz-transform: rotate(30deg); - -webkit-transform: rotate(30deg); - -o-transform: rotate(30deg); - -footer.footer - background: $white - .level-start - +mobile() - text-align: center - .level-end - .field - flex-wrap: wrap - align-items: center - +mobile() - justify-content: center - margin-top: 1rem - -.navbar-logo, -.footer-logo - img - max-height: 1.75rem - -.thumbnail - object-fit: cover - width: 100% !important - height: 100% !important - -.pagination - .pagination-link, - .pagination-ellipsis, - .pagination-previous, - .pagination-next - a - color: $black-ter - .pagination-link, - .pagination-previous, - .pagination-next - border: none - background: $white - box-shadow: $shadow - .pagination-link.is-current - background: $primary - -.post-navigation - color: $grey - flex-wrap: wrap - justify-content: space-around - .level-item - margin-bottom: 0 - -.searchbox - display: none - top: 0 - left: 0 - width: 100% - height: 100% - z-index: 100 - background: rgba(0, 0, 0, 0.7) - &.show - display: block - &, - .searchbox-container - position: fixed - .searchbox-container - overflow: hidden - .searchbox-selectable - cursor: pointer - .searchbox-input-wrapper - position: relative - .searchbox-input - width: 100% - border: none - outline: none - font-size: 16px - box-shadow: none - font-weight: 200 - border-radius: 0 - background: #fff - line-height: 20px - box-sizing: border-box - padding: 12px 28px 12px 20px - border-bottom: 1px solid #e2e2e2 - .searchbox-close - top: 50% - right: 6px - width: 20px - height: 20px - line-height: 20px - font-size: 16px - margin-top: -11px - position: absolute - text-align: center - display: inline-block - &:hover - color: $primary - .searchbox-result-wrapper - left: 0 - right: 0 - top: 45px - bottom: 0 - overflow-y: auto - position: absolute - .searchbox-container - left: 50% - top: 100px - width: 540px - z-index: 101 - bottom: 100px - margin-left: -270px - box-sizing: border-box -@media screen and (max-width: 559px), screen and (max-height: 479px) - .searchbox .searchbox-container - top: 0 - left: 0 - margin: 0 - width: 100% - height: 100% - background: #f7f7f7 - -@media screen and (min-width: 769px) and (max-width: 1087px) - .card - margin-top: 4rem; - -.timeline - margin-left: 1rem - padding-left: 1.5rem - padding-top: 1rem - border-left: 1px solid hsl(0, 0%, 86%) - .media - position: relative - &:before, - &:last-child:after - content: '' - display: block - position: absolute - left: calc(-5px - 1.5rem) - &:before - width: 9px - height: 9px - top: 1.3rem - background: hsl(0, 0%, 86%) - border-radius: 50% - &:first-child:before - top: 0.3rem - &:last-child:after - top: calc(1.3rem + 9px) - width: 9px - bottom: 0 - background: white - &:first-child:last-child:after - top: calc(0.3rem + 9px) - -.rtl - direction: rtl - .level - &, &.is-mobile - .level-item:not(:last-child) - margin-left: 0.75rem - margin-right: 0 - -.donate - position: relative - .qrcode - display: none - position: absolute - z-index: 99 - bottom: 2.5em - line-height: 0 - overflow: hidden - border-radius: 4px - box-shadow: 0 4px 10px rgba(0,0,0,.1), 0 0 1px rgba(0,0,0,.2) - img - max-width: 140px - &:hover - .qrcode - display: block - &:first-child:not(:last-child) - .qrcode - left: -0.75rem - &:last-child:not(:first-child) - .qrcode - right: -0.75rem - -.gallery-item - .caption - color: $grey - -+mobile() - #toc - display: none - position: fixed - margin: 1rem - left: 0 - right: 0 - bottom: 0 - z-index: 100 - max-height: calc(100vh - 2rem) - overflow-y: auto - #toc-mask - display: none - position: fixed - top: 0 - left: 0 - right: 0 - bottom: 0 - z-index: 99 - background: rgba(0, 0, 0, 0.7) - #toc, - #toc-mask - &.is-active - display: block - -#back-to-top - position: fixed - padding: 8px 0 - transition: 0.4s ease opacity, 0.4s ease width, 0.4s ease transform, 0.4s ease border-radius - opacity: 0 - line-height: 24px - outline: none - transform: translateY(120px) - &.fade-in - opacity: 1 - &.rise-up - transform: translateY(0) - -.pace - user-select: none - pointer-events: none - .pace-progress - top: 0 - right: 100% - width: 100% - height: 2px - z-index: 2000 - position: fixed - background: $primary - -.pace-inactive - display: none - -// Overflow table -.table-overflow - overflow-x: auto - table - width: auto!important - th - word-break: keep-all - -// Video container -.video-container - position: relative - padding-bottom: 56.25% - padding-top: 25px - height: 0 - iframe - position: absolute - top: 0 - left: 0 - width: 100% - height: 100% - -/* --------------------------------- -* ToC Extension -* --------------------------------- */ -.menu-list { - .is-current { - color: #3273dc; - background: #f5f5f5; - } - a:hover { - color: #3273dc; - } -} - -/* --------------------------------- - * ToC Link Position Fix - * --------------------------------- */ -:target::before { - content: ""; - display: block; - height: 5.25rem; - margin: -5.25rem 0 0; -} - -// 自定义图片样式 -.img-x { - position: relative; - overflow-y: hidden; - height: 100%; - white-space: nowrap; - a { - box-sizing: border-box; - text-align: center; - position: relative; - display: inline-block; - padding: 10px 10px; - vertical-align: top; - height: 100%; - width: 40%; - } -} - -.img-y { - position: relative; - overflow-y: hidden; - height: 100%; - white-space: nowrap; - a { - box-sizing: border-box; - text-align: center; - position: relative; - display: inline-block; - padding: 10px 10px; - vertical-align: top; - height: 100%; - width: 30%; - } -} - -// 最新评论CSS -.body_hot_comment .comment-content { - font-size: 0.75em; - letter-spacing: 0.1em; - .card-comment-item { - display: inline-block; - margin-top: 10px; - width: 100%; - .ava { - height: 3rem !important; - margin-right: 0.2em !important; - border-radius: 40px; - } - img { - float: left; - transition: all 0.5s ease-in; - -webkit-transition: all 0.5s ease-in; - -moz-transition: all 0.5s ease-in; - -o-transition: all 0.5s ease-in; - } - - img:hover { - transform: rotate(360deg); - -webkit-transform: rotate(360deg); - -moz-transform: rotate(360deg); - -o-transform: rotate(360deg); - -ms-transform: rotate(360deg); - } - } - :first-child{ - margin-top: unset; - } - .item-header-text { - padding-left: 0.75em; - font-size: 0.75rem; - line-height: 1.5; - -webkit-line-clamp: 1; - overflow: hidden; - -webkit-box-orient: vertical; - display: -webkit-box; - - } - .item-text { - padding-left: 0.75em; - font-size: 0.75rem; - line-height: 1.5; - -webkit-line-clamp: 2; - text-overflow: ellipsis; - overflow: hidden; - height: auto; - -webkit-box-orient: vertical; - word-break: break-all; - display: -webkit-box; - white-space: normal; - } -} - - -.level0 { - background-color: #d9e6fd; - color:#4a4a4a; -} -.level1 { - background-color: #8fb8fb; - color:#4a4a4a; -} -.level2 { - background-color: #5593f7; - color:white; -} -.level3 { - background-color: #3273dc; - color:white; -} - -#index_hot_div { - margin-top: 10px; - display: flex; - flex-wrap: wrap; - .item { - align-items: center; - border-radius: 4px; - display: inline-flex; - font-size: 0.75rem; - height: 2.1rem; - justify-content: center; - line-height: 1.5; - padding-left: 0.5rem; - padding-right: 0.5rem; - white-space: nowrap; - margin-bottom: 0.75rem; - box-shadow: 0px 0px 2px 1px #b5b5b5; - } - -} - -.display-none-class { - display: none; -} - -.not-gallery-item{ - margin-top: 2px; -} - - - // 归档 -.post-calendar-pre { - overflow-x: auto; - justify-content: center; - max-width: 100%; -} -#post-calendar { - display: flex; - justify-context: center; - align-items: center; - left: 0px; - top: 0px; - width: 100%; - height: 200px; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); - margin-bottom: 2rem; -} - - -.post-copyright { - font-size: 1rem; - letter-spacing: 0.02rem; - word-break: break-all; - margin: 1.5rem 0 1.5rem 0; - padding: 1rem 1rem; - border-left: 3px solid #FF1700; - background-color: #F9F9F9; -} - -.recommend-post{ - margin: 0 0 1.5rem 0; -} - - -.content - blockquote - background-color: whitesmoke; - border-left: 3px solid #6190e8; - padding: 1.0em 1.0em; - overflow auto - -content-h-color = #3273dca8 -.content h1 { - font-size: 2em; - color: content-h-color -} - -.content h5 { - color: content-h-color -} - -.content h2 { - font-size: 1.8em; - color: content-h-color -} - -.content h3 { - font-size: 1.3em; - color: content-h-color -} - -.content h4 { - font-size: 1.2em; - color: content-h-color -} - -.content h5 { - color: content-h-color -} - -.hljs-comment, .hljs-quote { - color: #23d160ad !important; -} - -.button.is-small { - border-radius: 2px; -} - - -a.navbar-item:focus, -.navbar-link:focus, -a.navbar-item:focus-within, -.navbar-link:focus-within, -a.navbar-item:hover, -.navbar-link:hover, -a.navbar-item.is-active, -.navbar-link.is-active { - background-color: unset; -} - -.article hr { - background-color: #6190e8; - margin-top: -0.8rem; - margin-bottom: 1rem; - box-shadow: 1px 2px 8px #000; -} - - -.friend-title-item { - font-weight: bold; - text-align: center; -} - - -.friend-card-item { - width: 32%; - border-radius: 2px; - color: #4a4a4a; - padding: 0.5rem; - display: inline-block; - margin: 5px; - margin-top: 15px; - .text-desc { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - .ava { - width: 5rem !important; - height: 5rem !important; - margin: 0 !important; - margin-right: 0.2em !important; - border-radius: 40px; - } - img { - float: left; - transition: all 0.5s ease-in; - -webkit-transition: all 0.5s ease-in; - -moz-transition: all 0.5s ease-in; - -o-transition: all 0.5s ease-in; - } - img:hover { - transform: rotate(360deg); - -webkit-transform: rotate(360deg); - -moz-transform: rotate(360deg); - -o-transform: rotate(360deg); - -ms-transform: rotate(360deg); - } - &:hover { - transform: scale(0.995); - box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.12), 0 0 6px 0 rgba(0, 0, 0, 0.04); - } -} - - -.time-axis-main { - width: 90%; - margin: 30px auto; - .time-axis { - margin: 0; - padding: 0; - position: relative; - } - - .time-axis:before { - content: ''; - position: absolute; - left: 93px; - top: 15px; - width: 1px; - height: 100%; - background-color: #E4E4E4; - } - - .time-axis-item { - list-style: none; - padding-left: 150px; - position: relative; - line-height: 45px; - font-size: 14px; - color: #141414; - } - - .time-axis-date { - position: absolute; - left: -1.9%; - top: 0; - color: #3273dc; - font-style: italic; - font-weight: bold; - } - - .time-axis-title { - background-color: whitesmoke; - border-left: 3px solid #6190e8; - padding: 0.8em 1.0em; - font-weight: bold; - line-height: 25px; - } - - .time-axis-achievement { - background-color: whitesmoke; - border-left: 3px solid #e89b44; - padding: 0em 1.0em; - font-style: italic; - margin-bottom: 30px; - } - - .time-axis-date span { - position: absolute; - right: -25px; - top: 35%; - display: block; - width: 13px; - height: 13px; - border: 1px solid #ccc; - border-radius: 100%; - background-color: #fff; - } - - .time-axis-date span:after { - content: ''; - position: absolute; - left: 0; - top: 0; - right: 0; - bottom: 0; - width: 7px; - height: 7px; - margin: auto; - background-color: #ccc; - border: 1px solid #ccc; - border-radius: 100%; - } - - .time-axis-item:first-child .time-axis-date span { - border-color: #48BEB2; - } - - .time-axis-item:first-child .time-axis-date span:after { - background-color: #48BEB2; - border-color: #48BEB2; - } -} - - -.music-container { - .video-player .fa-video-camera:before { - content: "\f03d"; - } - - .video-player .fa-music:before { - content: "\f001"; - } - #musicarea { - margin: 20px auto; - width: 500px; - } - .music-player { - .d-title { - margin-bottom: 20px; - font-size: 2rem; - font-weight: 700; - text-align: center; - } - } -} - - -.video-player { - - .d-title { - margin-bottom: 20px; - font-size: 2rem; - font-weight: 700; - text-align: center; - } - - .fa { - display: inline-block; - font: normal normal normal 14px / 1 FontAwesome; - font-size: inherit; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - } - - .hits { - text-align: center; - font-size: 13px; - color: #cd0411 - } - - #video-list { - overflow-y: auto; - height: 300px; - blockquote { - font-size: 13px; - text-align: center; - border-right: 3px solid #6190e8; - } - } -} - - -.text-center { - text-align: center; -} - -.markdown-body { - font-family: $family-sans-serif !important; - img { - max-width: 30% !important; - } -} - -#hitokoto { - text-align: center; - cursor: pointer; - padding: 1rem; -} - -.text-tips { - text-align center; - font-size: 0.875em; -} -.social-share { - text-align: center; -} - -// 头像翻转 -.level img { - border-radius: 100px; - transition: all 0.5s ease-in; - -webkit-transition: all 0.5s ease-in; - -moz-transition: all 0.5s ease-in; - -o-transition: all 0.5s ease-in; -} - -.level figure img:hover { - transform: rotate(360deg); - -webkit-transform: rotate(360deg); - -moz-transform: rotate(360deg); - -o-transform: rotate(360deg); - -ms-transform: rotate(360deg); -} - -.content .gt-container .gt-comment-edit { - margin-right: 2%; -} - - -.content { - a { - img { - margin: auto; - display: block; - } - } -} - -.content .gt-container .gt-comment-admin .gt-comment-content { - border: 0.01em solid #deeafb; -} - -.aplayer-narrow{ - -webkit-transform: translateX(-100%); - transform: translateX(-100%); -} - -.aplayer-narrow:hover { - -webkit-transform: translateX(0); - transform: translateX(0); -} - -.aplayer{ - transition: all .5s ease-out; -} - -.aplayer .aplayer-miniswitcher { - background: white !important; -} - -// ============self-talking start -.content .gt-container .gt-comment-header { - font-size: 0.875em; - position: relative; - display: inline-block; - left: -6%; - margin-bottom: 10px; - padding: 0 10% 0 32px; - height: 32px; - line-height: 32px; - border-radius: 0 3px 3px 0; - background-color: #deeafb; -} - -.content .gt-container .gt-comment-content:hover { - -webkit-box-shadow: unset; - box-shadow: unset -} - -.content .gt-container .gt-comment-body { - padding-left: 2%; -} -.self-talking .gt-comment-reply .gt-ico-reply { - display: none; -} - -.content .gt-container .gt-avatar { - display: none !important; -} - - -.article .content .markdown-body a img { - margin-right: 1%; - margin-top: 1%; - display: unset; -} - -.gt-container .gt-comment-content:hover { - -webkit-box-shadow: unset !important; - box-shadow: unset !important; -} - -.toc-scroll { - max-height: 500px; - overflow: auto; -} - - -.navbar-highlight { - background-color #fff !important; -} - -.gt-container .gt-comment-owner { - padding: 0.2em 0.2em !important; - margin: 0 0.5em 0 0.5em !important; -} - - -hr { - margin: .0rem 0; -} - -.level:not(:last-child) { - margin-bottom: .5rem; -} - -.post-navigation .level { - margin-bottom: 1rem; -} - -.text-right { - text-align: right; -} - -.text-left { - text-align: left; -} - -.font1_1 { - font-size 1.1rem; -} - -// ============self-talking end - -// night Mode -// author by removef -// https://removeif.github.io/ -night-color = #151313 -night-color-hover = #7a7a7a -night-link = #3273dc - -.night { - - color: silver!important; - background-color black; - - .aplayer .aplayer-miniswitcher { - background:#c0c0c0 !important; - } - - .navbar-highlight{ - background-color night-color !important; - } - .content blockquote { - background-color: night-color - } - .button.is-light { - background-color: night-color; - } - .tag:not(body) { - background-color: night-color; - } - - strong { - color: white; - } - - .time-axis-achievement { - background-color: night-color; - color: white - } - - .time-axis-title { - background-color: night-color; - color: white - } - - .pagination .pagination-link:not(.is-current), .pagination .pagination-previous, .pagination .pagination-next { - background-color: night-color; - } - - .button.is-white { - color: white; - } - - .button.is-light { - color silver - } - - a:hover { - //background-color night-color-hover - color white - } - - hr{ - background-color: night-color; - } - - .menu-list a:hover { - background-color: night-color-hover; - color night-link - } - .menu-list a { - color silver - } - - .level a:hover { - //background-color: night-color-hover; - color night-link !important - } - - .level .is-rounded:hover { - color white !important - } - - .level .level-item.is-marginless:hover { - background-color: night-color; - color night-link - } - - .level .level-item.is-link:hover { - color white - } - - //.level .level-item .is-size-7:hover { - // background-color: black; - // color white - //} - - .navbar-menu a:hover { - color: night-link - } - - .post-copyright { - background-color: night-color; - } - - #back-to-top:hover { - color night-link - } - - .tags.has-addons .tag:hover { - color night-link - } - - input { - background-color black - color white - } - - .card { - color silver - } - - .has-text-grey { - color silver !important - } - .has-link-black-ter { - color night-link !important - } - .has-link-grey.-link { - color silver - } - .has-link-grey, .has-link-black-ter { - color silver !important; - } - - .menu-label { - color silver !important; - } - - .tag:not(body) { - color silver - } - - #body_hot_comment .comment-content .item { - color silver - } - - .has-text-black-ter { - color silver !important; - } - - .has-text-black-ter:hover { - color night-link !important - } - - .navbar-item, .navbar-link { - color silver - } - - .title { - color silver - } - - .level-item.tag.is-danger { - background-color night-link !important - color silver - } - - .friend-title-item { - color silver - } - - .music-container #musiclist { - background night-color - } - - .meplayer-container { - background-color night-color - } - - // --removeif - .navbar { - background-color night-color - } - .card { - background-color night-color - } - .footer { - background-color night-color - } - .button.is-white { - background-color night-color - } - .cardm { - background-color night-color - } - .waifu-tips { - background-color night-color - color silver - } - // -- - - .has-link-grey.-link:hover { - color night-link !important - } - .has-link-black-ter:hover { - color night-link !important - } - - .timeline .media:last-child:after { - background-color night-color - } - - .level-item.tag.is-danger, - .button:not(.is-white), #index_hot_div, - #post-calendar canvas, - .waifu canvas, - .is-current, - .button.is-marginless .fab, .fas, - .button.is-large, - .gt-btn, - .gt-comment-body pre, - .time-axis-main, - .meplayer-control-play, - .social-share, - .g-emoji, - .fa-envelope - input, - img { - filter: brightness(.6) !important - } - - figure { - filter: brightness(.7) !important - } - - strong { - filter: brightness(.8) !important; - } - - .content blockquote { - border-left: 3px solid #1e4584; - } - - .timeline { - border-left: 1px solid #dbdbdb70; - .media:before { - background: #dbdbdb70; - } - } - - .post-copyright { - border-left: 3px solid #ff170070; - } - - .button.is-light { - filter: brightness(1) !important; - } - - .breadcrumb li.is-active a { - color silver - } - - .menu-list li ul { - border-left: 1px solid #dbdbdb70; - } - - // comment start - - .markdown-body blockquote { - border-left: 0.25em solid #dfe2e590; - } - - .gt-container .gt-comment-content { - background-color black !important - color silver !important - } - - .gt-container .gt-comment-body { - color silver !important - } - - .gt-container .gt-comment-content:hover { - -webkit-box-shadow: 0 0.625em 3.75em 0 #f4f4f4; - box-shadow: 0 0.625em 3.75em 0 black; - } - - textarea { - background-color night-color; - color white; - } - - .gt-container .gt-header-textarea:hover { - background-color: black; - } - - .gt-container .gt-header-textarea { - background-color: black; - } - .ins-section-container { - background-color: night-color; - color: silver; - } - .searchbox .searchbox-input-wrapper .searchbox-input { - background-color: night-color; - } - .cardm { - color: unset; - } - .g-ads-x { - filter: brightness(0.6) !important; - } - .g-ads-y { - filter: brightness(0.6) !important; - } - .google-auto-placed { - filter: brightness(0.6) !important; - } - - .pagination-previous, .pagination-next, .pagination-link { - color: silver; - } - .pagination .pagination-link a, .pagination .pagination-ellipsis a, .pagination .pagination-previous a, .pagination .pagination-next a { - color: silver; - } - - .content .gt-container .gt-comment-header { - background-color: #151313; - } - .content .gt-container .gt-comment-admin .gt-comment-content { - border: 2px solid #151313; - } - - #post-calendar { - background-color:#626161; - //border-radius: 20rem; - } - .button.is-white, .button.is-transparent { - color: silver; - } - - hr, .index-category-tag hr { - background-color: #989898; - } - - .navbar-menu { - background-color: unset; - } - #index_hot_div{ - color: silver; - } - #index_hot_div{ - filter: unset !important; - .item{ - filter: brightness(0.6) !important; - } - } - .gt-container .gt-meta { - border-bottom: 2px solid #989898; - } - - figure.highlight figcaption * { - color: unset; - } - - figure.highlight figcaption.level .level-right a { - color: silver; - } - - .menu-list .is-current { - color: #3273dc; - background: #7a7a7a; - filter: unset !important; - } - - .friend-card-item { - color: unset; - } - - .index-category-tag{ - .button.is-small { - color: silver; - filter: unset !important; - } - .article-more:hover{ - background-color: unset !important; - } - } - -} - -////=================本博客使用样式 start -// -//// 首页去图 -//.body_hot_comment .comment-content .card-comment-item .ava, .media-left, .is-6-widescreen .card-image { -// display: none; -//} -// -//hover-color = #deeafb; -//// 去card -//.card { -// background-color: unset; -// //box-shadow: unset; -//} -// -//.navbar, footer.footer { -// background-color: unset; -//} -// -//body:not(.night) .navbar:hover, -//body:not(.night) .footer:hover, -//body:not(.night) .card:hover, -//body:not(.night) .pagination:hover, -//body:not(.night) .post-navigation:hover{ -// background-color: hover-color; -// box-shadow: 0 4px 10px rgba(0,0,0,0.05),0 0 1px rgba(0,0,0,0.1); -//} -// -//.pagination, .post-navigation{ -// padding: 10px; -// padding-top: 2rem; -//} -// -//.pagination .pagination-link:not(.is-current), .pagination .pagination-previous, .pagination .pagination-next { -// background-color:rgba(255,255,255,0); -//} -// -//.timeline .media:last-child:after { -// background: unset; -//} -// -//.footer { -// box-shadow: 0px 4px 10px 10px rgba(0,0,0,0.05); -// padding: 3rem 1.5rem 2rem; -//} -// -// -//@media screen and (max-width: 1087px) -// .navbar-menu { -// background-color: unset; -// } -// -////=================本博客使用样式 end - -.index-category-tag{ - margin-bottom: 1rem; - .level-item{ - display: unset; - } - .button.is-small { - border-radius: 2px; - margin-bottom: 4px; - background-color: unset; - } - hr { - background-color: #f5f5f5; - margin-top: .3rem; - margin-bottom: .5rem; - box-shadow: unset; - } -} - -//index banner -/* start commented backslash hack \*/ -* html .clearfix { height: 1%; } - -/* banner css */ -#banner { - margin-bottom: 1rem; - .pull-left { - float: left!important; - } - .pull-right{ - float: right!important; - } - .clearfix:after { - visibility: hidden; - display: block; - font-size: 0; - content: " "; - clear: both; - height: 0; - } - .clearfix { display: inline-block; } - .clearfix { display: block; } - ul,li{ - margin:0; - padding:0; - list-style-type: none; - } - .carousel-box{ - position: relative; - width:100%; - } - .transverse-box{ - position: relative; - width:66.7%; - } - .img-item{ - position: absolute; - top:0; - left:0; - z-index: 0; - } - .vertical-box{ - position: relative; - width:33.3%; - } - .vertical-box ul{ - overflow: hidden; - } - .img-item{ - transition: width 1s; - } - .img-item img{ - width:100%; - height:100%; - } - .vertical-box ul li{ - font-size: 0; - } - .vertical-box ul li img{ - width:100%; - height:100%; - } - .left-arrow{ - display: flex; - justify-content: center; - align-items: center; - position: absolute; - top:50%; - left:0px; - color:#fff; - margin-top:-35px; - font-size: 50px; - font-weight: 200; - text-align: center; - line-height: 100px; - width:50px; - height:70px; - background:rgba(0,0,0,0.6); - cursor: pointer; - z-index: 99; - } - .right-arrow{ - display: flex; - justify-content: center; - align-items: center; - position: absolute; - top:50%; - right:0px; - color:#fff; - margin-top:-35px; - font-size: 50px; - font-weight: 200; - text-align: center; - line-height: 100px; - width:50px; - height:70px; - background:rgba(0,0,0,0.6); - cursor: pointer; - z-index: 99; - } -} - -.index-categories,.index-tags{ - padding: 2px; -} - -article.article .article-meta { - height: 41px; -} \ No newline at end of file diff --git a/source/css/cyberpunk.styl b/source/css/cyberpunk.styl new file mode 100644 index 0000000..bee91a2 --- /dev/null +++ b/source/css/cyberpunk.styl @@ -0,0 +1,307 @@ +$family-sans-serif ?= 'Oxanium', Ubuntu, Roboto, 'Open Sans', 'Microsoft YaHei', sans-serif +$family-code ?= 'Roboto Mono', monospace, 'Microsoft YaHei' +// shadow and radius +$shadow ?= none +$radius ?= 0 +$radius-small ?= 0 +// base colors +$white ?= #fff +$white-bis ?= #cdcdcd +$grey ?= #848484 +$black ?= #000 +$black-bis ?= #050a0e +$orange ?= #ff8e3c +$yellow ?= #fcee09 +$green ?= #00ff41 +$blue ?= #02d7f2 +$purple ?= #9561d2 +$red ?= #ff003c +$primary ?= $yellow +$info ?= $blue +$success ?= $green +$warning ?= $orange +$danger ?= $red +// invert colors +$orange-invert ?= #121617 +$yellow-invert ?= #121617 +$green-invert ?= #121617 +$blue-invert ?= #121617 +$purple-invert ?= #121617 +$red-invert ?= #121617 +$primary-invert ?= #121617 +$info-invert ?= #121617 +$success-invert ?= #121617 +$warning-invert ?= #121617 +$danger-invert ?= #121617 +// derived colors +$scheme-main ?= $black +$link ?= $blue +$link-hover ?= $primary +$text ?= $white-bis +$text-strong ?= $yellow +$body-background-color ?= $scheme-main +$input-color ?= $text +$input-placeholder-color ?= rgba($input-color, .8) +$footer-color ?= $black +$footer-background-color ?= $yellow +$navbar-background-color ?= $yellow +$navbar-item-color ?= $black +$navbar-item-active-color ?= $black +$navbar-item-hover-color ?= $black +$navbar-item-hover-background-color ?= transparent +$navbar-item-margin-v ?= 1.25rem +$navbar-item-margin-h ?= .25rem +$navbar-item-padding-v ?= 0 +$navbar-item-padding-h ?= .5rem +$card-background-color ?= transparent +$menu-label-color ?= $blue +$menu-item-hover-color ?= $black +$menu-item-hover-background-color ?= $yellow +$menu-item-active-color ?= $black +$menu-item-active-background-color ?= $yellow +$menu-list-border-left ?= 1px solid $text +$tag-color ?= $black +$tag-background-color ?= $blue +$timeline-fg-line ?= $blue +$timeline-bg-line ?= $body-background-color +$post-navigation-fg ?= $white-bis +$searchbox-bg-container ?= $black-bis +$searchbox-border ?= $blue +$searchbox-bg-input ?= $black-bis +$searchbox-bg-close-hover ?= $black +$searchbox-bg-close-active ?= $searchbox-bg-close-hover +$searchbox-bg-result-item-hover ?= $black + +@import 'style' + +clip-path(clip) + clip-path: clip + -webkit-clip-path: clip + +cut-corner(size) + clip-path(unquote('polygon(' + size + ' 0, 100% 0, 100% calc(100% - ' + size + '), calc(100% - ' + size + ') 100%, 0 100%, 0 ' + size + ')')) + +cut-corner-reverse(size) + clip-path(unquote('polygon(0 0, calc(100% - ' + size + ') 0, 100% ' + size + ', 100% 100%, ' + size + ' 100%, 0 calc(100% - ' + size + '), 0 0)')) + +cut-corner-top-right(size) + clip-path(unquote('polygon(0 0, calc(100% - ' + size + ') 0, 100% ' + size + ', 100% 100%, 0 100%)')) + +cut-corner-bottom-left(size) + clip-path(unquote('polygon(0 0, 100% 0, 100% 100%, ' + size + ' 100%, 0 calc(100% - ' + size + '))')) + +cut-corner-bottom-right(size) + clip-path(unquote('polygon(0 0, 100% 0, 100% calc(100% - ' + size + '), calc(100% - ' + size + ') 100%, 0 100%)')) + +undercover-before() + position: relative + + &:before + content: '' + position: absolute + z-index: -1 + top: 0 + left: 0 + right: 0 + bottom: 0 + +body + counter-reset: card + +::selection + color: $black + background: $blue + +.card:not(#back-to-top) + position: relative + counter-increment: card + + &, .card-content + undercover-before() + + &:before + top: -1.2px + left: -1.2px + right: -1.2px + bottom: -1.2px + background-color: $blue + cut-corner-reverse(16px) + + &:after + content: 'R' counter(card) + position: absolute + color: $blue + right: 2rem + bottom: -.6em + font-size: .75rem + padding: 0 .25em + background: $body-background-color + + .card-image + cut-corner-top-right(16px) + + .card-content:before + background-color: $body-background-color + cut-corner-reverse(16px) + + .card-image + .card-content:before + cut-corner-bottom-left(16px) + +clip-button($color, $color-invert) + &:before + background-color: $color + color: $color-invert + + &:hover:before, &.is-hovered:before + background-color: darken($color, 2.5%) + color: $color-invert + + &:focus:before, &.is-focused:before + color: $color-invert + + &:active:before, &.is-active:before + background-color: darken($color, 5%) + color: $color-invert + + &[disabled]:before, fieldset[disabled] &:before + background-color: $color + + &.is-inverted + &:before + background-color: $color-invert + color: $color + + &:hover:before, &.is-hovered:before + background-color: darken($color-invert, 5%) + + &[disabled]:before, fieldset[disabled] &:before + background-color: $color-invert + border-color: transparent + box-shadow: none + color: $color + +.button:not(input) + border: none + outline: none + background: transparent !important + undercover-before() + + &:before + cut-corner(8px) + + // clip-path will cut off overflown content inside a button + // thus we need to use :before pseudo-element to style the buttons + for $name, $pair in $colors + $color = $pair['1'] + $color-invert = $pair['2'] + + &.is-{$name} + clip-button($color, $color-invert) + +.field.has-addons + .control:not(:first-child) + .button + cut-corner-bottom-right(8px) + +.menu-list a + cut-corner(8px) + +.tags.has-addons + .tag:first-child + background: $yellow !important + + .tag:last-child + background: $blue !important + +.pagination-previous, .pagination-next, .pagination-link + cut-corner(8px) + + &:hover + background-color: $blue + + &, a + color: $black + +.navbar-main + padding-top: 10px + padding-bottom: 30px + + &:after + content: '' + position: absolute + left: 0 + right: 0 + bottom: -2px + background: url('../img/razor-top-black.svg') repeat-x top + height: 40px + + .navbar-menu + .navbar-item + &:hover, &.is-active + color: $navbar-background-color + background-color: $body-background-color !important + +article.article, article.media + .title a + background-image: linear-gradient(transparent calc(100% - 2px), $text-strong 2px) + background-repeat: no-repeat + background-size: 0 100% + transition: background-size .25s ease-in-out + + .title:hover a + background-size: 100% 100% + +article.article + .article-more + clip-button($info, $info-invert) + +.article-licensing + background: $black-ter + + .licensing-title + a + @extend .size-small, .has-text-grey + +.content + blockquote + background: transparent + border: .5px solid $blue + border-left: 5px solid $blue + +.footer + position: relative + + &:before + content: '' + position: absolute + left: 0 + right: 0 + top: -1px + height: 39px + background: url('../img/razor-bottom-black.svg') repeat-x top + + & > .container + padding-top: 40px + +.timeline .media + &:before + clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%) + +.searchbox .searchbox-container + border: 1px solid $blue + + .searchbox-body + border-bottom: 1px solid $searchbox-border + + li:last-child .searchbox-result-section + border-bottom: none + + .searchbox-result-item + em + color: $black + +#back-to-top + color: $black + background: $blue + margin-top: 45px + cut-corner(8px) diff --git a/source/css/default.styl b/source/css/default.styl new file mode 100644 index 0000000..97102a8 --- /dev/null +++ b/source/css/default.styl @@ -0,0 +1 @@ +@import 'style' diff --git a/source/css/e-style.styl b/source/css/e-style.styl deleted file mode 100644 index 40bfc79..0000000 --- a/source/css/e-style.styl +++ /dev/null @@ -1,10 +0,0 @@ -body{ - //reference https://www.zpf23.cn/ - background: url(/img/background.png); -} - -.night { - .navbar, footer.footer, .card { - background-color: #151313ad; - } -} \ No newline at end of file diff --git a/source/css/insight.css b/source/css/insight.css deleted file mode 100644 index d145ba6..0000000 --- a/source/css/insight.css +++ /dev/null @@ -1,57 +0,0 @@ -.ins-section-container { - position: relative; - background: #f7f7f7; -} - -.ins-section { - font-size: 14px; - line-height: 16px; -} - -.ins-section .ins-section-header, .ins-section .ins-search-item { - padding: 8px 15px; -} - -.ins-section .ins-section-header { - color: #9a9a9a; - border-bottom: 1px solid #e2e2e2; -} - -.ins-section .ins-slug { - margin-left: 5px; - color: #9a9a9a; -} - -.ins-section .ins-slug:before { - content: '('; -} - -.ins-section .ins-slug:after { - content: ')'; -} - -.ins-section .ins-search-item header, .ins-section .ins-search-item .ins-search-preview { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; -} - -.ins-section .ins-search-item header .ins-title { - margin-left: 8px; -} - -.ins-section .ins-search-item .ins-search-preview { - height: 15px; - font-size: 12px; - color: #9a9a9a; - margin: 5px 0 0 20px; -} - -.ins-section .ins-search-item:hover, .ins-section .ins-search-item.active { - color: #fff; - background: #3273dc; -} - -.ins-section .ins-search-item:hover .ins-slug, .ins-section .ins-search-item.active .ins-slug, .ins-section .ins-search-item:hover .ins-search-preview, .ins-section .ins-search-item.active .ins-search-preview { - color: #fff; -} \ No newline at end of file diff --git a/source/css/style.styl b/source/css/style.styl index b19399c..21c070e 100644 --- a/source/css/style.styl +++ b/source/css/style.styl @@ -1,2 +1,24 @@ -@import "base" -@import "helper" +// Base CSS framework +@import '../../include/style/base' +// Helper classes & mixins +@import '../../include/style/helper' +// Icarus components +@import '../../include/style/button' +@import '../../include/style/card' +@import '../../include/style/article' +@import '../../include/style/navbar' +@import '../../include/style/footer' +@import '../../include/style/pagination' +@import '../../include/style/timeline' +@import '../../include/style/search' +@import '../../include/style/codeblock' +@import '../../include/style/donate' +@import '../../include/style/plugin' +@import '../../include/style/responsive' +@import '../../include/style/mystyle/article' +@import '../../include/style/mystyle/navbar' +@import '../../include/style/mystyle/responsive' +@import '../../include/style/mystyle/widget' +@import '../../include/style/mystyle/night' +@import '../../include/style/mystyle/footer' +@import '../../include/style/mystyle/base' diff --git a/source/img/avatar.png b/source/img/avatar.png index 3f7b07d..baba51e 100644 Binary files a/source/img/avatar.png and b/source/img/avatar.png differ diff --git a/source/img/avatar1.png b/source/img/avatar1.png deleted file mode 100644 index baba51e..0000000 Binary files a/source/img/avatar1.png and /dev/null differ diff --git a/source/img/background.png b/source/img/background.png deleted file mode 100644 index 48c736d..0000000 Binary files a/source/img/background.png and /dev/null differ diff --git a/source/img/chat.svg b/source/img/chat.svg deleted file mode 100644 index ba1dc2a..0000000 --- a/source/img/chat.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/source/img/favicon.png b/source/img/favicon.png deleted file mode 100644 index 71ece78..0000000 Binary files a/source/img/favicon.png and /dev/null differ diff --git a/source/img/logo.png b/source/img/logo.png deleted file mode 100644 index cd6a2ce..0000000 Binary files a/source/img/logo.png and /dev/null differ diff --git a/source/img/razor-bottom-black.svg b/source/img/razor-bottom-black.svg new file mode 100644 index 0000000..352165f --- /dev/null +++ b/source/img/razor-bottom-black.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/source/img/razor-top-black.svg b/source/img/razor-top-black.svg new file mode 100644 index 0000000..eec3274 --- /dev/null +++ b/source/img/razor-top-black.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/source/img/thumbnail.svg b/source/img/thumbnail.svg deleted file mode 100644 index 59505dc..0000000 --- a/source/img/thumbnail.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/source/js/.eslintrc.json b/source/js/.eslintrc.json deleted file mode 100644 index 58cddaf..0000000 --- a/source/js/.eslintrc.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "../../.eslintrc.json", - "env": { - "browser": true, - "jquery": true, - "node": false - } -} \ No newline at end of file diff --git a/source/js/animation.js b/source/js/animation.js index f147d8b..50c7c3f 100644 --- a/source/js/animation.js +++ b/source/js/animation.js @@ -3,12 +3,6 @@ return Array.prototype.slice.call(document.querySelectorAll.apply(document, arguments)); } - if ($('.columns .column-right').length && $('.columns .column-right-shadow').length && !$('.columns .column-right-shadow')[0].children.length) { - for (const child of $('.columns .column-right')[0].children) { - $('.columns .column-right-shadow')[0].append(child.cloneNode(true)); - } - } - $('body > .navbar, body > .section, body > .footer').forEach(element => { element.style.transition = '0s'; element.style.opacity = '0'; diff --git a/source/js/back-to-top.js b/source/js/back_to_top.js similarity index 93% rename from source/js/back-to-top.js rename to source/js/back_to_top.js index 6d13157..64ca3bb 100644 --- a/source/js/back-to-top.js +++ b/source/js/back_to_top.js @@ -15,8 +15,7 @@ function loadBackTop() { classname: 'card has-text-centered', left: '', width: 64, - bottom: bottomMargin, - 'border-radius': 4 + bottom: bottomMargin } }; state['desktop-hidden'] = Object.assign({}, state.base, { @@ -26,9 +25,8 @@ function loadBackTop() { classname: state['desktop-hidden'].classname + ' fade-in' }); state['desktop-dock'] = Object.assign({}, state['desktop-visible'], { - classname: state['desktop-visible'].classname + ' fade-in', - width: 40, - 'border-radius': '50%' + classname: state['desktop-visible'].classname + ' fade-in is-rounded', + width: 40 }); state['mobile-hidden'] = Object.assign({}, state.base, { classname: state.base.classname + ' fade-in', @@ -84,7 +82,7 @@ function loadBackTop() { if (!hasRightSidebar()) { return 0; } - return Math.max.apply(null, $rightSidebar.find('.widget').map(function () { + return Math.max.apply(null, $rightSidebar.find('.widget').map(function() { return $(this).offset().top + $(this).outerHeight(true); })); } @@ -147,6 +145,10 @@ function loadBackTop() { $(window).scroll(update); $('#back-to-top').on('click', () => { - $('body, html').animate({ scrollTop: 0 }, 400); + if (CSS && CSS.supports && CSS.supports('(scroll-behavior: smooth)')) { + window.scroll({ top: 0, behavior: 'smooth' }); + } else { + $('body, html').animate({ scrollTop: 0 }, 400); + } }); -} +}; diff --git a/source/js/column.js b/source/js/column.js new file mode 100644 index 0000000..a39d8aa --- /dev/null +++ b/source/js/column.js @@ -0,0 +1,12 @@ +(function() { + function $() { + return Array.prototype.slice.call(document.querySelectorAll.apply(document, arguments)); + } + + // copy widgets in the right column, when exist, to the bottom of the left column + if ($('.columns .column-right').length && $('.columns .column-right-shadow').length && !$('.columns .column-right-shadow')[0].children.length) { + for (const child of $('.columns .column-right')[0].children) { + $('.columns .column-right-shadow')[0].append(child.cloneNode(true)); + } + } +}()); diff --git a/source/js/insight.js b/source/js/insight.js deleted file mode 100644 index 8c503f0..0000000 --- a/source/js/insight.js +++ /dev/null @@ -1,242 +0,0 @@ -/** - * Insight search plugin - * @author PPOffice { @link https://github.com/ppoffice } - */ -(function($, CONFIG) { - const $main = $('.ins-search'); - const $input = $main.find('.ins-search-input'); - const $wrapper = $main.find('.ins-section-wrapper'); - const $container = $main.find('.ins-section-container'); - $main.parent().remove('.ins-search'); - $('body').append($main); - - function section(title) { - return $('

    ').addClass('ins-section') - .append($('
    ').addClass('ins-section-header').text(title)); - } - - function searchItem(icon, title, slug, preview, url) { - return $('
    ').addClass('ins-selectable').addClass('ins-search-item') - .append($('
    ').append($('').addClass('fa').addClass('fa-' + icon)) - .append($('').addClass('ins-title').text(title != null && title !== '' ? title : CONFIG.TRANSLATION.UNTITLED)) - .append(slug ? $('').addClass('ins-slug').text(slug) : null)) - .append(preview ? $('

    ').addClass('ins-search-preview').text(preview) : null) - .attr('data-url', url); - } - - function sectionFactory(type, array) { - let $searchItems; - if (array.length === 0) return null; - const sectionTitle = CONFIG.TRANSLATION[type]; - switch (type) { - case 'POSTS': - case 'PAGES': - $searchItems = array.map(item => { - // Use config.root instead of permalink to fix url issue - return searchItem('file', item.title, null, item.text.slice(0, 150), item.link); - }); - break; - case 'CATEGORIES': - case 'TAGS': - $searchItems = array.map(item => { - return searchItem(type === 'CATEGORIES' ? 'folder' : 'tag', item.name, item.slug, null, item.link); - }); - break; - default: - return null; - } - return section(sectionTitle).append($searchItems); - } - - function parseKeywords(keywords) { - return keywords.split(' ').filter(keyword => { - return !!keyword; - }).map(keyword => { - return keyword.toUpperCase(); - }); - } - - /** - * Judge if a given post/page/category/tag contains all of the keywords. - * @param Object obj Object to be weighted - * @param Array fields Object's fields to find matches - */ - function filter(keywords, obj, fields) { - const keywordArray = parseKeywords(keywords); - const containKeywords = keywordArray.filter(keyword => { - const containFields = fields.filter(field => { - if (!Object.prototype.hasOwnProperty.call(obj, field)) { - return false; - } - if (obj[field].toUpperCase().indexOf(keyword) > -1) { - return true; - } - return false; - }); - if (containFields.length > 0) { - return true; - } - return false; - }); - return containKeywords.length === keywordArray.length; - } - - function filterFactory(keywords) { - return { - post: function(obj) { - return filter(keywords, obj, ['title', 'text']); - }, - page: function(obj) { - return filter(keywords, obj, ['title', 'text']); - }, - category: function(obj) { - return filter(keywords, obj, ['name', 'slug']); - }, - tag: function(obj) { - return filter(keywords, obj, ['name', 'slug']); - } - }; - } - - /** - * Calculate the weight of a matched post/page/category/tag. - * @param Object obj Object to be weighted - * @param Array fields Object's fields to find matches - * @param Array weights Weight of every field - */ - function weight(keywords, obj, fields, weights) { - let value = 0; - parseKeywords(keywords).forEach(keyword => { - const pattern = new RegExp(keyword, 'img'); // Global, Multi-line, Case-insensitive - fields.forEach((field, index) => { - if (Object.prototype.hasOwnProperty.call(obj, field)) { - const matches = obj[field].match(pattern); - value += matches ? matches.length * weights[index] : 0; - } - }); - }); - return value; - } - - function weightFactory(keywords) { - return { - post: function(obj) { - return weight(keywords, obj, ['title', 'text'], [3, 1]); - }, - page: function(obj) { - return weight(keywords, obj, ['title', 'text'], [3, 1]); - }, - category: function(obj) { - return weight(keywords, obj, ['name', 'slug'], [1, 1]); - }, - tag: function(obj) { - return weight(keywords, obj, ['name', 'slug'], [1, 1]); - } - }; - } - - function search(json, keywords) { - const weights = weightFactory(keywords); - const filters = filterFactory(keywords); - const posts = json.posts; - const pages = json.pages; - const tags = json.tags; - const categories = json.categories; - return { - posts: posts.filter(filters.post).sort((a, b) => { return weights.post(b) - weights.post(a); }).slice(0, 5), - pages: pages.filter(filters.page).sort((a, b) => { return weights.page(b) - weights.page(a); }).slice(0, 5), - categories: categories.filter(filters.category).sort((a, b) => { return weights.category(b) - weights.category(a); }).slice(0, 5), - tags: tags.filter(filters.tag).sort((a, b) => { return weights.tag(b) - weights.tag(a); }).slice(0, 5) - }; - } - - function searchResultToDOM(searchResult) { - $container.empty(); - for (const key in searchResult) { - $container.append(sectionFactory(key.toUpperCase(), searchResult[key])); - } - } - - function scrollTo($item) { - if ($item.length === 0) return; - const wrapperHeight = $wrapper[0].clientHeight; - const itemTop = $item.position().top - $wrapper.scrollTop(); - const itemBottom = $item[0].clientHeight + $item.position().top; - if (itemBottom > wrapperHeight + $wrapper.scrollTop()) { - $wrapper.scrollTop(itemBottom - $wrapper[0].clientHeight); - } - if (itemTop < 0) { - $wrapper.scrollTop($item.position().top); - } - } - - function selectItemByDiff(value) { - const $items = $.makeArray($container.find('.ins-selectable')); - let prevPosition = -1; - $items.forEach((item, index) => { - if ($(item).hasClass('active')) { - prevPosition = index; - - } - }); - const nextPosition = ($items.length + prevPosition + value) % $items.length; - $($items[prevPosition]).removeClass('active'); - $($items[nextPosition]).addClass('active'); - scrollTo($($items[nextPosition])); - } - - function gotoLink($item) { - if ($item && $item.length) { - location.href = $item.attr('data-url'); - } - } - - $.getJSON(CONFIG.CONTENT_URL, json => { - if (location.hash.trim() === '#ins-search') { - $main.addClass('show'); - } - $input.on('input', function() { - const keywords = $(this).val(); - searchResultToDOM(search(json, keywords)); - }); - $input.trigger('input'); - }); - - let touch = false; - $(document).on('click focus', '.navbar-main .search', () => { - $main.addClass('show'); - $main.find('.ins-search-input').focus(); - }).on('click touchend', '.ins-search-item', function(e) { - if (e.type !== 'click' && !touch) { - return; - } - gotoLink($(this)); - touch = false; - }).on('click touchend', '.ins-close', e => { - if (e.type !== 'click' && !touch) { - return; - } - $('.navbar-main').css('pointer-events', 'none'); - setTimeout(() => { - $('.navbar-main').css('pointer-events', 'auto'); - }, 400); - $main.removeClass('show'); - touch = false; - }).on('keydown', e => { - if (!$main.hasClass('show')) return; - switch (e.keyCode) { - case 27: // ESC - $main.removeClass('show'); break; - case 38: // UP - selectItemByDiff(-1); break; - case 40: // DOWN - selectItemByDiff(1); break; - case 13: // ENTER - gotoLink($container.find('.ins-selectable.active').eq(0)); break; - } - }).on('touchstart', e => { - touch = true; - }).on('touchmove', e => { - touch = false; - }); -}(jQuery, window.INSIGHT_CONFIG)); diff --git a/source/js/main.js b/source/js/main.js index 07e3740..28f092d 100644 --- a/source/js/main.js +++ b/source/js/main.js @@ -1,11 +1,5 @@ /* eslint-disable node/no-unsupported-features/node-builtins */ -// (mainJs(jQuery, window.moment, window.ClipboardJS, window.IcarusThemeSettings)); - function loadMainJs($, moment, ClipboardJS, config) { - if (!$('.columns .column-right-shadow').children().length) { - $('.columns .column-right-shadow').append($('.columns .column-right').children().clone()); - } - $('.article img:not(".not-gallery-item")').each(function () { // wrap images with link and add caption if possible if ($(this).parent('a').length === 0) { @@ -16,15 +10,15 @@ function loadMainJs($, moment, ClipboardJS, config) { } }); - // render images - if (typeof ($.fn.lightGallery) === 'function') { - $('.article').lightGallery({ selector: '.gallery-item', mode: 'lg-fade' }); + if (typeof $.fn.lightGallery === 'function') { + $('.article').lightGallery({selector: '.gallery-item'}); } - if (typeof ($.fn.justifiedGallery) === 'function') { + if (typeof $.fn.justifiedGallery === 'function') { if ($('.justified-gallery > p > .gallery-item').length) { $('.justified-gallery > p > .gallery-item').unwrap(); } - $('.justified-gallery').justifiedGallery({ rowHeight: 230, margins: 4 }); + // 调整gallery图片渲染尺寸 + $('.justified-gallery').justifiedGallery({rowHeight: 230, margins: 4}); } if (typeof moment === 'function') { @@ -47,6 +41,7 @@ function loadMainJs($, moment, ClipboardJS, config) { $('.navbar-main .navbar-menu').removeClass('justify-content-start'); } } + adjustNavbar(); $(window).resize(adjustNavbar); @@ -141,61 +136,6 @@ function loadMainJs($, moment, ClipboardJS, config) { $mask.on('click', toggleToc); $('.navbar-main .catalogue').on('click', toggleToc); } - - // hexo-util/lib/is_external_link.js - function isExternalLink(input, sitehost, exclude) { - try { - sitehost = new URL(sitehost).hostname; - } catch (e) { } - - if (!sitehost) return false; - - // handle relative url - var data; - try { - data = new URL(input, 'http://' + sitehost); - } catch (e) { - return false; - } - - // handle mailto: javascript: vbscript: and so on - if (data.origin === 'null') return false; - - const host = data.hostname; - - if (exclude) { - exclude = Array.isArray(exclude) ? exclude : [exclude]; - - if (exclude && exclude.length) { - for (const i of exclude) { - if (host === i) return false; - } - } - } - - if (host !== sitehost) return true; - - return false; - } - - if (typeof config !== 'undefined' - && typeof config.site.url !== 'undefined' - && typeof config.site.external_link !== 'undefined' - && config.site.external_link.enable) { - $('.article .content a').filter((i, link) => { - return link.href - && !$(link).attr('href').startsWith('#') - && link.classList.length === 0 - && isExternalLink(link.href, - config.site.url, - config.site.external_link.exclude); - }).each((i, link) => { - link.relList.add('noopener'); - link.target = '_blank'; - }); - } - // load toc fold or show - loadToc(); } function loadMathJax() { //加载mathjax @@ -227,4 +167,4 @@ $(document).ready(function () { navbar1.removeClass("navbar-highlight"); } }); -}); \ No newline at end of file +}); diff --git a/source/js/toc.js b/source/js/toc.js deleted file mode 100644 index 1f61ae7..0000000 --- a/source/js/toc.js +++ /dev/null @@ -1,127 +0,0 @@ -// 参考自 主题https://github.com/fi3ework/hexo-theme-archer -let prevHeight = 0 -function initTocLinksScrollTop(tocLinks) { - return [...tocLinks].map(link => { - return getAbsPosition(link).y - }) -} - -let calcAnchorLink = (heights, currHeight) => { - for (let i = 0; i < heights.length; i++) { - if (Math.abs(currHeight - heights[i]) < 1.1) { - return i - } - } - return -1 -} - -let isPassingThrough = (currHeight, prevHeight, linkHeight) => { - return (currHeight + 1 - linkHeight) * (prevHeight + 1 - linkHeight) <= 0 -} - -function calcScrollIntoScreenIndex(heights, prevHeight, currHeight) { - let anchorLinkIndex = calcAnchorLink(heights, currHeight) - if (anchorLinkIndex >= 0) { - return anchorLinkIndex - } - - for (let i = 0; i < heights.length; i++) { - if (isPassingThrough(currHeight, prevHeight, heights[i])) { - // if is scrolling down, select current - if (currHeight > prevHeight) { - return i - } else { - // if is scrolling up, select previous - return i - 1 - } - } - } -} - -// hide all ol -function hideAllOl(root) { - ;[...root.querySelectorAll('ul')].forEach(li => { - hideItem(li) - }) -} - -function showOrHidden(tocs, cur) { - var i = 0; - tocs.forEach(ul => { - if (i > 0) { - if (ul.innerText.indexOf(cur.innerText) > -1) { - showItem(ul); - } else { - hideItem(ul); - } - } - i++; - }) -} - -// back to default state -function initFold(toc) { - ;[...toc.children].forEach(child => { - hideAllOl(child) - }) - ;[...toc.querySelectorAll('.is-current')].forEach(child => { - child.classList.remove('is-current') - }) -} - -function resetFold(toc) { - initFold(toc) -} - -function hideItem(node) { - node.style.display = 'none' -} - -function showItem(node) { - node.style.display = '' -} - -function getAbsPosition(e) { - let x = e.offsetLeft, - y = e.offsetTop - while ((e = e.offsetParent)) { - x += e.offsetLeft - y += e.offsetTop - } - return { - x: x, - y: y - } -} - -function loadToc() { - let toc = document.querySelector('.toc') - let tocs = document.querySelectorAll('.toc') - let tocItems = document.querySelectorAll('.toc-item') - if (!tocItems.length || toc == null) { - return - } - initFold(toc) - let headers = document.querySelectorAll( - '.article-entry h1, h2, h3, h4, h5, h6' - ) - // get links height - let heights = initTocLinksScrollTop(headers) - document.addEventListener('scroll', () => { - let currHeight = $(document).scrollTop() - let currHeightIndex = calcScrollIntoScreenIndex( - heights, - prevHeight, - currHeight - ) - prevHeight = currHeight - if (typeof currHeightIndex === 'undefined') { - return - } - let currItem = tocItems[currHeightIndex] - if (currItem) { - // show or hidden toc - showOrHidden(tocs, currItem); - } - }) -} \ No newline at end of file