Repository: ppoffice/hexo-theme-icarus Branch: master Commit: 76d8cd019700 Files: 122 Total size: 183.3 KB Directory structure: gitextract_bspt8wyp/ ├── .eslintignore ├── .eslintrc.json ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ ├── Bug反馈.md │ │ ├── bug_report.md │ │ ├── config.yml │ │ ├── feature_request.md │ │ └── 功能建议.md │ ├── PULL_REQUEST_TEMPLATE/ │ │ └── pull_request_template.md │ ├── dependabot.yml │ ├── stale.yml │ └── workflows/ │ ├── github-release.yml │ ├── lint.yml │ ├── npm-publish.yml │ └── test.yml ├── .gitignore ├── .npmignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── include/ │ ├── config.js │ ├── dependency.js │ ├── migration/ │ │ ├── head.js │ │ ├── v2_v3.js │ │ ├── v3_v4.js │ │ ├── v4_v5.js │ │ └── v5_v5.1.js │ ├── register.js │ ├── schema/ │ │ ├── comment/ │ │ │ └── .gitkeep │ │ ├── common/ │ │ │ ├── article.json │ │ │ ├── comment.json │ │ │ ├── donates.json │ │ │ ├── footer.json │ │ │ ├── head.json │ │ │ ├── navbar.json │ │ │ ├── plugins.json │ │ │ ├── providers.json │ │ │ ├── search.json │ │ │ ├── share.json │ │ │ ├── sidebar.json │ │ │ └── widgets.json │ │ ├── config.json │ │ ├── donate/ │ │ │ └── .gitkeep │ │ ├── misc/ │ │ │ └── .gitkeep │ │ ├── plugin/ │ │ │ ├── animejs.json │ │ │ ├── back_to_top.json │ │ │ └── pjax.json │ │ ├── search/ │ │ │ └── .gitkeep │ │ ├── share/ │ │ │ └── .gitkeep │ │ └── widget/ │ │ └── profile.json │ ├── style/ │ │ ├── article.styl │ │ ├── base.styl │ │ ├── button.styl │ │ ├── card.styl │ │ ├── codeblock.styl │ │ ├── donate.styl │ │ ├── footer.styl │ │ ├── helper.styl │ │ ├── navbar.styl │ │ ├── pagination.styl │ │ ├── plugin.styl │ │ ├── responsive.styl │ │ ├── search.styl │ │ ├── timeline.styl │ │ └── widget.styl │ └── util/ │ └── console.js ├── languages/ │ ├── de.yml │ ├── en.yml │ ├── es.yml │ ├── fr.yml │ ├── id.yml │ ├── it.yml │ ├── ja.yml │ ├── ko.yml │ ├── pl.yml │ ├── pt-BR.yml │ ├── ru.yml │ ├── sv.yml │ ├── tk.yml │ ├── tr.yml │ ├── vn.yml │ ├── zh-CN.yml │ └── zh-TW.yml ├── layout/ │ ├── archive.jsx │ ├── categories.jsx │ ├── category.jsx │ ├── comment/ │ │ └── .gitkeep │ ├── common/ │ │ ├── article.jsx │ │ ├── comment.jsx │ │ ├── donates.jsx │ │ ├── footer.jsx │ │ ├── head.jsx │ │ ├── navbar.jsx │ │ ├── plugins.jsx │ │ ├── scripts.jsx │ │ ├── search.jsx │ │ ├── share.jsx │ │ └── widgets.jsx │ ├── donate/ │ │ └── .gitkeep │ ├── index.jsx │ ├── layout.jsx │ ├── misc/ │ │ └── .gitkeep │ ├── page.jsx │ ├── plugin/ │ │ ├── animejs.jsx │ │ ├── back_to_top.jsx │ │ └── pjax.jsx │ ├── post.jsx │ ├── search/ │ │ └── .gitkeep │ ├── share/ │ │ └── .gitkeep │ ├── tag.jsx │ ├── tags.jsx │ └── widget/ │ └── profile.jsx ├── package.json ├── scripts/ │ └── index.js └── source/ ├── css/ │ ├── cyberpunk.styl │ ├── default.styl │ └── style.styl └── js/ ├── .eslintrc.json ├── animation.js ├── back_to_top.js ├── column.js ├── main.js └── pjax.js ================================================ FILE CONTENTS ================================================ ================================================ FILE: .eslintignore ================================================ node_modules/ ================================================ FILE: .eslintrc.json ================================================ { "extends": [ "hexo", "plugin:react/recommended", "plugin:json/recommended" ], "settings": { "node": { "tryExtensions": [ ".js", ".jsx", ".json" ] }, "react": { "version": "16.0" } }, "parserOptions": { "ecmaFeatures": { "jsx": true }, "sourceType": "module", "ecmaVersion": "latest" }, "plugins": [ "react" ], "rules": { "react/jsx-uses-vars": "error", "indent": [ "error", 4, { "SwitchCase": 1 } ], "react/no-unknown-property": [ "error", { "ignore": [ "class", "onclick", "onload", "onsubmit", "crossorigin" ] } ], "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 } ] } } ================================================ FILE: .github/ISSUE_TEMPLATE/Bug反馈.md ================================================ --- 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. 出现‘...’的错误 **期望行为** 简洁清晰地描述没有这个情况下你期望得到的结果。 **截图** 如果可以的话,请附上几张截图来帮助说明你遇到的问题。 **额外上下文** 附上与问题有关的其他上下文信息。 ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.md ================================================ --- 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. ================================================ FILE: .github/ISSUE_TEMPLATE/config.yml ================================================ blank_issues_enabled: false contact_links: - name: GitHub Discussions url: https://github.com/ppoffice/hexo-theme-icarus/discussions about: Redirect your Icarus usage questions to here. - name: GitHub讨论组 url: https://github.com/ppoffice/hexo-theme-icarus/discussions 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可能会被直接关闭。 ================================================ FILE: .github/ISSUE_TEMPLATE/feature_request.md ================================================ --- 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. ================================================ FILE: .github/ISSUE_TEMPLATE/功能建议.md ================================================ --- 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)来了解你的建议是否已经被他人提出过。 **你的功能建议与某个使用问题相关么?请详述。** 简洁清晰地描述你遇到的问题是什么(如:我在使用...的时候遇到了...)。 **描述你想要的解决方案** 简洁清晰地描述你想要的解决方案可以达到的效果。 **描述你考虑过的替代办法** 简洁清晰地描述你考虑过的替代解决方案或是新功能。 **额外上下文** 附上与功能请求有关的其他上下文信息或者截图。 ================================================ FILE: .github/PULL_REQUEST_TEMPLATE/pull_request_template.md ================================================ --- 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. ================================================ FILE: .github/dependabot.yml ================================================ version: 2 updates: - package-ecosystem: 'npm' directory: '/' schedule: interval: 'daily' ================================================ FILE: .github/stale.yml ================================================ # 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 ================================================ FILE: .github/workflows/github-release.yml ================================================ name: GitHub Release on: push: tags: - '*' jobs: publish: runs-on: ubuntu-latest permissions: contents: write steps: - uses: actions/checkout@v3 - uses: ncipollo/release-action@v1 with: tag: ${{ github.ref }} name: ${{ github.ref }} draft: true prerelease: false ================================================ FILE: .github/workflows/lint.yml ================================================ name: Code Linting on: [push, pull_request] jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: latest - run: npm install - run: npm run lint ================================================ FILE: .github/workflows/npm-publish.yml ================================================ name: Node.js Package on: release: types: [published] jobs: publish: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: 14 registry-url: https://registry.npmjs.org/ - run: npm publish env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} ================================================ FILE: .github/workflows/test.yml ================================================ name: Test on: [push, pull_request] jobs: test: runs-on: ubuntu-latest strategy: matrix: node-version: [14, latest] fail-fast: false steps: - uses: actions/checkout@v3 with: repository: hexojs/hexo-starter ref: dcd18588de8f5c1bcc689c101e2f21726c11c4d6 # pin blog dependencies to support node.js 14 - uses: actions/checkout@v3 with: path: themes/icarus - uses: actions/checkout@v3 with: repository: SukkaLab/hexo-many-posts path: source/_posts/hexo-many-posts - uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} - uses: actions/cache@v3 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 hexo-tag-embed - run: npx hexo config theme icarus - run: time NODE_ENV=production npx hexo g -b ================================================ FILE: .gitignore ================================================ # Logs logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* lerna-debug.log* # Diagnostic reports (https://nodejs.org/api/report.html) report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json # Runtime data pids *.pid *.seed *.pid.lock # Directory for instrumented libs generated by jscoverage/JSCover lib-cov # Coverage directory used by tools like istanbul coverage *.lcov # nyc test coverage .nyc_output # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) .grunt # Bower dependency directory (https://bower.io/) bower_components # node-waf configuration .lock-wscript # Compiled binary addons (https://nodejs.org/api/addons.html) build/Release # Dependency directories node_modules/ jspm_packages/ # TypeScript v1 declaration files typings/ # TypeScript cache *.tsbuildinfo # Optional npm cache directory .npm # Optional eslint cache .eslintcache # Microbundle cache .rpt2_cache/ .rts2_cache_cjs/ .rts2_cache_es/ .rts2_cache_umd/ # Optional REPL history .node_repl_history # Output of 'npm pack' *.tgz # Yarn Integrity file .yarn-integrity # dotenv environment variables file .env .env.test # parcel-bundler cache (https://parceljs.org/) .cache # Next.js build output .next # Nuxt.js build / generate output .nuxt dist # Gatsby files .cache/ # Comment in the public line in if your project uses Gatsby and not Next.js # https://nextjs.org/blog/next-9-1#public-directory-support # public # vuepress build output .vuepress/dist # Serverless directories .serverless/ # FuseBox cache .fusebox/ # DynamoDB Local files .dynamodb/ # TernJS port file .tern-port # Stores VSCode versions used for testing VSCode extensions .vscode-test _config*.yml* yarn.lock # Intellij Idea config file .idea *.ipr *.iws *.iml ================================================ FILE: .npmignore ================================================ .github/ .eslintignore .eslintrc.json .travis.yml yarn.lock ================================================ FILE: CONTRIBUTING.md ================================================ # 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. ================================================ FILE: LICENSE ================================================ The MIT License (MIT) 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 in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================


A simple, delicate, and modern theme for the static site generator Hexo.
Preview | Documentation | Discuss on GitHub

![](https://ppoffice.github.io/hexo-theme-icarus/gallery/preview.png?1 "Icarus Preview") ## :cd: Installation ```shell $ npm install hexo-theme-icarus $ hexo config theme icarus ``` Please refer to [Getting Started with Icarus](https://ppoffice.github.io/hexo-theme-icarus/uncategorized/getting-started-with-icarus/) for more details. ## :gift: Features ### Cyberpunk Theme Variant Tap into the future cyber world with the newly added Cyberpunk theme variant. Inspired by [Cyberpunk 2077](https://www.cyberpunk.net). ![Icarus Cyberpunk](https://ppoffice.github.io/hexo-theme-icarus/gallery/screenshots/cyberpunk.png "Icarus Cyberpunk") ### Extensive Plugin Support Icarus includes plentiful search, comment, sharing and other plugins out of the box that makes your blog feature-rich and powerful. **[Comment](https://ppoffice.github.io/hexo-theme-icarus/categories/Plugins/Comment/)** Changyan · Disqus · DisqusJS · Facebook · Gitalk · Gitment · Isso · LiveRe · Utterance · Valine **[Donate Button](https://ppoffice.github.io/hexo-theme-icarus/categories/Plugins/Donation/)** Afdian.net · Alipay · Buy me a coffee · Patreon · Paypal · Wecat **[Search](https://ppoffice.github.io/hexo-theme-icarus/categories/Plugins/Search/)** Algolia · Baidu · Google CSE · Insight **[Share](https://ppoffice.github.io/hexo-theme-icarus/categories/Plugins/Share/)** AddThis · AddToAny · Baidu Share · Share.js · ShareThis **[Widgets](https://ppoffice.github.io/hexo-theme-icarus/categories/Widgets/)** Google Adsense · Archives · Categories · External Site Links · Recent Posts · Google Feedburner · Tags · Table of Contents **[Analytics](https://ppoffice.github.io/hexo-theme-icarus/Plugins/Analytics/icarus-user-guide-web-analytics-plugins/)** Baidu Statistics · Bing Webmaster · BuSuanZi Web Counter · CNZZ Statistics · Google Analytics · Hotjar · StatCounter · Twitter Conversion Tracking **[Other Plugins](https://ppoffice.github.io/hexo-theme-icarus/categories/Plugins/)** Cookie Consent · LightGallery · Justified Gallery · KaTeX · MathJax · Oudated Browser · Page Loading Animations ### Colorful Code Highlight Icarus directly import stylesheets from the [highlight.js](https://highlightjs.org/) package and makes more than 90 code highlight themes available to you.
Atom One Light Monokai Kimbie Dark
### Flexible Theme Configuration Icarus allows you to configure your site on a per-page or per-layout basis.
_config.yml post.md _config.page.yml
widgets:
  - type: profile
    position: left
  - type: recent_posts
    position: right
widgets:
  - type: profile
    position: left
  - type: recent_posts
    position: left
widgets: null
 
 
 
### Responsive Layout Give your audiences best viewing experience with Icarus's mobile-friendly responsive layout. ![Responsive Layout](https://ppoffice.github.io/hexo-theme-icarus/gallery/responsive.png) ## :hammer: Development This project is built with - [Hexo](https://hexo.io/) - [Inferno.js](https://infernojs.org/) - [Stylus](https://stylus-lang.com/) - [Bulma](https://bulma.io/) Please refer to the [documentation](https://ppoffice.github.io/hexo-theme-icarus/categories/) and [contributing guide](https://github.com/ppoffice/hexo-theme-icarus/blob/master/CONTRIBUTING.md) for implementation details. ## :tada: Contribute If you feel like to help us build a better Icarus, you can :black_nib: [Submit a tutorial](https://github.com/ppoffice/hexo-theme-icarus/new/site/source/_posts) | :earth_asia: [Add a translation](https://github.com/ppoffice/hexo-theme-icarus/tree/master/languages) | :triangular_flag_on_post: [Report a bug](https://github.com/ppoffice/hexo-theme-icarus/issues) | :electric_plug: [Suggest a new feature](https://github.com/ppoffice/hexo-theme-icarus/pulls) ## :memo: License This project is licensed under the MIT License - see the [LICENSE](https://github.com/ppoffice/hexo-theme-icarus/blob/master/LICENSE) file for details. ================================================ FILE: include/config.js ================================================ /* eslint no-process-exit: "off" */ const fs = require('fs'); const path = require('path'); const util = require('util'); const crypto = require('crypto'); const createLogger = 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'); const logger = createLogger.default(); 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')) { logger.info('=== Checking theme configurations ==='); const siteCfgFile = path.join(hexo.base_dir, '_config.yml'); const themeSiteCfg = path.join(hexo.base_dir, '_config.icarus.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'); if (!process.argv.includes('--icarus-dont-generate-config')) { 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".'); } } 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)}`); } 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)}.`); } } 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); } }; ================================================ FILE: include/dependency.js ================================================ /* eslint no-process-exit: "off" */ const semver = require('semver'); const createLogger = require('hexo-log'); const packageInfo = require('../package.json'); const { yellow, red, green } = require('./util/console'); const logger = createLogger.default(); module.exports = hexo => { function checkDependency(name, reqVer) { try { require.resolve(name); const version = require(name + '/package.json').version; if (!semver.satisfies(version, reqVer)) { logger.error(`Package ${yellow(name)}'s version (${yellow(version)}) does not satisfy the required version (${red(reqVer)}).`); return false; } return true; } catch (e) { logger.error(`Package ${yellow(name)} is not installed.`); } return false; } logger.info('=== Checking package dependencies ==='); const dependencies = Object.assign({}, 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}@${dependencies[name]}`).join(' '))); logger.error('or:'); logger.error(green('yarn add ' + missingDeps.map(name => `${name}@${dependencies[name]}`).join(' '))); process.exit(-1); } }; ================================================ FILE: include/migration/head.js ================================================ module.exports = require('./v5_v5.1'); ================================================ FILE: include/migration/v2_v3.js ================================================ const createLogger = require('hexo-log'); const deepmerge = require('deepmerge'); const Migration = require('hexo-component-inferno/lib/core/migrate').Migration; const logger = createLogger.default(); module.exports = class extends Migration { constructor() { super('3.0.0', null); } upgrade(config) { const result = deepmerge({}, config); result.head = { favicon: config.favicon || null, canonical_url: config.canonical_url || null, open_graph: config.open_graph || null, meta: config.meta || null, rss: config.rss || null }; delete result.favicon; delete result.canonical_url; delete result.open_graph; delete result.meta; delete result.rss; if (result.logo === '/images/logo.svg') { result.logo = result.logo.replace(/^\/images/, '/img'); } if (result.head.favicon === '/img/favicon.svg') { result.head.favicon = result.head.favicon.replace(/^\/images/, '/img'); } if (result.search && Object.prototype.hasOwnProperty.call(result.search, 'type')) { switch (result.search.type) { case 'google-cse': result.search.type = 'google_cse'; break; } } if (result.comment && Object.prototype.hasOwnProperty.call(result.comment, 'type')) { switch (result.comment.type) { case 'changyan': result.comment.app_id = config.comment.appid; delete result.comment.appid; break; } } 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')) { switch (widget.type) { case 'archive': widget.type = 'archives'; break; case 'category': widget.type = 'categories'; break; case 'tag': widget.type = 'tags'; break; case 'tagcloud': logger.warn('The tagcloud widget has been removed from Icarus in version 3.0.0.'); logger.warn('Please remove it from your configuration file.'); break; } } } } if (result.plugins && typeof result.plugins === 'object') { for (const name in result.plugins) { switch (name) { case 'outdated-browser': result.plugins.outdated_browser = result.plugins[name]; delete result.plugins[name]; break; case 'back-to-top': result.plugins.back_to_top = result.plugins[name]; delete result.plugins[name]; break; case 'baidu-analytics': result.plugins.baidu_analytics = result.plugins[name]; delete result.plugins[name]; break; case 'google-analytics': result.plugins.google_analytics = result.plugins[name]; delete result.plugins[name]; break; } } } return result; } }; ================================================ FILE: include/migration/v3_v4.js ================================================ 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; } }; ================================================ FILE: include/migration/v4_v5.js ================================================ const Migration = require('hexo-component-inferno/lib/core/migrate').Migration; module.exports = class extends Migration { constructor() { super('5.0.0', null); } upgrade(config) { return config; } }; ================================================ FILE: include/migration/v5_v5.1.js ================================================ const Migration = require('hexo-component-inferno/lib/core/migrate').Migration; module.exports = class extends Migration { constructor() { super('5.1.0', null); } upgrade(config) { // Upgrade Waline configurations from v1 to v2. const comment = config.comment || {}; const renamedOptions = { 'visitor': 'pageview', 'uploadImage': 'image_uploader', 'highlight': 'highlighter', 'math': 'tex_renderer' }; if (comment.type === 'waline') { for (const option in renamedOptions) { if (typeof comment[option] !== 'undefined') { if (typeof comment[renamedOptions[option]] === 'undefined') { comment[renamedOptions[option]] = comment[option]; } delete comment[option]; } } } return config; } }; ================================================ FILE: include/register.js ================================================ const createLogger = require('hexo-log'); const logger = createLogger.default(); module.exports = hexo => { 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/manifest')(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/hexo/tag/message')(hexo); require('hexo-component-inferno/lib/hexo/tag/tabs')(hexo); require('hexo-component-inferno/lib/core/view').init(hexo); }; ================================================ FILE: include/schema/comment/.gitkeep ================================================ ================================================ FILE: include/schema/common/article.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$id": "/common/article.json", "description": "Article related configurations", "type": "object", "properties": { "highlight": { "type": "object", "description": "Code highlight settings", "properties": { "theme": { "type": "string", "description": "Code highlight themes\nhttps://github.com/highlightjs/highlight.js/tree/master/src/styles", "default": "atom-one-light", "nullable": true }, "clipboard": { "type": "boolean", "description": "Show copy code button", "default": true, "nullable": true }, "fold": { "type": "string", "description": "Default folding status of the code blocks. Can be \"\", \"folded\", \"unfolded\"", "enum": [ "", "folded", "unfolded" ], "default": "unfolded", "nullable": true } }, "nullable": true }, "readtime": { "type": "boolean", "description": "Whether to show estimated article reading time", "default": true, "nullable": true }, "update_time": { "type": ["boolean", "string"], "description": "Whether to show updated time. For \"auto\", shows article update time only when page.updated is set and it is different from page.date", "default": true, "enum": [true, false, "auto"], "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/" } } ] } } } ================================================ FILE: include/schema/common/comment.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$id": "/common/comment.json", "description": "Comment plugin configurations\nhttps://ppoffice.github.io/hexo-theme-icarus/categories/Plugins/Comment/", "type": "object", "oneOf": [ { "$ref": "/comment/disqus.json" }, { "$ref": "/comment/changyan.json" }, { "$ref": "/comment/disqusjs.json" }, { "$ref": "/comment/facebook.json" }, { "$ref": "/comment/giscus.json" }, { "$ref": "/comment/gitalk.json" }, { "$ref": "/comment/gitment.json" }, { "$ref": "/comment/isso.json" }, { "$ref": "/comment/livere.json" }, { "$ref": "/comment/utterances.json" }, { "$ref": "/comment/valine.json" }, { "$ref": "/comment/waline.json" }, { "$ref": "/comment/twikoo.json" } ] } ================================================ FILE: include/schema/common/donates.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$id": "/common/donates.json", "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" }, { "$ref": "/donate/buymeacoffee.json" }, { "$ref": "/donate/patreon.json" }, { "$ref": "/donate/paypal.json" }, { "$ref": "/donate/wechat.json" } ] } } ================================================ FILE: include/schema/common/footer.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$id": "/common/footer.json", "description": "Page footer configurations", "type": "object", "properties": { "copyright": { "description": "Copyright text", "type": "string", "examples": [ "© 2019", "© 2019 - 2020", "© 2019 - 2020, Company Name", "© 2019 - 2020, Company Name. All rights reserved.", "粤ICP备12345678号" ] }, "links": { "$ref": "/misc/poly_links.json", "description": "Links to be shown on the right of the footer section", "examples": [ { "Creative Commons": { "icon": "fab fa-creative-commons", "url": "https://creativecommons.org/" }, "Attribution 4.0 International": { "icon": "fab fa-creative-commons-by", "url": "https://creativecommons.org/licenses/by/4.0/" }, "Download on GitHub": { "icon": "fab fa-github", "url": "https://github.com/ppoffice/hexo-theme-icarus" } } ] } } } ================================================ FILE: include/schema/common/head.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$id": "/common/head.json", "description": "Page metadata configurations", "type": "object", "properties": { "favicon": { "type": "string", "description": "URL or path to the website's icon", "default": "/img/favicon.svg", "nullable": true }, "manifest": { "$ref": "/misc/manifest.json" }, "open_graph": { "$ref": "/misc/open_graph.json" }, "structured_data": { "$ref": "/misc/structured_data.json" }, "meta": { "$ref": "/misc/meta.json" }, "rss": { "type": "string", "description": "URL or path to the website's RSS atom.xml", "nullable": true } } } ================================================ FILE: include/schema/common/navbar.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$id": "/common/navbar.json", "description": "Page top navigation bar configurations", "type": "object", "properties": { "menu": { "type": "object", "description": "Navigation menu items", "patternProperties": { ".+": { "type": "string", "description": "URL or path of the menu link" } }, "examples": [ { "Home": "/", "Archives": "/archives", "Categories": "/categories", "Tags": "/tags", "About": "/about" } ], "nullable": true }, "links": { "$ref": "/misc/poly_links.json", "description": "Links to be shown on the right of the navigation bar", "examples": [ { "Download on GitHub": { "icon": "fab fa-github", "url": "https://github.com/ppoffice/hexo-theme-icarus" } } ] } } } ================================================ FILE: include/schema/common/plugins.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$id": "/common/plugins.json", "description": "Plugin configurations\nhttps://ppoffice.github.io/hexo-theme-icarus/categories/Plugins/", "type": "object", "properties": { "animejs": { "$ref": "/plugin/animejs.json" }, "back_to_top": { "$ref": "/plugin/back_to_top.json" }, "baidu_analytics": { "$ref": "/plugin/baidu_analytics.json" }, "bing_webmaster": { "$ref": "/plugin/bing_webmaster.json" }, "busuanzi": { "$ref": "/plugin/busuanzi.json" }, "cnzz": { "$ref": "/plugin/cnzz.json" }, "cookie_consent": { "$ref": "/plugin/cookie_consent.json" }, "gallery": { "$ref": "/plugin/gallery.json" }, "google_analytics": { "$ref": "/plugin/google_analytics.json" }, "hotjar": { "$ref": "/plugin/hotjar.json" }, "katex": { "$ref": "/plugin/katex.json" }, "mathjax": { "$ref": "/plugin/mathjax.json" }, "outdated_browser": { "$ref": "/plugin/outdated_browser.json" }, "pjax": { "$ref": "/plugin/pjax.json" }, "progressbar": { "$ref": "/plugin/progressbar.json" }, "statcounter": { "$ref": "/plugin/statcounter.json" }, "twitter_conversion_tracking": { "$ref": "/plugin/twitter_conversion_tracking.json" } } } ================================================ FILE: include/schema/common/providers.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$id": "/common/providers.json", "description": "CDN provider settings\nhttps://ppoffice.github.io/hexo-theme-icarus/Configuration/Theme/speed-up-your-site-with-custom-cdn/", "type": "object", "properties": { "cdn": { "type": "string", "description": "Name or URL template of the JavaScript and/or stylesheet CDN provider", "default": "jsdelivr", "nullable": true }, "fontcdn": { "type": "string", "description": "Name or URL template of the webfont CDN provider", "default": "google", "nullable": true }, "iconcdn": { "type": "string", "description": "Name or URL of the fontawesome icon font CDN provider", "default": "fontawesome", "nullable": true } } } ================================================ FILE: include/schema/common/search.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$id": "/common/search.json", "description": "Search plugin configurations\nhttps://ppoffice.github.io/hexo-theme-icarus/categories/Plugins/Search/", "type": "object", "oneOf": [ { "$ref": "/search/insight.json" }, { "$ref": "/search/baidu.json" }, { "$ref": "/search/google_cse.json" }, { "$ref": "/search/algolia.json" } ] } ================================================ FILE: include/schema/common/share.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$id": "/common/share.json", "description": "Share plugin configurations\nhttps://ppoffice.github.io/hexo-theme-icarus/categories/Plugins/Share/", "type": "object", "oneOf": [ { "$ref": "/share/sharethis.json" }, { "$ref": "/share/addthis.json" }, { "$ref": "/share/addtoany.json" }, { "$ref": "/share/bdshare.json" }, { "$ref": "/share/sharejs.json" } ] } ================================================ FILE: include/schema/common/sidebar.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$id": "/common/sidebar.json", "description": "Sidebar configurations.\nPlease be noted that a sidebar is only visible when it has at least one widget", "type": "object", "properties": { "left": { "type": "object", "description": "Left sidebar configurations", "properties": { "sticky": { "type": "boolean", "description": "Whether the sidebar sticks to the top when page scrolls", "default": false } } }, "right": { "type": "object", "description": "Right sidebar configurations", "properties": { "sticky": { "type": "boolean", "description": "Whether the sidebar sticks to the top when page scrolls", "default": false } } } } } ================================================ FILE: include/schema/common/widgets.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$id": "/common/widgets.json", "description": "Sidebar widget configurations\nhttp://ppoffice.github.io/hexo-theme-icarus/categories/Widgets/", "type": "array", "items": { "type": "object", "properties": { "position": { "type": "string", "description": "Where should the widget be placed, left sidebar or right sidebar", "default": "left" } }, "oneOf": [ { "$ref": "/widget/profile.json" }, { "$ref": "/widget/toc.json" }, { "$ref": "/widget/links.json" }, { "$ref": "/widget/categories.json" }, { "$ref": "/widget/recent_posts.json" }, { "$ref": "/widget/archives.json" }, { "$ref": "/widget/tags.json" }, { "$ref": "/widget/subscribe_email.json" }, { "$ref": "/widget/adsense.json" }, { "$ref": "/widget/followit.json" } ], "required": [ "position" ] } } ================================================ FILE: include/schema/config.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$id": "/config.json", "description": "The configuration file definition", "type": "object", "properties": { "version": { "type": "string", "description": "Version of the configuration file", "default": "5.1.0" }, "variant": { "type": "string", "description": "Icarus theme variant, can be \"default\" or \"cyberpunk\"", "enum": [ "default", "cyberpunk" ], "default": "default" }, "logo": { "type": [ "string", "object" ], "description": "Path or URL to the website's logo", "default": "/img/logo.svg", "properties": { "text": { "type": "string", "description": "Text to be shown in place of the logo image" } }, "required": [ "text" ] }, "head": { "$ref": "/common/head.json" }, "navbar": { "$ref": "/common/navbar.json" }, "footer": { "$ref": "/common/footer.json" }, "article": { "$ref": "/common/article.json" }, "search": { "$ref": "/common/search.json" }, "comment": { "$ref": "/common/comment.json" }, "donates": { "$ref": "/common/donates.json" }, "share": { "$ref": "/common/share.json" }, "sidebar": { "$ref": "/common/sidebar.json" }, "widgets": { "$ref": "/common/widgets.json" }, "plugins": { "$ref": "/common/plugins.json" }, "providers": { "$ref": "/common/providers.json" } }, "required": [ "version" ] } ================================================ FILE: include/schema/donate/.gitkeep ================================================ ================================================ FILE: include/schema/misc/.gitkeep ================================================ ================================================ FILE: include/schema/plugin/animejs.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$id": "/plugin/animejs.json", "description": "Enable page startup animations", "type": "boolean", "default": true } ================================================ FILE: include/schema/plugin/back_to_top.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$id": "/plugin/back_to_top.json", "description": "Show the \"back to top\" button", "type": "boolean", "default": true } ================================================ FILE: include/schema/plugin/pjax.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$id": "/plugin/pjax.json", "description": "Enable PJAX", "type": "boolean", "default": true } ================================================ FILE: include/schema/search/.gitkeep ================================================ ================================================ FILE: include/schema/share/.gitkeep ================================================ ================================================ FILE: include/schema/widget/profile.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$id": "/widget/profile.json", "description": "Profile widget configurations", "type": "object", "properties": { "type": { "type": "string", "const": "profile", "nullable": true }, "author": { "type": "string", "description": "Author name", "examples": [ "Your name" ], "nullable": true }, "author_title": { "type": "string", "description": "Author title", "examples": [ "Your title" ], "nullable": true }, "location": { "type": "string", "description": "Author's current location", "examples": [ "Your location" ], "nullable": true }, "avatar": { "type": "string", "description": "URL or path to the avatar image", "nullable": true }, "avatar_rounded": { "type": "boolean", "description": "Whether show the rounded avatar image", "default": false, "nullable": true }, "gravatar": { "type": "string", "description": "Email address for the Gravatar", "nullable": true }, "follow_link": { "type": "string", "description": "URL or path for the follow button", "examples": [ "https://github.com/ppoffice" ], "nullable": true }, "social_links": { "$ref": "/misc/poly_links.json", "description": "Links to be shown on the bottom of the profile widget", "examples": [ { "Github": { "icon": "fab fa-github", "url": "https://github.com/ppoffice" }, "Facebook": { "icon": "fab fa-facebook", "url": "https://facebook.com" }, "Twitter": { "icon": "fab fa-twitter", "url": "https://twitter.com" }, "Dribbble": { "icon": "fab fa-dribbble", "url": "https://dribbble.com" }, "RSS": { "icon": "fas fa-rss", "url": "/" } } ] } }, "required": [ "type" ] } ================================================ FILE: include/style/article.styl ================================================ /* --------------------------------- * Article Summary and Content * --------------------------------- */ $article-font-size ?= 1.1rem article &.media color: $text-light a color: inherit &:hover color: $primary .image width: 64px height: 64px img object-fit: cover width: 100% height: 100% .title @extend .is-size-6 margin-bottom: .25em .date, .categories @extend .is-size-7 .categories @extend .is-uppercase .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 .article-tags display: flex flex-wrap: wrap .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: .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 .is-size-7, .has-text-grey .licensing-meta .level-item @extend .mr-4 .icons .icon @extend .ml-1 width: 1.2em height: 1.2em font-size: 1.2em vertical-align: bottom h6 @extend .is-size-7 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 ================================================ FILE: include/style/base.styl ================================================ 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' $size-7 ?= .85rem $size-small ?= .75rem $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) ================================================ FILE: include/style/button.styl ================================================ /* --------------------------------- * Buttons * --------------------------------- */ .button &.is-transparent color: inherit background: transparent border-color: transparent ================================================ FILE: include/style/card.styl ================================================ /* --------------------------------- * 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 ================================================ FILE: include/style/codeblock.styl ================================================ /* --------------------------------- * 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 figure.highlight.foldable div.level-left cursor: pointer // clicking the codeblock filename can toggle folding /* --------------------------------- * Fix Gist Snippet * --------------------------------- */ .gist table tr:hover background: transparent td border: none .file all: initial ================================================ FILE: include/style/donate.styl ================================================ /* --------------------------------- * Donate Buttons * --------------------------------- */ $donate-qrcode-max-width ?= 280px $donate-qrcode-shadow ?= $card-shadow $donate-qrcode-box-radius ?= $card-radius $donate-button-colors ?= { 'afdian': rgb(136, 95, 217), 'alipay': rgb(0, 160, 232), 'buymeacoffee': rgb(255, 221, 0), 'paypal': rgb(254, 183, 0), 'patreon': rgb(255, 66, 77), 'wechat': rgb(26, 173, 25), } .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 for $name, $color in $donate-button-colors &[data-type={'"' + $name + '"'}] color: findColorInvert($color) background-color: $color border-color: transparent &:active background-color: darken($color, 5%) &:hover background-color: darken($color, 2.5%) &:focus:not(:active) box-shadow: 0 0 0 .125em rgba($color, .25) ================================================ FILE: include/style/footer.styl ================================================ /* --------------------------------- * 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 ================================================ FILE: include/style/helper.styl ================================================ /* --------------------------------- * Spacing helpers * --------------------------------- */ $spacer ?= 1rem $spacers ?= 0, $spacer * .25, $spacer * .5, $spacer, $spacer * 1.5, $spacer * 3 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) .order-{n} order: n !important .justify-content-start justify-content: start !important .justify-content-center justify-content: center !important .flex-shrink-1 flex-shrink: 1 !important /* --------------------------------- * Color helpers * --------------------------------- */ .link-muted color: inherit &:hover color: $primary !important /* --------------------------------- * Image helpers * --------------------------------- */ .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 ================================================ FILE: include/style/navbar.styl ================================================ /* --------------------------------- * 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-container overflow-x: auto .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 @media screen and (min-width: $desktop) .navbar > .container .navbar-menu, .container > .navbar .navbar-menu margin-right: 0rem ================================================ FILE: include/style/pagination.styl ================================================ /* --------------------------------- * Pagination and Post Navigation * --------------------------------- */ $pagination-box-shadow ?= $card-shadow $pagination-background-color ?= $button-background-color $post-navigation-fg ?= $grey .pagination @extend .pagination.is-centered margin-top: 1.5rem .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 ================================================ FILE: include/style/plugin.styl ================================================ /* --------------------------------- * 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 /* --------------------------------- * 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, .MathJax_Display, .MJXc-display, .MathJax_SVG_Display, .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 /* --------------------------------- * Cookie Consent * --------------------------------- */ .cc-window, .cc-revoke font-size: 1.1rem !important font-family: $family-sans-serif !important .cc-window color: $text !important background-color: $scheme-main !important &.cc-floating border-radius: $card-radius box-shadow: $card-shadow &.cc-banner background-color: darken($scheme-main, 2.5%) !important &.cc-theme-block, &.cc-theme-classic .cc-compliance > .cc-btn border-radius: $radius-rounded .cc-compliance > .cc-btn font-weight: 400 border: none color: $primary-invert background-color: $primary &:hover, &:focus background-color: darken($primary, 2.5%) &.cc-deny &:hover color: $primary text-decoration: none .cc-revoke padding: .5rem 1rem !important color: $primary-invert !important background-color: $primary !important &:hover text-decoration: none !important background-color: darken($primary, 2.5%) ================================================ FILE: include/style/responsive.styl ================================================ /* --------------------------------- * 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 ================================================ FILE: include/style/search.styl ================================================ /* --------------------------------- * 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 ================================================ FILE: include/style/timeline.styl ================================================ /* --------------------------------- * 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) ================================================ FILE: include/style/widget.styl ================================================ .widget .menu-list li ul margin-right: 0 .level margin-bottom: 0 .level-left, .level-right, .level-item flex-shrink: 1 .level-left, .level-right align-items: flex-start .tag background: $light-grey color: $white-invert .tags .tag:first-child background: $primary color: $primary-invert .tag:last-child background: $light-grey color: $white-invert .level.is-multiline flex-wrap: wrap /* --------------------------------- * Table of Content Widget * --------------------------------- */ +mobile() .widget.card#toc display: none position: fixed margin: 1rem left: 0 right: 0 bottom: 0 z-index: 100 .card-content padding: 0 .menu padding: 1.5rem 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) .widget.card#toc, #toc-mask &.is-active display: block ================================================ FILE: include/util/console.js ================================================ let chalk; try { chalk = require('chalk'); // eslint-disable-line node/no-extraneous-require } catch (e) { } module.exports = new Proxy({}, { get(obj, prop) { if (chalk) { return chalk[prop]; } return function() { return arguments.length === 1 ? arguments[0] : arguments; }; } }); ================================================ FILE: languages/de.yml ================================================ common: archive: one: 'Archiv' other: 'Archive' category: one: 'Kategorie' other: 'Kategorien' tag: one: 'Tag' other: 'Tags' post: one: 'Seite' other: 'Seiten' page: one: 'Page' other: 'Pages' prev: 'Zurück' next: 'Weiter' widget: follow: 'Folgen' recents: 'Letzte Einträge' links: 'Links' catalogue: 'Katalog' subscribe_email: 'Abonnieren Sie Updates' subscribe: 'Abonnieren' adsense: 'Werbung' followit: 'follow.it' article: created_at: 'Gepostet vor %s' updated_at: 'Aktualisiert vor %s' more: 'Mehr lesen' comments: 'Kommentare' 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_count: '%s Besuche' visitor_count: 'Von %s Nutzern besucht' cookie_consent: message: Diese Website verwendet Cookies, um Ihre Erfahrung zu verbessern. dismiss: Verstanden! allow: Cookies zulassen deny: Ablehnen link: Mehr erfahren policy: Cookie-Richtlinie search: search: 'Suche' hint: 'Tippen Sie etwas...' no_result: 'Keine Ergebnisse für' untitled: '(Ohne Titel)' empty_preview: '(Keine Vorschau)' ================================================ FILE: languages/en.yml ================================================ common: archive: one: 'Archive' other: 'Archives' category: one: 'Category' other: 'Categories' tag: one: 'Tag' other: 'Tags' post: one: 'Post' other: 'Posts' page: one: 'Page' other: 'Pages' prev: 'Previous' next: 'Next' widget: follow: 'Follow' recents: 'Recents' links: 'Links' catalogue: 'Catalogue' subscribe_email: 'Subscribe for updates' subscribe: 'Subscribe' adsense: 'Advertisement' followit: 'follow.it' article: created_at: 'Posted %s' updated_at: 'Updated %s' more: 'Read more' comments: 'Comments' read_time: '%s read' 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' visit_count: '%s visits' visitor_count: 'Visited by %s users' cookie_consent: message: This website uses cookies to improve your experience. dismiss: Got it! allow: Allow cookies deny: Decline link: Learn more policy: Cookie Policy search: search: 'Search' hint: 'Type something...' no_result: 'No results for' untitled: '(Untitled)' empty_preview: '(No preview)' ================================================ FILE: languages/es.yml ================================================ #By SrWoOoW common: archive: one: 'Archivo' other: 'Archivos' category: one: 'Categoría' other: 'Categorías' tag: one: 'Etiqueta' other: 'Etiquetas' post: one: 'Entrada' other: 'Entradas' page: one: 'Página' other: 'Páginas' prev: 'Anterior' next: 'Siguiente' widget: follow: 'SEGUIR' recents: 'Recientes' links: 'Enlaces' catalogue: 'Catálogo' subscribe_email: 'Suscríbete para recibir actualizaciones' subscribe: 'Suscribir' adsense: 'Anuncio' followit: 'follow.it' article: created_at: 'Publicado hace %s' updated_at: 'Actualizado hace %s' more: 'Leer más' comments: 'Comentarios' 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' cookie_consent: message: Este sitio web utiliza cookies para mejorar su experiencia. dismiss: ¡Entendido! allow: Permitir cookies deny: Descenso link: Aprende más policy: Política de cookies search: search: 'Buscar' hint: 'Teclea algo...' no_result: 'No hay resultados para' untitled: '(Sin título)' empty_preview: '(Sin vista previa)' ================================================ FILE: languages/fr.yml ================================================ common: archive: one: 'Archive' other: 'Archives' category: one: 'Catégorie' other: 'Catégories' tag: one: 'Tag' other: 'Tags' post: one: 'Article' other: 'Articles' page: one: 'Page' other: 'Pages' prev: 'Préc' next: 'Suiv' widget: follow: 'Suivre' recents: 'Récents' links: 'Liens' catalogue: 'Catalogue' subscribe_email: 'Abonnez-vous aux mises à jour' subscribe: 'Abonnez-vous' adsense: 'Publicités' followit: 'follow.it' article: created_at: 'Publié il y a %s' updated_at: 'Mis à jour il y a %s' more: 'Lire la suite' comments: 'Commentaires' read_time: '%s de lecture' word_count: one: 'Environ %d mot' other: 'Environ %d mots' licensing: author: 'Auteur' created_at: 'Posté le' updated_at: 'Mis à jour le' licensed_under: 'Licencié sous' 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 en haut' visit_count: '%s visites' visitor_count: 'Visité par %s utilisateurs' cookie_consent: message: 'Ce site Web utilise des cookies pour améliorer votre expérience.' dismiss: "C'est bon" allow: 'Autoriser les cookies' deny: 'Refuser' link: 'En savoir plus' policy: 'Politique relative aux cookies' search: search: 'Rechercher' hint: 'Ecrivez quelque chose...' no_result: 'Aucun résultat pour' untitled: '(Sans titre)' empty_preview: '(Pas de prévisualisation)' ================================================ FILE: languages/id.yml ================================================ common: archive: one: 'Arsip' other: 'Arsip' category: one: 'Kategori' other: 'Kategori' tag: one: 'Tag' other: 'Tag' post: one: 'Artikel' other: 'Artikel' page: one: 'Halaman' other: 'Halaman' prev: 'Sebelumnya' next: 'Berikutnya' widget: follow: 'IKUTI' recents: 'Terbaru' links: 'Tautan' catalogue: 'Katalog' subscribe_email: 'Berlangganan untuk pembaruan' subscribe: 'Berlangganan' adsense: 'Iklan' followit: 'follow.it' article: created_at: 'Diposting %s' updated_at: 'Diperbarui %s' more: 'Selengkapnya' comments: 'Komentar' 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' cookie_consent: message: Situs web ini menggunakan cookie untuk meningkatkan pengalaman Anda. dismiss: Mengerti! allow: Izinkan cookie deny: Menolak link: Belajarlah lagi policy: Kebijakan Cookie search: search: 'Pencarian' hint: 'Tulis Sesuatu..' no_result: 'Tidak ada hasil untuk' untitled: '(Tanpa judul)' empty_preview: '(Tidak ada preview)' ================================================ FILE: languages/it.yml ================================================ common: archive: one: 'Archivio' other: 'Archivi' category: one: 'Categoria' other: 'Categorie' tag: one: 'Tag' other: 'Tag' post: one: 'Articolo' other: 'Articoli' page: one: 'Pagina' other: 'Pagine' prev: 'Precedente' next: 'Successivo' widget: follow: 'Segui' recents: 'Recenti' links: 'Collegamenti' catalogue: 'Catalogo' subscribe_email: 'Iscriviti per aggiornamenti' subscribe: 'Iscriviti' adsense: 'Pubblicità' followit: 'follow.it' article: created_at: 'Pubblicato il %s' updated_at: 'Aggiornato il %s' more: 'Di più' comments: 'Commenti' read_time: '%s di lettura' word_count: one: 'Circa %d parola' other: 'Circa %d parole' licensing: author: 'Autore' created_at: 'Pubblicato il' updated_at: 'Aggiornato il' licensed_under: 'Licenza' donate: title: "Ti è piaciuto questo articolo? Supporta l'autore con" afdian: 'Afdian.net' alipay: 'Alipay' wechat: 'Wechat' paypal: 'Paypal' patreon: 'Patreon' buymeacoffee: 'Buy me a coffee' plugin: backtotop: 'Torna su' visit_count: '%s visite' visitor_count: 'Visto da %s usenti' cookie_consent: message: Questo sito usa i cookie per migliorare la tua esperienza. dismiss: "D'accordo!" allow: Accetta i cookie deny: Rifiuta link: Più informazioni policy: Politica dei cookie search: search: 'Cerca' hint: 'Digita qualcosa...' no_result: 'Nessun risultato per' untitled: '(Senza titolo)' empty_preview: '(Senza anteprima)' ================================================ FILE: languages/ja.yml ================================================ common: archive: one: 'アーカイブ' other: 'アーカイブ' category: one: 'カテゴリ' other: 'カテゴリ' tag: one: 'タグ' other: 'タグ' post: one: '投稿' other: '投稿' page: one: 'ページ' other: 'ページ' prev: '前' next: '次' widget: follow: 'フォローする' recents: '最近の記事' links: 'リンク' catalogue: 'カタログ' subscribe_email: '更新を購読する' subscribe: '購読する' adsense: '広告' followit: 'follow.it' article: created_at: '%sに投稿' updated_at: '%sに更新' more: '続きを読む' comments: 'コメント' 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人のユーザーがアクセス' cookie_consent: message: このウェブサイトはあなたの経験を改善するためにCookieを使用しています。 dismiss: 了解しました allow: Cookiesを許可する deny: 拒否する link: もっと詳しく知る policy: Cookieポリシー search: search: '検索' hint: '何かを入力してください...' no_result: 'の結果はありません' untitled: '(無題)' empty_preview: '(プレビューなし)' ================================================ FILE: languages/ko.yml ================================================ common: archive: one: '아카이브' other: '아카이브' category: one: '카테고리' other: '카테고리' tag: one: '태그' other: '태그' post: one: '포스트' other: '포스트' page: one: '페이지' other: '페이지' prev: '이전' next: '다음' widget: follow: '팔로우' recents: '최근 글' links: '링크' catalogue: '카탈로그' subscribe_email: '업데이트 소식 받기' subscribe: '구독' adsense: '광고' followit: 'follow.it' article: created_at: '%s 게시 됨' updated_at: '%s 업데이트 됨' more: '자세히 보기' comments: '댓글' 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명의 사용자가 방문 함' cookie_consent: message: 이 웹 사이트는 귀하의 경험을 향상시키기 위해 Cookie를 사용합니다. dismiss: 무시 allow: 허용 deny: 거부 link: 더 알아보기 policy: Cookie 정책 search: search: '검색' hint: '입력 하세요...' no_result: '에 대한 결과 없음' untitled: '(제목 없음)' empty_preview: '(미리보기 없음)' ================================================ FILE: languages/pl.yml ================================================ common: archive: one: 'Archiwum' other: 'Archiwum' category: one: 'Kategoria' other: 'Kategorie' tag: one: 'Tag' other: 'Tagi' post: one: 'Artykuł' other: 'Artykuły' page: one: 'Strona' other: 'Strony' prev: 'Poprzedni' next: 'Następny' widget: follow: 'SUBSKRYBUJ' recents: 'Najnowsze wpisy' links: 'Linki' catalogue: 'Spis treści' subscribe_email: 'Zapisz się, aby otrzymywać aktualizacje' subscribe: 'Subskrybuj' adsense: 'Reklama' followit: 'follow.it' article: created_at: 'Opublikowano %s' updated_at: 'Zaktualizowano %s' more: 'Czytaj dalej' comments: 'Komentarze' 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' cookie_consent: message: Ta strona korzysta z plików cookie, aby poprawić Twoje doświadczenia. dismiss: Rozumiem! allow: Zezwól na pliki cookie deny: Odrzucać link: Ucz się więcej policy: Polityka Cookie search: search: 'szukaj' hint: 'Wpisz coś...' no_result: 'Brak wyników dla' untitled: '(Bez tytułu)' empty_preview: '(Brak podglądu)' ================================================ FILE: languages/pt-BR.yml ================================================ common: archive: one: 'Arquivo' other: 'Arquivos' category: one: 'Categoria' other: 'Categorias' tag: one: 'Tag' other: 'Tags' post: one: 'Artigo' other: 'Artigos' page: one: 'Página' other: 'Páginas' prev: 'Anterior' next: 'Próximo' widget: follow: 'Seguir' recents: 'Recentes' links: 'Links' catalogue: 'Catálogo' subscribe_email: 'Subscrição de atualizações' subscribe: 'Se inscrever' adsense: 'Anúncio' followit: 'follow.it' article: created_at: 'Postado %s' updated_at: 'Atualizado %s' more: 'Ler Mais' comments: 'Comentarios' 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' cookie_consent: message: Este site usa cookies para melhorar sua experiência. dismiss: Entendi! allow: Permitir cookies deny: Declínio link: Saber mais policy: Política de Cookies search: search: 'Procurar' hint: 'Digite alguma coisa...' no_result: 'Sem resultados para' untitled: '(Sem título)' empty_preview: '(Não há visualização)' ================================================ FILE: languages/ru.yml ================================================ common: archive: one: 'архив' other: 'архивы' category: one: 'категории' other: 'категории' tag: one: 'тег' other: 'теги' post: one: 'пост' other: 'посты' page: one: 'страница' other: 'страницы' prev: 'Назад' next: 'Далее' widget: follow: 'Подписаться' recents: 'недавние' links: 'ссылки' catalogue: 'Каталог' subscribe_email: 'Подпишитесь на обновления' subscribe: 'Подписывайся' adsense: 'Рекламное объявление' followit: 'follow.it' article: created_at: 'Опубликовано %s' updated_at: 'Обновлено %s' more: 'Читать дальше' comments: 'Комментарии' 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 пользователя' cookie_consent: message: Этот веб-сайт использует файлы cookie для улучшения вашего опыта. dismiss: Понял! allow: Разрешить cookies deny: Отказаться link: Учить больше policy: Политика Cookie search: search: 'Поиск' hint: 'Введите что-нибудь...' no_result: 'Нет результатов по запросу' untitled: '(Без названия)' empty_preview: '(Нет предварительного просмотра)' ================================================ FILE: languages/sv.yml ================================================ common: archive: one: 'Arkiv' other: 'Arkiv' category: one: 'Kategori' other: 'Kategorier' tag: one: 'Etikett' other: 'Etiketter' post: one: 'Inlägg' other: 'Inlägg' page: one: 'Sida' other: 'Sidor' prev: 'Föregående' next: 'Nästa' widget: follow: 'Följ' recents: 'Senaste' links: 'Länkar' catalogue: 'Katalog' subscribe_email: 'Prenumerera för uppdateringar' subscribe: 'Prenumerera' adsense: 'Marknadsföring' followit: 'follow.it' article: created_at: 'Publicerad %s' updated_at: 'Uppdaterad %s' more: 'Läs mer' comments: 'Kommentarer' read_time: '%s lästid' word_count: one: 'Cirka %d ord' other: 'Cirka %d ord' licensing: author: 'Författare' created_at: 'Publicerad' updated_at: 'Uppdaterad' licensed_under: 'Licensierad under' donate: title: 'Tycker du om den här artikeln? Stöd författaren genom' afdian: 'Afdian.net' alipay: 'Alipay' wechat: 'Wechat' paypal: 'Paypal' patreon: 'Patreon' buymeacoffee: 'Köp mig en kaffe' plugin: backtotop: 'Tillbaka till början' visit_count: '%s besök' visitor_count: 'Besökt av %s användare' cookie_consent: message: Den här hemsidan använder kakor för att förbättra funktionen. dismiss: Jag förstår! allow: Tillåt kakor deny: Avböj kakor link: Lär mer policy: Kakpolicy search: search: 'Sök' hint: 'Skriv någonting...' no_result: 'Inga sökresultat för' untitled: '(Utan titel)' empty_preview: '(Ingen förhandsvisning)' ================================================ FILE: languages/tk.yml ================================================ common: archive: one: 'Arhiw' other: 'Arhiwler' category: one: 'Bölüm' other: 'Bölümler' tag: one: 'Teg' other: 'Tegler' post: one: 'Post' other: 'Postlar' page: one: 'Sahypa' other: 'Sahypalar' prev: 'Öňki' next: 'Indiki' widget: follow: 'Abuna bol' recents: 'Täze habarlar' links: 'Linkler' catalogue: 'Katalog' subscribe_email: 'Täzelikler üçin ýazyl' subscribe: 'Ýazyl' adsense: 'Mahabat' followit: 'follow.it' article: created_at: 'Paýlaşyldy %s' updated_at: 'Üýtgedildi %s' more: 'Dowamy...' comments: 'Kommentariýa' read_time: '%s okaldy' word_count: one: 'Ortaça %d söz' other: 'Ortaça %d söz' licensing: author: 'Awtor' created_at: 'Paýlaşdy' updated_at: 'Üýtgetdi' licensed_under: 'Resmileşdirilen' donate: title: 'Haladynmy? Awtory gollaň' afdian: 'Afdian.net' alipay: 'Alipay' wechat: 'Wechat' paypal: 'Paypal' patreon: 'Patreon' buymeacoffee: 'Buy me a coffee' plugin: backtotop: 'Ýokaryk' visit_count: '%s görüldi' visitor_count: '%s adam gördi' cookie_consent: message: Bu web saýt siziň üçin kuki ulanýar. dismiss: Düşündim! allow: Kukini kabul et! deny: Närazylyk bildir link: Dowamy... policy: Kuki syýasaty search: search: 'Gözle' hint: 'Birzatlar ýazyň...' no_result: 'Tapylmady' untitled: 'Atlandyrylmadyk' empty_preview: 'Boş' ================================================ FILE: languages/tr.yml ================================================ common: archive: one: 'Arşiv' other: 'Arşivler' category: one: 'Kategori' other: 'Kategoriler' tag: one: 'Etiket' other: 'Etiketler' 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' catalogue: 'Katalog' subscribe_email: 'Güncellemeler için abone olun' subscribe: 'Abone ol' adsense: 'İlan' followit: 'follow.it' article: created_at: '%s yayınlandı' updated_at: '%s güncellendi' more: 'Daha fazla oku' comments: 'Yorumlar' read_time: '%s okuma süresi' 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' cookie_consent: message: Bu web sitesi, deneyiminizi geliştirmek için çerezler kullanır. dismiss: Anladım! allow: Çerezlere izin ver deny: Reddet link: Daha fazla bilgi edin policy: Çerez politikası search: search: 'Ara' hint: 'Bir şeyler yaz...' no_result: 'İçin sonuç yok' untitled: '(Başlıksız)' empty_preview: '(Önizleme yok)' ================================================ FILE: languages/vn.yml ================================================ common: archive: one: 'Lưu trữ' other: 'Lưu trữ' category: one: 'Thể loại' other: 'Thể loại' tag: 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' 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' followit: 'follow.it' article: created_at: 'Đã đăng %s' updated_at: 'Đã cập nhật %s' more: 'Đọc thêm' comments: 'Bình luận' 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_count: '%s Bạn đọc' visitor_count: 'Thăm bởi %s bạn đọc' cookie_consent: message: Trang web này sử dụng cookie để cải thiện trải nghiệm của bạn. dismiss: Hiểu rồi! allow: Cho phép cookie deny: Từ chối link: Tìm hiểu thêm policy: Chính sách Cookie search: search: 'Tìm kiếm' hint: 'Gõ gì đó...' no_result: 'Không có kết quả cho' untitled: '(Không có tiêu đề)' empty_preview: '(Không có xem trước)' ================================================ FILE: languages/zh-CN.yml ================================================ common: archive: one: '归档' other: '归档' category: one: '分类' other: '分类' tag: one: '标签' other: '标签' post: one: '文章' other: '文章' page: one: '页面' other: '页面' prev: '上一页' next: '下一页' widget: follow: '关注我' recents: '最新文章' links: '链接' catalogue: '目录' subscribe_email: '订阅更新' subscribe: '订阅' adsense: '广告' followit: 'follow.it' article: created_at: '%s发表' updated_at: '%s更新' more: '阅读更多' comments: '评论' 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个访客' cookie_consent: message: 此网站使用Cookie来改善您的体验。 dismiss: 知道了! allow: 允许使用Cookie deny: 拒绝 link: 了解更多 policy: Cookie政策 search: search: '搜索' hint: '想要查找什么...' no_result: '未找到搜索结果' untitled: '(无标题)' empty_preview: '(无内容预览)' ================================================ FILE: languages/zh-TW.yml ================================================ common: archive: one: '彙整' other: '彙整' category: one: '分類' other: '分類' tag: one: '標籤' other: '標籤' post: one: '文章' other: '文章' page: one: '頁面' other: '頁面' prev: '上一頁' next: '下一頁' widget: follow: '追蹤' recents: '最新文章' links: '連結' catalogue: '文章目錄' subscribe_email: '訂閱 Email' subscribe: '訂閱' adsense: '廣告' followit: 'follow.it' article: created_at: '%s發表' updated_at: '%s更新' more: '繼續閱讀' comments: '評論' 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個訪客' cookie_consent: message: 此網站使用Cookie來改善您的體驗。 dismiss: 知道了! allow: 允許使用Cookie deny: 拒絕 link: 了解更多 policy: Cookie政策 search: search: '搜尋' hint: '請輸入關鍵字...' no_result: '未找到搜索結果' untitled: '(無標題)' empty_preview: '(無內容預覽)' ================================================ FILE: layout/archive.jsx ================================================ const moment = require('moment'); const { Component, Fragment } = require('inferno'); const { toMomentLocale } = require('hexo/dist/plugins/helper/date'); 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, helper } = this.props; const { url_for, __, date_xml, date } = helper; const language = toMomentLocale(page.lang || page.language || config.language); function renderArticleList(posts, year, month = null) { const time = moment([page.year, page.month ? page.month - 1 : null].filter(i => i !== null)); return

{month === null ? year : time.locale(language).format('MMMM YYYY')}

{posts.map(post => { const categories = post.categories.map(category => ({ url: url_for(category.path), name: category.name })); return ; })}
; } let articleList; if (!page.year) { const years = {}; page.posts.each(p => { years[p.date.year()] = null; }); articleList = Object.keys(years).sort((a, b) => b - a).map(year => { const posts = page.posts.filter(p => p.date.year() === parseInt(year, 10)); return renderArticleList(posts, year, null); }); } else { articleList = renderArticleList(page.posts, page.year, page.month); } return {articleList} {page.total > 1 ? : null} ; } }; ================================================ FILE: layout/categories.jsx ================================================ const { Component } = require('inferno'); const Categories = require('hexo-component-inferno/lib/view/widget/categories'); module.exports = class extends Component { render() { const { site, page, helper } = this.props; return ; } }; ================================================ FILE: layout/category.jsx ================================================ const { Component, Fragment } = require('inferno'); const Index = require('./index'); module.exports = class extends Component { render() { const { config, page, helper } = this.props; const { url_for, _p } = helper; return
; } }; ================================================ FILE: layout/comment/.gitkeep ================================================ ================================================ FILE: layout/common/article.jsx ================================================ const moment = require('moment'); const { Component, Fragment } = require('inferno'); const { toMomentLocale } = require('hexo/dist/plugins/helper/date'); const Share = require('./share'); const Donates = require('./donates'); const Comment = require('./comment'); const ArticleLicensing = require('hexo-component-inferno/lib/view/misc/article_licensing'); /** * 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; } module.exports = class extends Component { render() { const { config, helper, page, index } = this.props; const { article, plugins } = config; const { url_for, date, date_xml, __, _p } = helper; const defaultLanguage = Array.isArray(config.language) && config.language.length ? config.language[0] : config.language; const indexLanguage = toMomentLocale(defaultLanguage || 'en'); const language = toMomentLocale(page.lang || page.language || defaultLanguage || 'en'); const cover = page.cover ? url_for(page.cover) : null; const updateTime = article && article.update_time !== undefined ? article.update_time : true; const isUpdated = page.updated && !moment(page.date).isSame(moment(page.updated)); const shouldShowUpdated = page.updated && ((updateTime === 'auto' && isUpdated) || updateTime === true); return {/* Main content */}
{/* Thumbnail */} {cover ?
{index ? {page.title : {page.title }
: null}
{/* Metadata */} {page.layout !== 'page' ? : null} {/* Title */} {page.title !== '' && index ?

{page.title}

: null} {page.title !== '' && !index ?

{page.title}

: null} {/* Content/Excerpt */}
{/* Licensing block */} {!index && article && article.licenses && Object.keys(article.licenses) ? : null} {/* Tags */} {!index && page.tags && page.tags.length ? : null} {/* "Read more" button */} {index && page.excerpt ? {__('article.more')} : null} {/* Share button */} {!index ? : null}
{/* Donate button */} {!index ? : null} {/* Post navigation */} {!index && (page.prev || page.next) ? : null} {/* Comment */} {!index ? : null}
; } }; ================================================ FILE: layout/common/comment.jsx ================================================ const createLogger = require('hexo-log'); const { Component } = require('inferno'); const view = require('hexo-component-inferno/lib/core/view'); const logger = createLogger.default(); module.exports = class extends Component { render() { const { config, page, helper } = this.props; const { __ } = helper; const { comment } = config; if (!comment || typeof comment.type !== 'string') { return null; } return

{__('article.comments')}

{(() => { try { let Comment = view.require('comment/' + comment.type); Comment = Comment.Cacheable ? Comment.Cacheable : Comment; return ; } catch (e) { logger.w(`Icarus cannot load comment "${comment.type}"`); return null; } })()}
; } }; ================================================ FILE: layout/common/donates.jsx ================================================ const createLogger = require('hexo-log'); const { Component } = require('inferno'); const view = require('hexo-component-inferno/lib/core/view'); const logger = createLogger.default(); module.exports = class extends Component { render() { const { config, helper } = this.props; const { __ } = helper; const { donates = [] } = config; if (!Array.isArray(donates) || !donates.length) { return null; } return
{donates.map(service => { const type = service.type; if (typeof type === 'string') { try { let Donate = view.require('donate/' + type); Donate = Donate.Cacheable ? Donate.Cacheable : Donate; return ; } catch (e) { logger.w(`Icarus cannot load donate button "${type}"`); } } return null; })}
; } }; ================================================ FILE: layout/common/footer.jsx ================================================ const { Component } = require('inferno'); const { cacheComponent } = require('hexo-component-inferno/lib/util/cache'); class Footer extends Component { render() { const { logo, logoUrl, siteUrl, siteTitle, siteYear, author, links, copyright, showVisitorCounter, visitorCounterTitle } = this.props; let footerLogo = ''; if (logo) { if (logo.text) { footerLogo = logo.text; } else { footerLogo = {siteTitle}; } } else { footerLogo = siteTitle; } return ; } } module.exports = cacheComponent(Footer, 'common.footer', props => { const { config, helper } = props; const { url_for, _p, date } = helper; const { logo, title, author, footer, plugins } = config; const links = {}; if (footer && footer.links) { Object.keys(footer.links).forEach(name => { const link = footer.links[name]; links[name] = { url: url_for(typeof link === 'string' ? link : link.url), icon: link.icon }; }); } return { logo, logoUrl: url_for(logo), siteUrl: url_for('/'), siteTitle: title, siteYear: date(new Date(), 'YYYY'), author, links, copyright: footer?.copyright ?? '', showVisitorCounter: plugins && plugins.busuanzi === true, visitorCounterTitle: _p('plugin.visitor_count', '0') }; }); ================================================ FILE: layout/common/head.jsx ================================================ const { Component } = require('inferno'); const MetaTags = require('hexo-component-inferno/lib/view/misc/meta'); const WebApp = require('hexo-component-inferno/lib/view/misc/web_app'); 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'); function getPageTitle(page, siteTitle, helper) { let title = page.title; if (helper.is_archive()) { title = helper._p('common.archive', Infinity); if (helper.is_month()) { title += ': ' + page.year + '/' + page.month; } else if (helper.is_year()) { title += ': ' + page.year; } } else if (helper.is_category()) { title = helper._p('common.category', 1) + ': ' + page.category; } else if (helper.is_tag()) { title = helper._p('common.tag', 1) + ': ' + page.tag; } else if (helper.is_categories()) { title = helper._p('common.category', Infinity); } else if (helper.is_tags()) { title = helper._p('common.tag', Infinity); } return [title, siteTitle].filter(str => typeof str !== 'undefined' && str.trim() !== '').join(' - '); } module.exports = class extends Component { render() { const { site, config, helper, page } = this.props; const { url_for, cdn, fontcdn, iconcdn, is_post } = helper; const { url, head = {}, article, highlight, variant = 'default' } = config; const { meta = [], manifest = {}, open_graph = {}, structured_data = {}, canonical_url = page.permalink, rss, favicon } = head; const noIndex = helper.is_archive() || helper.is_category() || helper.is_tag(); 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; } else if (article && article.highlight && article.highlight.theme) { hlTheme = article.highlight.theme; } else { hlTheme = 'atom-one-light'; } if (typeof page.og_image === 'string') { images = [page.og_image]; } 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(']*src=['"]([^'"]+)([^>]*>)/gi; while ((img = imgPattern.exec(page.content)) !== null) { images.push(img[1]); } } else { images = [url_for('/img/og_image.png')]; } let adsenseClientId = null; if (Array.isArray(config.widgets)) { const widget = config.widgets.find(widget => widget.type === 'adsense'); if (widget) { adsenseClientId = widget.client_id; } } let openGraphImages = images; 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 ((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; } let followItVerificationCode = null; if (Array.isArray(config.widgets)) { const widget = config.widgets.find(widget => widget.type === 'followit'); if (widget) { followItVerificationCode = widget.verification_code; } } return {noIndex ? : null} {meta && meta.length ? : null} {getPageTitle(page, config.title, helper)} {typeof open_graph === 'object' && open_graph !== null ? : null} {typeof structured_data === 'object' && structured_data !== null ? : null} {canonical_url ? : null} {rss ? : null} {favicon ? : null} {hlTheme ? : null} {adsenseClientId ? : null} {followItVerificationCode ? : null} ; } }; ================================================ FILE: layout/common/navbar.jsx ================================================ const { Component, Fragment } = require('inferno'); 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) { let paths = url.replace(/(^\w+:|^)\/\//, '').split('#')[0].split('/').filter(p => p.trim() !== ''); if (paths.length > 0 && paths[paths.length - 1].trim() === 'index.html') { paths = paths.slice(0, paths.length - 1); } return paths.join('/'); } return santize(a) === santize(b); } class Navbar extends Component { render() { const { logo, logoUrl, siteUrl, siteTitle, menu, links, showToc, tocTitle, showSearch, searchTitle } = this.props; let navbarLogo = ''; if (logo) { if (logo.text) { navbarLogo = logo.text; } else { navbarLogo = {siteTitle}; } } else { navbarLogo = siteTitle; } return ; } } module.exports = cacheComponent(Navbar, 'common.navbar', props => { const { config, helper, page } = props; const { url_for, _p, __ } = helper; const { logo, title, navbar, widgets, search } = config; const hasTocWidget = Array.isArray(widgets) && widgets.find(widget => widget.type === 'toc'); const showToc = (config.toc === true || page.toc) && hasTocWidget && ['page', 'post'].includes(page.layout); const menu = {}; if (navbar && navbar.menu) { const pageUrl = typeof page.path !== 'undefined' ? url_for(page.path) : ''; Object.keys(navbar.menu).forEach(name => { const url = url_for(navbar.menu[name]); const active = isSameLink(url, pageUrl); menu[name] = { url, active }; }); } const links = {}; if (navbar && navbar.links) { Object.keys(navbar.links).forEach(name => { const link = navbar.links[name]; links[name] = { url: url_for(typeof link === 'string' ? link : link.url), icon: link.icon }; }); } return { logo, logoUrl: url_for(logo), siteUrl: url_for('/'), siteTitle: title, menu, links, showToc, tocTitle: _p('widget.catalogue', Infinity), showSearch: search && search.type, searchTitle: __('search.search') }; }); ================================================ FILE: layout/common/plugins.jsx ================================================ const createLogger = require('hexo-log'); const { Component, Fragment } = require('inferno'); const view = require('hexo-component-inferno/lib/core/view'); const logger = createLogger.default(); module.exports = class extends Component { render() { const { site, config, page, helper, head } = this.props; const { plugins = [] } = config; return {Object.keys(plugins).map(name => { // plugin is not enabled if (!plugins[name]) { return null; } try { let Plugin = view.require('plugin/' + name); Plugin = Plugin.Cacheable ? Plugin.Cacheable : Plugin; return ; } catch (e) { logger.w(`Icarus cannot load plugin "${name}"`); return null; } })} ; } }; ================================================ FILE: layout/common/scripts.jsx ================================================ const { Component, Fragment } = require('inferno'); const { toMomentLocale } = require('hexo/dist/plugins/helper/date'); const Plugins = require('./plugins'); module.exports = class extends Component { render() { const { site, config, helper, page } = this.props; const { url_for, cdn } = helper; const { article } = config; const language = toMomentLocale(page.lang || page.language || config.language || 'en'); let fold = 'unfolded'; let clipboard = true; if (article && article.highlight) { if (typeof article.highlight.clipboard !== 'undefined') { clipboard = !!article.highlight.clipboard; } if (typeof article.highlight.fold === 'string') { fold = article.highlight.fold; } } const embeddedConfig = `var IcarusThemeSettings = { article: { highlight: { clipboard: ${clipboard}, fold: '${fold}' } } };`; return {clipboard && } ; } }; ================================================ FILE: layout/common/search.jsx ================================================ const createLogger = require('hexo-log'); const { Component } = require('inferno'); const view = require('hexo-component-inferno/lib/core/view'); const logger = createLogger.default(); module.exports = class extends Component { render() { const { config, helper } = this.props; const { search } = config; if (!search || typeof search.type !== 'string') { return null; } try { let Search = view.require('search/' + search.type); Search = Search.Cacheable ? Search.Cacheable : Search; return ; } catch (e) { logger.w(`Icarus cannot load search "${search.type}"`); return null; } } }; ================================================ FILE: layout/common/share.jsx ================================================ const createLogger = require('hexo-log'); const { Component } = require('inferno'); const view = require('hexo-component-inferno/lib/core/view'); const logger = createLogger.default(); module.exports = class extends Component { render() { const { config, page, helper } = this.props; const { share } = config; if (!share || typeof share.type !== 'string') { return null; } try { let Share = view.require('share/' + share.type); Share = Share.Cacheable ? Share.Cacheable : Share; return ; } catch (e) { logger.w(`Icarus cannot load share button "${share.type}"`); return null; } } }; ================================================ FILE: layout/common/widgets.jsx ================================================ const createLogger = require('hexo-log'); const { Component } = require('inferno'); const view = require('hexo-component-inferno/lib/core/view'); const classname = require('hexo-component-inferno/lib/util/classname'); const logger = createLogger.default(); function formatWidgets(widgets) { const result = {}; if (Array.isArray(widgets)) { widgets.filter(widget => typeof widget === 'object').forEach(widget => { if ('position' in widget && (widget.position === 'left' || widget.position === 'right')) { if (!(widget.position in result)) { result[widget.position] = [widget]; } else { result[widget.position].push(widget); } } }); } return result; } function hasColumn(widgets, position, config, page) { const showToc = (config.toc === true) && ['page', 'post'].includes(page.layout); if (Array.isArray(widgets)) { return typeof widgets.find(widget => { if (widget.type === 'toc' && !showToc) { return false; } return widget.position === position; }) !== 'undefined'; } return false; } function getColumnCount(widgets, config, page) { return [hasColumn(widgets, 'left', config, page), hasColumn(widgets, 'right', config, page)].filter(v => !!v).length + 1; } function getColumnSizeClass(columnCount) { switch (columnCount) { case 2: return 'is-4-tablet is-4-desktop is-4-widescreen'; case 3: return 'is-4-tablet is-4-desktop is-3-widescreen'; } return ''; } function getColumnVisibilityClass(columnCount, position) { if (columnCount === 3 && position === 'right') { return 'is-hidden-touch is-hidden-desktop-only'; } return ''; } function getColumnOrderClass(position) { return position === 'left' ? 'order-1' : 'order-3'; } function isColumnSticky(config, position) { return typeof config.sidebar === 'object' && position in config.sidebar && config.sidebar[position].sticky === true; } class Widgets extends Component { render() { const { site, config, helper, page, position } = this.props; const widgets = formatWidgets(config.widgets)[position] || []; const columnCount = getColumnCount(config.widgets, config, page); if (!widgets.length) { return null; } return
{widgets.map(widget => { // widget type is not defined if (!widget.type) { return null; } try { let Widget = view.require('widget/' + widget.type); Widget = Widget.Cacheable ? Widget.Cacheable : Widget; return ; } catch (e) { logger.w(`Icarus cannot load widget "${widget.type}"`); } return null; })} {position === 'left' && hasColumn(config.widgets, 'right', config, page) ?
: null}
; } } Widgets.getColumnCount = getColumnCount; module.exports = Widgets; ================================================ FILE: layout/donate/.gitkeep ================================================ ================================================ FILE: layout/index.jsx ================================================ const { Component, Fragment } = require('inferno'); const Paginator = require('hexo-component-inferno/lib/view/misc/paginator'); const Article = require('./common/article'); module.exports = class extends Component { render() { const { config, page, helper } = this.props; const { __, url_for } = helper; return {page.posts.map(post =>
)} {page.total > 1 ? : null} ; } }; ================================================ FILE: layout/layout.jsx ================================================ const { Component } = require('inferno'); const classname = require('hexo-component-inferno/lib/util/classname'); const Head = require('./common/head'); const Navbar = require('./common/navbar'); const Widgets = require('./common/widgets'); const Footer = require('./common/footer'); const Scripts = require('./common/scripts'); const Search = require('./common/search'); module.exports = class extends Component { render() { const { site, config, page, helper, body } = this.props; const language = page.lang || page.language || config.language; const columnCount = Widgets.getColumnCount(config.widgets, config, page); return