mirror of
https://github.com/sergeyyarkov/yarkov.tech.git
synced 2026-10-11 10:29:21 +03:00
Merge branch 'release/1.1.6' into main
This commit is contained in:
commit
94e9effbb1
4
.env.example
Normal file
4
.env.example
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
IS_SITE_UNDER_CONSTRUCTION=false
|
||||||
|
REDIS_HOST=localhost
|
||||||
|
REDIS_PORT=6379
|
||||||
|
REDIS_PASSWORD=12345
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@ -16,3 +16,5 @@ pnpm-debug.log*
|
|||||||
|
|
||||||
# macOS-specific files
|
# macOS-specific files
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
# Local Netlify folder
|
||||||
|
.netlify
|
||||||
|
|||||||
@ -1,3 +1,10 @@
|
|||||||
[build]
|
[build]
|
||||||
command = "npm run build"
|
command = "npm run build"
|
||||||
publish = "dist"
|
publish = "dist"
|
||||||
|
functions = "netlify/functions"
|
||||||
|
|
||||||
|
[[redirects]]
|
||||||
|
from = "/api/*" # simplify all calls to serverless functions
|
||||||
|
to = "/.netlify/functions/:splat" # all function calls will go to this path
|
||||||
|
status = 200 # ok code
|
||||||
|
force = true # ensure to always redirect
|
||||||
42
netlify/functions/views.ts
Normal file
42
netlify/functions/views.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import { Handler } from "@netlify/functions";
|
||||||
|
|
||||||
|
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> => {
|
||||||
|
let views = 1;
|
||||||
|
const data = await redis.get(`views:${slug}`);
|
||||||
|
if (data) views = Number.parseInt(data, 10);
|
||||||
|
if (Number.isNaN(views)) views = 1;
|
||||||
|
return views;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handler: Handler = async (event) => {
|
||||||
|
const slug = event.queryStringParameters?.slug;
|
||||||
|
|
||||||
|
switch (event.httpMethod) {
|
||||||
|
case "GET": {
|
||||||
|
if (!slug) return { statusCode: 400, body: "Bad request." };
|
||||||
|
const views = await getViewsBySlug(slug);
|
||||||
|
return { statusCode: 200, body: views.toString() };
|
||||||
|
}
|
||||||
|
case "POST": {
|
||||||
|
if (!slug) return { statusCode: 400, body: "Bad request." };
|
||||||
|
const views = await redis.incr(`views:${slug}`);
|
||||||
|
return { statusCode: 200, body: views.toString() };
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return {
|
||||||
|
statusCode: 500,
|
||||||
|
body: "Unrecognized HTTP Method, must be one of GET/POST",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export { handler };
|
||||||
180
package-lock.json
generated
180
package-lock.json
generated
@ -1,14 +1,16 @@
|
|||||||
{
|
{
|
||||||
"name": "yarkov.tech",
|
"name": "yarkov.tech",
|
||||||
"version": "1.0.3",
|
"version": "1.0.6",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "yarkov.tech",
|
"name": "yarkov.tech",
|
||||||
"version": "1.0.3",
|
"version": "1.0.6",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@netlify/functions": "^1.3.0",
|
||||||
|
"ioredis": "^5.2.4",
|
||||||
"sharp": "^0.31.2"
|
"sharp": "^0.31.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@ -798,6 +800,11 @@
|
|||||||
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
|
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@ioredis/commands": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg=="
|
||||||
|
},
|
||||||
"node_modules/@jridgewell/gen-mapping": {
|
"node_modules/@jridgewell/gen-mapping": {
|
||||||
"version": "0.1.1",
|
"version": "0.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
|
||||||
@ -927,6 +934,17 @@
|
|||||||
"rollup": ">=2"
|
"rollup": ">=2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@netlify/functions": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@netlify/functions/-/functions-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-hN/Fgpz8XIOBfsBPLYUMxVKBlCopgeqGB0popayicnmkFLnvKByTTMYgF01wcF9DBtBQdV0H2h1kPFpMl34I8w==",
|
||||||
|
"dependencies": {
|
||||||
|
"is-promise": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@node-minify/core": {
|
"node_modules/@node-minify/core": {
|
||||||
"version": "5.3.0",
|
"version": "5.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@node-minify/core/-/core-5.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@node-minify/core/-/core-5.3.0.tgz",
|
||||||
@ -2333,6 +2351,14 @@
|
|||||||
"node": ">=0.8"
|
"node": ">=0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cluster-key-slot": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/color": {
|
"node_modules/color": {
|
||||||
"version": "4.2.3",
|
"version": "4.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
|
||||||
@ -2485,7 +2511,6 @@
|
|||||||
"version": "4.3.4",
|
"version": "4.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ms": "2.1.2"
|
"ms": "2.1.2"
|
||||||
},
|
},
|
||||||
@ -2591,6 +2616,14 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/denque": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/dequal": {
|
"node_modules/dequal": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
|
||||||
@ -4796,6 +4829,29 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ioredis": {
|
||||||
|
"version": "5.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.2.4.tgz",
|
||||||
|
"integrity": "sha512-qIpuAEt32lZJQ0XyrloCRdlEdUUNGG9i0UOk6zgzK6igyudNWqEBxfH6OlbnOOoBBvr1WB02mm8fR55CnikRng==",
|
||||||
|
"dependencies": {
|
||||||
|
"@ioredis/commands": "^1.1.1",
|
||||||
|
"cluster-key-slot": "^1.1.0",
|
||||||
|
"debug": "^4.3.4",
|
||||||
|
"denque": "^2.0.1",
|
||||||
|
"lodash.defaults": "^4.2.0",
|
||||||
|
"lodash.isarguments": "^3.1.0",
|
||||||
|
"redis-errors": "^1.2.0",
|
||||||
|
"redis-parser": "^3.0.0",
|
||||||
|
"standard-as-callback": "^2.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.22.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/ioredis"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/is-alphabetical": {
|
"node_modules/is-alphabetical": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz",
|
||||||
@ -5070,6 +5126,11 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/is-promise": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="
|
||||||
|
},
|
||||||
"node_modules/is-reference": {
|
"node_modules/is-reference": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.0.tgz",
|
||||||
@ -5404,6 +5465,16 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/lodash.defaults": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="
|
||||||
|
},
|
||||||
|
"node_modules/lodash.isarguments": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg=="
|
||||||
|
},
|
||||||
"node_modules/lodash.merge": {
|
"node_modules/lodash.merge": {
|
||||||
"version": "4.6.2",
|
"version": "4.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
||||||
@ -6735,8 +6806,7 @@
|
|||||||
"node_modules/ms": {
|
"node_modules/ms": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/nanoid": {
|
"node_modules/nanoid": {
|
||||||
"version": "3.3.4",
|
"version": "3.3.4",
|
||||||
@ -7590,6 +7660,25 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/redis-errors": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/redis-parser": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==",
|
||||||
|
"dependencies": {
|
||||||
|
"redis-errors": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/regexp.prototype.flags": {
|
"node_modules/regexp.prototype.flags": {
|
||||||
"version": "1.4.3",
|
"version": "1.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
|
||||||
@ -8472,6 +8561,11 @@
|
|||||||
"deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility",
|
"deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/standard-as-callback": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A=="
|
||||||
|
},
|
||||||
"node_modules/string_decoder": {
|
"node_modules/string_decoder": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||||
@ -10663,6 +10757,11 @@
|
|||||||
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
|
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@ioredis/commands": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg=="
|
||||||
|
},
|
||||||
"@jridgewell/gen-mapping": {
|
"@jridgewell/gen-mapping": {
|
||||||
"version": "0.1.1",
|
"version": "0.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
|
||||||
@ -10771,6 +10870,14 @@
|
|||||||
"vfile": "^5.0.0"
|
"vfile": "^5.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@netlify/functions": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@netlify/functions/-/functions-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-hN/Fgpz8XIOBfsBPLYUMxVKBlCopgeqGB0popayicnmkFLnvKByTTMYgF01wcF9DBtBQdV0H2h1kPFpMl34I8w==",
|
||||||
|
"requires": {
|
||||||
|
"is-promise": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@node-minify/core": {
|
"@node-minify/core": {
|
||||||
"version": "5.3.0",
|
"version": "5.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@node-minify/core/-/core-5.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@node-minify/core/-/core-5.3.0.tgz",
|
||||||
@ -11818,6 +11925,11 @@
|
|||||||
"integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
|
"integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"cluster-key-slot": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA=="
|
||||||
|
},
|
||||||
"color": {
|
"color": {
|
||||||
"version": "4.2.3",
|
"version": "4.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
|
||||||
@ -11944,7 +12056,6 @@
|
|||||||
"version": "4.3.4",
|
"version": "4.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"ms": "2.1.2"
|
"ms": "2.1.2"
|
||||||
}
|
}
|
||||||
@ -12014,6 +12125,11 @@
|
|||||||
"object-keys": "^1.1.1"
|
"object-keys": "^1.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"denque": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw=="
|
||||||
|
},
|
||||||
"dequal": {
|
"dequal": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
|
||||||
@ -13577,6 +13693,22 @@
|
|||||||
"side-channel": "^1.0.4"
|
"side-channel": "^1.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ioredis": {
|
||||||
|
"version": "5.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.2.4.tgz",
|
||||||
|
"integrity": "sha512-qIpuAEt32lZJQ0XyrloCRdlEdUUNGG9i0UOk6zgzK6igyudNWqEBxfH6OlbnOOoBBvr1WB02mm8fR55CnikRng==",
|
||||||
|
"requires": {
|
||||||
|
"@ioredis/commands": "^1.1.1",
|
||||||
|
"cluster-key-slot": "^1.1.0",
|
||||||
|
"debug": "^4.3.4",
|
||||||
|
"denque": "^2.0.1",
|
||||||
|
"lodash.defaults": "^4.2.0",
|
||||||
|
"lodash.isarguments": "^3.1.0",
|
||||||
|
"redis-errors": "^1.2.0",
|
||||||
|
"redis-parser": "^3.0.0",
|
||||||
|
"standard-as-callback": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"is-alphabetical": {
|
"is-alphabetical": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz",
|
||||||
@ -13743,6 +13875,11 @@
|
|||||||
"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
|
"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"is-promise": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="
|
||||||
|
},
|
||||||
"is-reference": {
|
"is-reference": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.0.tgz",
|
||||||
@ -13988,6 +14125,16 @@
|
|||||||
"p-locate": "^5.0.0"
|
"p-locate": "^5.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"lodash.defaults": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="
|
||||||
|
},
|
||||||
|
"lodash.isarguments": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg=="
|
||||||
|
},
|
||||||
"lodash.merge": {
|
"lodash.merge": {
|
||||||
"version": "4.6.2",
|
"version": "4.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
||||||
@ -14889,8 +15036,7 @@
|
|||||||
"ms": {
|
"ms": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"nanoid": {
|
"nanoid": {
|
||||||
"version": "3.3.4",
|
"version": "3.3.4",
|
||||||
@ -15485,6 +15631,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"redis-errors": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w=="
|
||||||
|
},
|
||||||
|
"redis-parser": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==",
|
||||||
|
"requires": {
|
||||||
|
"redis-errors": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"regexp.prototype.flags": {
|
"regexp.prototype.flags": {
|
||||||
"version": "1.4.3",
|
"version": "1.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
|
||||||
@ -16131,6 +16290,11 @@
|
|||||||
"integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==",
|
"integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"standard-as-callback": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A=="
|
||||||
|
},
|
||||||
"string_decoder": {
|
"string_decoder": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "yarkov.tech",
|
"name": "yarkov.tech",
|
||||||
"version": "1.0.6",
|
"version": "1.1.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "Personal website created with Astro.",
|
"description": "Personal website created with Astro.",
|
||||||
"author": {
|
"author": {
|
||||||
@ -47,6 +47,8 @@
|
|||||||
"solid-js": "^1.6.1"
|
"solid-js": "^1.6.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@netlify/functions": "^1.3.0",
|
||||||
|
"ioredis": "^5.2.4",
|
||||||
"sharp": "^0.31.2"
|
"sharp": "^0.31.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
---
|
---
|
||||||
import { Picture } from "@astrojs/image/components";
|
import { Picture } from "@astrojs/image/components";
|
||||||
|
import { Icon } from "astro-icon";
|
||||||
import { createDateFormatter } from "@root/utils";
|
import { createDateFormatter } from "@root/utils";
|
||||||
import { isURL } from "@utils/string";
|
import { isURL } from "@utils/string";
|
||||||
import ArticleComments from "@components/ArticleComments";
|
import ArticleComments from "@components/ArticleComments";
|
||||||
import TranslatedLink from "../TranslatedLink";
|
import TranslatedLink from "../TranslatedLink";
|
||||||
import "./ArticlePost.scss";
|
import "./ArticlePost.scss";
|
||||||
|
import { useTranslation } from "@root/i18n/utils";
|
||||||
|
|
||||||
export type Props = {
|
export type Props = {
|
||||||
data: ArticleType;
|
data: ArticleType;
|
||||||
@ -12,11 +14,13 @@ export type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const { data, lang } = Astro.props as Props;
|
const { data, lang } = Astro.props as Props;
|
||||||
const { title, description, coverImage, tags, author, published_at } = data;
|
const { slug, title, description, coverImage, tags, author, published_at } = data;
|
||||||
|
const t = useTranslation(Astro);
|
||||||
---
|
---
|
||||||
|
|
||||||
<article itemscope itemtype="http://schema.org/BlogPosting" class="article">
|
<article itemscope itemtype="http://schema.org/BlogPosting" class="article">
|
||||||
<header>
|
<header>
|
||||||
|
<div>
|
||||||
<div class="tags">
|
<div class="tags">
|
||||||
<ul itemprop="keywords">
|
<ul itemprop="keywords">
|
||||||
{
|
{
|
||||||
@ -30,6 +34,11 @@ const { title, description, coverImage, tags, author, published_at } = data;
|
|||||||
}
|
}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="views">
|
||||||
|
<Icon name="eye" width="21" height="21" />
|
||||||
|
<span><span id="views">---</span> {t("article.views")}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="heading">
|
<div class="heading">
|
||||||
<h1 itemprop="headline">{title}</h1>
|
<h1 itemprop="headline">{title}</h1>
|
||||||
</div>
|
</div>
|
||||||
@ -65,3 +74,13 @@ const { title, description, coverImage, tags, author, published_at } = data;
|
|||||||
<slot />
|
<slot />
|
||||||
<ArticleComments />
|
<ArticleComments />
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
|
<script define:vars={{ slug }}>
|
||||||
|
(async () => {
|
||||||
|
const response = await fetch(`/api/views?slug=${slug}`, { method: "POST" });
|
||||||
|
const views = await response.text();
|
||||||
|
const $views = document.getElementById("views");
|
||||||
|
|
||||||
|
if ($views) $views.textContent = views;
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
|||||||
@ -1,5 +1,18 @@
|
|||||||
.article {
|
.article {
|
||||||
& header {
|
& header {
|
||||||
|
& div:nth-child(1) {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
& .views {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
& span {
|
||||||
|
margin-left: 3.5px;
|
||||||
|
font-size: var(--font-size-sm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
& .heading {
|
& .heading {
|
||||||
margin-top: 1.125rem;
|
margin-top: 1.125rem;
|
||||||
|
|
||||||
@ -62,8 +75,15 @@
|
|||||||
|
|
||||||
@media screen and (max-width: 560px) {
|
@media screen and (max-width: 560px) {
|
||||||
.article {
|
.article {
|
||||||
& header .heading h1 {
|
& header {
|
||||||
|
& div:nth-child(1) {
|
||||||
|
flex-direction: column-reverse;
|
||||||
|
row-gap: 10px;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
& .heading h1 {
|
||||||
font-size: 2rem;
|
font-size: 2rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@ export default {
|
|||||||
"article.availableOn": "Available on",
|
"article.availableOn": "Available on",
|
||||||
"articles.empty": "No articles found...",
|
"articles.empty": "No articles found...",
|
||||||
"articlePost.comments": "Comments",
|
"articlePost.comments": "Comments",
|
||||||
|
"article.views": "views",
|
||||||
"recentArticles.empty": "There is nothing here yet...",
|
"recentArticles.empty": "There is nothing here yet...",
|
||||||
/* Page titles */
|
/* Page titles */
|
||||||
"pageTitle.about": "About me",
|
"pageTitle.about": "About me",
|
||||||
|
|||||||
@ -6,6 +6,7 @@ export default {
|
|||||||
"article.availableOn": "Доступно на",
|
"article.availableOn": "Доступно на",
|
||||||
"articles.empty": "Не найдено ни одной статьи...",
|
"articles.empty": "Не найдено ни одной статьи...",
|
||||||
"articlePost.comments": "Комментарии",
|
"articlePost.comments": "Комментарии",
|
||||||
|
"article.views": "просмотров",
|
||||||
"recentArticles.empty": "Пока что здесь ничего нет...",
|
"recentArticles.empty": "Пока что здесь ничего нет...",
|
||||||
/* Page titles */
|
/* Page titles */
|
||||||
"pageTitle.about": "Обо мне",
|
"pageTitle.about": "Обо мне",
|
||||||
|
|||||||
3
src/icons/eye.svg
Normal file
3
src/icons/eye.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg width="21" height="21" viewBox="0 0 21 21" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M3.45443 11.6532C3.37609 11.8671 3.21746 12.042 3.01222 12.1408C2.80699 12.2395 2.57133 12.2544 2.35533 12.1821C2.13932 12.1099 1.95999 11.9563 1.85545 11.754C1.7509 11.5516 1.72937 11.3165 1.79543 11.0985C1.77793 11.151 1.79543 11.0968 1.79543 11.0968C1.82655 11.0004 1.86277 10.9058 1.90393 10.8132C1.97393 10.647 2.07718 10.4177 2.21893 10.1465C2.50768 9.604 2.95743 8.88125 3.62068 8.1585C4.95943 6.69725 7.15218 5.25 10.4999 5.25C13.8477 5.25 16.0404 6.69725 17.3792 8.1585C18.0938 8.94246 18.6733 9.83956 19.0942 10.8132L19.1747 11.011C19.1799 11.025 19.1974 11.116 19.2149 11.2035L19.2499 11.375C19.2499 11.375 19.3969 11.9577 18.6514 12.2045C18.4319 12.2778 18.1922 12.2612 17.9849 12.1582C17.7777 12.0552 17.6196 11.8743 17.5454 11.655V11.6498L17.5349 11.6217C17.447 11.3969 17.3465 11.1773 17.2339 10.9637C16.9228 10.3767 16.5382 9.83153 16.0894 9.3415C15.0219 8.17775 13.2772 7 10.4999 7C7.72268 7 5.97793 8.17775 4.91043 9.3415C4.33248 9.97512 3.86247 10.6993 3.51918 11.4853C3.50082 11.5304 3.48332 11.5759 3.46668 11.6217L3.45443 11.6532V11.6532ZM6.99993 12.25C6.99993 11.3217 7.36868 10.4315 8.02506 9.77513C8.68143 9.11875 9.57167 8.75 10.4999 8.75C11.4282 8.75 12.3184 9.11875 12.9748 9.77513C13.6312 10.4315 13.9999 11.3217 13.9999 12.25C13.9999 13.1783 13.6312 14.0685 12.9748 14.7249C12.3184 15.3813 11.4282 15.75 10.4999 15.75C9.57167 15.75 8.68143 15.3813 8.02506 14.7249C7.36868 14.0685 6.99993 13.1783 6.99993 12.25V12.25Z" fill="#21262D"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
@ -3,6 +3,7 @@
|
|||||||
"target": "ESNext",
|
"target": "ESNext",
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
|
"esModuleInterop": true,
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"types": ["vite/client", "@astrojs/image/client", "@types/mdx"],
|
"types": ["vite/client", "@astrojs/image/client", "@types/mdx"],
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user