Merge branch 'master' into deploy
7
.docker/Dockerfile
Normal file
|
@ -0,0 +1,7 @@
|
|||
FROM docker.io/library/nginx:1.23.1-alpine
|
||||
|
||||
COPY ./dist/ /usr/share/nginx/html/
|
||||
|
||||
COPY ./.docker/default.conf /etc/nginx/conf.d/
|
||||
|
||||
HEALTHCHECK CMD wget -O- http://127.0.0.1/status.txt | grep -q 'OK'
|
|
@ -1,4 +1,4 @@
|
|||
# Nginx config
|
||||
# Nginx config
|
||||
# Inspired by https://git.shivering-isles.com/shivering-isles/blog/blob/deploy/_docker/default.conf
|
||||
|
||||
# Expires map
|
|
@ -1,3 +1,3 @@
|
|||
*
|
||||
!public
|
||||
!_docker
|
||||
!dist
|
||||
!.docker
|
||||
|
|
18
.editorconfig
Normal file
|
@ -0,0 +1,18 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.{yml,yaml}]
|
||||
indent_size = 2
|
||||
|
||||
[docker-compose.yml]
|
||||
indent_size = 4
|
22
.eslintrc.cjs
Normal file
|
@ -0,0 +1,22 @@
|
|||
module.exports = {
|
||||
extends: ['@clickbar/typescript', 'plugin:astro/recommended'],
|
||||
overrides: [
|
||||
{
|
||||
// Define the configuration for `.astro` file.
|
||||
files: ['*.astro'],
|
||||
// Allows Astro components to be parsed.
|
||||
parser: 'astro-eslint-parser',
|
||||
// Parse the script in `.astro` as TypeScript by adding the following configuration.
|
||||
// It's the setting you need when using TypeScript.
|
||||
parserOptions: {
|
||||
parser: '@typescript-eslint/parser',
|
||||
extraFileExtensions: ['.astro'],
|
||||
},
|
||||
rules: {
|
||||
// override/add rules settings here, such as:
|
||||
// Does not work well with typescript
|
||||
'no-undef': 'off',
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
27
.gitignore
vendored
|
@ -1,14 +1,19 @@
|
|||
# Created by https://www.gitignore.io/api/hugo
|
||||
# Edit at https://www.gitignore.io/?templates=hugo
|
||||
# build output
|
||||
dist/
|
||||
|
||||
### Hugo ###
|
||||
# Generated files by hugo
|
||||
/public/
|
||||
/resources/_gen/
|
||||
# dependencies
|
||||
node_modules/
|
||||
|
||||
# Executable may be added to repository
|
||||
hugo.exe
|
||||
hugo.darwin
|
||||
hugo.linux
|
||||
# logs
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
# End of https://www.gitignore.io/api/hugo
|
||||
|
||||
# environment variables
|
||||
.env
|
||||
.env.production
|
||||
|
||||
# macOS-specific files
|
||||
.DS_Store
|
||||
|
|
|
@ -7,34 +7,30 @@ variables:
|
|||
GIT_SUBMODULE_STRATEGY: recursive
|
||||
|
||||
stages:
|
||||
- orthography
|
||||
- build
|
||||
- package
|
||||
- test
|
||||
- deploy
|
||||
|
||||
spellcheck:
|
||||
stage: orthography
|
||||
image: docker.io/library/node:17.6
|
||||
before_script:
|
||||
- npm i -g markdown-spellcheck
|
||||
script:
|
||||
- mdspell -r -n -a --en-gb "content/posts/*.md" "content/posts/*.markdown"
|
||||
|
||||
build:
|
||||
image: docker.io/cibuilds/hugo:0.93
|
||||
image: docker.io/library/node:18.4
|
||||
stage: build
|
||||
variables:
|
||||
HUGO_ENV: production
|
||||
LANG: C.UTF-8
|
||||
before_script:
|
||||
- hugo --minify --enableGitInfo
|
||||
- npm install -g pnpm@7
|
||||
- pnpm config set store-dir .pnpm-store
|
||||
script:
|
||||
- htmlproofer ./public --allow-hash-href --check-html --empty-alt-ignore --disable-external
|
||||
- pnpm install # install dependencies
|
||||
- pnpm run build
|
||||
cache:
|
||||
key:
|
||||
files:
|
||||
- pnpm-lock.yaml
|
||||
paths:
|
||||
- .pnpm-store
|
||||
artifacts:
|
||||
untracked: true
|
||||
paths:
|
||||
- public
|
||||
- dist
|
||||
expire_in: 1 week
|
||||
|
||||
package:
|
||||
|
@ -47,7 +43,7 @@ package:
|
|||
before_script:
|
||||
- podman login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
|
||||
script:
|
||||
- podman build --pull -f _docker/Dockerfile -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG" .
|
||||
- podman build --pull -f .docker/Dockerfile -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG" .
|
||||
- podman push "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG"
|
||||
except:
|
||||
- deploy
|
||||
|
@ -62,7 +58,7 @@ package-deploy:
|
|||
before_script:
|
||||
- podman login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
|
||||
script:
|
||||
- podman build --pull -f _docker/Dockerfile -t "$CI_REGISTRY_IMAGE" .
|
||||
- podman build --pull -f .docker/Dockerfile -t "$CI_REGISTRY_IMAGE" .
|
||||
- podman push "$CI_REGISTRY_IMAGE"
|
||||
only:
|
||||
- deploy
|
||||
|
|
3
.gitmodules
vendored
|
@ -1,3 +0,0 @@
|
|||
[submodule "themes/hermit"]
|
||||
path = themes/hermit
|
||||
url = https://github.com/Track3/hermit.git
|
2
.npmrc
Normal file
|
@ -0,0 +1,2 @@
|
|||
# Expose Astro dependencies for `pnpm` users
|
||||
shamefully-hoist=true
|
11
.prettierrc.cjs
Normal file
|
@ -0,0 +1,11 @@
|
|||
module.exports = {
|
||||
plugins: [require.resolve('prettier-plugin-astro')],
|
||||
overrides: [
|
||||
{
|
||||
files: '*.astro',
|
||||
options: {
|
||||
parser: 'astro',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
|
@ -1,6 +0,0 @@
|
|||
# markdown-spellcheck spelling configuration file
|
||||
# Format - lines begining # are comments
|
||||
# global dictionary is at the start, file overrides afterwards
|
||||
# one word per line, to define a file override use ' - filename'
|
||||
# where filename is relative to this configuration file
|
||||
saibotk
|
4
.vscode/extensions.json
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"recommendations": ["astro-build.astro-vscode"],
|
||||
"unwantedRecommendations": []
|
||||
}
|
11
.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"command": "./node_modules/.bin/astro dev",
|
||||
"name": "Development server",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
}
|
||||
]
|
||||
}
|
2
LICENSE
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2020 Saibotk
|
||||
Copyright (c) 2022 Saibotk
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
64
README.md
|
@ -1,2 +1,64 @@
|
|||
# saiblog
|
||||
# Astro Starter Kit: Blog
|
||||
|
||||
```
|
||||
npm create astro@latest -- --template blog
|
||||
```
|
||||
|
||||
[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/blog)
|
||||
|
||||
> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
|
||||
|
||||
|
||||
![blog](https://user-images.githubusercontent.com/4677417/186189140-4ef17aac-c3c9-4918-a8c2-ce86ba1bb394.png)
|
||||
|
||||
Features:
|
||||
|
||||
- ✅ Minimal styling (make it your own!)
|
||||
- ✅ 100/100 Lighthouse performance
|
||||
- ✅ SEO-friendly with canonical URLs and OpenGraph data
|
||||
- ✅ Sitemap support
|
||||
- ✅ RSS Feed support
|
||||
- ✅ Markdown & MDX support
|
||||
|
||||
## 🚀 Project Structure
|
||||
|
||||
Inside of your Astro project, you'll see the following folders and files:
|
||||
|
||||
```
|
||||
├── public/
|
||||
├── src/
|
||||
│ ├── components/
|
||||
│ ├── layouts/
|
||||
│ └── pages/
|
||||
├── astro.config.mjs
|
||||
├── README.md
|
||||
├── package.json
|
||||
└── tsconfig.json
|
||||
```
|
||||
|
||||
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
|
||||
|
||||
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
|
||||
|
||||
Any static assets, like images, can be placed in the `public/` directory.
|
||||
|
||||
## 🧞 Commands
|
||||
|
||||
All commands are run from the root of the project, from a terminal:
|
||||
|
||||
| Command | Action |
|
||||
| :--------------------- | :----------------------------------------------- |
|
||||
| `npm install` | Installs dependencies |
|
||||
| `npm run dev` | Starts local dev server at `localhost:3000` |
|
||||
| `npm run build` | Build your production site to `./dist/` |
|
||||
| `npm run preview` | Preview your build locally, before deploying |
|
||||
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
|
||||
| `npm run astro --help` | Get help using the Astro CLI |
|
||||
|
||||
## 👀 Want to learn more?
|
||||
|
||||
Check out [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).
|
||||
|
||||
## Credit
|
||||
|
||||
This theme is based off of the lovely [Bear Blog](https://github.com/HermanMartinus/bearblog/).
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
FROM docker.io/library/nginx:1.21.6-alpine
|
||||
|
||||
COPY ./public/ /usr/share/nginx/html/
|
||||
|
||||
COPY ./_docker/default.conf /etc/nginx/conf.d/
|
||||
|
||||
HEALTHCHECK CMD wget -O- http://127.0.0.1/status.txt | grep -q 'OK'
|
|
@ -1,6 +0,0 @@
|
|||
---
|
||||
title: "{{ replace .Name "-" " " | title }}"
|
||||
date: {{ .Date }}
|
||||
draft: true
|
||||
---
|
||||
|
|
@ -1,106 +0,0 @@
|
|||
/**
|
||||
* Utils
|
||||
*
|
||||
* From https://github.com/Track3/hermit/blob/master/assets/js/main.js
|
||||
*
|
||||
* MIT licensed
|
||||
*/
|
||||
|
||||
// Throttle
|
||||
//
|
||||
const throttle = (callback, limit) => {
|
||||
let timeoutHandler = null;
|
||||
return () => {
|
||||
if (timeoutHandler == null) {
|
||||
timeoutHandler = setTimeout(() => {
|
||||
callback();
|
||||
timeoutHandler = null;
|
||||
}, limit);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// addEventListener Helper
|
||||
//
|
||||
const listen = (ele, e, callback) => {
|
||||
if (document.querySelector(ele) !== null) {
|
||||
document.querySelector(ele).addEventListener(e, callback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Functions
|
||||
*/
|
||||
|
||||
// Auto Hide Header
|
||||
//
|
||||
let header = document.getElementById('site-header');
|
||||
let lastScrollPosition = window.pageYOffset;
|
||||
|
||||
const autoHideHeader = () => {
|
||||
let currentScrollPosition = Math.max(window.pageYOffset, 0);
|
||||
if (currentScrollPosition > lastScrollPosition && document.documentElement.clientHeight + currentScrollPosition < document.documentElement.offsetHeight) {
|
||||
header.classList.remove('slideInUp');
|
||||
header.classList.add('slideOutDown');
|
||||
} else {
|
||||
header.classList.remove('slideOutDown');
|
||||
header.classList.add('slideInUp');
|
||||
}
|
||||
lastScrollPosition = currentScrollPosition;
|
||||
}
|
||||
|
||||
// Mobile Menu Toggle
|
||||
//
|
||||
let mobileMenuVisible = false;
|
||||
|
||||
const toggleMobileMenu = () => {
|
||||
let mobileMenu = document.getElementById('mobile-menu');
|
||||
if (mobileMenuVisible == false) {
|
||||
mobileMenu.style.animationName = 'bounceInRight';
|
||||
mobileMenu.style.webkitAnimationName = 'bounceInRight';
|
||||
mobileMenu.style.display = 'block';
|
||||
mobileMenuVisible = true;
|
||||
} else {
|
||||
mobileMenu.style.animationName = 'bounceOutRight';
|
||||
mobileMenu.style.webkitAnimationName = 'bounceOutRight'
|
||||
mobileMenuVisible = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Featured Image Toggle
|
||||
//
|
||||
const showImg = () => {
|
||||
document.querySelector('.bg-img').classList.add('show-bg-img');
|
||||
}
|
||||
|
||||
const hideImg = () => {
|
||||
document.querySelector('.bg-img').classList.remove('show-bg-img');
|
||||
}
|
||||
|
||||
// ToC Toggle
|
||||
//
|
||||
const toggleToc = () => {
|
||||
document.getElementById('toc').classList.toggle('show-toc');
|
||||
}
|
||||
|
||||
if (header !== null) {
|
||||
listen('#menu-btn', "click", toggleMobileMenu);
|
||||
listen('#toc-btn', "click", toggleToc);
|
||||
listen('#img-btn', "click", showImg);
|
||||
listen('.bg-img', "click", hideImg);
|
||||
|
||||
document.querySelectorAll('.post-year').forEach((ele)=> {
|
||||
ele.addEventListener('click', () => {
|
||||
window.location.hash = '#' + ele.id;
|
||||
});
|
||||
});
|
||||
|
||||
window.addEventListener('scroll', throttle(() => {
|
||||
autoHideHeader();
|
||||
|
||||
if (mobileMenuVisible == true) {
|
||||
toggleMobileMenu();
|
||||
}
|
||||
}, 450));
|
||||
}
|
||||
|
16
astro.config.mjs
Normal file
|
@ -0,0 +1,16 @@
|
|||
import { defineConfig } from 'astro/config'
|
||||
import mdx from '@astrojs/mdx'
|
||||
import sitemap from '@astrojs/sitemap'
|
||||
|
||||
import tailwind from '@astrojs/tailwind'
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
site: 'https://saibotk.de',
|
||||
integrations: [mdx(), sitemap(), tailwind()],
|
||||
markdown: {
|
||||
shikiConfig: {
|
||||
theme: 'rose-pine-moon',
|
||||
},
|
||||
},
|
||||
})
|
81
config.toml
|
@ -1,81 +0,0 @@
|
|||
baseURL = "https://saibotk.de"
|
||||
languageCode = "en-us"
|
||||
defaultContentLanguage = "en"
|
||||
title = "Saiblog"
|
||||
theme = "hermit"
|
||||
enableGitInfo = true
|
||||
pygmentsCodefences = true
|
||||
pygmentsUseClasses = true
|
||||
# hasCJKLanguage = true # If Chinese/Japanese/Korean is your main content language, enable this to make wordCount works right.
|
||||
rssLimit = 10 # Maximum number of items in the RSS feed.
|
||||
copyright = "This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License." # This message is only used by the RSS template.
|
||||
enableEmoji = true # Shorthand emojis in content files - https://gohugo.io/functions/emojify/
|
||||
# googleAnalytics = "UA-123-45"
|
||||
# disqusShortname = "yourdiscussshortname"
|
||||
enableRobotsTXT=true
|
||||
|
||||
[author]
|
||||
name = "saibotk"
|
||||
|
||||
[blackfriday]
|
||||
# hrefTargetBlank = true
|
||||
# noreferrerLinks = true
|
||||
# nofollowLinks = true
|
||||
|
||||
[taxonomies]
|
||||
tag = "tags"
|
||||
# Categories are disabled by default.
|
||||
|
||||
[params]
|
||||
dateform = "Jan 2, 2006"
|
||||
dateformShort = "Jan 2"
|
||||
dateformNum = "2006-01-02"
|
||||
dateformNumTime = "2006-01-02 15:04 -0700"
|
||||
|
||||
# Metadata mostly used in document's head
|
||||
description = "My personal blog about various code / devops related things."
|
||||
# images = [""]
|
||||
themeColor = "#494f5c"
|
||||
|
||||
homeSubtitle = "My personal blog about various code / devops related things."
|
||||
footerCopyright = ' · <a href="https://creativecommons.org/licenses/by-nc/4.0/" target="_blank" rel="noopener">CC BY-NC 4.0</a>'
|
||||
# bgImg = "" # Homepage background-image URL
|
||||
|
||||
# Prefix of link to the git commit detail page. GitInfo must be enabled.
|
||||
gitUrl = "https://git.saibotk.de/saibotk.de/saiblog/commit/"
|
||||
|
||||
# Toggling this option needs to rebuild SCSS, requires Hugo extended version
|
||||
justifyContent = false # Set "text-align: justify" to `.content`.
|
||||
|
||||
relatedPosts = true # Add a related content section to all single posts page
|
||||
|
||||
code_copy_button = true # Turn on/off the code-copy-button for code-fields
|
||||
|
||||
# Add custom css
|
||||
# customCSS = ["css/foo.css", "css/bar.css"]
|
||||
|
||||
# Social Icons
|
||||
# Check https://github.com/Track3/hermit#social-icons for more info.
|
||||
|
||||
#[[params.social]]
|
||||
# name = "email"
|
||||
# url = "mailto:info (a t) saibotk.de"
|
||||
|
||||
[[params.social]]
|
||||
name = "github"
|
||||
url = "https://github.com/saibotk"
|
||||
|
||||
[[params.social]]
|
||||
name = "gitlab"
|
||||
url = "https://git.saibotk.de/saibotk"
|
||||
|
||||
[[params.social]]
|
||||
name = "mastodon"
|
||||
url = "https://flausch.social/@saibotk"
|
||||
|
||||
[menu]
|
||||
|
||||
[[menu.main]]
|
||||
name = "Posts"
|
||||
url = "posts/"
|
||||
weight = 10
|
|
@ -1,33 +0,0 @@
|
|||
{{ define "header" }}
|
||||
{{ partialCached "header.html" . }}
|
||||
{{ end }}
|
||||
|
||||
{{ define "main" }}
|
||||
<main class="site-main section-inner thin animated fadeIn faster">
|
||||
<h1>#{{ .Title }}</h1>
|
||||
{{- if .Content }}
|
||||
<div class="content">
|
||||
{{ .Content }}
|
||||
</div>
|
||||
{{- end }}
|
||||
{{- range .Data.Pages.GroupByDate "2006" }}
|
||||
<div class="posts-group">
|
||||
<div class="post-year" id="{{ .Key }}">{{ .Key }}</div>
|
||||
<ul class="posts-list">
|
||||
{{- range .Pages }}
|
||||
<li class="post-item">
|
||||
<a href="{{.Permalink}}">
|
||||
<span class="post-title">{{.Title}}</span>
|
||||
<span class="post-day">{{ .Date.Format .Site.Params.dateformShort }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{{- end }}
|
||||
</ul>
|
||||
</div>
|
||||
{{- end }}
|
||||
</main>
|
||||
{{ end }}
|
||||
|
||||
{{ define "footer" }}
|
||||
{{ partialCached "footer.html" . }}
|
||||
{{ end }}
|
|
@ -1,37 +0,0 @@
|
|||
{{ define "head" }}
|
||||
{{ if .Site.Params.bgImg -}}
|
||||
<style>.bg-img {background-image: url('{{.Site.Params.bgImg}}');}</style>
|
||||
{{- else if .Site.Params.images -}}
|
||||
{{- range first 1 .Site.Params.images -}}
|
||||
<style>.bg-img {background-image: url('{{. | absURL}}');}</style>
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{ end }}
|
||||
|
||||
{{ define "main" }}
|
||||
{{- if (or .Site.Params.images .Site.Params.bgImg) }}
|
||||
<div class="bg-img"></div>
|
||||
{{- end }}
|
||||
<div id="spotlight" class="animated fadeIn">
|
||||
<div id="home-center">
|
||||
<h1 id="home-title">{{ .Site.Title }}</h1>
|
||||
{{- with .Site.Params.homeSubtitle }}
|
||||
<p id="home-subtitle">{{.}}</p>
|
||||
{{- end }}
|
||||
{{- with .Site.Params.social }}
|
||||
<div id="home-social">
|
||||
{{ partialCached "social-icons.html" . }}
|
||||
</div>
|
||||
{{- end }}
|
||||
<nav id="home-nav" class="site-nav">
|
||||
{{ partialCached "menu.html" . }}
|
||||
</nav>
|
||||
</div>
|
||||
<div id="home-footer">
|
||||
<p>
|
||||
© {{ now.Format "2006" }} <a href="{{ .Site.BaseURL }}">{{ .Site.Author.name }}</a>{{ .Site.Params.footerCopyright | safeHTML }} · <a href="https://git.saibotk.de/saibotk.de/saiblog" target="_blank">Source Code</a>
|
||||
{{- with (not (in (.Site.Language.Get "disableKinds") "RSS")) }} · <a href="{{ "posts/index.xml" | absLangURL }}" target="_blank" title="rss"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-rss"><path d="M4 11a9 9 0 0 1 9 9"></path><path d="M4 4a16 16 0 0 1 16 16"></path><circle cx="5" cy="19" r="1"></circle></svg></a>{{ end }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
|
@ -1,7 +0,0 @@
|
|||
<footer id="site-footer" class="section-inner thin animated fadeIn faster">
|
||||
<p>© {{ now.Format "2006" }} <a href="{{ .Site.BaseURL }}">{{ .Site.Author.name }}</a>{{ .Site.Params.footerCopyright | safeHTML }}</p>
|
||||
<p>
|
||||
Made with <a href="https://gohugo.io/" target="_blank" rel="noopener">Hugo</a> · Theme <a href="https://github.com/Track3/hermit" target="_blank" rel="noopener">Hermit</a> · <a href="https://git.saibotk.de/saibotk.de/saiblog" target="_blank">Source Code</a>
|
||||
{{- with (not (in (.Site.Language.Get "disableKinds") "RSS")) }} · <a href="{{ "posts/index.xml" | absLangURL }}" target="_blank" title="rss"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-rss"><path d="M4 11a9 9 0 0 1 9 9"></path><path d="M4 4a16 16 0 0 1 16 16"></path><circle cx="5" cy="19" r="1"></circle></svg></a>{{ end }}
|
||||
</p>
|
||||
</footer>
|
|
@ -1,31 +0,0 @@
|
|||
<header id="site-header" class="animated">
|
||||
<div class="hdr-wrapper section-inner">
|
||||
<div class="hdr-left">
|
||||
<div class="site-branding">
|
||||
<a href="{{.Site.BaseURL}}">{{ .Site.Title }}</a>
|
||||
</div>
|
||||
<nav class="site-nav hide-in-mobile">
|
||||
{{ partialCached "menu.html" . }}
|
||||
</nav>
|
||||
</div>
|
||||
<div class="hdr-right hdr-icons">
|
||||
{{ if (or .Params.images .Params.featuredImg) -}}
|
||||
<button id="img-btn" class="hdr-btn" title="{{i18n "featuredImage"}}"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-image"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><circle cx="8.5" cy="8.5" r="1.5"></circle><polyline points="21 15 16 10 5 21"></polyline></svg></button>
|
||||
{{- end }}
|
||||
{{- with .Params.toc -}}
|
||||
<button id="toc-btn" class="hdr-btn desktop-only-ib" title="{{i18n "tableOfContents"}}"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-list"><line x1="8" y1="6" x2="21" y2="6"></line><line x1="8" y1="12" x2="21" y2="12"></line><line x1="8" y1="18" x2="21" y2="18"></line><line x1="3" y1="6" x2="3" y2="6"></line><line x1="3" y1="12" x2="3" y2="12"></line><line x1="3" y1="18" x2="3" y2="18"></line></svg></button>
|
||||
{{- end }}
|
||||
{{- with .Site.Params.social -}}
|
||||
<span class="hdr-social hide-in-mobile">{{ partialCached "social-icons.html" . }}</span>
|
||||
{{- end -}}
|
||||
<button id="menu-btn" class="hdr-btn" title="{{i18n "menu"}}"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-menu"><line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line></svg></button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div id="mobile-menu" class="animated fast">
|
||||
<ul>
|
||||
{{- range .Site.Menus.main }}
|
||||
<li><a href="{{ .URL | absLangURL }}">{{ .Name }}</a></li>
|
||||
{{- end }}
|
||||
</ul>
|
||||
</div>
|
|
@ -1,49 +0,0 @@
|
|||
{{- if (eq .name "codepen") -}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="feather" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 22 8.5 22 15.5 12 22 2 15.5 2 8.5 12 2"></polygon><line x1="12" y1="22" x2="12" y2="15.5"></line><polyline points="22 8.5 12 15.5 2 8.5"></polyline><polyline points="2 15.5 12 8.5 22 15.5"></polyline><line x1="12" y1="2" x2="12" y2="8.5"></line></svg>
|
||||
{{- else if (eq .name "facebook") -}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="feather" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z"></path></svg>
|
||||
{{- else if (eq .name "github") -}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="feather" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path></svg>
|
||||
{{- else if (eq .name "gitlab") -}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="feather" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22.65 14.39L12 22.13 1.35 14.39a.84.84 0 0 1-.3-.94l1.22-3.78 2.44-7.51A.42.42 0 0 1 4.82 2a.43.43 0 0 1 .58 0 .42.42 0 0 1 .11.18l2.44 7.49h8.1l2.44-7.51A.42.42 0 0 1 18.6 2a.43.43 0 0 1 .58 0 .42.42 0 0 1 .11.18l2.44 7.51L23 13.45a.84.84 0 0 1-.35.94z"></path></svg>
|
||||
{{- else if (eq .name "instagram") -}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="feather" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="2" width="20" height="20" rx="5" ry="5"></rect><path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"></path><line x1="17.5" y1="6.5" x2="17.5" y2="6.5"></line></svg>
|
||||
{{- else if (eq .name "linkedin") -}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="feather" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"></path><rect x="2" y="9" width="4" height="12"></rect><circle cx="4" cy="4" r="2"></circle></svg>
|
||||
{{- else if (eq .name "slack") -}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="feather" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22.08 9C19.81 1.41 16.54-.35 9 1.92S-.35 7.46 1.92 15 7.46 24.35 15 22.08 24.35 16.54 22.08 9z"></path><line x1="12.57" y1="5.99" x2="16.15" y2="16.39"></line><line x1="7.85" y1="7.61" x2="11.43" y2="18.01"></line><line x1="16.39" y1="7.85" x2="5.99" y2="11.43"></line><line x1="18.01" y1="12.57" x2="7.61" y2="16.15"></line></svg>
|
||||
{{- else if (eq .name "stackoverflow") -}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="feather" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2.913 16.041v6.848h17.599v-6.848M7.16 18.696h8.925M7.65 13.937l8.675 1.8M9.214 9.124l8.058 3.758M12.086 4.65l6.849 5.66M15.774 1.111l5.313 7.162"/></svg>
|
||||
{{- else if (eq .name "telegram") -}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="feather" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21.198 2.433a2.242 2.242 0 0 0-1.022.215l-8.609 3.33c-2.068.8-4.133 1.598-5.724 2.21a405.15 405.15 0 0 1-2.849 1.09c-.42.147-.99.332-1.473.901-.728.968.193 1.798.919 2.286 1.61.516 3.275 1.009 4.654 1.472.509 1.793.997 3.592 1.48 5.388.16.36.506.494.864.498l-.002.018s.281.028.555-.038a2.1 2.1 0 0 0 .933-.517c.345-.324 1.28-1.244 1.811-1.764l3.999 2.952.032.018s.442.311 1.09.355c.324.022.75-.04 1.116-.308.37-.27.613-.702.728-1.196.342-1.492 2.61-12.285 2.997-14.072l-.01.042c.27-1.006.17-1.928-.455-2.474a1.654 1.654 0 0 0-1.034-.407z"/></svg>
|
||||
{{- else if (eq .name "twitch") -}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="feather" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 2H3v16h5v4l4-4h5l4-4V2zm-10 9V7m5 4V7"></path></svg>
|
||||
{{- else if (eq .name "twitter") -}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="feather" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M23 3a10.9 10.9 0 0 1-3.14 1.53 4.48 4.48 0 0 0-7.86 3v1A10.66 10.66 0 0 1 3 4s-4 9 5 13a11.64 11.64 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0-.08-.83A7.72 7.72 0 0 0 23 3z"></path></svg>
|
||||
{{- else if (eq .name "youtube") -}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="feather" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22.54 6.42a2.78 2.78 0 0 0-1.94-2C18.88 4 12 4 12 4s-6.88 0-8.6.46a2.78 2.78 0 0 0-1.94 2A29 29 0 0 0 1 11.75a29 29 0 0 0 .46 5.33A2.78 2.78 0 0 0 3.4 19c1.72.46 8.6.46 8.6.46s6.88 0 8.6-.46a2.78 2.78 0 0 0 1.94-2 29 29 0 0 0 .46-5.25 29 29 0 0 0-.46-5.33z"></path><polygon points="9.75 15.02 15.5 11.75 9.75 8.48 9.75 15.02"></polygon></svg>
|
||||
{{- else if (eq .name "email") -}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="feather" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path><polyline points="22,6 12,13 2,6"></polyline></svg>
|
||||
{{- else if (eq .name "dribbble") -}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="feather" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle style="font-variation-settings:normal" cx="12.004" cy="12" r="9.39" paint-order="stroke fill markers"/><path style="font-variation-settings:normal" d="M5.858 19.136s2.343-5.79 8.161-6.422c5.818-.633 7.442.479 7.442.479M2.68 10.839s4.91.752 10.112-1.11c5.202-1.863 5.887-4.601 5.887-4.601"/><path style="font-variation-settings:normal" d="M8.533 3.208s2.888 2.73 5.339 9.235c2.451 6.505 2.344 8.4 2.344 8.4"/></svg>
|
||||
{{- else if (eq .name "behance") -}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="feather" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path paint-order="stroke fill markers" stroke-linejoin="miter" stroke-width="2" style="font-variation-settings:normal" d="M1.774 18.063V5.466h5.51c1.978 0 3.116 1.326 3.055 2.806-.043 1.049-.711 2.988-2.643 2.988h-5.93H7.73c1.224 0 3.532 1.13 3.532 3.532 0 2.4-1.873 3.27-3.318 3.27zm12.57-4.459h7.89s.012-4.18-4.167-4.18c-5.237 0-5.277 9.11-.3 9.11 3.06 0 3.935-1.806 3.935-1.806M15.526 5.823h4.987"/></svg>
|
||||
{{- else if (eq .name "freepik") -}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="feather" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5.737 17.28s3.423.84 7.61.162c4.188-.676 6.862-2.57 6.862-2.57s.28 3.943-4.967 5.33c-5.248 1.388-8.543.657-9.506-2.923zm-.62-3.104s4.491 1.361 8.728.344c4.237-1.016 5.94-2.568 5.94-2.568s-1.81-6.448-7.405-5.648c-5.597.8-8.061 4.414-7.263 7.872z" style="font-variation-settings:normal" stroke-linejoin="round"/><path d="M1.265 12.607c.159-1.98.561-3.898 2.08-5.701m5.148-3.29c2.006-.66 3.968-1.157 6.446-.844m5.202 2.98c1.192 1.275 1.963 2.163 2.594 3.815" style="font-variation-settings:normal" stroke="currentColor" stroke-linejoin="round"/><circle r=".989" cy="10.404" cx="14.746" fill="currentColor" stroke="none"/><circle cx="9.637" cy="11.305" r="1.477" fill="currentColor" stroke="none"/></svg>
|
||||
{{- else if (eq .name "adobestock") -}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="feather" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path style="font-variation-settings:normal" d="M2.235 2.235h19.53v19.53H2.235z"/><path style="font-variation-settings:normal" d="M6.165 16.659s3.16 1.2 4.602-.17c1.37-1.3.787-3.163-.754-4.05-1.68-.969-3.284-1.788-3.036-3.536.446-3.138 4.386-1.851 4.386-1.851M15.792 7.794v7.774c0 1.023.635 1.766 2.043 1.624M17.826 10.04h-3.582"/></svg>
|
||||
{{- else if (eq .name "shutterstock") -}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="feather" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect ry="5" rx="5" height="20" width="20" y="2" x="2"/><path d="M7.728 11.725V9.032c0-1.025.824-1.85 1.849-1.85h2.815m3.88 5.093v2.693a1.845 1.845 0 0 1-1.849 1.85h-2.815" stroke-linecap="square" stroke-linejoin="miter"/></svg>
|
||||
{{- else if (eq .name "123rf") -}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="feather" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path style="font-variation-settings:normal" d="M7.48 3.826c-.702 0-1.345.388-1.675 1.008l-.711 1.334a4.214 4.214 0 0 1-1.614 1.67l-.388.224a2.207 2.207 0 0 0-1.104 1.913v8.607c0 .878.712 1.592 1.59 1.592h1.186c.468 0 .916-.19 1.244-.524l1.478-1.504c.266-.27.628-.421 1.006-.421h7.04c.378 0 .74.151 1.005.421l1.478 1.504c.329.334.778.524 1.247.524h1.183c.879 0 1.592-.714 1.592-1.592V9.975c0-.79-.422-1.518-1.106-1.912l-.388-.225a4.214 4.214 0 0 1-1.613-1.67l-.711-1.334a1.899 1.899 0 0 0-1.676-1.008z" stroke-linejoin="miter"/><circle cx="12" cy="12.467" r="2.723"/></svg>
|
||||
{{- else if (eq .name "dreamstime") -}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="feather" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19.834 20.994s4.824-4.08 2.044-12.03C19.252 1.456 6.822-1.223 2.508 7.566c-3.936 8.023 2.18 14.46 7.88 14.374 4.889-.075 8.475-3.226 7.813-8.604-.76-6.18-6.73-6.816-9.275-4.184-2.256 2.334-1.816 7.034.873 7.823 2.241.844 4.661-1.265 3.161-3.215" style="font-variation-settings:normal" stroke="currentColor" stroke-linejoin="bevel" paint-order="stroke fill markers"/></svg>
|
||||
{{- else if (eq .name "paypal") -}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="feather" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7.144 19.532l1.049-5.751c.11-.606.691-1.002 1.304-.948 2.155.192 6.877.1 8.818-4.002 2.554-5.397-.59-7.769-6.295-7.769H7.43a1.97 1.97 0 0 0-1.944 1.655L2.77 19.507a.857.857 0 0 0 .846.994h2.368a1.18 1.18 0 0 0 1.161-.969zM7.967 22.522a.74.74 0 0 0 .666.416h2.313c.492 0 .923-.351 1.003-.837l.759-4.601c.095-.523.597-.866 1.127-.819 1.86.166 5.567-.118 6.85-3.821.554-1.6.705-2.954.408-4.018" style="font-variation-settings:normal" stroke="currentColor" stroke-linejoin="miter"/></svg>
|
||||
{{- else if (eq .name "qq") -}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="feather" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path transform="scale(0.04) translate(75 40)" stroke-width="50" d="M433.754 420.445c-11.526 1.393-44.86-52.741-44.86-52.741 0 31.345-16.136 72.247-51.051 101.786 16.842 5.192 54.843 19.167 45.803 34.421-7.316 12.343-125.51 7.881-159.632 4.037-34.122 3.844-152.316 8.306-159.632-4.037-9.045-15.25 28.918-29.214 45.783-34.415-34.92-29.539-51.059-70.445-51.059-101.792 0 0-33.334 54.134-44.859 52.741-5.37-.65-12.424-29.644 9.347-99.704 10.261-33.024 21.995-60.478 40.144-105.779C60.683 98.063 108.982.006 224 0c113.737.006 163.156 96.133 160.264 214.963 18.118 45.223 29.912 72.85 40.144 105.778 21.768 70.06 14.716 99.053 9.346 99.704z"></path></svg>
|
||||
{{- else if (eq .name "mastodon") -}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="feather" width="24" height="24" viewBox="0 0 216.4144 232.00976"><path fill-rule="evenodd" fill="currentColor" d="M211.80734 139.0875c-3.18125 16.36625-28.4925 34.2775-57.5625 37.74875-15.15875 1.80875-30.08375 3.47125-45.99875 2.74125-26.0275-1.1925-46.565-6.2125-46.565-6.2125 0 2.53375.15625 4.94625.46875 7.2025 3.38375 25.68625 25.47 27.225 46.39125 27.9425 21.11625.7225 39.91875-5.20625 39.91875-5.20625l.8675 19.09s-14.77 7.93125-41.08125 9.39c-14.50875.7975-32.52375-.365-53.50625-5.91875C9.23234 213.82 1.40609 165.31125.20859 116.09125c-.365-14.61375-.14-28.39375-.14-39.91875 0-50.33 32.97625-65.0825 32.97625-65.0825C49.67234 3.45375 78.20359.2425 107.86484 0h.72875c29.66125.2425 58.21125 3.45375 74.8375 11.09 0 0 32.975 14.7525 32.975 65.0825 0 0 .41375 37.13375-4.59875 62.915 Z M177.50984 80.077v60.94125h-24.14375v-59.15c0-12.46875-5.24625-18.7975-15.74-18.7975-11.6025 0-17.4175 7.5075-17.4175 22.3525v32.37625H96.20734V85.42325c0-14.845-5.81625-22.3525-17.41875-22.3525-10.49375 0-15.74 6.32875-15.74 18.7975v59.15H38.90484V80.077c0-12.455 3.17125-22.3525 9.54125-29.675 6.56875-7.3225 15.17125-11.07625 25.85-11.07625 12.355 0 21.71125 4.74875 27.8975 14.2475l6.01375 10.08125 6.015-10.08125c6.185-9.49875 15.54125-14.2475 27.8975-14.2475 10.6775 0 19.28 3.75375 25.85 11.07625 6.36875 7.3225 9.54 17.22 9.54 29.675 Z"/></svg>
|
||||
{{- else -}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="feather feather-link" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
{{- end -}}
|
|
@ -1,2 +0,0 @@
|
|||
|
||||
User-agent: *
|
31
package.json
Normal file
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"name": "@saibotk/saiblog",
|
||||
"type": "module",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"start": "astro dev",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview",
|
||||
"lint": "eslint --ext .js,.cjs,.mjs,.ts,.cts,.mts,.tsx,.astro .",
|
||||
"fix": "eslint --fix --ext .js,.cjs,.mjs,.ts,.cts,.mts,.tsx,.astro .",
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/mdx": "^0.11.4",
|
||||
"@astrojs/rss": "^1.0.2",
|
||||
"@astrojs/sitemap": "^1.0.0",
|
||||
"@astrojs/tailwind": "^2.1.1",
|
||||
"@clickbar/eslint-config-typescript": "^4.0.10",
|
||||
"@fontsource/fira-code": "^4.5.12",
|
||||
"@fontsource/inter": "^4.5.14",
|
||||
"@tailwindcss/typography": "^0.5.7",
|
||||
"astro": "^1.5.2",
|
||||
"eslint": "^8.26.0",
|
||||
"eslint-plugin-astro": "^0.20.0",
|
||||
"prettier-plugin-astro": "^0.6.0",
|
||||
"tailwindcss": "^3.2.1",
|
||||
"typescript": "^4.8.4"
|
||||
}
|
||||
}
|
5604
pnpm-lock.yaml
generated
Normal file
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 636 B After Width: | Height: | Size: 636 B |
Before Width: | Height: | Size: 911 B After Width: | Height: | Size: 911 B |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 900 B After Width: | Height: | Size: 900 B |
Before Width: | Height: | Size: 788 B After Width: | Height: | Size: 788 B |
|
@ -4,6 +4,6 @@
|
|||
"config:base",
|
||||
"docker:enableMajor"
|
||||
],
|
||||
"prConcurrentLimit": 5,
|
||||
"prConcurrentLimit": 0,
|
||||
"gitLabAutomerge": true
|
||||
}
|
||||
|
|
44
src/components/BaseHead.astro
Normal file
|
@ -0,0 +1,44 @@
|
|||
---
|
||||
// Import the global.css file here so that it is included on
|
||||
// all pages through the use of the <BaseHead /> component.
|
||||
import '../styles/global.css'
|
||||
|
||||
export interface Props {
|
||||
title: string
|
||||
description: string
|
||||
image?: string
|
||||
}
|
||||
|
||||
const { title, description, image = '/android-chrome-192x192.png' } = Astro.props
|
||||
---
|
||||
|
||||
<!-- Global Metadata -->
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
|
||||
<link rel="manifest" href="/site.webmanifest" />
|
||||
<link rel="mask-icon" href="safari-pinned-tab.svg" color="" />
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
|
||||
<!-- Primary Meta Tags -->
|
||||
<title>{title}</title>
|
||||
<meta name="title" content={title} />
|
||||
<meta name="description" content={description} />
|
||||
|
||||
<!-- Open Graph / Facebook -->
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content={Astro.url} />
|
||||
<meta property="og:title" content={title} />
|
||||
<meta property="og:description" content={description} />
|
||||
<meta property="og:image" content={new URL(image, Astro.url)} />
|
||||
|
||||
<!-- Twitter -->
|
||||
<meta property="twitter:card" content="summary_large_image" />
|
||||
<meta property="twitter:url" content={Astro.url} />
|
||||
<meta property="twitter:title" content={title} />
|
||||
<meta property="twitter:description" content={description} />
|
||||
<meta property="twitter:image" content={new URL(image, Astro.url)} />
|
27
src/components/Footer.astro
Normal file
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
import RSS from './icons/RSS.astro'
|
||||
|
||||
const today = new Date()
|
||||
---
|
||||
|
||||
<footer class="mt-24 mb-24 w-full flex flex-col items-center text-zinc-400">
|
||||
<div class="">
|
||||
<span>© {today.getFullYear()} saibotk</span>
|
||||
<span>·</span>
|
||||
<a href="https://creativecommons.org/licenses/by-nc/4.0/" target="_blank" rel="noopener">
|
||||
CC BY-NC 4.0
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="inline-block">
|
||||
Made with <a href="https://astro.build/" target="_blank" rel="noopener">Astro</a>
|
||||
</div>
|
||||
<span>·</span>
|
||||
<a href="https://git.saibotk.de/saibotk.de/saiblog" target="_blank" rel="noopener">
|
||||
Source Code
|
||||
</a>
|
||||
<span>·</span>
|
||||
<a href="/rss.xml" target="_blank" rel="noopener"><RSS class="w-4 inline-block" /></a>
|
||||
</div>
|
||||
</footer>
|
44
src/components/Header.astro
Normal file
|
@ -0,0 +1,44 @@
|
|||
---
|
||||
import { SITE_TITLE } from '../config'
|
||||
import HeaderLink from './HeaderLink.astro'
|
||||
import GitHub from './icons/GitHub.astro'
|
||||
import Mastodon from './icons/Mastodon.astro'
|
||||
import GitLab from './icons/GitLab.astro'
|
||||
---
|
||||
|
||||
<header class="mt-8">
|
||||
<h2 class="text-3xl font-semibold mb-2">
|
||||
{SITE_TITLE}
|
||||
</h2>
|
||||
<nav class="gap-2 flex items-center">
|
||||
<HeaderLink href="/">Home</HeaderLink>
|
||||
<HeaderLink href="/posts">Posts</HeaderLink>
|
||||
|
||||
<div class="ml-auto space-x-2">
|
||||
<a
|
||||
class="inline-block hover:text-purple-600"
|
||||
href="https://flausch.social/@saibotk"
|
||||
target="_blank"
|
||||
aria-label="Link to my Mastodon account"
|
||||
>
|
||||
<Mastodon class="w-6" />
|
||||
</a>
|
||||
<a
|
||||
class="inline-block hover:text-purple-600"
|
||||
href="https://git.saibotk.de/saibotk"
|
||||
target="_blank"
|
||||
aria-label="Link to my Gitlab account"
|
||||
>
|
||||
<GitLab class="w-6" />
|
||||
</a>
|
||||
<a
|
||||
class="inline-block hover:text-purple-600"
|
||||
href="https://github.com/saibotk"
|
||||
target="_blank"
|
||||
aria-label="Link to my GitHub account"
|
||||
>
|
||||
<GitHub class="w-6" />
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
28
src/components/HeaderLink.astro
Normal file
|
@ -0,0 +1,28 @@
|
|||
---
|
||||
export type Props = astroHTML.JSX.AnchorHTMLAttributes
|
||||
|
||||
const { href, class: className, ...props } = Astro.props
|
||||
const pathname = Astro.url.pathname
|
||||
const isActive =
|
||||
typeof href === 'string' && ((href !== '/' && pathname.startsWith(href)) || pathname === href)
|
||||
---
|
||||
|
||||
<a
|
||||
href={href}
|
||||
class:list={[
|
||||
'group inline-block relative text-zinc-50 px-4 rounded',
|
||||
className,
|
||||
{
|
||||
'font-semibold bg-gradient-to-r from-purple-600 to-pink-400': isActive,
|
||||
},
|
||||
]}
|
||||
{...props}
|
||||
>
|
||||
<div
|
||||
class="absolute rounded inset-0 block opacity-0 group-hover:opacity-100 bg-gradient-to-r from-purple-900 to-purple-500 transition duration-200"
|
||||
>
|
||||
</div>
|
||||
<div class="relative z-10">
|
||||
<slot />
|
||||
</div>
|
||||
</a>
|
19
src/components/icons/GitHub.astro
Normal file
|
@ -0,0 +1,19 @@
|
|||
---
|
||||
export type Props = astroHTML.JSX.SVGAttributes
|
||||
|
||||
const { class: classes, ...props } = Astro.props
|
||||
---
|
||||
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
viewBox="0 0 24 24"
|
||||
class={classes}
|
||||
aria-label="GitHub logo"
|
||||
{...props}
|
||||
><path
|
||||
fill="currentColor"
|
||||
fill-rule="evenodd"
|
||||
d="M12 2C6.475 2 2 6.475 2 12a9.994 9.994 0 0 0 6.838 9.488c.5.087.687-.213.687-.476c0-.237-.013-1.024-.013-1.862c-2.512.463-3.162-.612-3.362-1.175c-.113-.288-.6-1.175-1.025-1.413c-.35-.187-.85-.65-.013-.662c.788-.013 1.35.725 1.538 1.025c.9 1.512 2.338 1.087 2.912.825c.088-.65.35-1.087.638-1.337c-2.225-.25-4.55-1.113-4.55-4.938c0-1.088.387-1.987 1.025-2.688c-.1-.25-.45-1.275.1-2.65c0 0 .837-.262 2.75 1.026a9.28 9.28 0 0 1 2.5-.338c.85 0 1.7.112 2.5.337c1.912-1.3 2.75-1.024 2.75-1.024c.55 1.375.2 2.4.1 2.65c.637.7 1.025 1.587 1.025 2.687c0 3.838-2.337 4.688-4.562 4.938c.362.312.675.912.675 1.85c0 1.337-.013 2.412-.013 2.75c0 .262.188.574.688.474A10.016 10.016 0 0 0 22 12c0-5.525-4.475-10-10-10Z"
|
||||
></path>
|
||||
</svg>
|
18
src/components/icons/GitLab.astro
Normal file
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
export type Props = astroHTML.JSX.SVGAttributes
|
||||
|
||||
const { class: classes, ...props } = Astro.props
|
||||
---
|
||||
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
viewBox="-2 -2.5 24 24"
|
||||
class={classes}
|
||||
aria-label="GitLab logo"
|
||||
{...props}
|
||||
><path
|
||||
fill="currentColor"
|
||||
d="M10.006 18.443L6.326 7.118h7.36l-3.68 11.325zm0 0L1.168 7.118h5.158l3.68 11.325zM1.168 7.118l8.838 11.325l-9.68-7.032a.762.762 0 0 1-.276-.852l1.118-3.441zm0 0L3.385.296a.38.38 0 0 1 .724 0l2.217 6.822H1.168zm8.838 11.325l3.68-11.325h5.157l-8.837 11.325zm8.837-11.325l1.119 3.441a.762.762 0 0 1-.277.852l-9.68 7.032l8.838-11.325zm0 0h-5.157L15.902.296a.38.38 0 0 1 .725 0l2.216 6.822z"
|
||||
></path>
|
||||
</svg>
|
18
src/components/icons/Mastodon.astro
Normal file
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
export type Props = astroHTML.JSX.SVGAttributes
|
||||
|
||||
const { class: classes, ...props } = Astro.props
|
||||
---
|
||||
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
viewBox="0 0 24 24"
|
||||
class={classes}
|
||||
aria-label="Mastodon logo"
|
||||
{...props}
|
||||
><path
|
||||
fill="currentColor"
|
||||
d="M12.158 0c-3.068.025-6.02.357-7.74 1.147c0 0-3.41 1.526-3.41 6.733c0 1.192-.024 2.617.014 4.129c.123 5.091.933 10.11 5.64 11.355c2.171.575 4.035.695 5.535.613c2.722-.151 4.25-.972 4.25-.972l-.09-1.974s-1.945.613-4.13.538c-2.163-.074-4.448-.233-4.798-2.89a5.448 5.448 0 0 1-.048-.745s2.124.519 4.816.642c1.647.076 3.19-.096 4.759-.283c3.007-.36 5.625-2.212 5.954-3.905c.519-2.667.476-6.508.476-6.508c0-5.207-3.411-6.733-3.411-6.733C18.255.357 15.302.025 12.233 0h-.075ZM8.686 4.068c1.278 0 2.245.491 2.885 1.474l.622 1.043l.623-1.043c.64-.983 1.607-1.474 2.885-1.474c1.105 0 1.995.388 2.675 1.146c.658.757.986 1.781.986 3.07v6.303h-2.497V8.47c0-1.29-.543-1.945-1.628-1.945c-1.2 0-1.802.777-1.802 2.313v3.349h-2.483v-3.35c0-1.535-.601-2.312-1.802-2.312c-1.085 0-1.628.655-1.628 1.945v6.118H5.024V8.283c0-1.288.328-2.312.987-3.07c.68-.757 1.57-1.145 2.675-1.145Z"
|
||||
></path>
|
||||
</svg>
|
18
src/components/icons/RSS.astro
Normal file
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
export type Props = astroHTML.JSX.SVGAttributes
|
||||
|
||||
const { class: classes, ...props } = Astro.props
|
||||
---
|
||||
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
viewBox="0 0 256 256"
|
||||
class={classes}
|
||||
aria-label="RSS icon"
|
||||
{...props}
|
||||
><path
|
||||
fill="currentColor"
|
||||
d="M101.7 154.3A75.2 75.2 0 0 1 124 208a12 12 0 0 1-24 0a51.9 51.9 0 0 0-52-52a12 12 0 0 1 0-24a75.2 75.2 0 0 1 53.7 22.3ZM48 84a12 12 0 0 0 0 24a100 100 0 0 1 100 100a12 12 0 0 0 24 0A123.9 123.9 0 0 0 48 84Zm121.6 2.4A170.9 170.9 0 0 0 48 36a12 12 0 0 0 0 24a147.8 147.8 0 0 1 148 148a12 12 0 0 0 24 0a170.7 170.7 0 0 0-50.4-121.6ZM52 188a16 16 0 1 0 16 16a16 16 0 0 0-16-16Z"
|
||||
></path>
|
||||
</svg>
|
5
src/config.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
// Place any global data in this file.
|
||||
// You can import this data from anywhere in your site by using the `import` keyword.
|
||||
|
||||
export const SITE_TITLE = "Saibotk's blog"
|
||||
export const SITE_DESCRIPTION = 'Welcome to my personal blog!'
|
1
src/environment.d.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/// <reference types="astro/client" />
|
35
src/layouts/Base.astro
Normal file
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
import '@fontsource/inter/variable-full.css'
|
||||
import '@fontsource/fira-code'
|
||||
|
||||
import BaseHead from '../components/BaseHead.astro'
|
||||
import Header from '../components/Header.astro'
|
||||
import Footer from '../components/Footer.astro'
|
||||
import { SITE_TITLE, SITE_DESCRIPTION } from '../config'
|
||||
|
||||
export interface Props {
|
||||
pageTitle?: string
|
||||
description?: string
|
||||
}
|
||||
|
||||
const { pageTitle, description } = Astro.props
|
||||
---
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<BaseHead
|
||||
title={((pageTitle && pageTitle + ' - ') || '') + SITE_TITLE}
|
||||
description={(description && description) || SITE_DESCRIPTION}
|
||||
/>
|
||||
</head>
|
||||
<body
|
||||
class="font-sans bg-zinc-900 text-zinc-300 w-full max-w-3xl px-4 mx-auto min-h-screen flex flex-col"
|
||||
>
|
||||
<Header title={SITE_TITLE} />
|
||||
<main class="grow flex flex-col my-4 mx-4">
|
||||
<slot />
|
||||
</main>
|
||||
<Footer />
|
||||
</body>
|
||||
</html>
|
43
src/layouts/BlogPost.astro
Normal file
|
@ -0,0 +1,43 @@
|
|||
---
|
||||
import Base from './Base.astro'
|
||||
|
||||
export interface Props {
|
||||
content: {
|
||||
title: string
|
||||
description: string
|
||||
pubDate?: string
|
||||
updatedDate?: string
|
||||
heroImage?: string
|
||||
}
|
||||
}
|
||||
|
||||
const {
|
||||
content: { title, description, pubDate, updatedDate, heroImage },
|
||||
} = Astro.props
|
||||
---
|
||||
|
||||
<Base pageTitle={title} description={description}>
|
||||
<article>
|
||||
<div class="text-center">
|
||||
<h1 class="mt-20 mb-2 text-5xl font-bold text-purple-400">{title}</h1>
|
||||
{pubDate && <time class="text-base text-zinc-400">{pubDate}</time>}
|
||||
{
|
||||
updatedDate && (
|
||||
<div class="text-sm italic font-thin text-zinc-400">
|
||||
Last updated on <time>{updatedDate}</time>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
|
||||
{
|
||||
heroImage && (
|
||||
<img class="my-20 w-full rounded" src={heroImage} alt="hero image of the blog post" />
|
||||
)
|
||||
}
|
||||
|
||||
<div class="prose-custom">
|
||||
<slot />
|
||||
</div>
|
||||
</article>
|
||||
</Base>
|
16
src/pages/index.astro
Normal file
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
import Base from '../layouts/Base.astro'
|
||||
---
|
||||
|
||||
<Base>
|
||||
<div class="flex flex-col justify-center items-center grow">
|
||||
<div class="prose-custom">
|
||||
<h1 class="text-center">⛵️ Welcome on board!</h1>
|
||||
<p>
|
||||
We will cross the ocean of my written posts. Join me on my journey and learn about various
|
||||
things I encountered during my daily adventures. Mostly related to the far lands of
|
||||
containerization & Ansible, Laravel, PHP and Vue.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Base>
|
36
src/pages/posts.astro
Normal file
|
@ -0,0 +1,36 @@
|
|||
---
|
||||
import Base from '../layouts/Base.astro'
|
||||
|
||||
const rawPosts = await Astro.glob('./posts/*.{md,mdx}')
|
||||
const posts = rawPosts
|
||||
.filter((post) => !post.frontmatter.draft)
|
||||
.sort(
|
||||
(a, b) => new Date(b.frontmatter.pubDate).valueOf() - new Date(a.frontmatter.pubDate).valueOf()
|
||||
)
|
||||
---
|
||||
|
||||
<Base>
|
||||
<section class="my-12">
|
||||
<ul class="space-y-2">
|
||||
{
|
||||
posts.map((post) => (
|
||||
<li class="flex">
|
||||
<time
|
||||
datetime={post.frontmatter.pubDate}
|
||||
class="w-32 italic text-zinc-400 underline underline-offset-3"
|
||||
>
|
||||
{new Date(post.frontmatter.pubDate).toLocaleDateString('en-us', {
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
})}
|
||||
</time>
|
||||
<a class="visited:text-purple-600 hover:text-purple-800" href={post.url}>
|
||||
{post.frontmatter.title}
|
||||
</a>
|
||||
</li>
|
||||
))
|
||||
}
|
||||
</ul>
|
||||
</section>
|
||||
</Base>
|
|
@ -1,13 +1,8 @@
|
|||
---
|
||||
layout: "../../layouts/BlogPost.astro"
|
||||
title: "First Post"
|
||||
date: 2020-01-07T22:46:09+01:00
|
||||
draft: false
|
||||
toc: false
|
||||
images:
|
||||
tags:
|
||||
- welcome
|
||||
- blog
|
||||
- me
|
||||
description: "The first introductory and obligatory post on a typical blog :)"
|
||||
pubDate: "Jan 07 2020"
|
||||
---
|
||||
|
||||
## Hello and welcome on my blog
|
||||
|
@ -19,5 +14,5 @@ The purpose will be to present solutions / things I encounter during my
|
|||
daily work and to hopefully give back some knowledge to other people,
|
||||
who are looking for the same problems or are just generally interested in reading about it.
|
||||
|
||||
Thank you,
|
||||
saibotk
|
||||
Thank you,
|
||||
saibotk
|
10
src/pages/rss.xml.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
import rss from '@astrojs/rss'
|
||||
import { SITE_TITLE, SITE_DESCRIPTION } from '../config'
|
||||
|
||||
export const get = () =>
|
||||
rss({
|
||||
title: SITE_TITLE,
|
||||
description: SITE_DESCRIPTION,
|
||||
site: import.meta.env.SITE,
|
||||
items: import.meta.glob('./posts/**/*.{md,mdx}'),
|
||||
})
|
15
src/styles/global.css
Normal file
|
@ -0,0 +1,15 @@
|
|||
html {
|
||||
@apply font-sans bg-zinc-900 text-zinc-300 w-full max-w-3xl mx-auto;
|
||||
}
|
||||
|
||||
.prose-custom {
|
||||
@apply prose prose-invert max-w-full;
|
||||
}
|
||||
|
||||
.prose-custom code {
|
||||
@apply font-code;
|
||||
}
|
||||
|
||||
.prose-custom :not(pre) code {
|
||||
@apply before:hidden after:hidden bg-zinc-700 p-0.5 px-1 inline rounded-sm;
|
||||
}
|
16
tailwind.config.cjs
Normal file
|
@ -0,0 +1,16 @@
|
|||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const defaultTheme = require('tailwindcss/defaultTheme')
|
||||
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
|
||||
theme: {
|
||||
extend: {
|
||||
fontFamily: {
|
||||
sans: ['InterVariable', ...defaultTheme.fontFamily.sans],
|
||||
code: ['Fira Code', ...defaultTheme.fontFamily.mono],
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [require('@tailwindcss/typography')],
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 2dc35c5c6a52168a3a7b35c5ad51209f40a851cf
|
3
tsconfig.json
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"extends": "astro/tsconfigs/strictest"
|
||||
}
|