Merge branch 'release/1.2.7' into main

This commit is contained in:
Sergey Yarkov 2022-11-20 18:20:40 +03:00
commit e8016f4cf8
No known key found for this signature in database
GPG Key ID: E91CE1FABC619B6F
11 changed files with 470 additions and 330 deletions

View File

@ -7,15 +7,16 @@ Personal website created with Astro.
### Features ### Features
- [x] HTML layout
- [x] Adaptive & Responsive layout - [x] Adaptive & Responsive layout
- [x] Search articles by title or description - [x] Search articles by title or description
- [x] Dark/Light Theme - [x] Dark/Light Theme
- [x] Multilang web-site - [x] Multilang web-site
- [x] Prefetch pages via [Quicklink](https://getquick.link/)
- [x] Form handling via [Netlify Forms](https://www.netlify.com/products/forms/) - [x] Form handling via [Netlify Forms](https://www.netlify.com/products/forms/)
- [x] Comment system via [utterances](https://utteranc.es/) - [x] Comment system via [utterances](https://utteranc.es/)
- [x] RSS Feed for articles - [x] RSS Feed for articles
- [x] SEO optimized - [x] SEO optimized
- [x] Views counter
## License ## License

View File

@ -100,14 +100,5 @@ export default defineConfig({
ssr: { ssr: {
external: ["svgo"], external: ["svgo"],
}, },
build: {
rollupOptions: {
output: {
entryFileNames: `[name].[hash].js`,
chunkFileNames: `chunks/[name].[hash].js`,
assetFileNames: `assets/[hash].[ext]`,
},
},
},
}, },
}); });

View File

@ -1,16 +1,9 @@
import { Handler } from "@netlify/functions"; import { Handler } from "@netlify/functions";
import { redisClient } from "../../redis";
import Redis from "ioredis";
const redis = new Redis({
host: process.env.REDIS_HOST,
port: Number.parseInt(process.env.REDIS_PORT || "6379", 10),
password: process.env.REDIS_PASSWORD,
});
const getViewsBySlug = async (slug: string): Promise<number> => { const getViewsBySlug = async (slug: string): Promise<number> => {
let views = 1; let views = 1;
const data = await redis.get(`views:${slug}`); const data = await redisClient.get(`views:${slug}`);
if (data) views = Number.parseInt(data, 10); if (data) views = Number.parseInt(data, 10);
if (Number.isNaN(views)) views = 1; if (Number.isNaN(views)) views = 1;
return views; return views;
@ -27,7 +20,7 @@ const handler: Handler = async (event) => {
} }
case "POST": { case "POST": {
if (!slug) return { statusCode: 400, body: "Bad request." }; if (!slug) return { statusCode: 400, body: "Bad request." };
const views = await redis.incr(`views:${slug}`); const views = await redisClient.incr(`views:${slug}`);
return { statusCode: 200, body: views.toString() }; return { statusCode: 200, body: views.toString() };
} }
default: { default: {

726
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "yarkov.tech", "name": "yarkov.tech",
"version": "1.1.7", "version": "1.2.7",
"private": true, "private": true,
"description": "Personal website created with Astro.", "description": "Personal website created with Astro.",
"author": { "author": {
@ -19,18 +19,18 @@
"lint": "eslint '**/*.{js,mjs,ts,tsx}'" "lint": "eslint '**/*.{js,mjs,ts,tsx}'"
}, },
"devDependencies": { "devDependencies": {
"@astrojs/image": "^0.11.1", "@astrojs/image": "^0.11.6",
"@astrojs/mdx": "^0.11.5", "@astrojs/mdx": "^0.11.6",
"@astrojs/rss": "^1.0.3", "@astrojs/rss": "^1.0.3",
"@astrojs/sitemap": "^1.0.0", "@astrojs/sitemap": "^1.0.0",
"@astrojs/solid-js": "^1.2.2", "@astrojs/solid-js": "^1.2.3",
"@types/html-escaper": "^3.0.0", "@types/html-escaper": "^3.0.0",
"@types/mdx": "^2.0.3", "@types/mdx": "^2.0.3",
"@typescript-eslint/eslint-plugin": "^5.42.0", "@typescript-eslint/eslint-plugin": "^5.43.0",
"@typescript-eslint/parser": "^5.42.0", "@typescript-eslint/parser": "^5.43.0",
"astro": "^1.6.3", "astro": "^1.6.10",
"astro-icon": "^0.8.0", "astro-icon": "^0.8.0",
"eslint": "^8.26.0", "eslint": "^8.27.0",
"eslint-plugin-solid": "^0.8.0", "eslint-plugin-solid": "^0.8.0",
"hast-util-to-string": "^2.0.0", "hast-util-to-string": "^2.0.0",
"hastscript": "^7.1.0", "hastscript": "^7.1.0",
@ -43,12 +43,13 @@
"rehype-slug": "^5.1.0", "rehype-slug": "^5.1.0",
"remark-gfm": "^3.0.1", "remark-gfm": "^3.0.1",
"remark-smartypants": "^2.0.0", "remark-smartypants": "^2.0.0",
"sass": "^1.56.0", "sass": "^1.56.1",
"solid-js": "^1.6.1" "solid-js": "^1.6.2"
}, },
"dependencies": { "dependencies": {
"@netlify/functions": "^1.3.0", "@netlify/functions": "^1.3.0",
"ioredis": "^5.2.4", "ioredis": "^5.2.4",
"quicklink": "^2.3.0",
"sharp": "^0.31.2" "sharp": "^0.31.2"
} }
} }

9
redis.ts Normal file
View File

@ -0,0 +1,9 @@
import Redis from "ioredis";
const redisClient = new Redis({
host: process.env.REDIS_HOST,
port: Number.parseInt(process.env.REDIS_PORT || "6379", 10),
password: process.env.REDIS_PASSWORD,
});
export { redisClient };

View File

@ -20,7 +20,7 @@ import UIString from "../UIString";
$commentsScript.setAttribute("crossorigin", "anonymous"); $commentsScript.setAttribute("crossorigin", "anonymous");
if (window.theme) { if (window.theme) {
$commentsScript.setAttribute("theme", theme === "dark" ? "dark-blue" : "github-light"); $commentsScript.setAttribute("theme", window.theme === "dark" ? "dark-blue" : "github-light");
} else { } else {
$commentsScript.setAttribute("theme", "github-light"); $commentsScript.setAttribute("theme", "github-light");
} }

View File

@ -84,6 +84,7 @@ const t = useTranslation(Astro);
const views = await response.text(); const views = await response.text();
const $views = document.getElementById("views"); const $views = document.getElementById("views");
if (isNaN(parseInt(views, 10))) return;
if ($views) $views.textContent = views; if ($views) $views.textContent = views;
})(); })();
</script> </script>

View File

@ -51,4 +51,5 @@ const { title = SITE_METADATA.title, description, canonicalUrl } = Astro.props a
<meta name="msapplication-TileColor" content="#da532c" /> <meta name="msapplication-TileColor" content="#da532c" />
<slot /> <slot />
<script is:inline src="/assets/js/detect-theme.js"></script> <script is:inline src="/assets/js/detect-theme.js"></script>
<script src="../quicklink.js"></script>
</head> </head>

View File

@ -46,14 +46,16 @@ export function fetchTranslatedArticles(Astro: Readonly<AstroGlobal>): MDXInstan
return utils.getPublishedArticles(articles); return utils.getPublishedArticles(articles);
} }
export async function fetchAboutMe(Astro: Readonly<AstroGlobal>): Promise<MDXInstance<{}>> { export async function fetchAboutMe(Astro: Readonly<AstroGlobal>): Promise<MDXInstance<Record<string, never>>> {
const lang = getLanguageFromURL(Astro.url.pathname); const lang = getLanguageFromURL(Astro.url.pathname);
let markdown: MDXInstance<{}> | undefined; let markdown: MDXInstance<Record<string, never>> | undefined;
try { try {
markdown = (await import(`../../content/about/${lang}/index.mdx`)) as MDXInstance<{}>; markdown = (await import(`../../content/about/${lang}/index.mdx`)) as MDXInstance<Record<string, never>>;
} catch (error) { } catch (error) {
markdown = (await import(`../../content/about/${DEFAULT_LANGUAGE}/index.mdx`)) as MDXInstance<{}>; markdown = (await import(`../../content/about/${DEFAULT_LANGUAGE}/index.mdx`)) as MDXInstance<
Record<string, never>
>;
} }
return markdown; return markdown;

5
src/quicklink.js Normal file
View File

@ -0,0 +1,5 @@
import { listen } from "quicklink/dist/quicklink.mjs";
window.addEventListener("load", () => {
listen({ el: document.querySelector("body > header") });
listen({ el: document.querySelector("body > main article header") });
});