refactor: removed unused css & removed js form

This commit is contained in:
Sergey Yarkov 2022-08-26 14:50:21 +03:00
parent e1d6e60e03
commit 3648b735a2
30 changed files with 314 additions and 557 deletions

View File

@ -1,14 +1,26 @@
import solid from "@astrojs/solid-js";
// import image from "@astrojs/image";
import compress from "astro-compress";
import mdx from "@astrojs/mdx";
import sitemap from "@astrojs/sitemap";
import { defineConfig } from "astro/config";
import { h } from "hastscript";
import { toString } from "hast-util-to-string";
import { escape } from "html-escaper";
/**
* Integrations
*/
import solid from "@astrojs/solid-js";
import mdx from "@astrojs/mdx";
import sitemap from "@astrojs/sitemap";
// import image from "@astrojs/image";
import compress from "astro-compress";
/**
* Remark plugins
*/
import remarkGfm from "remark-gfm";
import remarkSmartypants from "remark-smartypants";
/**
* Rehype plugins
*/
import rehypeSlug from "rehype-slug";
import rehypeAutolinkHeadings from "rehype-autolink-headings";
@ -87,7 +99,6 @@ export default defineConfig({
external: ["svgo"],
},
build: {
minify: "esbuild",
rollupOptions: {
output: {
entryFileNames: `[name].[hash].js`,

254
package-lock.json generated
View File

@ -15,10 +15,10 @@
"@astrojs/sitemap": "^1.0.0",
"@astrojs/solid-js": "^1.0.0",
"@types/mdx": "^2.0.2",
"@typescript-eslint/eslint-plugin": "^5.34.0",
"@typescript-eslint/parser": "^5.34.0",
"astro": "^1.0.8",
"astro-compress": "^1.0.4",
"@typescript-eslint/eslint-plugin": "^5.35.1",
"@typescript-eslint/parser": "^5.35.1",
"astro": "^1.0.9",
"astro-compress": "^1.0.5",
"astro-icon": "^0.7.3",
"eslint": "^8.22.0",
"eslint-plugin-solid": "^0.7.1",
@ -28,7 +28,7 @@
"mime-types": "^2.1.35",
"netlify-plugin-minify-html": "^0.3.1",
"prettier": "^2.7.1",
"prettier-plugin-astro": "^0.5.2",
"prettier-plugin-astro": "^0.5.3",
"rehype-autolink-headings": "^6.1.1",
"rehype-slug": "^5.0.1",
"remark-gfm": "^3.0.1",
@ -51,9 +51,9 @@
}
},
"node_modules/@astrojs/compiler": {
"version": "0.19.0",
"resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-0.19.0.tgz",
"integrity": "sha512-8nvyxZTfCXLyRmYfTttpJT6EPhfBRg0/q4J/Jj3/pNPLzp+vs05ZdktsY6QxAREaOMAnNEtSqcrB4S5DsXOfRg==",
"version": "0.23.4",
"resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-0.23.4.tgz",
"integrity": "sha512-vNZIa5Tf5nOqBEGJvM6xyYBnGcz4MAp+bBPnyVI0UYRjsIWlP7RgMdCpRV0OOh5kgh00BoAypGv27kcoJCMVfA==",
"dev": true
},
"node_modules/@astrojs/image": {
@ -1142,14 +1142,14 @@
"dev": true
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "5.34.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.34.0.tgz",
"integrity": "sha512-eRfPPcasO39iwjlUAMtjeueRGuIrW3TQ9WseIDl7i5UWuFbf83yYaU7YPs4j8+4CxUMIsj1k+4kV+E+G+6ypDQ==",
"version": "5.35.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.35.1.tgz",
"integrity": "sha512-RBZZXZlI4XCY4Wzgy64vB+0slT9+yAPQRjj/HSaRwUot33xbDjF1oN9BLwOLTewoOI0jothIltZRe9uJCHf8gg==",
"dev": true,
"dependencies": {
"@typescript-eslint/scope-manager": "5.34.0",
"@typescript-eslint/type-utils": "5.34.0",
"@typescript-eslint/utils": "5.34.0",
"@typescript-eslint/scope-manager": "5.35.1",
"@typescript-eslint/type-utils": "5.35.1",
"@typescript-eslint/utils": "5.35.1",
"debug": "^4.3.4",
"functional-red-black-tree": "^1.0.1",
"ignore": "^5.2.0",
@ -1190,14 +1190,14 @@
}
},
"node_modules/@typescript-eslint/parser": {
"version": "5.34.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.34.0.tgz",
"integrity": "sha512-SZ3NEnK4usd2CXkoV3jPa/vo1mWX1fqRyIVUQZR4As1vyp4fneknBNJj+OFtV8WAVgGf+rOHMSqQbs2Qn3nFZQ==",
"version": "5.35.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.35.1.tgz",
"integrity": "sha512-XL2TBTSrh3yWAsMYpKseBYTVpvudNf69rPOWXWVBI08My2JVT5jR66eTt4IgQFHA/giiKJW5dUD4x/ZviCKyGg==",
"dev": true,
"dependencies": {
"@typescript-eslint/scope-manager": "5.34.0",
"@typescript-eslint/types": "5.34.0",
"@typescript-eslint/typescript-estree": "5.34.0",
"@typescript-eslint/scope-manager": "5.35.1",
"@typescript-eslint/types": "5.35.1",
"@typescript-eslint/typescript-estree": "5.35.1",
"debug": "^4.3.4"
},
"engines": {
@ -1217,13 +1217,13 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "5.34.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.34.0.tgz",
"integrity": "sha512-HNvASMQlah5RsBW6L6c7IJ0vsm+8Sope/wu5sEAf7joJYWNb1LDbJipzmdhdUOnfrDFE6LR1j57x1EYVxrY4ow==",
"version": "5.35.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.35.1.tgz",
"integrity": "sha512-kCYRSAzIW9ByEIzmzGHE50NGAvAP3wFTaZevgWva7GpquDyFPFcmvVkFJGWJJktg/hLwmys/FZwqM9EKr2u24Q==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "5.34.0",
"@typescript-eslint/visitor-keys": "5.34.0"
"@typescript-eslint/types": "5.35.1",
"@typescript-eslint/visitor-keys": "5.35.1"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@ -1234,12 +1234,12 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
"version": "5.34.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.34.0.tgz",
"integrity": "sha512-Pxlno9bjsQ7hs1pdWRUv9aJijGYPYsHpwMeCQ/Inavhym3/XaKt1ZKAA8FIw4odTBfowBdZJDMxf2aavyMDkLg==",
"version": "5.35.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.35.1.tgz",
"integrity": "sha512-8xT8ljvo43Mp7BiTn1vxLXkjpw8wS4oAc00hMSB4L1/jIiYbjjnc3Qp2GAUOG/v8zsNCd1qwcqfCQ0BuishHkw==",
"dev": true,
"dependencies": {
"@typescript-eslint/utils": "5.34.0",
"@typescript-eslint/utils": "5.35.1",
"debug": "^4.3.4",
"tsutils": "^3.21.0"
},
@ -1260,9 +1260,9 @@
}
},
"node_modules/@typescript-eslint/types": {
"version": "5.34.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.34.0.tgz",
"integrity": "sha512-49fm3xbbUPuzBIOcy2CDpYWqy/X7VBkxVN+DC21e0zIm3+61Z0NZi6J9mqPmSW1BDVk9FIOvuCFyUPjXz93sjA==",
"version": "5.35.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.35.1.tgz",
"integrity": "sha512-FDaujtsH07VHzG0gQ6NDkVVhi1+rhq0qEvzHdJAQjysN+LHDCKDKCBRlZFFE0ec0jKxiv0hN63SNfExy0KrbQQ==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@ -1273,13 +1273,13 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "5.34.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.34.0.tgz",
"integrity": "sha512-mXHAqapJJDVzxauEkfJI96j3D10sd567LlqroyCeJaHnu42sDbjxotGb3XFtGPYKPD9IyLjhsoULML1oI3M86A==",
"version": "5.35.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.35.1.tgz",
"integrity": "sha512-JUqE1+VRTGyoXlDWWjm6MdfpBYVq+hixytrv1oyjYIBEOZhBCwtpp5ZSvBt4wIA1MKWlnaC2UXl2XmYGC3BoQA==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "5.34.0",
"@typescript-eslint/visitor-keys": "5.34.0",
"@typescript-eslint/types": "5.35.1",
"@typescript-eslint/visitor-keys": "5.35.1",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
@ -1315,15 +1315,15 @@
}
},
"node_modules/@typescript-eslint/utils": {
"version": "5.34.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.34.0.tgz",
"integrity": "sha512-kWRYybU4Rn++7lm9yu8pbuydRyQsHRoBDIo11k7eqBWTldN4xUdVUMCsHBiE7aoEkFzrUEaZy3iH477vr4xHAQ==",
"version": "5.35.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.35.1.tgz",
"integrity": "sha512-v6F8JNXgeBWI4pzZn36hT2HXXzoBBBJuOYvoQiaQaEEjdi5STzux3Yj8v7ODIpx36i/5s8TdzuQ54TPc5AITQQ==",
"dev": true,
"dependencies": {
"@types/json-schema": "^7.0.9",
"@typescript-eslint/scope-manager": "5.34.0",
"@typescript-eslint/types": "5.34.0",
"@typescript-eslint/typescript-estree": "5.34.0",
"@typescript-eslint/scope-manager": "5.35.1",
"@typescript-eslint/types": "5.35.1",
"@typescript-eslint/typescript-estree": "5.35.1",
"eslint-scope": "^5.1.1",
"eslint-utils": "^3.0.0"
},
@ -1339,12 +1339,12 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "5.34.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.34.0.tgz",
"integrity": "sha512-O1moYjOSrab0a2fUvFpsJe0QHtvTC+cR+ovYpgKrAVXzqQyc74mv76TgY6z+aEtjQE2vgZux3CQVtGryqdcOAw==",
"version": "5.35.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.35.1.tgz",
"integrity": "sha512-cEB1DvBVo1bxbW/S5axbGPE6b7FIMAbo3w+AGq6zNDA7+NYJOIkKj/sInfTv4edxd4PxJSgdN4t6/pbvgA+n5g==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "5.34.0",
"@typescript-eslint/types": "5.35.1",
"eslint-visitor-keys": "^3.3.0"
},
"engines": {
@ -1571,12 +1571,12 @@
}
},
"node_modules/astro": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/astro/-/astro-1.0.8.tgz",
"integrity": "sha512-cWey5M/EjdgeZCRlOAB6YP05ui3U9ZfHPdb4r5HmumOE/1w8auDqRiHPpb2RCGYD7RpxOXcJu5XfJL4V2F1UpQ==",
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/astro/-/astro-1.0.9.tgz",
"integrity": "sha512-Pa/7wLIuXFs+sgdVxUTT0QHe+9yKQVE21jxZU/p2ZzcUrAB+8JN32fHEG28QTwEx+NuwTqvC5xTvDBXLZJGtqw==",
"dev": true,
"dependencies": {
"@astrojs/compiler": "^0.23.3",
"@astrojs/compiler": "^0.23.4",
"@astrojs/language-server": "^0.20.0",
"@astrojs/markdown-remark": "^1.0.0",
"@astrojs/telemetry": "^1.0.0",
@ -1617,7 +1617,7 @@
"recast": "^0.20.5",
"rehype": "^12.0.1",
"resolve": "^1.22.0",
"rollup": "^2.75.6",
"rollup": "~2.77.0",
"semver": "^7.3.7",
"shiki": "^0.10.1",
"sirv": "^2.0.2",
@ -1641,9 +1641,9 @@
}
},
"node_modules/astro-compress": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/astro-compress/-/astro-compress-1.0.4.tgz",
"integrity": "sha512-94VCrgdERV8P2HfE4tIcRePaLZNAFVVb3bDzzAf8u15rx4lQNWC/5X3veNIJkGBgwqFuNUZLPXy2bh+amhyDrQ==",
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/astro-compress/-/astro-compress-1.0.5.tgz",
"integrity": "sha512-XK24SMSK+bWogAPAPxZcI//vc4NN7NvGqbrMXfgEtrRoIcWLZ8jHMw9r9+0aw2a2ITMrW/EDFpaWeFxqxKWCHw==",
"dev": true,
"dependencies": {
"csso": "5.0.5",
@ -1652,7 +1652,7 @@
"html-minifier-terser": "7.0.0",
"sharp": "0.30.7",
"svgo": "2.8.0",
"terser": "5.14.2"
"terser": "5.15.0"
}
},
"node_modules/astro-icon": {
@ -1666,12 +1666,6 @@
"svgo": "^2.8.0"
}
},
"node_modules/astro/node_modules/@astrojs/compiler": {
"version": "0.23.3",
"resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-0.23.3.tgz",
"integrity": "sha512-eBWo0d3DoRDeg2Di1/5YJtOXh5eGFSjJMp1wVoVfoITHR4egdUGgsrDHZTzj0a25M/S9W5S6SpXCyNWcqi8jOA==",
"dev": true
},
"node_modules/astro/node_modules/semver": {
"version": "7.3.7",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
@ -7308,12 +7302,12 @@
}
},
"node_modules/prettier-plugin-astro": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/prettier-plugin-astro/-/prettier-plugin-astro-0.5.2.tgz",
"integrity": "sha512-P6i5ARkfK0B0/uPWruH81lBPL1QcrJLVREKAuqih24Y7x4ySxdBMdaulEWpzhPuiXoRLQ9v0I1VTS4wb6KKDqg==",
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/prettier-plugin-astro/-/prettier-plugin-astro-0.5.3.tgz",
"integrity": "sha512-g4uJ/7k1rJeIWBifeBgTqzgV5gmMTG+lOmOvUZvtIh1R91aqa+yYMzbysIlsJKRaRyWefejrOpvpIuEePBDAyw==",
"dev": true,
"dependencies": {
"@astrojs/compiler": "^0.19.0",
"@astrojs/compiler": "^0.23.3",
"prettier": "^2.7.1",
"sass-formatter": "^0.7.2",
"synckit": "^0.7.0"
@ -8657,9 +8651,9 @@
}
},
"node_modules/terser": {
"version": "5.14.2",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz",
"integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==",
"version": "5.15.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz",
"integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==",
"dev": true,
"dependencies": {
"@jridgewell/source-map": "^0.3.2",
@ -9541,9 +9535,9 @@
}
},
"@astrojs/compiler": {
"version": "0.19.0",
"resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-0.19.0.tgz",
"integrity": "sha512-8nvyxZTfCXLyRmYfTttpJT6EPhfBRg0/q4J/Jj3/pNPLzp+vs05ZdktsY6QxAREaOMAnNEtSqcrB4S5DsXOfRg==",
"version": "0.23.4",
"resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-0.23.4.tgz",
"integrity": "sha512-vNZIa5Tf5nOqBEGJvM6xyYBnGcz4MAp+bBPnyVI0UYRjsIWlP7RgMdCpRV0OOh5kgh00BoAypGv27kcoJCMVfA==",
"dev": true
},
"@astrojs/image": {
@ -10432,14 +10426,14 @@
"dev": true
},
"@typescript-eslint/eslint-plugin": {
"version": "5.34.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.34.0.tgz",
"integrity": "sha512-eRfPPcasO39iwjlUAMtjeueRGuIrW3TQ9WseIDl7i5UWuFbf83yYaU7YPs4j8+4CxUMIsj1k+4kV+E+G+6ypDQ==",
"version": "5.35.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.35.1.tgz",
"integrity": "sha512-RBZZXZlI4XCY4Wzgy64vB+0slT9+yAPQRjj/HSaRwUot33xbDjF1oN9BLwOLTewoOI0jothIltZRe9uJCHf8gg==",
"dev": true,
"requires": {
"@typescript-eslint/scope-manager": "5.34.0",
"@typescript-eslint/type-utils": "5.34.0",
"@typescript-eslint/utils": "5.34.0",
"@typescript-eslint/scope-manager": "5.35.1",
"@typescript-eslint/type-utils": "5.35.1",
"@typescript-eslint/utils": "5.35.1",
"debug": "^4.3.4",
"functional-red-black-tree": "^1.0.1",
"ignore": "^5.2.0",
@ -10460,52 +10454,52 @@
}
},
"@typescript-eslint/parser": {
"version": "5.34.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.34.0.tgz",
"integrity": "sha512-SZ3NEnK4usd2CXkoV3jPa/vo1mWX1fqRyIVUQZR4As1vyp4fneknBNJj+OFtV8WAVgGf+rOHMSqQbs2Qn3nFZQ==",
"version": "5.35.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.35.1.tgz",
"integrity": "sha512-XL2TBTSrh3yWAsMYpKseBYTVpvudNf69rPOWXWVBI08My2JVT5jR66eTt4IgQFHA/giiKJW5dUD4x/ZviCKyGg==",
"dev": true,
"requires": {
"@typescript-eslint/scope-manager": "5.34.0",
"@typescript-eslint/types": "5.34.0",
"@typescript-eslint/typescript-estree": "5.34.0",
"@typescript-eslint/scope-manager": "5.35.1",
"@typescript-eslint/types": "5.35.1",
"@typescript-eslint/typescript-estree": "5.35.1",
"debug": "^4.3.4"
}
},
"@typescript-eslint/scope-manager": {
"version": "5.34.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.34.0.tgz",
"integrity": "sha512-HNvASMQlah5RsBW6L6c7IJ0vsm+8Sope/wu5sEAf7joJYWNb1LDbJipzmdhdUOnfrDFE6LR1j57x1EYVxrY4ow==",
"version": "5.35.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.35.1.tgz",
"integrity": "sha512-kCYRSAzIW9ByEIzmzGHE50NGAvAP3wFTaZevgWva7GpquDyFPFcmvVkFJGWJJktg/hLwmys/FZwqM9EKr2u24Q==",
"dev": true,
"requires": {
"@typescript-eslint/types": "5.34.0",
"@typescript-eslint/visitor-keys": "5.34.0"
"@typescript-eslint/types": "5.35.1",
"@typescript-eslint/visitor-keys": "5.35.1"
}
},
"@typescript-eslint/type-utils": {
"version": "5.34.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.34.0.tgz",
"integrity": "sha512-Pxlno9bjsQ7hs1pdWRUv9aJijGYPYsHpwMeCQ/Inavhym3/XaKt1ZKAA8FIw4odTBfowBdZJDMxf2aavyMDkLg==",
"version": "5.35.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.35.1.tgz",
"integrity": "sha512-8xT8ljvo43Mp7BiTn1vxLXkjpw8wS4oAc00hMSB4L1/jIiYbjjnc3Qp2GAUOG/v8zsNCd1qwcqfCQ0BuishHkw==",
"dev": true,
"requires": {
"@typescript-eslint/utils": "5.34.0",
"@typescript-eslint/utils": "5.35.1",
"debug": "^4.3.4",
"tsutils": "^3.21.0"
}
},
"@typescript-eslint/types": {
"version": "5.34.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.34.0.tgz",
"integrity": "sha512-49fm3xbbUPuzBIOcy2CDpYWqy/X7VBkxVN+DC21e0zIm3+61Z0NZi6J9mqPmSW1BDVk9FIOvuCFyUPjXz93sjA==",
"version": "5.35.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.35.1.tgz",
"integrity": "sha512-FDaujtsH07VHzG0gQ6NDkVVhi1+rhq0qEvzHdJAQjysN+LHDCKDKCBRlZFFE0ec0jKxiv0hN63SNfExy0KrbQQ==",
"dev": true
},
"@typescript-eslint/typescript-estree": {
"version": "5.34.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.34.0.tgz",
"integrity": "sha512-mXHAqapJJDVzxauEkfJI96j3D10sd567LlqroyCeJaHnu42sDbjxotGb3XFtGPYKPD9IyLjhsoULML1oI3M86A==",
"version": "5.35.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.35.1.tgz",
"integrity": "sha512-JUqE1+VRTGyoXlDWWjm6MdfpBYVq+hixytrv1oyjYIBEOZhBCwtpp5ZSvBt4wIA1MKWlnaC2UXl2XmYGC3BoQA==",
"dev": true,
"requires": {
"@typescript-eslint/types": "5.34.0",
"@typescript-eslint/visitor-keys": "5.34.0",
"@typescript-eslint/types": "5.35.1",
"@typescript-eslint/visitor-keys": "5.35.1",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
@ -10525,26 +10519,26 @@
}
},
"@typescript-eslint/utils": {
"version": "5.34.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.34.0.tgz",
"integrity": "sha512-kWRYybU4Rn++7lm9yu8pbuydRyQsHRoBDIo11k7eqBWTldN4xUdVUMCsHBiE7aoEkFzrUEaZy3iH477vr4xHAQ==",
"version": "5.35.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.35.1.tgz",
"integrity": "sha512-v6F8JNXgeBWI4pzZn36hT2HXXzoBBBJuOYvoQiaQaEEjdi5STzux3Yj8v7ODIpx36i/5s8TdzuQ54TPc5AITQQ==",
"dev": true,
"requires": {
"@types/json-schema": "^7.0.9",
"@typescript-eslint/scope-manager": "5.34.0",
"@typescript-eslint/types": "5.34.0",
"@typescript-eslint/typescript-estree": "5.34.0",
"@typescript-eslint/scope-manager": "5.35.1",
"@typescript-eslint/types": "5.35.1",
"@typescript-eslint/typescript-estree": "5.35.1",
"eslint-scope": "^5.1.1",
"eslint-utils": "^3.0.0"
}
},
"@typescript-eslint/visitor-keys": {
"version": "5.34.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.34.0.tgz",
"integrity": "sha512-O1moYjOSrab0a2fUvFpsJe0QHtvTC+cR+ovYpgKrAVXzqQyc74mv76TgY6z+aEtjQE2vgZux3CQVtGryqdcOAw==",
"version": "5.35.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.35.1.tgz",
"integrity": "sha512-cEB1DvBVo1bxbW/S5axbGPE6b7FIMAbo3w+AGq6zNDA7+NYJOIkKj/sInfTv4edxd4PxJSgdN4t6/pbvgA+n5g==",
"dev": true,
"requires": {
"@typescript-eslint/types": "5.34.0",
"@typescript-eslint/types": "5.35.1",
"eslint-visitor-keys": "^3.3.0"
}
},
@ -10716,12 +10710,12 @@
"dev": true
},
"astro": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/astro/-/astro-1.0.8.tgz",
"integrity": "sha512-cWey5M/EjdgeZCRlOAB6YP05ui3U9ZfHPdb4r5HmumOE/1w8auDqRiHPpb2RCGYD7RpxOXcJu5XfJL4V2F1UpQ==",
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/astro/-/astro-1.0.9.tgz",
"integrity": "sha512-Pa/7wLIuXFs+sgdVxUTT0QHe+9yKQVE21jxZU/p2ZzcUrAB+8JN32fHEG28QTwEx+NuwTqvC5xTvDBXLZJGtqw==",
"dev": true,
"requires": {
"@astrojs/compiler": "^0.23.3",
"@astrojs/compiler": "^0.23.4",
"@astrojs/language-server": "^0.20.0",
"@astrojs/markdown-remark": "^1.0.0",
"@astrojs/telemetry": "^1.0.0",
@ -10762,7 +10756,7 @@
"recast": "^0.20.5",
"rehype": "^12.0.1",
"resolve": "^1.22.0",
"rollup": "^2.75.6",
"rollup": "~2.77.0",
"semver": "^7.3.7",
"shiki": "^0.10.1",
"sirv": "^2.0.2",
@ -10778,12 +10772,6 @@
"zod": "^3.17.3"
},
"dependencies": {
"@astrojs/compiler": {
"version": "0.23.3",
"resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-0.23.3.tgz",
"integrity": "sha512-eBWo0d3DoRDeg2Di1/5YJtOXh5eGFSjJMp1wVoVfoITHR4egdUGgsrDHZTzj0a25M/S9W5S6SpXCyNWcqi8jOA==",
"dev": true
},
"semver": {
"version": "7.3.7",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
@ -10796,9 +10784,9 @@
}
},
"astro-compress": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/astro-compress/-/astro-compress-1.0.4.tgz",
"integrity": "sha512-94VCrgdERV8P2HfE4tIcRePaLZNAFVVb3bDzzAf8u15rx4lQNWC/5X3veNIJkGBgwqFuNUZLPXy2bh+amhyDrQ==",
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/astro-compress/-/astro-compress-1.0.5.tgz",
"integrity": "sha512-XK24SMSK+bWogAPAPxZcI//vc4NN7NvGqbrMXfgEtrRoIcWLZ8jHMw9r9+0aw2a2ITMrW/EDFpaWeFxqxKWCHw==",
"dev": true,
"requires": {
"csso": "5.0.5",
@ -10807,7 +10795,7 @@
"html-minifier-terser": "7.0.0",
"sharp": "0.30.7",
"svgo": "2.8.0",
"terser": "5.14.2"
"terser": "5.15.0"
}
},
"astro-icon": {
@ -14739,12 +14727,12 @@
"dev": true
},
"prettier-plugin-astro": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/prettier-plugin-astro/-/prettier-plugin-astro-0.5.2.tgz",
"integrity": "sha512-P6i5ARkfK0B0/uPWruH81lBPL1QcrJLVREKAuqih24Y7x4ySxdBMdaulEWpzhPuiXoRLQ9v0I1VTS4wb6KKDqg==",
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/prettier-plugin-astro/-/prettier-plugin-astro-0.5.3.tgz",
"integrity": "sha512-g4uJ/7k1rJeIWBifeBgTqzgV5gmMTG+lOmOvUZvtIh1R91aqa+yYMzbysIlsJKRaRyWefejrOpvpIuEePBDAyw==",
"dev": true,
"requires": {
"@astrojs/compiler": "^0.19.0",
"@astrojs/compiler": "^0.23.3",
"prettier": "^2.7.1",
"sass-formatter": "^0.7.2",
"synckit": "^0.7.0"
@ -15717,9 +15705,9 @@
}
},
"terser": {
"version": "5.14.2",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz",
"integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==",
"version": "5.15.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz",
"integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==",
"dev": true,
"requires": {
"@jridgewell/source-map": "^0.3.2",

View File

@ -25,10 +25,10 @@
"@astrojs/sitemap": "^1.0.0",
"@astrojs/solid-js": "^1.0.0",
"@types/mdx": "^2.0.2",
"@typescript-eslint/eslint-plugin": "^5.34.0",
"@typescript-eslint/parser": "^5.34.0",
"astro": "^1.0.8",
"astro-compress": "^1.0.4",
"@typescript-eslint/eslint-plugin": "^5.35.1",
"@typescript-eslint/parser": "^5.35.1",
"astro": "^1.0.9",
"astro-compress": "^1.0.5",
"astro-icon": "^0.7.3",
"eslint": "^8.22.0",
"eslint-plugin-solid": "^0.7.1",
@ -38,7 +38,7 @@
"mime-types": "^2.1.35",
"netlify-plugin-minify-html": "^0.3.1",
"prettier": "^2.7.1",
"prettier-plugin-astro": "^0.5.2",
"prettier-plugin-astro": "^0.5.3",
"rehype-autolink-headings": "^6.1.1",
"rehype-slug": "^5.0.1",
"remark-gfm": "^3.0.1",

View File

@ -0,0 +1,37 @@
---
export type Props = astroHTML.JSX.ButtonHTMLAttributes;
const attrs = Astro.props as Props;
---
<button {...attrs}>
<slot />
</button>
<style lang="scss">
button {
cursor: pointer;
display: inline-flex;
column-gap: 7px;
font-family: var(--font-family-base);
font-weight: 500;
color: var(--font-color);
padding: 5px 16px;
border: 1px solid var(--border-color);
border-radius: var(--border-radius-md);
background: none;
font-size: var(--font-size-sm);
&:hover {
border: 1px solid var(--border-color-hover);
}
&[disabled] {
opacity: 0.5;
cursor: not-allowed;
&:hover {
border: 1px solid var(--border-color);
}
}
}
</style>

View File

@ -1,28 +0,0 @@
.btn {
cursor: pointer;
display: inline-flex;
column-gap: 7px;
align-items: center;
font-family: var(--font-family-base);
font-weight: 500;
font-size: var(--font-size-md);
color: var(--font-color);
padding: 5px 16px;
border: 1px solid var(--border-color);
border-radius: var(--border-radius-md);
background: none;
font-size: var(--font-size-sm);
&:hover {
border: 1px solid var(--border-color-hover);
}
&[disabled] {
opacity: 0.5;
&:hover {
border: 1px solid var(--border-color);
}
}
&[data-loading="true"] {
user-select: none;
cursor: not-allowed;
}
}

View File

@ -1,22 +0,0 @@
import type { ParentComponent, JSX } from "solid-js";
import { splitProps } from "solid-js";
import Spinner from "@components/Spinner";
import "./Button.scss";
type ButtonProps = {
isLoading?: boolean | undefined;
loadingText?: string | undefined;
} & JSX.ButtonHTMLAttributes<HTMLButtonElement>;
const Button: ParentComponent<ButtonProps> = (props) => {
const [local, attrs] = splitProps(props, ["children", "isLoading", "loadingText"]);
return (
<button disabled={local.isLoading} class={`btn`} data-loading={local.isLoading} {...attrs}>
{local.isLoading && <Spinner />}
{local.isLoading ? local.loadingText || "Loading..." : local.children}
</button>
);
};
export default Button;

View File

@ -1 +1 @@
export { default } from "./Button";
export { default } from "./Button.astro";

View File

@ -0,0 +1,58 @@
---
import Button from "@components/Button";
import { useTranslation } from "@i18n/utils";
const t = useTranslation(Astro);
---
<form name="contact" method="post" netlify-honeypot="bot-field" data-netlify="true">
<div hidden>
Don't fill this out if you're human
<input name="bot-field" />
</div>
<div class="flex">
<div>
<input name="name" placeholder={t("input.nameField")} type="text" maxlength="20" autocomplete="off" required />
</div>
<div>
<input name="email" placeholder="example@email.com" autocomplete="off" type="email" required />
</div>
</div>
<input name="subject" placeholder={t("input.subjectField")} type="text" autocomplete="off" required />
<textarea name="message" placeholder={t("input.messageField")} id="message" autocomplete="off" cols={30} rows={10} required></textarea>
<div class="footer">
<Button type="submit">{t("btn.submit")}</Button>
</div>
</form>
<style lang="scss">
form {
display: flex;
flex-direction: column;
row-gap: 7px;
margin-bottom: 3.125rem;
& .flex {
column-gap: 10px;
& div {
width: 100%;
}
}
& input.error-input,
& textarea.error-input {
border: 1px solid var(--color-error);
}
& .footer {
text-align: center;
}
}
@media screen and (max-width: 560px) {
.contact-form .flex {
flex-direction: column;
row-gap: 7px;
}
}
</style>

View File

@ -1,140 +0,0 @@
import type { Component, JSX } from "solid-js";
import { createSignal } from "solid-js";
import { createStore } from "solid-js/store";
import { useForm } from "@hooks/index";
import { encode } from "@utils/url";
import Button from "@components/Button";
import validations from "./validations";
import Submitted from "./Submitted";
import Error from "./Error";
import "./ContactForm.scss";
type UiStringsType = {
"form.contactSuccess": string;
"form.contactError": string;
"input.nameField": string;
"input.subjectField": string;
"input.messageField": string;
"btn.send": string;
"btn.sending": string;
"error.invalidEmail": string;
};
const ErrorMessage: Component<{ message: string }> = (props) => <span class="error-message">{props.message}</span>;
const ContactForm: Component<{ i18n: UiStringsType }> = (props) => {
const { formSubmit, validate, errors } = useForm({ errorClass: "error-input" });
const [isSubmitted, setIsSubmitted] = createSignal<boolean>(false);
const [isLoading, setIsLoading] = createSignal<boolean>(false);
const [isError, setIsError] = createSignal<boolean>(false);
const [state, setState] = createStore<ContactFieldsType>({ name: "", email: "", subject: "", message: "", "bot-field": "" });
const { validateEmail } = validations;
const reset = (form: HTMLFormElement) => {
for (const key in state) {
form.elements[key].value = "";
setState({ [key]: "" });
}
};
const sendMessage = async (form: HTMLFormElement) => {
try {
setIsLoading(true);
fetch("/", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: encode({
"form-name": "contact",
...state,
}),
});
} catch (error) {
setIsError(true);
console.error(error);
} finally {
setIsLoading(false);
setIsSubmitted(true);
reset(form);
}
};
const onChange: JSX.EventHandler<HTMLInputElement, InputEvent> = (e) => {
const key = e.currentTarget.name;
const value = e.currentTarget.value;
if (!Object.hasOwn(state, key)) return;
setState({ [key]: value });
};
return (
<form use:formSubmit={sendMessage} class="contact-form" name="contact" method="post" data-netlify="true">
<div hidden>
Don't fill this out if you're human
<input onInput={onChange} name="bot-field" />
</div>
<div class="flex">
<div>
<input
onInput={onChange}
use:validate
name="name"
placeholder={props.i18n["input.nameField"]}
type="text"
maxLength="20"
autocomplete="off"
required
/>
{errors.name && <ErrorMessage message={errors.name} />}
</div>
<div>
<input
onInput={onChange}
use:validate={[validateEmail(props.i18n["error.invalidEmail"])]}
name="email"
placeholder="example@email.com"
autocomplete="off"
type="text"
required
/>
{errors.email && <ErrorMessage message={errors.email} />}
</div>
</div>
<input
value={state.subject}
onInput={onChange}
use:validate
name="subject"
placeholder={props.i18n["input.subjectField"]}
type="text"
autocomplete="off"
required
/>
{errors.subject && <ErrorMessage message={errors.subject} />}
<textarea
onInput={onChange}
use:validate
name="message"
placeholder={props.i18n["input.messageField"]}
id="message"
autocomplete="off"
cols={30}
rows={10}
required
/>
{errors.message && <ErrorMessage message={errors.message} />}
<div class="form-footer">
{!isError() && !isSubmitted() && (
<Button isLoading={isLoading()} loadingText={props.i18n["btn.sending"]} type="submit">
{props.i18n["btn.send"]}
</Button>
)}
{!isError() && isSubmitted() && <Submitted text={props.i18n["form.contactSuccess"]} />}
{isError() && isSubmitted() && <Error text={props.i18n["form.contactError"]} />}
</div>
</form>
);
};
export default ContactForm;

View File

@ -1,7 +0,0 @@
import type { Component } from "solid-js";
const Submitted: Component<{ text: string }> = (props) => {
return <div class="form-result">&#10060; {props.text}</div>;
};
export default Submitted;

View File

@ -1,7 +0,0 @@
import type { Component } from "solid-js";
const Submitted: Component<{ text: string }> = (props) => {
return <div class="form-result">&#10004;&#65039; {props.text}</div>;
};
export default Submitted;

View File

@ -1 +1 @@
export { default } from "./ContactForm";
export { default } from "./ContactForm.astro";

View File

@ -1,7 +0,0 @@
import { isEmail } from "@utils/string";
export default {
validateEmail: (error: string) => {
return (field: HTMLInputElement) => (isEmail(field.value) ? false : error);
},
};

View File

@ -1,15 +0,0 @@
.counter {
margin: 2rem 0;
display: flex;
flex-direction: column;
align-items: center;
row-gap: 15px;
border: 1px solid var(--border-color);
border-radius: var(--border-radius-md);
padding: 15px 5px;
}
.counter div {
display: flex;
column-gap: 3px;
}

View File

@ -1,8 +1,6 @@
import type { Component } from "solid-js";
import { createSignal, createEffect } from "solid-js";
import Button from "@components/Button";
import "./Counter.css";
const Counter: Component<{ tick?: number }> = (props) => {
const [isRunned, setIsRunned] = createSignal<boolean>(false);
@ -22,21 +20,37 @@ const Counter: Component<{ tick?: number }> = (props) => {
});
return (
<div class="counter">
<div
style={{
margin: "2rem 0",
display: "flex",
"flex-direction": "column",
"align-items": "center",
"row-gap": "15px",
border: "1px solid var(--border-color)",
"border-radius": "var(--border-radius-md)",
padding: "15px 5px",
}}
>
<span>{count()}</span>
<div>
<Button disabled={isRunned()} onClick={run}>
<div
style={{
display: "flex",
"column-gap": "3px",
}}
>
<button class="btn" disabled={isRunned()} onClick={run}>
Run
</Button>
<Button disabled={isRunned()} onClick={inc}>
</button>
<button class="btn" disabled={isRunned()} onClick={inc}>
+
</Button>
<Button disabled={isRunned()} onClick={dec}>
</button>
<button class="btn" disabled={isRunned()} onClick={dec}>
-
</Button>
<Button disabled={!isRunned()} onClick={stop}>
</button>
<button class="btn" disabled={!isRunned()} onClick={stop}>
Stop
</Button>
</button>
</div>
</div>
);

View File

@ -1,26 +0,0 @@
.spinner {
--spinner-size: 1em;
display: inline-block;
border-top: 1px solid var(--font-color);
border-right: 1px solid var(--font-color);
border-bottom-style: solid;
border-left-style: solid;
border-radius: 99999px;
border-bottom-width: 1px;
border-left-width: 1px;
border-bottom-color: transparent;
border-left-color: transparent;
animation: 0.45s linear 0s infinite normal none running spinner;
width: var(--spinner-size);
height: var(--spinner-size);
}
@keyframes spinner {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

View File

@ -1,11 +0,0 @@
import type { Component, JSX } from "solid-js";
import "./Spinner.scss";
type SpinnerProps = JSX.HTMLAttributes<HTMLDivElement>;
const Spinner: Component<SpinnerProps> = (props) => {
return <div class="spinner" {...props} />;
};
export default Spinner;

View File

@ -1 +0,0 @@
export { default } from "./Spinner";

View File

@ -1 +0,0 @@
export * from "./useForm";

View File

@ -1,80 +0,0 @@
import type { Accessor } from "solid-js";
import { createStore, SetStoreFunction } from "solid-js/store";
type HTMLElementsType = HTMLInputElement | HTMLTextAreaElement;
type CustomValidatorType = (element: HTMLElementsType) => string | false;
type FieldConfigType = { element: HTMLElementsType; validators: Array<CustomValidatorType> };
type FormSubmitFnType = (ref: HTMLFormElement, accessor: Accessor<(form: HTMLFormElement) => unknown>) => void;
type ValidateFnType = (ref: HTMLElementsType, accessor: Accessor<Array<CustomValidatorType>>) => void;
type СheckValidFnType = (config: FieldConfigType, setErrors: SetStoreFunction<Record<string, unknown>>, errorClass: string) => void;
const checkValid: СheckValidFnType = (fieldConfig, setErrors, errorClass) => {
const { element, validators = [] } = fieldConfig;
element.setCustomValidity("");
element.checkValidity();
let message = element.validationMessage;
/* Run custom validators */
if (Array.isArray(validators)) {
if (!message) {
for (const validator of validators) {
if (typeof validator === "function") {
const text = validator(element);
if (text) {
element.setCustomValidity(text);
break;
}
}
}
message = element.validationMessage;
}
}
/* Set errors if message exists and class to input element */
if (message) {
errorClass && element.classList.toggle(errorClass, true);
setErrors({ [element.name]: message });
}
};
export const useForm = ({ errorClass }) => {
const [errors, setErrors] = createStore<{ [key: string]: string | undefined }>({});
const fields = {};
const validate: ValidateFnType = (ref, accessor) => {
const validators = accessor();
let config: FieldConfigType;
fields[ref.name] = config = { element: ref, validators };
ref.onblur = () => checkValid(config, setErrors, errorClass);
ref.oninput = () => {
if (!errors[ref.name]) return;
setErrors({ [ref.name]: undefined });
errorClass && ref.classList.toggle(errorClass, false);
};
};
const formSubmit: FormSubmitFnType = (ref, accessor) => {
const callback = accessor();
ref.setAttribute("novalidate", "");
ref.onsubmit = (e) => {
e.preventDefault();
let isError = false;
/* Validate all fields of form */
for (const key in fields) {
const field = fields[key] as FieldConfigType;
checkValid(field, setErrors, errorClass);
if (!isError && field.element.validationMessage) {
field.element.focus();
isError = true;
}
}
if (typeof callback === "function") !isError && callback(ref);
};
};
return { validate, formSubmit, errors };
};

View File

@ -34,8 +34,8 @@ export default {
"404.heading": "404",
"404.description": "The page you are trying to find does not exist.",
/* Buttons */
"btn.send": "Submit",
"btn.sending": "Submitting...",
"btn.submit": "Submit",
"btn.submiting": "Submitting...",
"btn.sourceCode": "Source",
"btn.demo": "Demo",
"btn.article": "Article",

View File

@ -34,8 +34,8 @@ export default {
"404.heading": "404",
"404.description": "Страницу которую вы пытаетесь найти не существует.",
/* Buttons */
"btn.send": "Отправить",
"btn.sending": "Отправка...",
"btn.submit": "Отправить",
"btn.submitting": "Отправка...",
"btn.sourceCode": "Исходник",
"btn.demo": "Демо",
"btn.article": "Статья",

View File

@ -19,33 +19,6 @@ export function formatArticlesByLangs(data: Record<string, MDXInstance<ArticleTy
return modules;
}
export function getTranslatedArticles(Astro: Readonly<AstroGlobal>): MDXInstance<ArticleType>[] {
const data = import.meta.glob<MDXInstance<ArticleType>>("../../content/articles/**/*.mdx", { eager: true });
const modules = formatArticlesByLangs(data);
const siteLang = utils.getLanguageFromURL(Astro.url.pathname);
const articles: MDXInstance<ArticleType>[] = [];
for (const key of Object.keys(modules)) {
const langs = Object.keys(modules[key]);
for (const articleLang of langs) {
const isNonDefaultLanguage = !langs.includes(siteLang) && langs.length === 1;
const article = modules[key];
if (articleLang === siteLang) {
articles.push(article[siteLang]);
article[siteLang].frontmatter.lang = siteLang;
}
if (isNonDefaultLanguage) {
articles.push(article[articleLang]);
article[articleLang].frontmatter.lang = articleLang;
}
}
}
return articles;
}
export function getLanguageKeys(): Array<string> {
return Object.keys(languages);
}

View File

@ -0,0 +1,34 @@
import type { AstroGlobal, MDXInstance } from "astro";
import { formatArticlesByLangs } from "@i18n/utils";
import { getLanguageFromURL } from "@utils/url";
class ArticleService {
public getTranslatedArticles(Astro: Readonly<AstroGlobal>): MDXInstance<ArticleType>[] {
const data = import.meta.glob<MDXInstance<ArticleType>>("../../content/articles/**/*.mdx", { eager: true });
const modules = formatArticlesByLangs(data);
const siteLang = getLanguageFromURL(Astro.url.pathname);
const articles: MDXInstance<ArticleType>[] = [];
for (const key of Object.keys(modules)) {
const langs = Object.keys(modules[key]);
for (const articleLang of langs) {
const isNonDefaultLanguage = !langs.includes(siteLang) && langs.length === 1;
const article = modules[key];
if (articleLang === siteLang) {
articles.push(article[siteLang]);
article[siteLang].frontmatter.lang = siteLang;
}
if (isNonDefaultLanguage) {
articles.push(article[articleLang]);
article[articleLang].frontmatter.lang = articleLang;
}
}
}
return articles;
}
}
export default new ArticleService();

1
src/services/index.ts Normal file
View File

@ -0,0 +1 @@
export { default as ArticleService } from "./ArticleService";

View File

@ -128,8 +128,3 @@ a {
color: var(--color-blue-400);
}
}
button {
background: none;
border: none;
}

View File

@ -4,10 +4,11 @@ import PageHeading from "@components/PageHeading";
import ArticlesList from "@components/ArticlesList";
import { transformArticles, formatToArticleBlocks } from "@utils/articles";
import { getLanguageFromURL } from "@root/utils";
import { useTranslation, getTranslatedArticles } from "@i18n/utils";
import { useTranslation } from "@i18n/utils";
import { ArticleService } from "@services/index";
const t = useTranslation(Astro);
const data = getTranslatedArticles(Astro);
const data = ArticleService.getTranslatedArticles(Astro);
const tags = new Set(data.map((article) => article.frontmatter.tags).flat());
const lang = getLanguageFromURL(Astro.url.pathname);
const articles = transformArticles(data);

View File

@ -13,19 +13,7 @@ const lang = getLanguageFromURL(Astro.url.pathname);
<PageLayout noIndex lang={lang} title={t("pageTitle.contacts")} description={t("pageDescription.contacts")}>
<PageHeading heading={t("pageTitle.contacts")} description={t("pageDescription.contacts")} />
<section>
<ContactForm
i18n={{
"input.nameField": t("input.nameField"),
"input.subjectField": t("input.subjectField"),
"input.messageField": t("input.messageField"),
"btn.send": t("btn.send"),
"btn.sending": t("btn.sending"),
"error.invalidEmail": t("error.invalidEmail"),
"form.contactSuccess": t("form.contactSuccess"),
"form.contactError": t("form.contactError"),
}}
client:load
/>
<ContactForm />
<ContactsList />
</section>
</PageLayout>

View File

@ -4,10 +4,11 @@ import PageLayout from "@layouts/default.astro";
import RecentArticles from "@components/RecentArticles";
import { Splash, SplashHeading, SplashLinks, Link } from "@components/Splash";
import { getLanguageFromURL } from "@root/utils";
import { getTranslatedArticles, useTranslation } from "@i18n/utils";
import { useTranslation } from "@i18n/utils";
import { ArticleService } from "@services/index";
import UIString from "@components/UIString";
const data = getTranslatedArticles(Astro);
const data = ArticleService.getTranslatedArticles(Astro);
const t = useTranslation(Astro);
const lang = getLanguageFromURL(Astro.url.pathname);
const articles = utils.transformArticles(data);

View File

@ -19,7 +19,8 @@
"@stores/*": ["./src/stores/*"],
"@hooks/*": ["./src/hooks/*"],
"@i18n/*": ["./src/i18n/*"],
"@images/*": ["./src/images/*"]
"@images/*": ["./src/images/*"],
"@services/*": ["./src/services/*"]
},
"outDir": "./dist",
"typeRoots": ["./node_modules/@types", "./src/types"]