mirror of
https://github.com/sergeyyarkov/yarkov.tech.git
synced 2026-10-11 18:39:14 +03:00
Merge branch 'release/1.2.7' into main
This commit is contained in:
commit
e8016f4cf8
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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]`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -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
726
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
21
package.json
21
package.json
@ -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
9
redis.ts
Normal 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 };
|
||||||
@ -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");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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
5
src/quicklink.js
Normal 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") });
|
||||||
|
});
|
||||||
Loading…
x
Reference in New Issue
Block a user