From 132f0eb30bd24d5478cbc3c03b677f4f4793ac33 Mon Sep 17 00:00:00 2001 From: Ming Di Leom <2809763-curben@users.noreply.gitlab.com> Date: Sat, 28 Sep 2024 06:31:52 +0000 Subject: [PATCH] Initial microblog --- .gitignore | 8 + .gitlab-ci.yml | 73 + .npmrc | 4 + .nvmrc | 1 + .snyk | 14 + .vscode/settings.json | 22 + LICENSE.md | 22 + README.md | 83 + _config.yml | 111 + check-homepage.sh | 16 + netlify.toml | 4 + package.json | 26 + scaffolds/draft.md | 4 + scaffolds/page.md | 4 + scaffolds/post.md | 5 + scripts/image.js | 42 + scripts/smartypants.js | 48 + source/404.md | 5 + source/_headers | 10 + source/_posts/2024-07-15.md | 6 + source/_posts/2024-07-16.md | 6 + source/_posts/2024-07-18.md | 6 + source/_posts/2024-07-22.md | 6 + source/_posts/2024-08-23.md | 6 + source/_posts/2024-09-08.md | 6 + source/_posts/2024-09-15.md | 6 + source/_posts/2024-09-24.md | 8 + source/_redirects | 6 + source/android-chrome-192x192.png | Bin 0 -> 1352 bytes source/android-chrome-512x512.png | Bin 0 -> 3410 bytes source/apple-touch-icon-180x180.png | Bin 0 -> 1124 bytes source/favicon.ico | Bin 0 -> 15086 bytes source/icon/logo.png | Bin 0 -> 7259 bytes source/icon/logo.svg | 4 + source/robots-mdleom.com.txt | 6 + source/robots.txt | 3 + source/site.webmanifest | 20 + source/svg/codeberg.svg | 4 + source/svg/favicon.svg | 1 + source/svg/github.svg | 4 + source/svg/gitlab.svg | 4 + source/svg/linkedin.svg | 4 + source/svg/npm.svg | 4 + themes/chameleon/.npmrc | 2 + themes/chameleon/README.md | 56 + themes/chameleon/build/script.js | 33 + themes/chameleon/languages/default.yml | 1 + themes/chameleon/languages/en-GB.yml | 22 + .../layout/_partial/after-footer.ejs | 9 + .../layout/_partial/archive-post.ejs | 9 + themes/chameleon/layout/_partial/archive.ejs | 22 + themes/chameleon/layout/_partial/article.ejs | 53 + themes/chameleon/layout/_partial/footer.ejs | 16 + themes/chameleon/layout/_partial/head.ejs | 66 + themes/chameleon/layout/_partial/header.ejs | 51 + .../layout/_partial/post/category.ejs | 10 + .../chameleon/layout/_partial/post/date.ejs | 6 + .../layout/_partial/post/gallery.ejs | 11 + themes/chameleon/layout/_partial/post/nav.ejs | 20 + themes/chameleon/layout/_partial/post/tag.ejs | 7 + .../chameleon/layout/_partial/post/title.ejs | 18 + .../layout/_partial/post/updated-date.ejs | 3 + themes/chameleon/layout/archive.ejs | 5 + themes/chameleon/layout/category.ejs | 5 + themes/chameleon/layout/index.ejs | 15 + themes/chameleon/layout/layout.ejs | 16 + themes/chameleon/layout/page.ejs | 1 + themes/chameleon/layout/post.ejs | 1 + themes/chameleon/layout/tag-index.ejs | 10 + themes/chameleon/layout/tag.ejs | 5 + themes/chameleon/package.json | 17 + .../chameleon/preview/preview-dark-mode.png | Bin 0 -> 297644 bytes themes/chameleon/preview/preview.png | Bin 0 -> 94222 bytes themes/chameleon/scripts/copy-button.js | 16 + themes/chameleon/scripts/feed/.atom.xml | 55 + themes/chameleon/scripts/feed/generator.js | 58 + themes/chameleon/scripts/feed/index.js | 32 + themes/chameleon/scripts/heading-link.js | 33 + themes/chameleon/scripts/link.js | 26 + themes/chameleon/scripts/openGraph.js | 94 + themes/chameleon/scripts/sitemap/.LICENSE | 7 + themes/chameleon/scripts/sitemap/.sitemap.xml | 32 + themes/chameleon/scripts/sitemap/generator.js | 47 + themes/chameleon/scripts/sitemap/index.js | 19 + themes/chameleon/scripts/sitemap/template.js | 30 + themes/chameleon/scripts/titleCase.js | 13 + themes/chameleon/source/css/_source.css | 920 ++++++ themes/chameleon/source/css/chameleon.css | 1238 +++++++ themes/chameleon/source/js/chameleon.js | 70 + themes/chameleon/source/js/copy-button.js | 29 + .../source/libs/clipboard-2.0.6.min.js | 7 + .../forkawesome/css/forkawesome-1.1.7.min.css | 12 + .../forkawesome/fonts/forkawesome-webfont.eot | Bin 0 -> 188946 bytes .../forkawesome/fonts/forkawesome-webfont.svg | 2849 +++++++++++++++++ .../forkawesome/fonts/forkawesome-webfont.ttf | Bin 0 -> 188756 bytes .../fonts/forkawesome-webfont.woff | Bin 0 -> 115148 bytes .../fonts/forkawesome-webfont.woff2 | Bin 0 -> 91624 bytes themes/chameleon/source/svg/link.svg | 9 + themes/chameleon/source/svg/search.svg | 2 + themes/chameleon/source/svg/share.svg | 11 + 100 files changed, 6711 insertions(+) create mode 100644 .gitignore create mode 100644 .gitlab-ci.yml create mode 100644 .npmrc create mode 100644 .nvmrc create mode 100644 .snyk create mode 100644 .vscode/settings.json create mode 100644 LICENSE.md create mode 100644 README.md create mode 100644 _config.yml create mode 100644 check-homepage.sh create mode 100644 netlify.toml create mode 100644 package.json create mode 100644 scaffolds/draft.md create mode 100644 scaffolds/page.md create mode 100644 scaffolds/post.md create mode 100644 scripts/image.js create mode 100644 scripts/smartypants.js create mode 100644 source/404.md create mode 100644 source/_headers create mode 100644 source/_posts/2024-07-15.md create mode 100644 source/_posts/2024-07-16.md create mode 100644 source/_posts/2024-07-18.md create mode 100644 source/_posts/2024-07-22.md create mode 100644 source/_posts/2024-08-23.md create mode 100644 source/_posts/2024-09-08.md create mode 100644 source/_posts/2024-09-15.md create mode 100644 source/_posts/2024-09-24.md create mode 100644 source/_redirects create mode 100644 source/android-chrome-192x192.png create mode 100644 source/android-chrome-512x512.png create mode 100644 source/apple-touch-icon-180x180.png create mode 100644 source/favicon.ico create mode 100644 source/icon/logo.png create mode 100644 source/icon/logo.svg create mode 100644 source/robots-mdleom.com.txt create mode 100644 source/robots.txt create mode 100644 source/site.webmanifest create mode 100644 source/svg/codeberg.svg create mode 100644 source/svg/favicon.svg create mode 100644 source/svg/github.svg create mode 100644 source/svg/gitlab.svg create mode 100644 source/svg/linkedin.svg create mode 100644 source/svg/npm.svg create mode 100644 themes/chameleon/.npmrc create mode 100644 themes/chameleon/README.md create mode 100644 themes/chameleon/build/script.js create mode 120000 themes/chameleon/languages/default.yml create mode 100644 themes/chameleon/languages/en-GB.yml create mode 100644 themes/chameleon/layout/_partial/after-footer.ejs create mode 100644 themes/chameleon/layout/_partial/archive-post.ejs create mode 100644 themes/chameleon/layout/_partial/archive.ejs create mode 100644 themes/chameleon/layout/_partial/article.ejs create mode 100644 themes/chameleon/layout/_partial/footer.ejs create mode 100644 themes/chameleon/layout/_partial/head.ejs create mode 100644 themes/chameleon/layout/_partial/header.ejs create mode 100644 themes/chameleon/layout/_partial/post/category.ejs create mode 100644 themes/chameleon/layout/_partial/post/date.ejs create mode 100644 themes/chameleon/layout/_partial/post/gallery.ejs create mode 100644 themes/chameleon/layout/_partial/post/nav.ejs create mode 100644 themes/chameleon/layout/_partial/post/tag.ejs create mode 100644 themes/chameleon/layout/_partial/post/title.ejs create mode 100644 themes/chameleon/layout/_partial/post/updated-date.ejs create mode 100644 themes/chameleon/layout/archive.ejs create mode 100644 themes/chameleon/layout/category.ejs create mode 100644 themes/chameleon/layout/index.ejs create mode 100644 themes/chameleon/layout/layout.ejs create mode 100644 themes/chameleon/layout/page.ejs create mode 100644 themes/chameleon/layout/post.ejs create mode 100644 themes/chameleon/layout/tag-index.ejs create mode 100644 themes/chameleon/layout/tag.ejs create mode 100644 themes/chameleon/package.json create mode 100644 themes/chameleon/preview/preview-dark-mode.png create mode 100644 themes/chameleon/preview/preview.png create mode 100644 themes/chameleon/scripts/copy-button.js create mode 100644 themes/chameleon/scripts/feed/.atom.xml create mode 100644 themes/chameleon/scripts/feed/generator.js create mode 100644 themes/chameleon/scripts/feed/index.js create mode 100644 themes/chameleon/scripts/heading-link.js create mode 100644 themes/chameleon/scripts/link.js create mode 100644 themes/chameleon/scripts/openGraph.js create mode 100644 themes/chameleon/scripts/sitemap/.LICENSE create mode 100644 themes/chameleon/scripts/sitemap/.sitemap.xml create mode 100644 themes/chameleon/scripts/sitemap/generator.js create mode 100644 themes/chameleon/scripts/sitemap/index.js create mode 100644 themes/chameleon/scripts/sitemap/template.js create mode 100644 themes/chameleon/scripts/titleCase.js create mode 100644 themes/chameleon/source/css/_source.css create mode 100644 themes/chameleon/source/css/chameleon.css create mode 100644 themes/chameleon/source/js/chameleon.js create mode 100644 themes/chameleon/source/js/copy-button.js create mode 100644 themes/chameleon/source/libs/clipboard-2.0.6.min.js create mode 100644 themes/chameleon/source/libs/forkawesome/css/forkawesome-1.1.7.min.css create mode 100644 themes/chameleon/source/libs/forkawesome/fonts/forkawesome-webfont.eot create mode 100644 themes/chameleon/source/libs/forkawesome/fonts/forkawesome-webfont.svg create mode 100644 themes/chameleon/source/libs/forkawesome/fonts/forkawesome-webfont.ttf create mode 100644 themes/chameleon/source/libs/forkawesome/fonts/forkawesome-webfont.woff create mode 100644 themes/chameleon/source/libs/forkawesome/fonts/forkawesome-webfont.woff2 create mode 100644 themes/chameleon/source/svg/link.svg create mode 100644 themes/chameleon/source/svg/search.svg create mode 100644 themes/chameleon/source/svg/share.svg diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2d8d57f --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +.DS_Store +Thumbs.db +db.json +*.log +node_modules/ +package-lock.json +public/ +.deploy*/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..18d7fb1 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,73 @@ +image: node:alpine # Use latest version of Node.js on Alpine + +cache: + paths: + - node_modules/ + +variables: + NODE_ENV: "production" + +# Rename to 'pages' for gitlab pages +build: + stage: build + + before_script: + - apk update && apk add git + - npm install --include=optional --force + + script: + # Generate site + - npm run build + + rules: + # Only trigger through push & "Run pipeline" events not in "site" branch; Skip in renovate job + - if: '$RENOVATE != "true" && $CI_COMMIT_REF_NAME != "site" && ($CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "web")' + when: always + + artifacts: + paths: + - public/ + expire_in: 30 days + +test: + stage: test + + script: + # /microblog/ should exist and non-empty + - sh check-homepage.sh + + rules: + - if: '$RENOVATE != "true" && $CI_COMMIT_REF_NAME == "master" && ($CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "web")' + when: always + + artifacts: + paths: + - public/ + expire_in: 30 days + +deploy: + stage: deploy + + before_script: + - apk update && apk add openssh-client rsync + - mkdir -p ~/.ssh + - chmod 700 ~/.ssh + - echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts + - chmod 644 ~/.ssh/known_hosts + - echo "$SSH_KEY_1" > ~/.ssh/id_host_1 + - chmod 600 ~/.ssh/id_host_1 + - echo "$SSH_KEY_2" > ~/.ssh/id_host_2 + - chmod 600 ~/.ssh/id_host_2 + - echo "$SSH_CONFIG" > ~/.ssh/config + - chmod 600 ~/.ssh/config + + script: + - rsync -azvh --delete public/microblog/ host-1:/var/www/microblog/ + - rsync -azvh --delete public/microblog/ host-2:/var/www/microblog/ + + rules: + - if: '$RENOVATE != "true" && $CI_COMMIT_REF_NAME == "microblog" && ($CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "web")' + when: always + +include: + - template: Security/Secret-Detection.gitlab-ci.yml diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..d610e1d --- /dev/null +++ b/.npmrc @@ -0,0 +1,4 @@ +package-lock=false +optional=true +lockfile=false +force=true diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..209e3ef --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +20 diff --git a/.snyk b/.snyk new file mode 100644 index 0000000..65fc165 --- /dev/null +++ b/.snyk @@ -0,0 +1,14 @@ +# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. +version: v1.13.5 +# ignores vulnerabilities until expiry date; change duration by modifying expiry date +ignore: + SNYK-JS-HTMLMINIFIER-3091181: + - "*": + reason: Patch unavailable + expires: "2024-06-30T00:00:00.000Z" + SNYK-JS-HEXO-5889980: + - "*": + reason: "https://github.com/hexojs/hexo/pull/5251" + expires: "2024-06-30T00:00:00.000Z" +# patches apply the minimum changes required to fix a vulnerability +patch: diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..91900ed --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,22 @@ +{ + "editor.tabSize": 2, + "files.eol": "\n", + "files.trimTrailingWhitespace": true, + "files.insertFinalNewline": true, + "files.trimFinalNewlines": true, + "standard.run": "onSave", + "[markdown]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true + }, + "[yaml]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true + }, + "[json]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[jsonc]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + } +} diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..0c62922 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2016-2018 GeekPlux ([Typing](https://github.com/geekplux/hexo-theme-typing) theme) +Copyright (c) 2018-2024 Ming Di Leom + +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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..ac04d42 --- /dev/null +++ b/README.md @@ -0,0 +1,83 @@ +# [mdleom.com](https://mdleom.com/) + +[![Website Status](https://img.shields.io/website?url=https%3A%2F%2Fmdleom.com)](https://stats.uptimerobot.com/1394zup2LQ) +[![Netlify Status](https://api.netlify.com/api/v1/badges/3f4b970a-c258-454c-97d6-3a8164f63262/deploy-status)](https://app.netlify.com/sites/curben/deploys) +[![Build Status](https://gitlab.com/curben/blog/badges/master/pipeline.svg)](https://gitlab.com/curben/blog/-/jobs) +[![Hexo version](https://img.shields.io/badge/hexo-hexojs/hexo-brightgreen.svg)](https://github.com/hexojs/hexo) + +### Plugins + +- Installed [hexo-yam](https://github.com/curbengh/hexo-yam) (author) to pre-compress static assets (html, css, js and svg). +- Installed [hexo-nofollow](https://github.com/curbengh/hexo-nofollow) for SEO purpose to prevent search engines from following external links. +- [copy-button.js](/themes/chameleon/scripts/copy-button.js) - A [filter](https://hexo.io/api/filter) plugin to add a copy button to each code block. +- [feed](/themes/chameleon/scripts/feed) - A generator plugin to generate [an RSS feed](https://en.wikipedia.org/wiki/Web_feed). Adapted from [hexo-generator-feed](https://github.com/hexojs/hexo-generator-feed) for simpler use case. +- [heading-link.js](/themes/chameleon/scripts/heading-link.js) - A filter plugin to add a link button next to each heading. +- [image.js](/scripts/image.js) - A [tag](https://hexo.io/api/tag) plugin to easily embed images in a post with responsive image support. +- [link.js](/themes/chameleon/scripts/link.js) - A [helper](https://hexo.io/api/helper) plugin to add a link. Modified from [link_to.js](https://github.com/hexojs/hexo/blob/master/lib/plugins/helper/link_to.js) to remove title attribute and 'external' option. +- [openGraph](/themes/chameleon/scripts/openGraph.js) - A helper plugin to add [Open Graph](https://ogp.me/) tags. Modified from [open_graph.js](https://github.com/hexojs/hexo/blob/master/lib/plugins/helper/open_graph.js) to use additional [Open Graph](https://www.ogp.me/) tags and [WHATWG URL API](https://nodejs.org/api/url.html#url_the_whatwg_url_api). +- [sitemap](/scripts/sitemap) - A [generator](https://hexo.io/api/generator) plugin to generate [a sitemap](https://en.wikipedia.org/wiki/Sitemaps). Modified from [hexo-generator-sitemap](https://github.com/hexojs/hexo-generator-sitemap) with this [patch](https://github.com/hexojs/hexo-generator-sitemap/pull/26) to include tags/categories and [remove](https://github.com/pyyzcwg2833/hexo-generator-sitemap/commit/a92dbbb83cc39ff60d43faa5cd688a56574a3889) [index.html](https://github.com/hexojs/hexo-generator-sitemap/pull/59) from the URL. + +## Changes + +The following are the major changes I made compared to the upstream. + +### [Hexo](https://gitlab.com/pages/hexo) site + +- Updated [.gitlab-ci.yml](.gitlab-ci.yml) to use the latest version of [Node.js](https://hub.docker.com/_/node/) in Alpine docker image. +- [All packages](package.json) are installed from their respective master branch, instead of npm published version. +- Removed unused packages, [hexo-generator-category](https://github.com/hexojs/hexo-generator-category) and [hexo-renderer-stylus](https://github.com/hexojs/hexo-renderer-stylus) from the [default packages](https://github.com/hexojs/hexo-starter/blob/571320ba41a83e065d7560e050eb3fa63ad74a57/package.json#L9-L17). +- Replaced the bundled Landscape theme with Typing theme. +- Add `lastUpdated` to the front-matter to manually set updated time of a post, instead of using `post.updated`. + - This is no longer necessary, thanks to [`updated_option`](https://github.com/hexojs/hexo/pull/4278) feature. + +### [Chameleon theme](/themes/chameleon) + +Chameleon is a fork of [Typing](https://github.com/geekplux/hexo-theme-typing) theme, rewrote from scratch with the following changes/features: + +- [sanitize.css](https://github.com/csstools/sanitize.css/) and [autoprefixer](https://github.com/csstools/sanitize.css/) for consistent cross-browser styling. +- Utilise [relative length](https://www.w3schools.com/CSSref/css_units.asp) instead of absolute length in the css. +- [`prefers-color-scheme`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) to apply light/dark theme according to the OS preference. +- Add a [Copy](https://clipboardjs.com/) button to each code block. +- Removed jQuery, fancyBox, web analytics, comment plugins, donation links and [typo.css](https://github.com/sofish/typo.css). +- Homepage shows recent posts and tags. + +## Installation + +Refer to [this post](https://mdleom.com/2018/09/21/how-to-create-a-hexo-blog/) for more detailed instruction. + +## License + +Copyright (c) 2018-2024 Ming Di Leom + +The content of this blog is licensed under a [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/) license, and the underlying source code used to format and display that content is licensed under an [MIT license](LICENSE.md), unless indicated otherwise. + +## Website Mirrors + +- https://curben.pages.dev/ +- https://curben.netlify.app/ +- https://curben.gitlab.io/ +- https://curbengh.github.io/ +- https://xw226dvxac7jzcpsf4xb64r4epr6o5hgn46dxlqk7gnjptakik6xnzqd.onion/ +- http://mdleom.i2p/ ([address helper](http://mdleom.i2p/?i2paddresshelper=-NjUAy6H3wkgRfB3rBwGrpS56L2P~RHRDnD8HnRV1mLSKFdbzxHTMsGLo-mdgGq360Kni2Ec0qhRzm-IUc8X4Y0Ug1eYvcEp2ubXwLe5JJg7yZJOdGxqdy5y5VbdHfIuUe2ooG3MNA4v6b4pGk7pUQ7hnTkUi0EObD~79ik4AY-vSsxIFrc8kJxtbRMCQ3NQRhAuvS1A14rSVk0wv50YwKS23y~FUIQWyG8ZpjTVYu50n~oBnJtVKSAHbCMWRcnJx6iGFsbTRh4ZsRtDh0drwfeRkvaQQqQmf6nZOc4-GLxZ0RT5QlS5gdPXL4V7eaIETbNJAIeYr2NzcpwVHs~zp93Ga-p7dlH3TsJX5gJSyqJWCc64vvmkxf7Vseh3uGaa4xqiLjTH5XsOyFQLp5D6myt-yH7ggReZbs70NKqG1Mj5iRLhIC3Q~pJ6LkPnMBJN6QeLNYNWcOPXkMzRfsavvH2l3yxdpkn41BLM2-7bBUdJNXfu4OhGAR22O0gFngjUBQAEAAcAAA==&update=true)) +- http://ggucqf2jmtfxcw7us5sts3x7u2qljseocfzlhzebfpihkyvhcqfa.b32.i2p/ + +## Repository Mirrors + +- https://github.com/curbengh +- https://pagure.io/projects/curben/%2A +- https://codeberg.org/curben +- https://git.disroot.org/curben +- https://git.nixnet.services/curben +- https://gitea.com/curben +- https://framagit.org/curben + +## Uptime Status + +- https://stats.uptimerobot.com/1394zup2LQ + +--- + +Useful links: + +- [Hexo Docs](https://hexo.io/docs/) +- [GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/index.html) diff --git a/_config.yml b/_config.yml new file mode 100644 index 0000000..c11e938 --- /dev/null +++ b/_config.yml @@ -0,0 +1,111 @@ +# Hexo Configuration +## Docs: https://hexo.io/docs/configuration.html +## Source: https://github.com/hexojs/hexo/ + +# Site +title: Ming Di Leom's Blog +subtitle: +description: +author: "Ming Di Leom" +language: en-GB +timezone: + +# URL +## If your site is put in a subdirectory, set url as 'http://yoursite.com/child' and root as '/child/' +url: https://mdleom.com +root: / +permalink: microblog/:title/ +permalink_defaults: +pretty_urls: + trailing_index: false + trailing_html: false + +# Directory +source_dir: source +public_dir: public +tag_dir: tags +tag_generator: + enable_index_page: true +archive_dir: microblog +category_dir: categories +code_dir: "" +i18n_dir: :lang +skip_render: +include: + - "_headers" # Netlify header rule + - "_redirects" # Netlify redirects rule + +# Writing +new_post_name: :title.md # File name of new posts +default_layout: post +titlecase: false # Transform title into titlecase +external_link: + enable: false # Open external links in new tab +filename_case: 0 +render_drafts: false +post_asset_folder: false +relative_link: false +future: true +highlight: + enable: true + line_number: false + auto_detect: false + tab_replace: " " + hljs: true + wrap: false + +# Tag +tag_map: + +# Date / Time format +## Hexo uses Moment.js to parse and display date +## You can customize the date format as defined in +## http://momentjs.com/docs/#/displaying/format/ +date_format: YYYY-MM-DD +time_format: HH:mm:ss +updated_option: empty + +# Pagination +## Set per_page to 0 to disable pagination +per_page: 10 +pagination_dir: page + +marked: + descriptionLists: false + modifyAnchors: 1 + +# Extensions +## Plugins: https://hexo.io/plugins/ +## Themes: https://hexo.io/themes/ +theme: chameleon + +feed: + icon: "/svg/favicon.svg" + +# theme config +theme_config: + # Header + menu: + Home: / + Blog: /blog/ + Microblog: /microblog/ + About: /about/ + Feed: /atom.xml + GitLab: https://gitlab.com/curben/blog + + footer: + Disclaimer: /disclaimer/ + Status: https://stats.uptimerobot.com/1394zup2LQ + Onion: https://xw226dvxac7jzcpsf4xb64r4epr6o5hgn46dxlqk7gnjptakik6xnzqd.onion/ + Eepsite: https://gitlab.com/curben/blog#mirrors + + # Load forkawesome icons? + icons: false + +# https://github.com/curbengh/hexo-yam +minify: + svg: + plugins: + cleanupIds: false + zstd: + enable: true diff --git a/check-homepage.sh b/check-homepage.sh new file mode 100644 index 0000000..f75e8ac --- /dev/null +++ b/check-homepage.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +## Homepage should exists and non-empty + +HOMEPAGE="public/microblog/index.html" + +if [ ! -f "$HOMEPAGE" ]; then + echo "Error: homepage doesn't exist" + exit 1 +else + FILE_SIZE=$(ls -s "$HOMEPAGE" | cut -d" " -f1) + if [ "$FILE_SIZE" = 0 ]; then + echo "Error: homepage is empty" + exit 1 + fi +fi diff --git a/netlify.toml b/netlify.toml new file mode 100644 index 0000000..edc81cd --- /dev/null +++ b/netlify.toml @@ -0,0 +1,4 @@ +[context.production] + environment = { NODE_ENV = "production" } + publish = "public" + command = "npm run build" diff --git a/package.json b/package.json new file mode 100644 index 0000000..af896fb --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "name": "blog", + "version": "1.0.0", + "private": true, + "hexo": { + "version": "7.2.0" + }, + "scripts": { + "build": "hexo generate", + "snyk": "snyk auth $SNYK_TOKEN && snyk-protect && snyk test && snyk monitor", + "renovate": "renovate --platform 'gitlab' --autodiscover false --onboarding false --update-lock-files false --labels 'renovate' --require-config='ignored' \"$CI_PROJECT_PATH\"" + }, + "dependencies": { + "hexo": "^7.0.0", + "hexo-filter-nofollow": "hexojs/hexo-filter-nofollow", + "hexo-generator-archive": "hexojs/hexo-generator-archive", + "hexo-generator-index": "hexojs/hexo-generator-index", + "hexo-generator-tag": "hexojs/hexo-generator-tag", + "hexo-renderer-ejs": "hexojs/hexo-renderer-ejs", + "hexo-renderer-marked": "hexojs/hexo-renderer-marked", + "hexo-yam": "curbengh/hexo-yam" + }, + "devDependencies": { + "hexo-server": "hexojs/hexo-server" + } +} diff --git a/scaffolds/draft.md b/scaffolds/draft.md new file mode 100644 index 0000000..498e95b --- /dev/null +++ b/scaffolds/draft.md @@ -0,0 +1,4 @@ +--- +title: {{ title }} +tags: +--- diff --git a/scaffolds/page.md b/scaffolds/page.md new file mode 100644 index 0000000..f01ba3c --- /dev/null +++ b/scaffolds/page.md @@ -0,0 +1,4 @@ +--- +title: {{ title }} +date: {{ date }} +--- diff --git a/scaffolds/post.md b/scaffolds/post.md new file mode 100644 index 0000000..1f9b9a4 --- /dev/null +++ b/scaffolds/post.md @@ -0,0 +1,5 @@ +--- +title: {{ title }} +date: {{ date }} +tags: +--- diff --git a/scripts/image.js b/scripts/image.js new file mode 100644 index 0000000..eb82a89 --- /dev/null +++ b/scripts/image.js @@ -0,0 +1,42 @@ +'use strict' +/* global hexo */ + +/* +* Embed an image with responsive images in a post +* https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images +* Image is resized on-the-fly using Statically (https://statically.io/) +* Usage: ![alt](/path/to/img "title") +*/ + +const { join } = require('path').posix + +hexo.extend.filter.register('marked:renderer', (renderer) => { + renderer.image = (href, title, alt) => { + if (!alt) alt = '' + if (!title) title = alt + + if (href.endsWith('.svg')) return `${alt}` + + // embed external image + if (href.startsWith('http')) return `${alt}` + + const fLink = (path, width) => { + const query = new URLSearchParams('f=auto') + if (typeof width === 'number') query.set('width', width) + const url = new URL('http://example.com/' + join('img', path) + '?' + query) + + return url.pathname + url.search + } + + return `` + + `${alt}` + } +}) diff --git a/scripts/smartypants.js b/scripts/smartypants.js new file mode 100644 index 0000000..87f7dbf --- /dev/null +++ b/scripts/smartypants.js @@ -0,0 +1,48 @@ +const { escapeHTML: escape } = require('hexo-util') + +// https://github.com/markedjs/marked/blob/b6773fca412c339e0cedd56b63f9fa1583cfd372/src/Lexer.js#L8-L24 +// Replace dashes only +const smartypants = (str) => { + return str + // em-dashes + .replace(/---/g, '\u2014') + // en-dashes + .replace(/--/g, '\u2013') + // opening singles + .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018') + // closing singles & apostrophes + .replace(/'/g, '\u2019') + // opening doubles + .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c') + // closing doubles + .replace(/"/g, '\u201d') + // ellipses + .replace(/\.{3}/g, '\u2026') + // right arrow + .replace(/->/g, '\u2192') +} + +hexo.extend.filter.register('marked:tokenizer', function (tokenizer) { + const { smartypants: isSmarty } = this.config.marked + tokenizer.inlineText = function (src) { + const { rules } = this + + // https://github.com/markedjs/marked/blob/b6773fca412c339e0cedd56b63f9fa1583cfd372/src/Tokenizer.js#L643-L658 + const cap = rules.inline.text.exec(src) + if (cap) { + let text + if (this.lexer.state.inRawBlock) { + text = cap[0] + } else { + text = escape(isSmarty ? smartypants(cap[0]) : cap[0]) + } + return { + // `type` value is a corresponding renderer method + // https://marked.js.org/using_pro#inline-level-renderer-methods + type: 'text', + raw: cap[0], + text + } + } + } +}) diff --git a/source/404.md b/source/404.md new file mode 100644 index 0000000..c35775e --- /dev/null +++ b/source/404.md @@ -0,0 +1,5 @@ +--- +title: Page not found +layout: page +sitemap: false +--- diff --git a/source/_headers b/source/_headers new file mode 100644 index 0000000..187466d --- /dev/null +++ b/source/_headers @@ -0,0 +1,10 @@ +/* + Content-Security-Policy: default-src 'self'; child-src 'none'; connect-src 'none'; font-src 'none'; frame-src 'none'; img-src 'self'; manifest-src 'self'; media-src 'none'; object-src 'none'; prefetch-src 'none'; script-src 'self'; style-src 'self'; worker-src 'none'; base-uri 'none'; form-action https://duckduckgo.com https://duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad.onion; frame-ancestors 'none'; block-all-mixed-content; sandbox allow-forms allow-scripts + Expires: 0 + Permissions-Policy: accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(), gamepad=(), geolocation=(), gyroscope=(), hid=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), serial=(), speaker=(), speaker-selection=(), usb=(), web-share=(self), xr-spatial-tracking=(), interest-cohort=() + Referrer-Policy: no-referrer + Strict-Transport-Security: max-age=31536000; includeSubDomains; preload + X-Content-Type-Options: nosniff + X-Frame-Options: DENY + X-XSS-Protection: 1; mode=block + X-Robots-Tag: noindex diff --git a/source/_posts/2024-07-15.md b/source/_posts/2024-07-15.md new file mode 100644 index 0000000..d330cb0 --- /dev/null +++ b/source/_posts/2024-07-15.md @@ -0,0 +1,6 @@ +--- +title: SSSD cache +date: 2024-07-15 +--- + +If sssd unable to starts after upgrade/downgrade, clear its cache by deleting all files in the "/var/lib/sss/db/" folder. Encountered [this issue](https://bugzilla.redhat.com/show_bug.cgi?id=1576597) when upgrading/switching AlmaLinux 8 and CentOS Stream 9 to AlmaLinux 9. diff --git a/source/_posts/2024-07-16.md b/source/_posts/2024-07-16.md new file mode 100644 index 0000000..606ba78 --- /dev/null +++ b/source/_posts/2024-07-16.md @@ -0,0 +1,6 @@ +--- +title: Failing task +date: 2024-07-16 +--- + +If a scheduled task has been failing for a while and no one bats an eye, just disable it. diff --git a/source/_posts/2024-07-18.md b/source/_posts/2024-07-18.md new file mode 100644 index 0000000..59f5311 --- /dev/null +++ b/source/_posts/2024-07-18.md @@ -0,0 +1,6 @@ +--- +title: TLS 1.3 in AWS services +date: 2024-07-18 +--- + +At least 30% of `PUT` traffic in a Cloudtrail bucket is still TLS 1.2. Don't set [`minimum_tls_version=1.3`](https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_s3/Bucket.html) on that bucket yet. diff --git a/source/_posts/2024-07-22.md b/source/_posts/2024-07-22.md new file mode 100644 index 0000000..d48e387 --- /dev/null +++ b/source/_posts/2024-07-22.md @@ -0,0 +1,6 @@ +--- +title: Opt-out from ChatGPT model training +date: 2024-07-22 +--- + +In OpenAI ChatGPT, it is now possible to disable [model training](https://help.openai.com/en/articles/7730893-data-controls-faq) while still keeping the chat history. [Previously](https://openai.com/index/new-ways-to-manage-your-data-in-chatgpt/), both had to be disabled together. diff --git a/source/_posts/2024-08-23.md b/source/_posts/2024-08-23.md new file mode 100644 index 0000000..9fbcc2f --- /dev/null +++ b/source/_posts/2024-08-23.md @@ -0,0 +1,6 @@ +--- +title: Huawei USB 4G + Creta +date: 2024-08-23 +--- + +Huawei USB 4G modem E3372h-608 firmware 10.0.5.1 works out-of-the-box as a tethering connection with GL.iNet Creta AR750 firmware 4.3.17 running OpenWrt 22.03.4 r20123-38ccc47687. diff --git a/source/_posts/2024-09-08.md b/source/_posts/2024-09-08.md new file mode 100644 index 0000000..f960825 --- /dev/null +++ b/source/_posts/2024-09-08.md @@ -0,0 +1,6 @@ +--- +title: Uninstall CentOS kernel +date: 2024-09-08 +--- + +After converting from CentOS to AlmaLinux, uninstall CentOS kernels which would otherwise prevent dnf from installing newer Alma kernel due to higher version of CentOS kernel. diff --git a/source/_posts/2024-09-15.md b/source/_posts/2024-09-15.md new file mode 100644 index 0000000..de9a0f7 --- /dev/null +++ b/source/_posts/2024-09-15.md @@ -0,0 +1,6 @@ +--- +title: eSIM RSP certificate +date: 2024-09-15 +--- + +If you are using any of these [removable eSIMs](https://euicc-manual.osmocom.org/docs/lpa/known-card/#product), when adding a new profile, check the SM-DP+ address has `81370f5125d0b1d408d4c3b232e6d25e795bebfb` (GSM Association - RSP2 Root CI1) as one of its issuer(s) in the [registry.csv](https://github.com/CursedHardware/gsma-rsp-certificates/blob/main/registry.csv) and does not contain an [ARA-M applet](https://osmocom.org/projects/sim-card-related/wiki/ESIM_profile_database) (which [complicates things](https://sysmocom.de/manuals/sysmoeuicc-manual.pdf) p. 26). diff --git a/source/_posts/2024-09-24.md b/source/_posts/2024-09-24.md new file mode 100644 index 0000000..196e326 --- /dev/null +++ b/source/_posts/2024-09-24.md @@ -0,0 +1,8 @@ +--- +title: Splunk Connect for Syslog +date: 2024-09-24 +--- + +In Splunk Connect for Syslog ([SC4S](https://splunk.github.io/splunk-connect-for-syslog/main/)), [`SC4S_DEST_GLOBAL_ALTERNATES`](https://splunk.github.io/splunk-connect-for-syslog/1.110.1/configuration/#configuration-of-alternate-destinations) has been deprecated since version 2. Instead, enable [`SC4S_ARCHIVE_GLOBAL`](https://splunk.github.io/splunk-connect-for-syslog/3.30.1/configuration/#archive-file-configuration) which stores a copy of events locally, not only for archiving (if that's what you intend) but also useful for troubleshooting dropped events. + +If [`compliance_meta_by_source.conf`](https://splunk.github.io/splunk-connect-for-syslog/3.30.1/configuration/#override-index-or-metadata-based-on-host-ip-or-subnet-compliance-overrides) is not working, you may have to create a [custom post-filter](https://splunk.github.io/splunk-connect-for-syslog/3.30.1/create-parser/#create-a-parser_1) in "/opt/sc4s/local/config/filters/" instead. diff --git a/source/_redirects b/source/_redirects new file mode 100644 index 0000000..94180c1 --- /dev/null +++ b/source/_redirects @@ -0,0 +1,6 @@ +# Reverse proxy to cdn +/img/* https://curben.gitlab.io/blog/:splat 200 +/files/* https://curben.gitlab.io/blog/:splat 200 +# https://statically.discourse.group/t/mobile-version-not-working-on-screenshot/225 +# /screenshot/* https://cdn.statically.io/screenshot/device=mobile/curben.netlify.app/:splat 200 +/screenshot/* https://cdn.statically.io/screenshot/curben.netlify.app/:splat 200 diff --git a/source/android-chrome-192x192.png b/source/android-chrome-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..e95c50283773efa2d0225980383d6a93f2b4685d GIT binary patch literal 1352 zcmX|B4OEh66#kGv6SYi4ZM0C-{OL=X#ne?Q(*#2l)Kch7{G*AL1eE5MGt8DbMJY{k zrumalYD#^arq(dUFj=|n)6{CYlXaTru}qsr**@!>o%25TzR!El``q{E+*=sU3b(dg zYY6~=HG>|?LA-7mE6|9oojtf2aVz$QM1}xByBzl}34?HygcD8!TJIA7L5Np0Gd7Hw zesHU#eVe51(+HF{BXsLW`pNzunr}+}K*z{;*1euM;jMM*!I|m0lME4vXCRHcd8L*ZOIcS$T z-*K$v!{89=YKyt+q`~^WLf+u!%M{^XzLU+3Q4c5QHQretbjPt43fO-sf4pxk#0 zub$kNBaE@raF*c1KOr6>{6;>x27g>I}^|z`#bR zy)~pTg}DzVL&MK={qw9W{7oLYzkBDg4$>-r1(S*)LaP}Ew9%7(alRpnzqNdpJ)SPs zfVC=2v}S~$a?)GTu~+0#?44z)*SzCnjCrXY-q{V6sQ&KOyxQS>ML(|_)EkxGKagFZ zA_6!0EQ-W^gGq)#7B{}ZBnxd7R)4KeWP)J|wwfPFd0@00rLn*eMLy?PDfh}5BAR#d z@z5>KEMb%u0fsA*8WDvD#&w#4Qto2jWs`)Db29->aSA^^&KbI4yrq4=sj&b(lF&b*5SQt<#hcH+6?h*{k* z#kI*muz((x?s4IfU@P;k2=Gh7Mh}6tP}#0yv}7>Pqj&(kqiRwX{p2@jb zIi%88n3+Rbw?M2`#F>g$#H8XJpoa=X#pAa8y_47^&Opwx>q12Wt{Ltao^Wa_$R9JD zLmp^Etv5`67GQbaQ{X0Suh%Wy7(1lPf{DC%^&w)vr=~#jE)mRfJ!>FPh08j75gqNX zN0nD~bdaN){z@E_`?}}mt4`&!at#i@(Noa5%8gt*u1wZ;9;HO{YlpFQ$ZwD#o6;_t z)|WkSY~m8yekjS%inBhex6BSdI}a|8X8X!MNr=XP08BBy6%)q z^~3qH`y-zh&kT{S{`RWKo&lPpit&sV;NMBFk}=!2#$*TT;~|%YeW^qUzx|ObOv*s@sN$m2X7`63uqrvI1v{%*V8u@^PS;nd!L$O z422y9EU^?%T}zMJI|s>f(p#tbyhF{Zz;`AJUe9>HyLFexaig=_R{! zV&kQpq%4w1oGD1(mqwBv5v7sRMbZ=i$o~1std+&VT^=5Hq6UnNryKxH#%)T$*^%vb zp2nl?NTGR~ds5NltFfek5!ldc>?QV^59HBnBQ^n(4z|)++Lm%81;7Yng|^c8vi|_h C!? literal 0 HcmV?d00001 diff --git a/source/android-chrome-512x512.png b/source/android-chrome-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..f305db29885a7ff5d0058bef23d93e419a9cd2a9 GIT binary patch literal 3410 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 literal 0 HcmV?d00001 diff --git a/source/apple-touch-icon-180x180.png b/source/apple-touch-icon-180x180.png new file mode 100644 index 0000000000000000000000000000000000000000..cbf835ef9f000c3dfb5e1b1513fe9e248fa55497 GIT binary patch literal 1124 zcmV-q1e^PbP)Px#Fi=cXMgRZ*J#(F`TPA)fVlAU`HZX3 zV2i$?y4lRy>v^5Xvd7@P&*W~F#3Fx1u>b%AZ%IT!RA}DqnZ0fkK@^3pNFlJhQFKWZ z*#R~&Pml;uY7`{55yjR4$vqN6wAq%*+aqD#z`TJU!CTYdnkIPzymtJvKXc~J5$@)+ zN9TC&%zT-((`tEnd3kwxd3kwxd3kyLFO9a=y!&x$)%(x4R{iAYoDcto?k~CJtG`3{ zUV3zMC}`pxkrTQ)f)hU$IlgAAyKv&yBJzi=PT|BqXVn9;dG9Tnc=yAs`Waarz=`)~ zuCUM~aNK+LUns{gKlF&qO;)P2>(}fdXEUIO~0fQz^ zAF2l&Fks>bmxCsN6E9r~ngmX~bSY?ZIPr8fbRD2cYtc4z_0ZIi5IOpUTs<^FLv{#V zH8e>>whvu3GtE5V}fe(#B{Tx;khY zkyt@va7CVyz^tJ$xhiN9L$(iH6*Rda8benFO=gI8psRr3GjJBaGa>oHPhvpo)c4z{S9YVME(y0YzalDXgg(eqtymDAQf64KyzRPro}>ocj!j7*9K_txtgd> zX#F=qJ20y+Zwxf}aZZ%OHA0gpUtb7la^(^d&}e|+pwR)NfF>q^p`gLLGf?k$12j5d z7-%dv%(edQt@N9q_J$#$NgN);5t`g#`5a%*GKWofgGLXGGc=JCU>0b~PqO#*^DDF7 zRI1;aB^>EX>4U6 zba`-PAZc)PV*mhnoa6Eg2ys>@D9TUE%t_@^00ScnE@KN5BNI!L6ay0=M1VBIWCJ6! qR3OXP)X2ol#2my2%YaCrN-hBE7ZG&wLN%2D0000l&4hq4GIfzJprUw)+IpwxsK##IP%*=w>kHB6(xV6^{zAoMR!J3UXu(wv)R^solA6$$5?*|cR**4w18oW|82l8R( znFm|a*RA1trwzQRC(K(#{wML0w#(8feWyM6zU|5Xr{DF@y_h!#j>E=NPj)!>ZE0uN z@4V#^H}^f*>vt}Dv;qIS=cWIoz#ngyE>NCNMH5LW6lZY^-A?O?;i2@RL|nP z<0}^XdA{b2d8%izz4%+L{I}IYy~^`j9V=hYX7$liEFP-9+1z6dm8oYbd%!B0{}=0( zX%6M;S=wI7SZM2&X%4WvOg&q$SLXYts9u@;U#6bv>@E5IX{=YKIp7(%)HAKUWnux_ zTPFWZe8+lLXwNYgk=$RId^GVbbGWfSI_`h1>y^oW%N#!6&lTZW#=^N?71<=uT+h<` zIUSy5EK>DDhvhPkwOdfn()$$?F0c&sEL}fLcs6`PJxlEuO?btz2o~yx3D1@fyNmTK zXTNU3E2?L@`eDMf;cIeu?s)F!JS`&-H`eEy1kz6K+7oHau z;gH9*f_TWixv_qj@ND@>4mY0Hn(#8Q@K&!(cHICCX-L{6g|I>=F{BVNcuR;Q@&i)HgC3J^k^&DjB8^C4Po;zAxW@jV z6~=Vb3hV5Tf=Nur!KA_dc=ITx;pS13{V+OC(Mc4wIQ~~c|Bj-7eOw0#jY`ndm~R`c zi#Go|trc{ttBQaUfgi4&f7zvd^ZDDS6!p}t3yzex(WEn64?b|j ziD-M+?_P4$n+&gBcrEJ#_PzHUabUlDiSdNqBNtul?{2F0_xs&9UG!twUhtcImgrw` z)DQPR>%1g=fbLyKeLmkSQlD7phmIJrKGzZSCXTux^`w1L=-+X~c*OYeSvcx(?srt% zyyu$2xYInaem{iH6Ic6OFIoHS1IOt(F7fVS?w!3n+Z=OU$BF!Xm-+AZy61HEIc_^A z$|drA21WTw<=ro`J;SrhN6a0RPx6P=8sK^{*|*F`@!FSInE!@F44%k*BlUC?Sf+e5 z&mF|D%mEuZd)aYAK1$_2sSBTr^2a2bZ={}%>hel9_e*`lyR(pQq@Ipy@=lNfxr z^VWeb-$*?j1y(j6<<@?w&v$##zCPbbJsr*B*~|m>Q~Ai0Z*;ch`19|I&OJF+MEQ;@ zF)-$vA}sRccNM8gmV7mT*yI}%<_yp68Djn$IE$Wt-sn7hQQXcd8f zD+06gne?w{jK!castxL++Nh3SHvDI?ag7|&2x~Z$sSTQw`k*zbk6K5KQ7~)c;J7*7 zJZ^@YQ7gp31`at6aKLeZ!wt>Fa|#|yw9)406xtmog#M!o`R~SVzk55|hU*vR-_poC zt64t#7{88ul>B>8=3B8B>~Koo-+1>0$mQ>WsN3tdz|Z@e#VL8iUhpaS>bIu6kNLC# zA9nI&5+8rc<6&(6y$=1exiag)A;xvSpQUYi?agGRZ!sPAy6d?u=%yjNnKlF7v9x|Gk-Z~O19zz4=_K?Y+F(595h>ZyIM z$2=M6t}>RYtjm484zZqGbWTEcb`~nc7l+6b10inW1Y}UdIWW$E57B=8N{Gj3e_%EI Mi5C6Nv()G99}bsQo&W#< literal 0 HcmV?d00001 diff --git a/source/icon/logo.png b/source/icon/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e618ddce0859e211061b09efda186e6653327726 GIT binary patch literal 7259 zcmd5>`6HBV_rGS0u{1@YMk!m#7Be9vW-MjNnvm9s9rXu?m8qgBXp7^Ox@gt5 zm~Be<3DIrWC6;}Q-_naSUwNcDCIp4D!%Sh{*igF9p~NDvs#)ECtZ*Z+Am55K)o$| z@$R5ta$@Gjn&$_VFo0J3?F^SUsC?l@reM~#d^?nne3U-UYWR$TgofVc1wZdO)vajK zy5bT5&R?p}wfv5jd6sx^3kEz6o9(I;IIT;i_|6De@lMY>Lc$wJ<((HlhL-?w(0_;5 zONz*l2*-A+{)!fxm81c(UArznUHL*>F_ydb3iKaOq576DzaLQ<$tfs|17w}z%DEHA zVtJGuzaF5(K~WB`R`4T=dDVX6m-i#0U@UyySep|akbj3)O+dfz?Om1yV!MFSiSvW$ zCywQu<*>|#V^#v21(DOOrZa5~R-H9QQ(yTT>`V!0aCt>2DJyvFgdy{qL`~$h8%7$W z^t{%e5UuLGsJA;sy#8b%nE9v#l5SeE4LcexP!vp$cOcoeCm3}_1K|Rd2&%Q20%jX2DM9aAm(tmuX(d3J zQLK{8-jMPwmg8qv^44xG8r<+)h??BHh3;%e(D`v%86>63H5-~VTj|uyX|ulOAq*F2 zo2q*FTj8uh=C8t3J$8BxfX${c@g{dG9ZU4Cb;=Zb(}DA^N*z{>?BH~f%S^eWpaYM8!WQ> z^v?85s{rRQG1Y5fb&MDr0zPYCDosvA8HAMHi>HQ4s3!gLZ8e2~&D~*=v>J5-<-ghl zo(UzLLL*a<^nKpvo?4O4B*T9e#ui};PO%M1`gC(bLJm?+z}<5}b5;csu_yaAY3HCp z=WSN7yMHV@GfM>+vp~WuAX*0l)RH=o%;NP3ODcbyMef8tLNegxVFuiVrI1ge*rHlk3qrV* zG9c7x%mDbJtF=z$4BOU%Wdv_k2`{_b~oIAG<0YOdD>WO0Rk%`LVz7hut zv-N8@BTfYpH?V!^cTtMsejrQ_ zkLgpFI=>17zV)AJrrb;;Y{P$b;p+9@9mSf1Z2h)10-Ot^#PKG&%v>7ePYt;H*S2bE z@#P!Ldp?i z;KD+)p_YNUu=Kqp9}r@fm^`iZV$S!HmlCGW2z?#U(v3dKU-42}h<((XWvPx`1sdEq zERyBT@^0qJox~*QVAvslWsgj_2H#k1vj*Z2ngo@2yUa{R=Af<+&XXlLa#!R8S6;@+ zib#NC+Zv3!qNbHSU||-r)@q^v7uwcLQIN1AB=qik2*|@hq%$W2%9qa`yqu_EP@}z# z;iZJ4*;fu_1aG4s-HaDwkse{xQNYkIPY=%`Ph-7VBv)tLMv(Mi7%l>JD(Ab*&gYjP zJUs;7jRkdn>Q-w6o(%$TK3nS5D*U+d$*&)C^(2-_ zo3bp~TyxGr)>;!m=tB^%KOI`+4k#xW)JDq0hLY+>`%$!~8hj%CjtPQkGW5wFKsoJW z>_ZqqAngu8ytfFwzZY{wdoSGs)oW!1DK(`|9QJkN_sH{ZSmVL;Cdx!+adgFPi&bDB z_v$3K9e1&lQZ(m#^;`qu^QYL7&tbKiYr9c^o*|EmJ$YN9P!6P|_bTe)U&ToXfdwI{ zhE~*@bJ%4H6|x}Zwr7GouDoU+$4OG?9WV5bxJ72gmMwN zoYCOF)wpkr-1dh$wc)Viwlm|mT5R(rZfB!8YoTltO$$`jrNwnDV&q@hV1- zH2@_^4~~}N8{SXRz!D+3+f+U2-;0*@SLnT2uZ+uJE~AFjA5a4%)J>s=F-vtHT-;L? zqR=A?2o0$*4yoxF1!mWL<1{t%>GC zw>s`*sf_ppWBZH;jv?9$JLTQ|x%>8Z0S7H}5c+RAaT4Wm@SQ=OUy$zVf+ma7Gdvv& z^zdxr8!_0rh|gX^gYklgPEYel;tSo4_j56Tt^jA$m|3)+{G!cv;@s&=d*PacsrDl8 zNuo?M6*DPETM0KizrkN)M`Vum|XAo>S*QKnI*dB4ed8}mo6_K$tB>T(#pSyJ78y+*mKC%xC7q|k>~G`k zLu8EIgi@Tsx^jdTGMtAn;(=+MnDh!_)0*UuZV2ujz668SB0uXWWyPJ!EO~UK7pL{v`vf%p6SG6!UXDd(P*Ykh3jw+s0#VWrcjdmm z;)sw{2tPHr(Q>ko7%}M$1zJeC$&BcP0vY-ycNF4-H4b$f3$thHCC{V77VMB(2XT3I zgDKmI`+~&Xg@j70G`-88+})_5Eo`Sku*vkzr^_{xgkz< zsX#%ikI@yhDZ7cOM*q4W0m*+Bj-;;JP_ z3|*jKbi_Sw)nB(6jr5(T-2=SMW~}^nk0n}nc^`>)#Qn})S_b#`GGb%}NyJ1H;%o79 zAA{PE0>9pn4lM+}0cJ@0F+{UCTxc@G#yF#RGU8XAl0f?WuuV1~=)*;6{oqSSQ;`gP zRprFU_$silPetWqp)ACioxRkmvr2HkZL*kPnNrS30Lq7yDp4G84WrOejy)YD$%(~GZ%&tfP^xl>6dIrx0j zUHORLV+a>b>s8b|Ih8t~k+{-g%)cF1UN9u)#E7yAZIq~R~_wz^cHY;$D#+< z(jg)8(^H9_m}S^L%O@adL8@Rbu1w)no+n4DF77x==_ur(RXOn$#{1H;Ry4U6f*-^T zEa)}G5{36UZB#gi9*X>Jpchqx@3lZ;j2z)eotC0}z3um9QEH{~eqckz?B&u?fpNWx zDI2Ypfr33;5mS*A3QkPxCH}bUgjC*~Shzb1<88G65sSPN3s|IyR?X^)LXVy@f) z+}>j#q*6W{TMGBrqTcx1Iq^|}UvAEbbVmQ~{Q@`LRoHStk7aPW8aI1hYL^d9?HhG^ z+PBLSWs@@5)KVeY{a!JrQd?J&o66{m(wizmzrYYeMYF5DvUAWh=<(36_E(F(V9btO zx5nq_;`?{|Q83^3Ll-ALmv`}biOLrYi?LS@i>g1s=cj;f7=q0|a-P=~K{BflxQh22 z@W6PD-4A8NY!l@vH5*#8M+C!y=-IbF6k{uZbZ&}QwhEFbga_>;!Q2$z$w4MMdsguQvy%&VW8I%lSvcqBuI$g$tm z$2X5w>Y*qO3~ILZ#~q`G2SoJMHg*I$Ul~aFk$? zJ;i9@su$ZxBa6>WXTBB&P(euDn&ShD?BCHCxO~c9ok(0fRM@Eq_mTA_=!_px8wnlA zx;ksRE{!MXO*@aSE)7>q1EmwoJh&panb+UbJNTbOET06%$2`Wt8nS~e6f>(92KZT0 zyur`^eWN3#@BDC#@}9iK*2l{b&xjepLQ0z;t`I=8T{4T@CJHrg(OXP3`f?vHo>OJ7 zyEUq*?aWXvc0E&&AUssKXk@%v=BQuiO$ zLV~|fC!Ob&`#z#J6qb+{9Zd;V57FP=|FofOLyP`oY+i7 z#n>(W6;DxdMvT&~ZICJqg67x6Qr;JCGd@ ztDy_2cxKjllu@haf#3B$2d_SlP*>LE`CaeLJM^cGapwbU5&r+|Rs1`PR|Ve?sBj}& zcX4PcKIZxgFuF_9T0n`Isj5C{$|6h8i>A-GBWu3V8twJm)45AHZEY%FI(9{gT92AsJf6?wXR`2j0% zCE~h2(fPWNf<`{+CHM6Qs^4OSCN}obs!n$DLBzK+O^sVxJ9305ZC@&x%r8s<64RS1-Jaloc_*c^57oi3({JsdU`oK>ZC2q+v_y z`5@aRDGroKFhWC-(>hf5@J@u5LRq-u#9>aRm7d=SFi-;%o1(o-aNyMSlVp(#h0>g8 z>dopw*%PI$qUX(Qx($j<7NsDbfEhs)yrT>iKP%TAIO>({CIScNP%6*YxlC9p&Evb^ z*_bLKufd{I&YW+E92pi>j4s-bd$M0ht=_Ma&@&HVh<6WIINHVR*ay2^B}`z)BF78S{_Zwb;LUsgz6z4>o_~=H2Th4sL||g&0TA)j}m&k2J1X#xtFSv%Mno zN7PhFB9xlBm)J5Q?77bVTP&TwU~dlT4vH<~u4lrIHAz$3q1!WbL=lQzAxSt#Y$-x~ zKbcs%!)}-P6TUkPc?xC8;8p3Ifg@7bKc~%ni7kP`sLfZZ9{lii!(m)}wqV;E=fp@8 z-)k~+7;tlqjXlmZ#incmPgo@1?}mT7_`riR7MbupkVR%|!d3hAJkYz+i}1&-8g>OWfa?l&(WuVN2cjs|~XjENDQT+-O5y+4)G| z#t`cxs&7=4LvvO>7X-=7>uT|1cx_eitOa>%H!sTf%5FvENNKCz1Et7e#OxAwvn_|c zvfcZ7@IeWDdd{2i*X!f}a$>R@&XmWK0`XCz?N?m=xqoJ z$h32*AA4i69qF*c4C=08G!%qWzglGddSv`{IpojzYQIra4wa+SRle#Ij!IJowHJCp z;OE|Kkl3M#Jew&WC?5UOiED5wYE^ytnGyc0rfY)Ir70Xf6&&kE%PP5}8bkQ*(nJ#z zf_6x4y6ZPw5D#*1BL|n=4hu{6pG{en{7$`FN7uqdvehzfG}l&ye1IFqzW1kTIN!+z z&IaUl?+%MBCQ1wUj>)A?5aB^h5dvI2U3!DU9D9BLo!yd(0cjI(i+@H)-6zfJHf0u> zj>_(I?jBMcaX#GFZc!$4v#Go8JOL;$?*Pp-o)$m#8eB`^W_xj`PW-!K6XYNCW^F2d z1a%$vInYVc0SaZ;fMz;$_w*93arykQ@#WwIhn=b=ZZdlldVfqty!*>kW77GHLEeKT zc&Nh6eui(jM#ldvlN2uI7--)M{K;Qe6FoVP}sh>*)qLW!g7IqbEC zpxC(XA$n@>eDGP7*D|+oW_feI6>hXV3HBige1&9-C+^7_(7s#*zSzWtuKl{<_wDMD z@n0RMxNFwv$c;4dk3fvbczEW4n{oli6Zsnam`?fpJ!{8N{U=KBL%E>kxeIuZh15b7 z*3#D2^}H<=UdMEv+r@FR^Me!p%B%~qW#H?g9qgybkIAh`aQiDg`1*Wwy0omI+Mx3E zl + + + diff --git a/source/robots-mdleom.com.txt b/source/robots-mdleom.com.txt new file mode 100644 index 0000000..2e09e35 --- /dev/null +++ b/source/robots-mdleom.com.txt @@ -0,0 +1,6 @@ +# This file only applies to mdleom.com via web server's internal rewrite +User-agent: * +Disallow: /404 +Disallow: /404.html + +Sitemap: https://mdleom.com/sitemap.xml diff --git a/source/robots.txt b/source/robots.txt new file mode 100644 index 0000000..860e8be --- /dev/null +++ b/source/robots.txt @@ -0,0 +1,3 @@ +# This file only applies to mirrors, see "robots-mdleom.com.txt" +User-agent: * +Disallow: / diff --git a/source/site.webmanifest b/source/site.webmanifest new file mode 100644 index 0000000..1dcb29d --- /dev/null +++ b/source/site.webmanifest @@ -0,0 +1,20 @@ +{ + "name": "", + "short_name": "", + "icons": [ + { + "src": "/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#3f72af", + "background_color": "#3f72af", + "start_url": "https://mdleom.com/", + "display": "standalone" +} diff --git a/source/svg/codeberg.svg b/source/svg/codeberg.svg new file mode 100644 index 0000000..addf948 --- /dev/null +++ b/source/svg/codeberg.svg @@ -0,0 +1,4 @@ + + + +CODEBERG: CURBENCODEBERGCURBEN \ No newline at end of file diff --git a/source/svg/favicon.svg b/source/svg/favicon.svg new file mode 100644 index 0000000..f6e9199 --- /dev/null +++ b/source/svg/favicon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/source/svg/github.svg b/source/svg/github.svg new file mode 100644 index 0000000..14736fe --- /dev/null +++ b/source/svg/github.svg @@ -0,0 +1,4 @@ + + + + GITHUBCURBENGH \ No newline at end of file diff --git a/source/svg/gitlab.svg b/source/svg/gitlab.svg new file mode 100644 index 0000000..94986d4 --- /dev/null +++ b/source/svg/gitlab.svg @@ -0,0 +1,4 @@ + + + + GITLABCURBEN \ No newline at end of file diff --git a/source/svg/linkedin.svg b/source/svg/linkedin.svg new file mode 100644 index 0000000..2fa3083 --- /dev/null +++ b/source/svg/linkedin.svg @@ -0,0 +1,4 @@ + + + +LINKEDIN: MDLEOMLINKEDINMDLEOM \ No newline at end of file diff --git a/source/svg/npm.svg b/source/svg/npm.svg new file mode 100644 index 0000000..f9c4303 --- /dev/null +++ b/source/svg/npm.svg @@ -0,0 +1,4 @@ + + + + NPMCURBEN \ No newline at end of file diff --git a/themes/chameleon/.npmrc b/themes/chameleon/.npmrc new file mode 100644 index 0000000..77171bd --- /dev/null +++ b/themes/chameleon/.npmrc @@ -0,0 +1,2 @@ +package-lock=false +optional=false diff --git a/themes/chameleon/README.md b/themes/chameleon/README.md new file mode 100644 index 0000000..6ab8726 --- /dev/null +++ b/themes/chameleon/README.md @@ -0,0 +1,56 @@ +# Chameleon theme + +Chameleon is a fork of [Typing](https://github.com/geekplux/hexo-theme-typing) theme, rewrote from scratch with the following changes/features: + +- [sanitize.css](https://github.com/csstools/sanitize.css/) and [autoprefixer](https://github.com/csstools/sanitize.css/) for consistent cross-browser styling. +- Utilise [relative length](https://www.w3schools.com/CSSref/css_units.asp) instead of absolute length in the css. +- [`prefers-color-scheme`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) to apply light/dark theme according to the OS preference. +- Add a [Copy](https://clipboardjs.com/) button to each code block. +- Removed jQuery, fancyBox, web analytics, comment plugins, donation links and [typo.css](https://github.com/sofish/typo.css). +- Homepage shows index of posts (same as /archives). + +## Options + +Configure this theme from your **site**'s configuration: + +``` yml +# _config.yml +theme_config: + # Header menu + menu: + Home: / + Archives: /archives/ + Feed: /atom.xml + + # Footer menu + footer: + GitLab: https://gitlab.com/curben/blog + + # Load forkawesome icons? + icons: false +``` + +## Codeblock highlight + +Following configurations need to be updated. + +``` yml +# _config.yml +highlight: + enable: true + line_number: false + hljs: true + wrap: false + +prismjs: + enable: false +``` + +## Build + +Build "source/css/_source.css" into "source/css/chameleon.css" + +``` +$ npm install +$ npm run build +``` diff --git a/themes/chameleon/build/script.js b/themes/chameleon/build/script.js new file mode 100644 index 0000000..92108fd --- /dev/null +++ b/themes/chameleon/build/script.js @@ -0,0 +1,33 @@ +'use strict' + +/* +* Normalize chameleon.css using sanitize.css +* Add browser prefixes using autoprefixer +*/ + +const { readFile, writeFile } = require('fs').promises +const { join, resolve } = require('path') + +const deps = ['autoprefixer', 'postcss', 'postcss-normalize'] +deps.forEach((dep) => { + try { + require.resolve(dep) + } catch (err) { + console.error(`Missing "${dep}" dependency. Please install it by running "npm install ${dep}".`) + } +}) + +const autoprefixer = require('autoprefixer') +const normalize = require('postcss-normalize') +const postcss = require('postcss') + +const build = async () => { + const cssPath = resolve(__dirname, '../source/css/') + const cssSource = join(cssPath, '_source.css') + const cssSave = join(cssPath, 'chameleon.css') + const inCss = await readFile(cssSource) + const { css: outCss } = await postcss([normalize, autoprefixer]).process(inCss, { from: cssSource }) + await writeFile(cssSave, outCss) +} + +build() diff --git a/themes/chameleon/languages/default.yml b/themes/chameleon/languages/default.yml new file mode 120000 index 0000000..e8f0f4b --- /dev/null +++ b/themes/chameleon/languages/default.yml @@ -0,0 +1 @@ +en-GB.yml \ No newline at end of file diff --git a/themes/chameleon/languages/en-GB.yml b/themes/chameleon/languages/en-GB.yml new file mode 100644 index 0000000..d445130 --- /dev/null +++ b/themes/chameleon/languages/en-GB.yml @@ -0,0 +1,22 @@ +categories: Categories +search: Search +tags: Tags +tagcloud: Tag Cloud +tweets: Tweets +prev: Prev +next: Next +comment: Comments +archive_a: Archives +archive_b: "Archives: %s" +page: Page %d +recent_posts: Recent Posts +newer: Newer +older: Older +share: Share +powered_by: Powered by +rss_feed: RSS Feed +category: Category +tag: Tag +date_published: Published Date +date_updated: Last Updated +source: Source diff --git a/themes/chameleon/layout/_partial/after-footer.ejs b/themes/chameleon/layout/_partial/after-footer.ejs new file mode 100644 index 0000000..9c98718 --- /dev/null +++ b/themes/chameleon/layout/_partial/after-footer.ejs @@ -0,0 +1,9 @@ +<% if (is_post()) { %> +<%- js([ + { src: '/libs/clipboard-2.0.6.min.js', defer: true }, + '/js/copy-button.js' + ]) %> +<% } %> + +<%/* javascript of Chameleon theme */%> +<%- js('/js/chameleon.js') %> diff --git a/themes/chameleon/layout/_partial/archive-post.ejs b/themes/chameleon/layout/_partial/archive-post.ejs new file mode 100644 index 0000000..ccfec57 --- /dev/null +++ b/themes/chameleon/layout/_partial/archive-post.ejs @@ -0,0 +1,9 @@ +
+
+
+ + <%- partial('post/title', {class_name: 'archive-article-title'}) %> + <%- post.more %> +
+
+
diff --git a/themes/chameleon/layout/_partial/archive.ejs b/themes/chameleon/layout/_partial/archive.ejs new file mode 100644 index 0000000..a785f25 --- /dev/null +++ b/themes/chameleon/layout/_partial/archive.ejs @@ -0,0 +1,22 @@ +<% page.posts.each((post, i) => { %> +
+
+ <%- partial('archive-post', { post }) %> +<% }) %> +<% if (page.posts.length) { %> +
+
+<% } %> +<% if (page.total > 1) { %> + +<% } %> diff --git a/themes/chameleon/layout/_partial/article.ejs b/themes/chameleon/layout/_partial/article.ejs new file mode 100644 index 0000000..6690c8a --- /dev/null +++ b/themes/chameleon/layout/_partial/article.ejs @@ -0,0 +1,53 @@ +
+ <%- partial('_partial/header', {}, { cache: true }) %> +
+
+ <%- partial('post/gallery') %> + <% if (post.link || post.title) { %> +
+ <%- partial('post/title', {class_name: 'p-name entry-title article-title'}) %> +
+ <% } %> + <% if (post.excerpt) { %> +

<%- post.excerpt %>

+ <% } %> +
+ <%- toc(page.content, {list_number: false}) %> + <%- post.more %> +
+
+ +
+
+ <% if (!index) { %> + <%- partial('post/nav') %> + <% } %> +
diff --git a/themes/chameleon/layout/_partial/footer.ejs b/themes/chameleon/layout/_partial/footer.ejs new file mode 100644 index 0000000..56bbdc0 --- /dev/null +++ b/themes/chameleon/layout/_partial/footer.ejs @@ -0,0 +1,16 @@ +<%/* Display footer on every page */%> +<%/* Use different CSS layout for different page layout */%> +<% if (is_post()) { %> +