This commit is contained in:
2026-01-01 23:01:44 +08:00
parent 1d888e9af0
commit 5fb144ea64
41 changed files with 163 additions and 253 deletions

4
.gitignore vendored
View File

@@ -9,3 +9,7 @@ node_modules
*.log
.env
bun.lock
yarn.lock

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 Rhen Cloud
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.

View File

@@ -1,20 +0,0 @@
Copyright (c) 2012-2023 Scott Chacon and others
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.

View File

@@ -22,7 +22,7 @@
## 📂 项目结构
```
```plaintext
.
├── app/ # 应用根目录
│ ├── assets/ # 静态资源
@@ -30,18 +30,16 @@
│ │ └── images/ # 图片资源
│ ├── components/ # Vue 组件
│ │ ├── archive/ # 归档相关组件
│ │ ├── blog/ # 博客相关组件
│ │ ├── posts/ # 博客相关组件
│ │ ├── category/ # 分类相关组件
│ │ ├── content/ # 内容组件
│ │ ├── footer/ # 页脚组件
│ │ ├── logo/ # Logo 组件
│ │ └── main/ # 主要组件
│ ├── config/ # 配置文件
│ ├── data/ # 数据文件
│ ├── layouts/ # 布局组件
│ ├── pages/ # 页面路由
│ │ ├── archive/ # 归档页面
│ │ ├── blogs/ # 博客列表页面
│ │ ├── posts/ # 博客列表页面
│ │ ├── categories/ # 分类页面
│ │ ├── tags/ # 标签页面
│ │ └── about.vue # 关于页面
@@ -53,7 +51,7 @@
│ └── router.options.ts # 路由配置
├── content/ # 文章内容
│ ├── about.md # 关于页内容
│ └── blogs/ # 博客文章目录
│ └── posts/ # 博客文章目录
├── public/ # 公共资源
├── server/ # 服务端代码
│ └── api/ # API 路由
@@ -163,19 +161,6 @@ const siteConfig = {
}
```
### 主题配置
修改 `tailwind.config.js` 自定义主题色:
```javascript
theme: {
colors: {
primary: '#bd83f3', // 主题色
// ...
}
}
```
### 评论系统
`app/config/index.ts` 配置 Twikoo
@@ -211,7 +196,7 @@ published: true
### Front Matter 字段说明
| 字段 | 类型 | 说明 |
|------|------|------|
| ------ | ------ | ------ |
| `title` | string | 文章标题 |
| `description` | string | 文章描述 |
| `date` | string | 发布日期 (YYYY-MM-DD) |
@@ -238,14 +223,10 @@ published: true
项目内置完整的 SEO 优化:
- ✅ Meta 标签title, description, keywords
- ✅ Open Graph 标签(社交分享)
- ✅ Twitter Card 标签
- ✅ hreflang 标签(多语言)
- ✅ Canonical 标签
- ✅ Schema.org 结构化数据
- ✅ Sitemap 自动生成
- ✅ RSS 订阅源
- ✅ 动态 OG 图片
## 🔧 常用命令
@@ -276,11 +257,11 @@ bun run format:fix # 格式化代码
## 📄 许可证
MIT License - 详见 [LICENSE.md](LICENSE.md)
MIT License - 详见 [LICENSE](LICENSE)
## 👤 作者
**RhenCloud**
## RhenCloud
- GitHub: [@RhenCloud](https://github.com/RhenCloud)
- Email: <i@rhen.cloud>
@@ -309,59 +290,3 @@ MIT License - 详见 [LICENSE.md](LICENSE.md)
- ✅ Sitemap 和 RSS 支持
---
**Made with ❤️ by RhenCloud**
- Blog list page with search and pagination
- About me page for user info
- Auto generate table of content for blog post
- Auto generate Sitemap
- Url preview with Nuxt ogImage
- Dark and light mode
- Server Side Rendered(SSR) with Nuxt4
- RSS feed
## How to Make This Blog Template Yours in 5 Minutes
- Clone this repo or use it as a template
- Go to `./app/data/index.ts` file & add your personal info
- Then head over to the `./content/blogs` folder to add new blogs
- Voilà! You've got a personalized blog site!
## Preview
<p align="center">
<a href="https://blog.nurriyad.com" target="_blank">
<img width="1090" src="./app/assets/images/preview1.png">
<img width="1090" src="./app/assets/images/preview2.png">
<img width="1090" src="./app/assets/images/preview3.png">
<img width="1090" src="./app/assets/images/preview4.png">
<br>
Live Demo
</a>
</p>
## Demo
<https://blog.nurriyad.com>
> Hosted on [Vercel](https://vercel.com/): `npm run build`
## Build Setup
**Requires Node.js 20.19+**
```bash
# install dependencies
yarn install
# serve in dev mode, with hot reload at localhost:5173
yarn run dev
# build for production
yarn run build
# serve in production mode
yarn run preview
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 389 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 343 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 294 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 240 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 279 KiB

View File

@@ -27,11 +27,11 @@ withDefaults(defineProps<Props>(), {
</h2>
<div class="text-black dark:text-zinc-300 text-sm mt-2 mb-1 md:flex md:space-x-6">
<div class="flex items-center">
<LogoDate class="-translate-y-[10%]" />
<Icon name="mdi:calendar" class="mr-1 w-4 h-4" />
<p>{{ date }}</p>
</div>
<div class="flex items-center gap-1 flex-wrap">
<LogoTag />
<Icon name="mdi:tag" class="w-4 h-4" />
<p
v-for="tag in tags"
:key="tag"
@@ -42,7 +42,7 @@ withDefaults(defineProps<Props>(), {
</div>
<div class="flex group-hover:underline text-sky-700 dark:text-sky-400 items-center pt-2">
<p>Read More</p>
<LogoArrow />
<Icon name="mdi:arrow-right" class="ml-1 w-4 h-4" />
</div>
</div>
</NuxtLink>

View File

@@ -1,22 +0,0 @@
<script setup lang="ts">
import siteConfig from "~/config";
</script>
<template>
<div class="container mx-auto mb-5">
<div class="grid grid-cols-1 sm:grid-cols-2 items-center">
<div class="px-6">
<h1
class="text-black dark:text-zinc-300 font-semibold leading-tight text-4xl md:text-5xl my-5">
{{ siteConfig.siteMeta.title }}
</h1>
<p class="dark:text-zinc-300">
{{ siteConfig.siteMeta.description }}
</p>
</div>
<div class="px-6 justify-self-center">
<LogoDogpow />
</div>
</div>
</div>
</template>

View File

@@ -24,7 +24,7 @@ withDefaults(defineProps<Props>(), {
<div class="flex items-center justify-center gap-3 mb-6">
<div
class="flex items-center text-sm font-bold text-violet-600 dark:text-violet-400 bg-violet-500/10 px-3 py-1 rounded-full border border-violet-500/20">
<LogoDate class="mr-2 w-4 h-4" />
<Icon name="mdi:calendar" class="mr-2 w-4 h-4" />
{{ date }}
</div>
<div class="flex items-center gap-2 flex-wrap">

View File

@@ -37,7 +37,7 @@ withDefaults(defineProps<Props>(), {
<div class="px-5 py-5">
<div class="flex items-center justify-between mb-3">
<div class="flex items-center text-xs font-medium text-zinc-500 dark:text-zinc-400">
<LogoDate class="mr-1.5 opacity-70" />
<Icon name="mdi:calendar" class="mr-1.5 opacity-70 w-4 h-4" />
{{ date }}
</div>
<div class="flex items-center gap-1.5 flex-wrap">
@@ -59,7 +59,7 @@ withDefaults(defineProps<Props>(), {
<div
class="flex items-center gap-1 text-sm font-bold text-violet-600 dark:text-violet-400 opacity-0 group-hover:opacity-100 transition-all duration-300 translate-y-2 group-hover:translate-y-0">
<span>Read More</span>
<LogoArrow class="w-4 h-4" />
<Icon name="mdi:arrow-right" class="w-4 h-4" />
</div>
</div>
</NuxtLink>

View File

@@ -1,19 +1,23 @@
<template>
<article class="group border dark:border-gray-800 m-2 rounded-2xl overflow-hidden shadow-lg text-zinc-700">
<article
class="group border dark:border-gray-800 m-2 rounded-2xl overflow-hidden shadow-lg text-zinc-700 bg-white/40 dark:bg-slate-900/40 backdrop-blur-md">
<NuxtLink to="/">
<div class="lg:h-48 md:h-36 w-full object-cover object-center group-hover:scale-[1.05] transition-all duration-500">
<LogoConfused />
<div
class="lg:h-48 md:h-36 w-full bg-linear-to-br from-slate-200 to-slate-300 dark:from-slate-700 dark:to-slate-800 group-hover:scale-[1.05] transition-all duration-500 flex items-center justify-center">
<Icon name="mdi:folder-open" size="80" class="text-slate-400 dark:text-slate-500" />
</div>
<div class="p-5">
<h2 class="text-3xl font-semibold text-black dark:text-zinc-300 pb-1 group-hover:text-sky-700 dark:group-hover:text-sky-400">
<h2
class="text-3xl font-semibold text-black dark:text-zinc-300 pb-1 group-hover:text-sky-700 dark:group-hover:text-sky-400">
No Post Available
</h2>
<div class="flex group-hover:underline text-sky-700 dark:text-sky-400 items-center pt-2">
<p>Back To Home</p>
<LogoArrow />
<Icon name="mdi:arrow-right" class="ml-1 w-4 h-4" />
</div>
</div>
</NuxtLink>
</article>
</template>;
</template>
;

View File

@@ -1,49 +0,0 @@
<script setup lang="ts">
interface Props {
title: string;
count: number;
}
withDefaults(defineProps<Props>(), {
title: "No title available",
count: 0,
});
// some random color for tags
const color = [
"#dc2626",
"#d97706",
"#65a30d",
"#059669",
"#0891b2",
"#0284c7",
"#4f46e5",
"#7c3aed",
"#c026d3",
"#db2777",
];
// get a random number
function getRandomInt(min: number, max: number) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
const picAColor = ref(`${color.at(getRandomInt(0, 8))}`);
</script>
<template>
<div
class="text-[#F1F2F4] px-5 py-3 rounded hover:underline rand-bg-color hover:scale-[1.05] transition-all duration-500">
<NuxtLink :to="`/categories/${title.toLocaleLowerCase()}`" class="text-lg font-extrabold">
<h1>#{{ title }}({{ count }})</h1>
</NuxtLink>
</div>
</template>
<style scoped>
.rand-bg-color {
background-color: v-bind(picAColor);
}
</style>

View File

@@ -1,22 +0,0 @@
<script setup lang="ts">
import { categoryPage } from "~/data";
</script>
<template>
<div class="container mx-auto">
<div class="grid grid-cols-1 sm:grid-cols-2 items-center">
<div class="px-6">
<h1
class="text-black dark:text-zinc-300 font-semibold leading-tight text-4xl md:text-5xl my-5">
{{ categoryPage.title }}
</h1>
<p class="dark:text-zinc-300">
{{ categoryPage.description }}
</p>
</div>
<div class="px-6 justify-self-center">
<LogoDogs />
</div>
</div>
</div>
</template>

View File

@@ -1,23 +0,0 @@
<script setup lang="ts">
const route = useRoute();
// take category from route params & make first char upper
const category = computed(() => {
const name = route.params.category || "";
let strName = "";
if (Array.isArray(name)) strName = name.at(0) || "";
else strName = name;
return strName;
});
</script>
<template>
<div class="container mx-auto">
<div class="p-6 my-4 mx-2 rounded-md bg-gray-200 dark:bg-slate-900">
<h1 class="text-black dark:text-white font-semibold leading-tight text-xl md:text-2xl">
#{{ category }}
</h1>
</div>
</div>
</template>

View File

@@ -11,9 +11,15 @@ useHead({
</script>
<template>
<div class="py-5">
<div class="container max-w-xl mx-auto">
<Logo404 />
<div class="py-20">
<div class="container max-w-xl mx-auto text-center">
<h1 class="text-6xl font-bold text-zinc-900 dark:text-white mb-4">404</h1>
<p class="text-xl text-zinc-600 dark:text-zinc-400 mb-8">页面未找到</p>
<NuxtLink
to="/"
class="inline-block bg-violet-600 hover:bg-violet-700 text-white font-semibold py-2 px-6 rounded-lg transition-colors">
返回首页
</NuxtLink>
</div>
</div>
</template>

View File

@@ -1,6 +1,16 @@
<script lang="ts" setup>
import Fuse from "fuse.js";
import { formatDate, getRandomFallbackImage } from "~/utils/helper";
import { formatDate } from "~/utils/helper";
useHead({
title: "Archive",
meta: [
{
name: "description",
content: "浏览所有已发布的文章,轻松找到您感兴趣的内容。",
},
],
});
const { data } = await useAsyncData("all-archive-post", () =>
queryCollection("content").where("published", "=", true).order("date", "DESC").all(),
@@ -15,7 +25,7 @@ const posts = computed(() => {
path: articles.path,
title: articles.title || "no-title available",
description: articles.description || "no-description available",
image: articles.image || getRandomFallbackImage(),
image: articles.image || "/404/dog.svg",
alt: articles.alt || "no alter data available",
date: formatDate(articles.date) || "not-date-available",
tags: articles.tags || [],
@@ -45,8 +55,34 @@ const searchResults = computed(() => {
<template>
<main class="container max-w-5xl mx-auto text-zinc-600">
<h1 class="text-3xl font-bold my-6">Archive</h1>
<!-- Hero 部分 -->
<div class="w-full py-12 mb-6">
<div class="container max-w-5xl mx-auto px-6">
<div class="flex flex-col items-center">
<NuxtLink
to="/"
class="flex items-center gap-2 text-sm font-bold text-violet-600 dark:text-violet-400 hover:underline mb-4">
<Icon name="heroicons:arrow-left-20-solid" />
返回首页
</NuxtLink>
<div class="p-3 bg-violet-500/10 rounded-2xl mb-4">
<Icon
name="mdi:file-document-multiple"
size="2.5em"
class="text-violet-600 dark:text-violet-400" />
</div>
<h1
class="text-4xl md:text-5xl font-bold text-zinc-800 dark:text-zinc-100 mb-4 tracking-tight">
归档
</h1>
<p class="text-zinc-600 dark:text-zinc-400 text-center max-w-2xl">
浏览所有已发布的文章轻松找到您感兴趣的内容
</p>
</div>
</div>
</div>
<!-- 搜索框 -->
<div class="px-6 mb-6">
<input
v-model="searchTest"
@@ -55,6 +91,7 @@ const searchResults = computed(() => {
class="block w-full bg-[#F1F2F4] dark:bg-slate-900 dark:placeholder-zinc-500 text-zinc-300 rounded-md border-gray-300 dark:border-gray-800 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50" />
</div>
<!-- 文章列表 -->
<div v-auto-animate class="space-y-5 my-5 px-4">
<template v-for="post in searchResults" :key="post.title">
<ArchiveCard

View File

@@ -49,9 +49,26 @@ useHead({
</script>
<template>
<main class="container max-w-5xl mx-auto text-zinc-600 px-4">
<CategoryTopic />
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3">
<main class="container max-w-5xl mx-auto text-zinc-600 px-4 py-12">
<div class="flex flex-col items-center mb-12">
<NuxtLink
to="/categories"
class="flex items-center gap-2 text-sm font-bold text-blue-600 dark:text-blue-400 hover:underline mb-4">
<Icon name="heroicons:arrow-left-20-solid" />
返回分类
</NuxtLink>
<div class="p-3 bg-blue-500/10 rounded-2xl mb-4">
<Icon name="mdi:folder-multiple" size="2.5em" class="text-blue-600 dark:text-blue-400" />
</div>
<h1
class="text-4xl md:text-5xl font-bold text-zinc-800 dark:text-zinc-100 mb-4 tracking-tight">
{{ category }}
</h1>
<p class="text-zinc-600 dark:text-zinc-400 text-center">
找到 {{ formattedData.length || 0 }} 篇分类下的文章
</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<BlogCard
v-for="post in formattedData"
:key="post.title"

View File

@@ -3,16 +3,16 @@ const { data } = await useAsyncData("all-blog-post-by-category", () =>
queryCollection("content").select("path", "categories").where("published", "=", true).all(),
);
const allTags = new Map();
const allCategories = new Map();
data.value?.forEach((blog) => {
const categories: Array<string> = (blog.categories as string[]) || [];
categories.forEach((category) => {
if (allTags.has(category)) {
const cnt = allTags.get(category);
allTags.set(category, cnt + 1);
if (allCategories.has(category)) {
const cnt = allCategories.get(category);
allCategories.set(category, cnt + 1);
} else {
allTags.set(category, 1);
allCategories.set(category, 1);
}
});
});
@@ -22,8 +22,7 @@ useHead({
meta: [
{
name: "description",
content:
"Below All the topics are listed on which either I have written a blog or will write a blog in near future.",
content: "以下列出了我撰写的文章主题。",
},
],
});
@@ -31,9 +30,42 @@ useHead({
<template>
<main class="container max-w-5xl mx-auto text-zinc-600">
<CategoryHero />
<div class="flex flex-col items-center mb-12 py-8">
<NuxtLink
to="/"
class="flex items-center gap-2 text-sm font-bold text-blue-600 dark:text-blue-400 hover:underline mb-4">
<Icon name="heroicons:arrow-left-20-solid" />
返回首页
</NuxtLink>
<div class="p-3 bg-blue-500/10 rounded-2xl mb-4">
<Icon name="mdi:folder-multiple" size="2.5em" class="text-blue-600 dark:text-blue-400" />
</div>
<h1
class="text-4xl md:text-5xl font-bold text-zinc-800 dark:text-zinc-100 mb-4 tracking-tight">
分类
</h1>
<p class="text-zinc-600 dark:text-zinc-400 text-center max-w-2xl">
以下列出了我撰写的文章主题
</p>
</div>
<div class="flex flex-wrap px-6 mt-12 gap-3">
<CategoryCard v-for="topic in allTags" :key="topic[0]" :title="topic[0]" :count="topic[1]" />
<!-- <CategoryCard v-for="topic in allCategories" :key="topic[0]" :title="topic[0]" :count="topic[1]" /> -->
<div class="flex flex-wrap justify-center gap-4">
<NuxtLink
v-for="[category, count] in allCategories"
:key="category"
:to="`/categories/${category.toLowerCase()}`"
class="group relative flex items-center gap-2 px-6 py-3 rounded-2xl bg-white/40 dark:bg-slate-900/40 backdrop-blur-md border border-white/20 dark:border-white/5 shadow-sm hover:shadow-xl hover:-translate-y-1 transition-all duration-300">
<span
class="text-lg font-bold text-zinc-700 dark:text-zinc-200 group-text-primary transition-colors">
#{{ category }}
</span>
<span
class="flex items-center justify-center min-w-6 h-6 px-1.5 rounded-full bg-primary-10 text-primary dark:text-primary text-xs font-bold border border-primary">
{{ count }}
</span>
</NuxtLink>
</div>
</div>
</main>
</template>

View File

@@ -57,7 +57,7 @@ useHead({
to="/tags"
class="flex items-center gap-2 text-sm font-bold text-primary hover:underline mb-4">
<Icon name="heroicons:arrow-left-20-solid" />
Back to all tags
返回标签
</NuxtLink>
<div class="p-3 bg-primary-10 rounded-2xl mb-4">
<Icon name="fa-solid:tag" size="2.5em" class="text-primary" />
@@ -67,7 +67,7 @@ useHead({
#{{ tag }}
</h1>
<p class="text-zinc-600 dark:text-zinc-400 text-center">
Found {{ formattedData.length || 0 }} posts with this tag
找到 {{ formattedData.length || 0 }} 篇关于此标签的文章
</p>
</div>

View File

@@ -24,7 +24,7 @@ useHead({
meta: [
{
name: "description",
content: "浏览所有标签,浏览我写过的文章的标签。",
content: "浏览所有我写过的文章的标签。",
},
],
});
@@ -38,10 +38,10 @@ useHead({
</div>
<h1
class="text-4xl md:text-5xl font-bold text-zinc-800 dark:text-zinc-100 mb-4 tracking-tight">
All Tags
标签
</h1>
<p class="text-zinc-600 dark:text-zinc-400 text-center max-w-md">
Browse through all the topics and technologies I've written about.
浏览所有我写过的文章的标签
</p>
</div>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 712 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 816 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 679 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 448 KiB