upd
This commit is contained in:
79
bun/index.ts
79
bun/index.ts
@@ -126,23 +126,60 @@ const server = Bun.serve({
|
||||
return Response.json(data[0]);
|
||||
},
|
||||
"/api/posts/:slug": async req => {
|
||||
const res = await connection.run(`
|
||||
SELECT
|
||||
*
|
||||
FROM wp_posts
|
||||
WHERE post_name = $slug
|
||||
AND post_status = 'publish'
|
||||
AND post_type IN ('post', 'page')
|
||||
LIMIT 1;
|
||||
`, { slug: req.params.slug.toString() });
|
||||
// First query: Get the post
|
||||
const postRes = await connection.run(`
|
||||
SELECT
|
||||
*
|
||||
FROM wp_posts
|
||||
WHERE post_name = $slug
|
||||
AND post_status = 'publish'
|
||||
AND post_type IN ('post', 'page')
|
||||
LIMIT 1;
|
||||
`, { slug: req.params.slug.toString() });
|
||||
|
||||
const data = await res.getRowObjectsJson()
|
||||
const postData = await postRes.getRowObjectsJson();
|
||||
|
||||
if (data.length === 0) {
|
||||
if (postData.length === 0) {
|
||||
return Response.json(null, { status: 404 });
|
||||
}
|
||||
|
||||
return Response.json(data[0], { status: 200 });
|
||||
const post = postData[0];
|
||||
|
||||
if (post && post.ID) {
|
||||
// Second query: Get all postmeta for this post
|
||||
const metaRes = await connection.run(`
|
||||
SELECT
|
||||
meta_id,
|
||||
meta_key,
|
||||
meta_value
|
||||
FROM wp_postmeta
|
||||
WHERE post_id = $postId;
|
||||
`, { postId: post.ID.toString() });
|
||||
|
||||
const metaData = await metaRes.getRowObjectsJson();
|
||||
|
||||
// Process thumbnail synchronously
|
||||
for (const meta of metaData) {
|
||||
if (meta?.meta_key === '_thumbnail_id' && meta.meta_value) {
|
||||
const thumbRes = await connection.run(`
|
||||
SELECT
|
||||
*
|
||||
FROM wp_posts
|
||||
WHERE ID = $post_id AND post_type = 'attachment';
|
||||
`, { post_id: meta.meta_value.toString() });
|
||||
|
||||
const thumbData = await thumbRes.getRowObjectsJson();
|
||||
post.thumbnail = thumbData[0];
|
||||
break; // Once we find the thumbnail, we can stop looking
|
||||
}
|
||||
}
|
||||
|
||||
// Add the meta data to the post object as an array
|
||||
post.wp_postmeta = metaData;
|
||||
}
|
||||
|
||||
|
||||
return Response.json(post, { status: 200 });
|
||||
},
|
||||
"/api/pages/:slug": async req => {
|
||||
const res = await connection.run(`
|
||||
@@ -180,15 +217,15 @@ const server = Bun.serve({
|
||||
},
|
||||
"/api/home": async req => {
|
||||
const res = await connection.run(`
|
||||
SELECT p.*
|
||||
FROM wp_posts p
|
||||
WHERE p.ID = (
|
||||
SELECT option_value
|
||||
FROM wp_options
|
||||
WHERE option_name = 'page_on_front'
|
||||
LIMIT 1
|
||||
)
|
||||
LIMIT 1;`);
|
||||
SELECT p.*
|
||||
FROM wp_posts p
|
||||
WHERE p.ID = (
|
||||
SELECT option_value
|
||||
FROM wp_options
|
||||
WHERE option_name = 'page_on_front'
|
||||
LIMIT 1
|
||||
)
|
||||
LIMIT 1;`);
|
||||
|
||||
const data = await res.getRowObjectsJson()
|
||||
|
||||
|
||||
@@ -2,6 +2,13 @@ import type { NextConfig } from "next";
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
/* config options here */
|
||||
serverExternalPackages: [
|
||||
"@duckdb/node-api",
|
||||
"duckdb",
|
||||
"duckdb-async",
|
||||
// "@duckdb/node-bindings-darwin-arm64", // Include platform-specific bindings
|
||||
// "@duckdb/node-bindings-linux-x64" // Include platform-specific bindings
|
||||
],
|
||||
reactCompiler: true,
|
||||
reactStrictMode: true,
|
||||
};
|
||||
|
||||
672
package-lock.json
generated
672
package-lock.json
generated
@@ -25,20 +25,27 @@
|
||||
"@tiptap/pm": "^3.19.0",
|
||||
"@tiptap/react": "^3.19.0",
|
||||
"@tiptap/starter-kit": "^3.19.0",
|
||||
"@types/dompurify": "^3.0.5",
|
||||
"@wordpress/block-serialization-default-parser": "^5.39.0",
|
||||
"axios": "^1.13.2",
|
||||
"clsx": "^2.1.1",
|
||||
"daisyui": "^5.5.14",
|
||||
"dompurify": "^3.3.1",
|
||||
"embla-carousel-auto-scroll": "^8.6.0",
|
||||
"embla-carousel-autoplay": "^8.6.0",
|
||||
"embla-carousel-react": "^8.6.0",
|
||||
"html-react-parser": "^5.2.17",
|
||||
"interweave": "^13.1.1",
|
||||
"jsdom": "^28.1.0",
|
||||
"next": "16.1.3",
|
||||
"next-themes": "^0.4.6",
|
||||
"node-html-parser": "^7.1.0",
|
||||
"react": "19.2.3",
|
||||
"react-dom": "19.2.3",
|
||||
"react-hook-form": "^7.71.2",
|
||||
"react-resizable-panels": "^4.6.4",
|
||||
"sass": "^1.97.3"
|
||||
"sass": "^1.97.3",
|
||||
"tailwind-merge": "^3.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/postcss": "^4",
|
||||
@@ -57,6 +64,12 @@
|
||||
"@duckdb/node-api": "^1.4.3-r.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@acemir/cssom": {
|
||||
"version": "0.9.31",
|
||||
"resolved": "https://registry.npmjs.org/@acemir/cssom/-/cssom-0.9.31.tgz",
|
||||
"integrity": "sha512-ZnR3GSaH+/vJ0YlHau21FjfLYjMpYVIzTD8M8vIEQvIGxeOXyXdzCI140rrCY862p/C/BbzWsjc1dgnM9mkoTA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@alloc/quick-lru": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
|
||||
@@ -70,6 +83,59 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@asamuzakjp/css-color": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-5.0.1.tgz",
|
||||
"integrity": "sha512-2SZFvqMyvboVV1d15lMf7XiI3m7SDqXUuKaTymJYLN6dSGadqp+fVojqJlVoMlbZnlTmu3S0TLwLTJpvBMO1Aw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@csstools/css-calc": "^3.1.1",
|
||||
"@csstools/css-color-parser": "^4.0.2",
|
||||
"@csstools/css-parser-algorithms": "^4.0.0",
|
||||
"@csstools/css-tokenizer": "^4.0.0",
|
||||
"lru-cache": "^11.2.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@asamuzakjp/css-color/node_modules/lru-cache": {
|
||||
"version": "11.2.6",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz",
|
||||
"integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/@asamuzakjp/dom-selector": {
|
||||
"version": "6.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-6.8.1.tgz",
|
||||
"integrity": "sha512-MvRz1nCqW0fsy8Qz4dnLIvhOlMzqDVBabZx6lH+YywFDdjXhMY37SmpV1XFX3JzG5GWHn63j6HX6QPr3lZXHvQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@asamuzakjp/nwsapi": "^2.3.9",
|
||||
"bidi-js": "^1.0.3",
|
||||
"css-tree": "^3.1.0",
|
||||
"is-potential-custom-element-name": "^1.0.1",
|
||||
"lru-cache": "^11.2.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@asamuzakjp/dom-selector/node_modules/lru-cache": {
|
||||
"version": "11.2.6",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz",
|
||||
"integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/@asamuzakjp/nwsapi": {
|
||||
"version": "2.3.9",
|
||||
"resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz",
|
||||
"integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
"version": "7.28.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz",
|
||||
@@ -310,6 +376,144 @@
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@bramus/specificity": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@bramus/specificity/-/specificity-2.4.2.tgz",
|
||||
"integrity": "sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"css-tree": "^3.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"specificity": "bin/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/@csstools/color-helpers": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.0.2.tgz",
|
||||
"integrity": "sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/csstools"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/csstools"
|
||||
}
|
||||
],
|
||||
"license": "MIT-0",
|
||||
"engines": {
|
||||
"node": ">=20.19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@csstools/css-calc": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.1.1.tgz",
|
||||
"integrity": "sha512-HJ26Z/vmsZQqs/o3a6bgKslXGFAungXGbinULZO3eMsOyNJHeBBZfup5FiZInOghgoM4Hwnmw+OgbJCNg1wwUQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/csstools"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/csstools"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20.19.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@csstools/css-parser-algorithms": "^4.0.0",
|
||||
"@csstools/css-tokenizer": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@csstools/css-color-parser": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.0.2.tgz",
|
||||
"integrity": "sha512-0GEfbBLmTFf0dJlpsNU7zwxRIH0/BGEMuXLTCvFYxuL1tNhqzTbtnFICyJLTNK4a+RechKP75e7w42ClXSnJQw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/csstools"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/csstools"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@csstools/color-helpers": "^6.0.2",
|
||||
"@csstools/css-calc": "^3.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.19.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@csstools/css-parser-algorithms": "^4.0.0",
|
||||
"@csstools/css-tokenizer": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@csstools/css-parser-algorithms": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz",
|
||||
"integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/csstools"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/csstools"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20.19.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@csstools/css-tokenizer": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@csstools/css-syntax-patches-for-csstree": {
|
||||
"version": "1.0.29",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.0.29.tgz",
|
||||
"integrity": "sha512-jx9GjkkP5YHuTmko2eWAvpPnb0mB4mGRr2U7XwVNwevm8nlpobZEVk+GNmiYMk2VuA75v+plfXWyroWKmICZXg==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/csstools"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/csstools"
|
||||
}
|
||||
],
|
||||
"license": "MIT-0"
|
||||
},
|
||||
"node_modules/@csstools/css-tokenizer": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz",
|
||||
"integrity": "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/csstools"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/csstools"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20.19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dnd-kit/abstract": {
|
||||
"version": "0.1.21",
|
||||
"resolved": "https://registry.npmjs.org/@dnd-kit/abstract/-/abstract-0.1.21.tgz",
|
||||
@@ -641,6 +845,23 @@
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@exodus/bytes": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.14.1.tgz",
|
||||
"integrity": "sha512-OhkBFWI6GcRMUroChZiopRiSp2iAMvEBK47NhJooDqz1RERO4QuZIZnjP63TXX8GAiLABkYmX+fuQsdJ1dd2QQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@noble/hashes": "^1.8.0 || ^2.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@noble/hashes": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/core": {
|
||||
"version": "1.7.4",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.4.tgz",
|
||||
@@ -3221,6 +3442,15 @@
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/dompurify": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-3.0.5.tgz",
|
||||
"integrity": "sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/trusted-types": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
||||
@@ -3301,6 +3531,12 @@
|
||||
"@types/react": "^19.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/trusted-types": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
|
||||
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/unist": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
|
||||
@@ -3900,6 +4136,15 @@
|
||||
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/agent-base": {
|
||||
"version": "7.1.4",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
|
||||
"integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/ajv": {
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
@@ -4217,6 +4462,21 @@
|
||||
"baseline-browser-mapping": "dist/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/bidi-js": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz",
|
||||
"integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"require-from-string": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/boolbase": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
||||
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||
@@ -4392,6 +4652,15 @@
|
||||
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/clsx": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
||||
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
@@ -4459,6 +4728,47 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/css-select": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz",
|
||||
"integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"boolbase": "^1.0.0",
|
||||
"css-what": "^6.1.0",
|
||||
"domhandler": "^5.0.2",
|
||||
"domutils": "^3.0.1",
|
||||
"nth-check": "^2.0.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
},
|
||||
"node_modules/css-tree": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz",
|
||||
"integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mdn-data": "2.12.2",
|
||||
"source-map-js": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/css-what": {
|
||||
"version": "6.2.2",
|
||||
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz",
|
||||
"integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==",
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
},
|
||||
"node_modules/cssesc": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
|
||||
@@ -4472,6 +4782,30 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/cssstyle": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-6.2.0.tgz",
|
||||
"integrity": "sha512-Fm5NvhYathRnXNVndkUsCCuR63DCLVVwGOOwQw782coXFi5HhkXdu289l59HlXZBawsyNccXfWRYvLzcDCdDig==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@asamuzakjp/css-color": "^5.0.1",
|
||||
"@csstools/css-syntax-patches-for-csstree": "^1.0.28",
|
||||
"css-tree": "^3.1.0",
|
||||
"lru-cache": "^11.2.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/cssstyle/node_modules/lru-cache": {
|
||||
"version": "11.2.6",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz",
|
||||
"integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/csstype": {
|
||||
"version": "3.2.3",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
|
||||
@@ -4494,6 +4828,28 @@
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause"
|
||||
},
|
||||
"node_modules/data-urls": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-7.0.0.tgz",
|
||||
"integrity": "sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"whatwg-mimetype": "^5.0.0",
|
||||
"whatwg-url": "^16.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/data-urls/node_modules/whatwg-mimetype": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz",
|
||||
"integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/data-view-buffer": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
|
||||
@@ -4552,7 +4908,6 @@
|
||||
"version": "4.4.3",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "^2.1.3"
|
||||
@@ -4566,6 +4921,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/decimal.js": {
|
||||
"version": "10.6.0",
|
||||
"resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz",
|
||||
"integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/deep-diff": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-1.0.2.tgz",
|
||||
@@ -4731,6 +5092,15 @@
|
||||
"url": "https://github.com/fb55/domhandler?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/dompurify": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.1.tgz",
|
||||
"integrity": "sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==",
|
||||
"license": "(MPL-2.0 OR Apache-2.0)",
|
||||
"optionalDependencies": {
|
||||
"@types/trusted-types": "^2.0.7"
|
||||
}
|
||||
},
|
||||
"node_modules/domutils": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
|
||||
@@ -5972,6 +6342,15 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/he": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
|
||||
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"he": "bin/he"
|
||||
}
|
||||
},
|
||||
"node_modules/hermes-estree": {
|
||||
"version": "0.25.1",
|
||||
"resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz",
|
||||
@@ -6015,6 +6394,18 @@
|
||||
"htmlparser2": "10.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/html-encoding-sniffer": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz",
|
||||
"integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@exodus/bytes": "^1.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/html-react-parser": {
|
||||
"version": "5.2.17",
|
||||
"resolved": "https://registry.npmjs.org/html-react-parser/-/html-react-parser-5.2.17.tgz",
|
||||
@@ -6077,6 +6468,32 @@
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/http-proxy-agent": {
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
|
||||
"integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"agent-base": "^7.1.0",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/https-proxy-agent": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
|
||||
"integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"agent-base": "^7.1.2",
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/ignore": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
||||
@@ -6446,6 +6863,12 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/is-potential-custom-element-name": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
|
||||
"integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/is-regex": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
|
||||
@@ -6653,6 +7076,67 @@
|
||||
"js-yaml": "bin/js-yaml.js"
|
||||
}
|
||||
},
|
||||
"node_modules/jsdom": {
|
||||
"version": "28.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-28.1.0.tgz",
|
||||
"integrity": "sha512-0+MoQNYyr2rBHqO1xilltfDjV9G7ymYGlAUazgcDLQaUf8JDHbuGwsxN6U9qWaElZ4w1B2r7yEGIL3GdeW3Rug==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@acemir/cssom": "^0.9.31",
|
||||
"@asamuzakjp/dom-selector": "^6.8.1",
|
||||
"@bramus/specificity": "^2.4.2",
|
||||
"@exodus/bytes": "^1.11.0",
|
||||
"cssstyle": "^6.0.1",
|
||||
"data-urls": "^7.0.0",
|
||||
"decimal.js": "^10.6.0",
|
||||
"html-encoding-sniffer": "^6.0.0",
|
||||
"http-proxy-agent": "^7.0.2",
|
||||
"https-proxy-agent": "^7.0.6",
|
||||
"is-potential-custom-element-name": "^1.0.1",
|
||||
"parse5": "^8.0.0",
|
||||
"saxes": "^6.0.0",
|
||||
"symbol-tree": "^3.2.4",
|
||||
"tough-cookie": "^6.0.0",
|
||||
"undici": "^7.21.0",
|
||||
"w3c-xmlserializer": "^5.0.0",
|
||||
"webidl-conversions": "^8.0.1",
|
||||
"whatwg-mimetype": "^5.0.0",
|
||||
"whatwg-url": "^16.0.0",
|
||||
"xml-name-validator": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"canvas": "^3.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"canvas": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/jsdom/node_modules/parse5": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz",
|
||||
"integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"entities": "^6.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/inikulin/parse5?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/jsdom/node_modules/whatwg-mimetype": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz",
|
||||
"integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/jsesc": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
|
||||
@@ -7146,6 +7630,12 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/mdn-data": {
|
||||
"version": "2.12.2",
|
||||
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz",
|
||||
"integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==",
|
||||
"license": "CC0-1.0"
|
||||
},
|
||||
"node_modules/mdurl": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
|
||||
@@ -7224,7 +7714,6 @@
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
@@ -7366,6 +7855,16 @@
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/node-html-parser": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-7.1.0.tgz",
|
||||
"integrity": "sha512-iJo8b2uYGT40Y8BTyy5ufL6IVbN8rbm/1QK2xffXU/1a/v3AAa0d1YAoqBNYqaS4R/HajkWIpIfdE6KcyFh1AQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"css-select": "^5.1.0",
|
||||
"he": "1.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/node-releases": {
|
||||
"version": "2.0.27",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz",
|
||||
@@ -7373,6 +7872,18 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/nth-check": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
|
||||
"integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"boolbase": "^1.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/nth-check?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
@@ -7932,7 +8443,6 @@
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
@@ -7989,6 +8499,22 @@
|
||||
"react": "^19.2.3"
|
||||
}
|
||||
},
|
||||
"node_modules/react-hook-form": {
|
||||
"version": "7.71.2",
|
||||
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.71.2.tgz",
|
||||
"integrity": "sha512-1CHvcDYzuRUNOflt4MOq3ZM46AronNJtQ1S7tnX6YN4y72qhgiUItpacZUAQ0TyWYci3yz1X+rXaSxiuEm86PA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/react-hook-form"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17 || ^18 || ^19"
|
||||
}
|
||||
},
|
||||
"node_modules/react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
@@ -8138,6 +8664,15 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/require-from-string": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
|
||||
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve": {
|
||||
"version": "1.22.11",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
|
||||
@@ -8295,6 +8830,18 @@
|
||||
"@parcel/watcher": "^2.4.1"
|
||||
}
|
||||
},
|
||||
"node_modules/saxes": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz",
|
||||
"integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"xmlchars": "^2.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=v12.22.7"
|
||||
}
|
||||
},
|
||||
"node_modules/scheduler": {
|
||||
"version": "0.27.0",
|
||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
|
||||
@@ -8760,6 +9307,22 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/symbol-tree": {
|
||||
"version": "3.2.4",
|
||||
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
|
||||
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tailwind-merge": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.5.0.tgz",
|
||||
"integrity": "sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/dcastil"
|
||||
}
|
||||
},
|
||||
"node_modules/tailwindcss": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz",
|
||||
@@ -8829,6 +9392,24 @@
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/tldts": {
|
||||
"version": "7.0.24",
|
||||
"resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.24.tgz",
|
||||
"integrity": "sha512-1r6vQTTt1rUiJkI5vX7KG8PR342Ru/5Oh13kEQP2SMbRSZpOey9SrBe27IDxkoWulx8ShWu4K6C0BkctP8Z1bQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tldts-core": "^7.0.24"
|
||||
},
|
||||
"bin": {
|
||||
"tldts": "bin/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/tldts-core": {
|
||||
"version": "7.0.24",
|
||||
"resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.24.tgz",
|
||||
"integrity": "sha512-pj7yygNMoMRqG7ML2SDQ0xNIOfN3IBDUcPVM2Sg6hP96oFNN2nqnzHreT3z9xLq85IWJyNTvD38O002DdOrPMw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
@@ -8842,6 +9423,30 @@
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tough-cookie": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.0.tgz",
|
||||
"integrity": "sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"tldts": "^7.0.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/tr46": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz",
|
||||
"integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"punycode": "^2.3.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-api-utils": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz",
|
||||
@@ -9041,6 +9646,15 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "7.22.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-7.22.0.tgz",
|
||||
"integrity": "sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20.18.1"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
||||
@@ -9213,6 +9827,27 @@
|
||||
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/w3c-xmlserializer": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz",
|
||||
"integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"xml-name-validator": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/webidl-conversions": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz",
|
||||
"integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==",
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/whatwg-mimetype": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz",
|
||||
@@ -9222,6 +9857,20 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/whatwg-url": {
|
||||
"version": "16.0.1",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-16.0.1.tgz",
|
||||
"integrity": "sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@exodus/bytes": "^1.11.0",
|
||||
"tr46": "^6.0.0",
|
||||
"webidl-conversions": "^8.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
@@ -9358,6 +10007,21 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/xml-name-validator": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz",
|
||||
"integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/xmlchars": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
|
||||
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/yallist": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
||||
|
||||
@@ -26,20 +26,27 @@
|
||||
"@tiptap/pm": "^3.19.0",
|
||||
"@tiptap/react": "^3.19.0",
|
||||
"@tiptap/starter-kit": "^3.19.0",
|
||||
"@types/dompurify": "^3.0.5",
|
||||
"@wordpress/block-serialization-default-parser": "^5.39.0",
|
||||
"axios": "^1.13.2",
|
||||
"clsx": "^2.1.1",
|
||||
"daisyui": "^5.5.14",
|
||||
"dompurify": "^3.3.1",
|
||||
"embla-carousel-auto-scroll": "^8.6.0",
|
||||
"embla-carousel-autoplay": "^8.6.0",
|
||||
"embla-carousel-react": "^8.6.0",
|
||||
"html-react-parser": "^5.2.17",
|
||||
"interweave": "^13.1.1",
|
||||
"jsdom": "^28.1.0",
|
||||
"next": "16.1.3",
|
||||
"next-themes": "^0.4.6",
|
||||
"node-html-parser": "^7.1.0",
|
||||
"react": "19.2.3",
|
||||
"react-dom": "19.2.3",
|
||||
"react-hook-form": "^7.71.2",
|
||||
"react-resizable-panels": "^4.6.4",
|
||||
"sass": "^1.97.3"
|
||||
"sass": "^1.97.3",
|
||||
"tailwind-merge": "^3.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/postcss": "^4",
|
||||
|
||||
@@ -13,8 +13,8 @@ export interface PageProps {
|
||||
|
||||
export default async function PostPage({ params }: PageProps) {
|
||||
const { slug } = await params;
|
||||
const baseUrl =
|
||||
process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000';
|
||||
|
||||
const baseUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000';
|
||||
|
||||
const res = await fetch(`${baseUrl}/api/posts/${slug}`, {
|
||||
next: { revalidate: 60 },
|
||||
|
||||
@@ -1,14 +1,34 @@
|
||||
// app/page.tsx
|
||||
import Flex from '@/components/Blocks/Flex/Flex';
|
||||
import Grid from '@/components/Blocks/Grid/Grid';
|
||||
import IFrame from '@/components/Blocks/IFrame/IFrame';
|
||||
import Section from '@/components/Blocks/Section/Section';
|
||||
import PostCard from '@/components/Post/PostCard';
|
||||
import EmblaCarousel from '@/components/UI/EmblaCarousel/EmblaCarousel';
|
||||
import Stat from '@/components/UI/Stat/Stat';
|
||||
import Areas from '@/components/WP/Areas/Areas';
|
||||
import { SmartSlider } from '@/components/WPRenderer/SmartSlider';
|
||||
import { renderPostContent } from '@/components/WPRenderer/WPRenderer';
|
||||
import { connection } from '@/lib/duckdb';
|
||||
import { transformLinks } from '@/lib/utils';
|
||||
import { CarouselSlide, PostData } from '@/types/entities';
|
||||
|
||||
export const revalidate = 10;
|
||||
|
||||
export default async function HomePage() {
|
||||
const duckRes = await connection.run(`
|
||||
SELECT p.*
|
||||
FROM wp_posts p
|
||||
WHERE p.ID = (
|
||||
SELECT option_value
|
||||
FROM wp_options
|
||||
WHERE option_name = 'page_on_front'
|
||||
LIMIT 1
|
||||
)
|
||||
LIMIT 1;`);
|
||||
|
||||
const duckData = await duckRes.getRowObjectsJson()
|
||||
|
||||
const baseUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000';
|
||||
|
||||
const res = await fetch(`${baseUrl}/api/home`, { next: { revalidate: 10 }, });
|
||||
@@ -18,7 +38,8 @@ export default async function HomePage() {
|
||||
throw new Error('Failed to fetch home posts');
|
||||
}
|
||||
|
||||
const posts: PostData[] = await res.json();
|
||||
//const posts: PostData[] = await res.json();
|
||||
const posts = duckData
|
||||
|
||||
const stats: { title: string, value: string }[] = [
|
||||
{
|
||||
@@ -206,36 +227,67 @@ export default async function HomePage() {
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="w-full flex flex-col items-center sm:gap-8 mb-8">
|
||||
<div className="w-full flex flex-col items-center sm:gap-8">
|
||||
{/* {posts.map(post => (
|
||||
<div key={post.ID} className="max-w-5xl">
|
||||
{renderPostContent(post.post_content)}
|
||||
</div>
|
||||
))} */}
|
||||
|
||||
<EmblaCarousel title_align='left' title_position='top' show_dots={true} show_title={true} slides={slides} />
|
||||
<EmblaCarousel autoplay title_align='left' title_position='top' show_dots={true} show_title={true} slides={slides} />
|
||||
|
||||
<Section title='Новости'>
|
||||
<div className='grid grid-cols-2 space-y-4 space-x-4'>
|
||||
<Grid gap={4} cols_mobile={1} cols_tablet={1} cols_desktop={2} rows_mobile={1} rows_tablet={1} rows_desktop={1}>
|
||||
<EmblaCarousel rounded title_align='left' shape='square' show_title title_position='bottom' autoplay={true} show_dots={true} slides_per_view={1} slides={slides} dots_position='bottom_inside' />
|
||||
</div>
|
||||
|
||||
<Flex justify='between' direction='col' gap={4}>
|
||||
<PostCard
|
||||
thumbnail_src='https://new.jkhsakha.ru/wp-content/uploads/2026/02/1-1-300x179.jpeg'
|
||||
post_href='/#'
|
||||
description='Post card test'
|
||||
title='Работники ЖКХ – обладатели Гран-при военно-патриотического конкурса'
|
||||
show_thumbnail={true}
|
||||
show_categories
|
||||
categories={[
|
||||
{
|
||||
id: 0,
|
||||
slug: 'news',
|
||||
name: 'Новости'
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
slug: 'news',
|
||||
name: 'Новости'
|
||||
}
|
||||
]}
|
||||
date='26.02.2026'
|
||||
show_date
|
||||
/>
|
||||
<PostCard
|
||||
post_href='/#'
|
||||
title='Осторожно! Мошенники рассылают СМС о возврате за отопление'
|
||||
description='asd'
|
||||
/>
|
||||
<PostCard
|
||||
post_href='/#'
|
||||
title='Профсоюз ГУП «ЖКХ РС(Я)» поздравил ветеранов с наступающим Новым годом'
|
||||
|
||||
/>
|
||||
</Flex>
|
||||
</Grid>
|
||||
</Section>
|
||||
|
||||
<Section title='О предприятии'>
|
||||
<div className={`grid grid-cols-1 lg:grid-cols-2 justify-center items-center`}>
|
||||
<div>
|
||||
<Areas />
|
||||
</div>
|
||||
<Grid cols_mobile={1} cols_tablet={1} cols_desktop={2} rows_mobile={1} rows_tablet={1} rows_desktop={1}>
|
||||
<Areas />
|
||||
|
||||
<div className="grid grid-cols-2 space-y-4 space-x-4">
|
||||
|
||||
<Grid cols_desktop={2} cols_mobile={2} cols_tablet={2} gap={4}>
|
||||
{stats.map((stat, index) => (
|
||||
<div key={index} className="grid grid-rows-[min-content_1fr] space-y-2">
|
||||
<div className="stat-value text-3xl sm:text-5xl text-[#0063A7]">{stat.value}</div>
|
||||
<div className="stat-title text-wrap text-lg sm:text-2xl text-neutral">{stat.title}</div>
|
||||
</div>
|
||||
<Stat key={index} value={stat.value} title={stat.title} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Section>
|
||||
|
||||
<Section title='Филиалы'>
|
||||
@@ -245,6 +297,12 @@ export default async function HomePage() {
|
||||
<Section title="Контакты">
|
||||
|
||||
</Section>
|
||||
|
||||
<IFrame iframe={`<iframe loading="lazy"
|
||||
src="https://maps.google.com/maps?q=%D0%B3.%20%D0%AF%D0%BA%D1%83%D1%82%D1%81%D0%BA%2C%20%D1%83%D0%BB.%20%D0%9A%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%2C%20%D0%B4.18%2C%20%D0%B1%D0%BB%D0%BE%D0%BA%20%22%D0%90%22&t=m&z=16&output=embed&iwloc=near"
|
||||
title="г. Якутск, ул. Кирова, д.18, блок "А""
|
||||
aria-label="г. Якутск, ул. Кирова, д.18, блок "А""
|
||||
></iframe>`} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import { PageProps } from "@/app/(client)/[slug]/page";
|
||||
import PostPage from "@/app/(client)/[slug]/page";
|
||||
import ClientLayout from "@/app/(client)/layout";
|
||||
import Post from "@/components/Post/Post";
|
||||
import Tiptap from "@/components/Tiptap/Tiptap";
|
||||
|
||||
export default async function EditorPage({ params }: PageProps) {
|
||||
|
||||
@@ -5,7 +5,7 @@ export const montserratFont = Montserrat({
|
||||
subsets: ['latin', 'cyrillic'],
|
||||
})
|
||||
|
||||
const mainFont = Roboto({
|
||||
export const mainFont = Roboto({
|
||||
subsets: ['latin', 'cyrillic'],
|
||||
})
|
||||
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import type { Data } from "@puckeditor/core";
|
||||
import { Render } from "@puckeditor/core";
|
||||
import puckConfig from "../../../puck.config";
|
||||
|
||||
export function Client({ data }: { data: Data }) {
|
||||
return <Render config={puckConfig} data={data} />
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/**
|
||||
* This file implements a catch-all route that renders the user-facing pages
|
||||
* generated by Puck. For any route visited (with exception of other hardcoded
|
||||
* pages in /app), it will check your database (via `getPage`) for a Puck page
|
||||
* and render it using <Render>.
|
||||
*
|
||||
* All routes produced by this page are statically rendered using incremental
|
||||
* static site generation. After the first visit, the page will be cached as
|
||||
* a static file. Subsequent visits will receive the cache. Publishing a page
|
||||
* will invalidate the cache as the page is written in /api/puck/route.ts
|
||||
*/
|
||||
|
||||
import { Client } from "./client";
|
||||
import { notFound } from "next/navigation";
|
||||
import { Metadata } from "next";
|
||||
import { getPage } from "@/lib/get-page";
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ puckPath: string[] }>;
|
||||
}): Promise<Metadata> {
|
||||
const { puckPath = [] } = await params;
|
||||
const path = `/${puckPath.join("/")}`;
|
||||
|
||||
const data = getPage(path)
|
||||
return {
|
||||
title: data?.root.props?.title,
|
||||
};
|
||||
}
|
||||
|
||||
export default async function Page({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ puckPath: string[] }>;
|
||||
}) {
|
||||
const { puckPath = [] } = await params;
|
||||
const path = `/${puckPath.join("/")}`;
|
||||
const data = await getPage(path);
|
||||
|
||||
if (!data) {
|
||||
return notFound();
|
||||
}
|
||||
|
||||
return <Client data={data} />;
|
||||
}
|
||||
|
||||
// Force Next.js to produce static pages: https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamic
|
||||
// Delete this if you need dynamic rendering, such as access to headers or cookies
|
||||
export const dynamic = "force-static";
|
||||
@@ -1,13 +1,15 @@
|
||||
// app/page.tsx
|
||||
|
||||
import Areas from "@/components/WP/Areas/Areas";
|
||||
import GetLK from "@/components/WP/GetLK/GetLK";
|
||||
|
||||
export const revalidate = 10;
|
||||
|
||||
export default async function TestPage() {
|
||||
return (
|
||||
<div className="w-full flex flex-col items-center">
|
||||
<Areas />
|
||||
{/* <Areas /> */}
|
||||
<GetLK />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ export default async function Banner({ title, subtitle, backgroundImage, logoIma
|
||||
<section className="relative w-full">
|
||||
<div className="hero bg-base-200 min-h-8 h-min overflow-hidden" >
|
||||
<div className="absolute inset-0 overflow-hidden">
|
||||
<div className="w-full h-full blur-xs scale-[1.1]" style={{
|
||||
<div className="w-full h-full " style={{
|
||||
backgroundImage: `url(${backgroundImage})`
|
||||
}}></div>
|
||||
</div>
|
||||
|
||||
15
src/components/Blocks/Featured/Featured.tsx
Normal file
15
src/components/Blocks/Featured/Featured.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import React from 'react'
|
||||
|
||||
interface FeaturedProps {
|
||||
|
||||
}
|
||||
|
||||
const Featured = () => {
|
||||
return (
|
||||
<div>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Featured
|
||||
41
src/components/Blocks/Flex/Flex.tsx
Normal file
41
src/components/Blocks/Flex/Flex.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import { cn } from '@/utils/tailwind'
|
||||
import { PropsWithChildren } from 'react'
|
||||
|
||||
type Justify = 'center' | 'between' | 'around' | 'start' | 'end' | 'evenly' | 'stretch'
|
||||
type Align = 'center' | 'end' | 'start' | 'stretch'
|
||||
type FlexGap = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
|
||||
type FlexDirection = 'col' | 'row'
|
||||
|
||||
export interface FlexProps extends PropsWithChildren {
|
||||
justify?: Justify
|
||||
align?: Align
|
||||
gap?: FlexGap
|
||||
direction?: FlexDirection
|
||||
className?: string
|
||||
}
|
||||
|
||||
const Flex = ({
|
||||
children,
|
||||
justify = 'start',
|
||||
align = 'start',
|
||||
gap = 2,
|
||||
direction = 'row',
|
||||
className
|
||||
}: FlexProps) => {
|
||||
const flexClassName = cn(
|
||||
'flex',
|
||||
direction && `flex-${direction}`,
|
||||
justify && `justify-${justify}`,
|
||||
align && `items-${align}`,
|
||||
gap !== undefined && `gap-${gap}`,
|
||||
className
|
||||
)
|
||||
|
||||
return (
|
||||
<div className={flexClassName}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Flex
|
||||
54
src/components/Blocks/Grid/Grid.tsx
Normal file
54
src/components/Blocks/Grid/Grid.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import { PropsWithChildren } from 'react'
|
||||
import { cn } from '@/utils/tailwind'
|
||||
|
||||
type GridRows = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
|
||||
type GridCols = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
|
||||
type GridGap = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
|
||||
|
||||
export interface GridProps extends PropsWithChildren {
|
||||
rows_tablet?: GridRows
|
||||
rows_mobile?: GridRows
|
||||
rows_desktop?: GridRows
|
||||
cols_mobile?: GridCols
|
||||
cols_tablet?: GridCols
|
||||
cols_desktop?: GridCols
|
||||
gap?: GridGap
|
||||
className?: string
|
||||
}
|
||||
|
||||
const Grid = ({
|
||||
children,
|
||||
gap = 4,
|
||||
rows_mobile = 1,
|
||||
rows_tablet = 1,
|
||||
rows_desktop = 1,
|
||||
cols_mobile = 1,
|
||||
cols_tablet = 1,
|
||||
cols_desktop = 1,
|
||||
className
|
||||
}: GridProps) => {
|
||||
const gridClassName = cn(
|
||||
'grid',
|
||||
// Cols
|
||||
cols_mobile && `grid-cols-${cols_mobile}`,
|
||||
cols_tablet && `md:grid-cols-${cols_tablet}`,
|
||||
cols_desktop && `lg:grid-cols-${cols_desktop}`,
|
||||
// Rows
|
||||
rows_mobile && `grid-rows-${rows_mobile}`,
|
||||
rows_tablet && `md:grid-rows-${rows_tablet}`,
|
||||
rows_desktop && `lg:grid-rows-${rows_desktop}`,
|
||||
// Gap
|
||||
gap !== undefined && `gap-${gap}`,
|
||||
// Custom classes
|
||||
className
|
||||
)
|
||||
|
||||
|
||||
return (
|
||||
<div className={gridClassName}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Grid
|
||||
26
src/components/Blocks/IFrame/IFrame.tsx
Normal file
26
src/components/Blocks/IFrame/IFrame.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import React from 'react'
|
||||
|
||||
export interface IFrameProps {
|
||||
iframe: string
|
||||
}
|
||||
|
||||
const IFrame = ({
|
||||
iframe
|
||||
}: IFrameProps) => {
|
||||
return (
|
||||
<>
|
||||
<style>
|
||||
{`
|
||||
iframe {
|
||||
width: 100%;
|
||||
min-height: 24rem;
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
<div className='w-full rounded-sm' dangerouslySetInnerHTML={{ __html: iframe }} />
|
||||
</>
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
export default IFrame
|
||||
@@ -1,7 +1,7 @@
|
||||
import { montserratFont } from '@/app/layout'
|
||||
import React, { PropsWithChildren } from 'react'
|
||||
|
||||
interface SectionProps extends PropsWithChildren {
|
||||
export interface SectionProps extends PropsWithChildren {
|
||||
title?: string
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,60 @@
|
||||
import { renderPostContent } from '../WPRenderer/WPRenderer'
|
||||
import { renderElementorContent, renderPostContent } from '../WPRenderer/WPRenderer'
|
||||
import { PostData } from '@/types/entities'
|
||||
|
||||
const Post = ({ post }: { post: PostData }) => {
|
||||
const getHtml = (el: {
|
||||
id: string
|
||||
elType: string
|
||||
elements: any[]
|
||||
settings: any
|
||||
}) => {
|
||||
let htmlString = ''
|
||||
|
||||
if (el.elements.length > 0) {
|
||||
el.elements.map(child => {
|
||||
htmlString = htmlString + getHtml(child)
|
||||
})
|
||||
}
|
||||
|
||||
if (el.settings.html) {
|
||||
htmlString = htmlString + el.settings.html
|
||||
}
|
||||
|
||||
return htmlString
|
||||
}
|
||||
|
||||
const preProcessElementor = () => {
|
||||
let htmlString = ''
|
||||
|
||||
post.wp_postmeta && post.wp_postmeta.map(meta => {
|
||||
if (meta.meta_key === '_elementor_data') {
|
||||
const elements = JSON.parse(meta.meta_value)
|
||||
if (Array.isArray(elements)) {
|
||||
elements.map((el: {
|
||||
id: string
|
||||
elType: string
|
||||
elements: any[]
|
||||
settings: any
|
||||
}) => {
|
||||
htmlString = htmlString + getHtml(el)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return htmlString
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="container mx-auto py-8 max-w-5xl">
|
||||
<div className="container mx-auto py-8 max-w-5xl px-2 sm:px-0">
|
||||
<article className="prose lg:prose-xl max-w-none">
|
||||
{
|
||||
post.thumbnail &&
|
||||
<div>
|
||||
<img className='' src={post.thumbnail.guid} />
|
||||
</div>
|
||||
}
|
||||
|
||||
<h1>{post.post_title}</h1>
|
||||
|
||||
{post.post_type === 'post' && (
|
||||
@@ -15,6 +65,7 @@ const Post = ({ post }: { post: PostData }) => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{post.wp_postmeta && post.wp_postmeta.find(meta => meta.meta_key === '_elementor_data') && renderElementorContent(preProcessElementor())}
|
||||
{renderPostContent(post.post_content)}
|
||||
</article>
|
||||
</div>
|
||||
|
||||
74
src/components/Post/PostCard.tsx
Normal file
74
src/components/Post/PostCard.tsx
Normal file
@@ -0,0 +1,74 @@
|
||||
import { mainFont } from '@/app/layout'
|
||||
import { PostCategory } from '@/types/entities'
|
||||
|
||||
interface PostCardProps {
|
||||
thumbnail_src?: string
|
||||
show_thumbnail?: boolean
|
||||
title: string
|
||||
show_description?: boolean
|
||||
description?: string
|
||||
post_href: string
|
||||
date?: string
|
||||
show_date?: boolean
|
||||
categories?: PostCategory[]
|
||||
show_categories?: boolean
|
||||
}
|
||||
|
||||
const PostCard = ({
|
||||
title,
|
||||
show_description = false,
|
||||
description,
|
||||
show_thumbnail = false,
|
||||
thumbnail_src,
|
||||
post_href,
|
||||
date,
|
||||
show_date = false,
|
||||
categories,
|
||||
show_categories = false
|
||||
}: PostCardProps) => {
|
||||
return (
|
||||
<div className={`${mainFont.className} text-[#0063A7] card sm:card-side bg-base-100 h-1/1 w-full shadow-sm`}>
|
||||
{show_thumbnail && thumbnail_src &&
|
||||
<figure className='sm:h-full sm:w-full'>
|
||||
<a href={post_href} className='w-full h-full'>
|
||||
<img
|
||||
className='object-cover w-full h-full'
|
||||
src={thumbnail_src}
|
||||
alt="Shoes" />
|
||||
</a>
|
||||
|
||||
</figure>
|
||||
}
|
||||
|
||||
<div className="card-body">
|
||||
<a href={post_href} className={`card-title`}>
|
||||
{title}
|
||||
</a>
|
||||
{description && show_description &&
|
||||
<p className='font-medium text-base-content'>
|
||||
{description}
|
||||
</p>
|
||||
}
|
||||
<div className="card-actions items-center justify-between">
|
||||
{date && show_date &&
|
||||
<span>{date}</span>
|
||||
}
|
||||
<div className='flex gap-2'>
|
||||
{categories && show_categories &&
|
||||
categories.map((cat, index) => (
|
||||
<a key={`category-${cat.id}`} href={cat.slug} className="badge badge-outline">
|
||||
{cat.name}
|
||||
</a>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
export default PostCard
|
||||
@@ -8,7 +8,7 @@ import { CarouselSlide } from '@/types/entities'
|
||||
import { IconChevronLeft, IconChevronRight } from '@tabler/icons-react'
|
||||
import { montserratFont } from '@/app/layout'
|
||||
|
||||
interface EmblaCarouselProps {
|
||||
export interface EmblaCarouselProps {
|
||||
slides: CarouselSlide[]
|
||||
slides_per_view?: number
|
||||
show_dots?: boolean
|
||||
|
||||
20
src/components/UI/Stat/Stat.tsx
Normal file
20
src/components/UI/Stat/Stat.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import React from 'react'
|
||||
|
||||
interface StatProps {
|
||||
title: string
|
||||
value: string
|
||||
}
|
||||
|
||||
const Stat = ({
|
||||
title,
|
||||
value
|
||||
}: StatProps) => {
|
||||
return (
|
||||
<div className="grid grid-rows-[min-content_1fr] space-y-2">
|
||||
<div className="stat-value text-3xl sm:text-5xl text-[#0063A7]">{value}</div>
|
||||
<div className="stat-title text-wrap text-lg sm:text-2xl text-neutral">{title}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Stat
|
||||
@@ -152,8 +152,8 @@ const Areas = () => {
|
||||
const [tooltip, setTooltip] = useState<{ name: string, x: number, y: number } | null>(null)
|
||||
|
||||
return (
|
||||
<div className='relative w-full h-96 flex flex-col justify-center items-center'>
|
||||
<img className='absolute w-full h-auto' src={'/karta-s-logo2.png'} />
|
||||
<div className='relative w-full min-h-64 md:min-h-96 max-h-96 flex flex-col justify-center items-center'>
|
||||
<img className='absolute w-auto h-full' src={'/karta-s-logo2.png'} />
|
||||
|
||||
{tooltip && <span className="rounded-sm text-nowrap absolute p-2 z-20 pointer-events-none bg-black/90 text-white text-sm text-center" style={{
|
||||
left: tooltip?.x,
|
||||
@@ -162,14 +162,14 @@ const Areas = () => {
|
||||
{tooltip?.name}
|
||||
</span>}
|
||||
<svg
|
||||
className='absolute w-full h-auto'
|
||||
className='absolute w-auto h-full'
|
||||
viewBox="15 0 520 520"
|
||||
aria-labelledby="img-title-1161"
|
||||
aria-describedby="img-desc-1161"
|
||||
role="group"
|
||||
>
|
||||
<title id="img-title-1161" />
|
||||
<g role="list" className="relative">
|
||||
<g role="list" className="">
|
||||
{
|
||||
areas.map((area, index) => (
|
||||
<a key={index} target="_blank" href={area.href} className="relative transition-all duration-300 opacity-0 hover:opacity-100 outline-none" tabIndex={0} aria-label={area.name} role="listitem">
|
||||
|
||||
344
src/components/WP/GetLK/GetLK.tsx
Normal file
344
src/components/WP/GetLK/GetLK.tsx
Normal file
@@ -0,0 +1,344 @@
|
||||
"use client"
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useForm } from 'react-hook-form'
|
||||
// curl 'https://api.jkhsakha.ru/lk/address/' \
|
||||
// -H 'Accept: application/json' \
|
||||
// -H 'Accept-Language: ru,en-US;q=0.9,en;q=0.8,de;q=0.7' \
|
||||
// -H 'Authorization: bearer' \
|
||||
// -H 'Connection: keep-alive' \
|
||||
// -H 'Content-Type: application/json' \
|
||||
// -H 'Origin: https://new.jkhsakha.ru' \
|
||||
// -H 'Referer: https://new.jkhsakha.ru/' \
|
||||
// -H 'Sec-Fetch-Dest: empty' \
|
||||
// -H 'Sec-Fetch-Mode: cors' \
|
||||
// -H 'Sec-Fetch-Site: same-site' \
|
||||
// -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36' \
|
||||
// -H 'sec-ch-ua: "Not:A-Brand";v="99", "Google Chrome";v="145", "Chromium";v="145"' \
|
||||
// -H 'sec-ch-ua-mobile: ?0' \
|
||||
// -H 'sec-ch-ua-platform: "macOS"' \
|
||||
// --data - raw '{"IDPersonalAccount":0,"IDRegion":0,"IDCity":0,"IDStreet":0,"IDHouse":0,"IDFlat":0}'
|
||||
|
||||
interface AddressData {
|
||||
IDPersonalAccount: number
|
||||
IDRegion: number
|
||||
IDCity: number
|
||||
IDStreet: number
|
||||
IDHouse: number
|
||||
IDFlat: number
|
||||
}
|
||||
|
||||
interface Region {
|
||||
IDRegion: number
|
||||
NameRegion: string
|
||||
}
|
||||
|
||||
interface City {
|
||||
IDCity: number
|
||||
NameCity: string
|
||||
}
|
||||
|
||||
interface Street {
|
||||
IDStreet: number
|
||||
NameStreet: string
|
||||
}
|
||||
|
||||
interface House {
|
||||
IDHouse: number
|
||||
NameHouse: string
|
||||
}
|
||||
|
||||
interface Flat {
|
||||
IDPersonalAccount: number
|
||||
NameFlat: string
|
||||
}
|
||||
|
||||
const API_BASE_URL = 'https://api.jkhsakha.ru/lk/address/'
|
||||
|
||||
const GetLK = () => {
|
||||
const [regions, setRegions] = useState<Region[]>([])
|
||||
const [cities, setCities] = useState<City[]>([])
|
||||
const [streets, setStreets] = useState<Street[]>([])
|
||||
const [houses, setHouses] = useState<House[]>([])
|
||||
const [flats, setFlats] = useState<Flat[]>([])
|
||||
|
||||
const [selectedAccount, setSelectedAccount] = useState<Flat | null>(null)
|
||||
|
||||
const { register, watch, setValue } = useForm<AddressData>({
|
||||
defaultValues: {
|
||||
IDPersonalAccount: 0,
|
||||
IDRegion: 0,
|
||||
IDCity: 0,
|
||||
IDStreet: 0,
|
||||
IDHouse: 0,
|
||||
IDFlat: 0
|
||||
}
|
||||
})
|
||||
|
||||
const watchRegion = watch('IDRegion')
|
||||
const watchCity = watch('IDCity')
|
||||
const watchStreet = watch('IDStreet')
|
||||
const watchHouse = watch('IDHouse')
|
||||
const watchFlat = watch('IDFlat')
|
||||
|
||||
// Fetch regions on component mount
|
||||
useEffect(() => {
|
||||
const fetchRegions = async () => {
|
||||
try {
|
||||
const response = await fetch(API_BASE_URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'bearer',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
IDPersonalAccount: 0,
|
||||
IDRegion: 0,
|
||||
IDCity: 0,
|
||||
IDStreet: 0,
|
||||
IDHouse: 0,
|
||||
IDFlat: 0
|
||||
})
|
||||
})
|
||||
const data = await response.json()
|
||||
setRegions(data)
|
||||
} catch (error) {
|
||||
console.error('Error fetching regions:', error)
|
||||
}
|
||||
}
|
||||
|
||||
fetchRegions()
|
||||
}, [])
|
||||
|
||||
// Fetch cities when region is selected
|
||||
useEffect(() => {
|
||||
if (watchRegion && watchRegion !== 0) {
|
||||
const fetchCities = async () => {
|
||||
try {
|
||||
const response = await fetch(API_BASE_URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'bearer',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
IDPersonalAccount: 0,
|
||||
IDRegion: watchRegion,
|
||||
IDCity: 0,
|
||||
IDStreet: 0,
|
||||
IDHouse: 0,
|
||||
IDFlat: 0
|
||||
})
|
||||
})
|
||||
const data = await response.json()
|
||||
setCities(data)
|
||||
setValue('IDCity', 0) // Reset city selection
|
||||
setStreets([]) // Clear dependent fields
|
||||
setHouses([])
|
||||
setFlats([])
|
||||
} catch (error) {
|
||||
console.error('Error fetching cities:', error)
|
||||
}
|
||||
}
|
||||
|
||||
fetchCities()
|
||||
}
|
||||
}, [watchRegion, setValue])
|
||||
|
||||
// Fetch streets when city is selected
|
||||
useEffect(() => {
|
||||
if (watchCity && watchCity !== 0) {
|
||||
const fetchStreets = async () => {
|
||||
try {
|
||||
const response = await fetch(API_BASE_URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'bearer',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
IDPersonalAccount: 0,
|
||||
IDRegion: watchRegion,
|
||||
IDCity: watchCity,
|
||||
IDStreet: 0,
|
||||
IDHouse: 0,
|
||||
IDFlat: 0
|
||||
})
|
||||
})
|
||||
const data = await response.json()
|
||||
setStreets(data)
|
||||
setValue('IDStreet', 0) // Reset street selection
|
||||
setHouses([]) // Clear dependent fields
|
||||
setFlats([])
|
||||
} catch (error) {
|
||||
console.error('Error fetching streets:', error)
|
||||
}
|
||||
}
|
||||
|
||||
fetchStreets()
|
||||
}
|
||||
}, [watchCity, watchRegion, setValue])
|
||||
|
||||
// Fetch houses when street is selected
|
||||
useEffect(() => {
|
||||
if (watchStreet && watchStreet !== 0) {
|
||||
const fetchHouses = async () => {
|
||||
try {
|
||||
const response = await fetch(API_BASE_URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'bearer',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
IDPersonalAccount: 0,
|
||||
IDRegion: watchRegion,
|
||||
IDCity: watchCity,
|
||||
IDStreet: watchStreet,
|
||||
IDHouse: 0,
|
||||
IDFlat: 0
|
||||
})
|
||||
})
|
||||
const data = await response.json()
|
||||
setHouses(data)
|
||||
setValue('IDHouse', 0) // Reset house selection
|
||||
setFlats([]) // Clear dependent fields
|
||||
} catch (error) {
|
||||
console.error('Error fetching houses:', error)
|
||||
}
|
||||
}
|
||||
|
||||
fetchHouses()
|
||||
}
|
||||
}, [watchStreet, watchCity, watchRegion, setValue])
|
||||
|
||||
// Fetch flats when house is selected
|
||||
useEffect(() => {
|
||||
if (watchHouse && watchHouse !== 0) {
|
||||
const fetchFlats = async () => {
|
||||
try {
|
||||
const response = await fetch(API_BASE_URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'bearer',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
IDPersonalAccount: 0,
|
||||
IDRegion: watchRegion,
|
||||
IDCity: watchCity,
|
||||
IDStreet: watchStreet,
|
||||
IDHouse: watchHouse,
|
||||
IDFlat: 0
|
||||
})
|
||||
})
|
||||
const data = await response.json()
|
||||
setFlats(data)
|
||||
setValue('IDFlat', 0) // Reset flat selection
|
||||
} catch (error) {
|
||||
console.error('Error fetching flats:', error)
|
||||
}
|
||||
}
|
||||
|
||||
fetchFlats()
|
||||
}
|
||||
}, [watchHouse, watchStreet, watchCity, watchRegion, setValue])
|
||||
|
||||
// Update selected account when flat is chosen
|
||||
useEffect(() => {
|
||||
if (watchFlat && watchFlat !== 0) {
|
||||
const selectedFlat = flats.find(flat => flat.IDPersonalAccount === watchFlat)
|
||||
if (selectedFlat) {
|
||||
setSelectedAccount(selectedFlat)
|
||||
}
|
||||
}
|
||||
}, [watchFlat, flats])
|
||||
|
||||
const form = [
|
||||
{
|
||||
label: 'Выберите район / улус',
|
||||
value: 'IDRegion',
|
||||
options: regions,
|
||||
valueKey: 'IDRegion',
|
||||
labelKey: 'NameRegion'
|
||||
},
|
||||
{
|
||||
label: 'Выберите нас.пункт',
|
||||
value: 'IDCity',
|
||||
options: cities,
|
||||
valueKey: 'IDCity',
|
||||
labelKey: 'NameCity',
|
||||
disabled: !watchRegion || watchRegion === 0
|
||||
},
|
||||
{
|
||||
label: 'Выберите улицу',
|
||||
value: 'IDStreet',
|
||||
options: streets,
|
||||
valueKey: 'IDStreet',
|
||||
labelKey: 'NameStreet',
|
||||
disabled: !watchCity || watchCity === 0
|
||||
},
|
||||
{
|
||||
label: '№ дома',
|
||||
value: 'IDHouse',
|
||||
options: houses,
|
||||
valueKey: 'IDHouse',
|
||||
labelKey: 'NameHouse',
|
||||
disabled: !watchStreet || watchStreet === 0
|
||||
},
|
||||
{
|
||||
label: 'Квартира',
|
||||
value: 'IDFlat',
|
||||
options: flats,
|
||||
valueKey: 'IDPersonalAccount',
|
||||
labelKey: 'NameFlat',
|
||||
disabled: !watchHouse || watchHouse === 0
|
||||
}
|
||||
]
|
||||
|
||||
return (
|
||||
<div className='flex flex-col gap-4'>
|
||||
<div className='text-lg font-medium'>Укажите адрес:</div>
|
||||
|
||||
<div className='flex flex-col gap-3'>
|
||||
{form.map((select, index) => (
|
||||
<select
|
||||
key={`select-${index}`}
|
||||
className="select appearance-none p-2 border rounded-md"
|
||||
{...register(select.value as keyof AddressData, {
|
||||
valueAsNumber: true,
|
||||
disabled: select.disabled
|
||||
})}
|
||||
disabled={select.disabled}
|
||||
>
|
||||
<option value={0} disabled={true}>{select.label}</option>
|
||||
{Array.isArray(select.options) && select.options.map((option) => (
|
||||
<option
|
||||
key={option[select.valueKey]}
|
||||
value={option[select.valueKey]}
|
||||
>
|
||||
{option[select.labelKey]}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{selectedAccount && (
|
||||
<div className='mt-4 p-3 bg-gray-100 rounded-md'>
|
||||
<div className='font-medium'>Выбрано:</div>
|
||||
<div>Лицевой счет: {selectedAccount.IDPersonalAccount}</div>
|
||||
<div>Квартира: {selectedAccount.NameFlat}</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
export default GetLK
|
||||
39
src/components/WPRenderer/HTMLRenderer.tsx
Normal file
39
src/components/WPRenderer/HTMLRenderer.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
"use client"
|
||||
|
||||
import { useEffect, useRef } from "react";
|
||||
|
||||
export function HTMLRenderer({ content }: {
|
||||
content: string
|
||||
}) {
|
||||
const iframeRef = useRef<HTMLIFrameElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!iframeRef.current || !content) return;
|
||||
|
||||
const iframe = iframeRef.current;
|
||||
const iframeDoc = iframe.contentDocument
|
||||
|
||||
if (iframeDoc) {
|
||||
// Write directly to iframe - scripts will execute!
|
||||
iframeDoc.open();
|
||||
iframeDoc.write(content);
|
||||
iframeDoc.close();
|
||||
|
||||
// // Adjust height after content loads
|
||||
// const adjustHeight = () => {
|
||||
// iframe.style.height = iframeDoc.body.scrollHeight + 'px';
|
||||
// };
|
||||
|
||||
// iframeDoc.addEventListener('load', adjustHeight);
|
||||
// return () => iframeDoc.removeEventListener('load', adjustHeight);
|
||||
}
|
||||
|
||||
}, [content]);
|
||||
|
||||
return (
|
||||
<iframe
|
||||
ref={iframeRef}
|
||||
sandbox="allow-scripts allow-cross-origin allow-same-origin allow-forms allow-popups"
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import PostGrid from '../WP/PostGrid/PostGrid.server';
|
||||
import { CarouselSlide, PagePayload } from '@/types/entities';
|
||||
import { transformLinks } from '@/lib/utils';
|
||||
import EmblaCarousel from '../UI/EmblaCarousel/EmblaCarousel';
|
||||
import { HTMLRenderer } from './HTMLRenderer';
|
||||
|
||||
const options: HTMLReactParserOptions = {
|
||||
replace: (domNode) => {
|
||||
@@ -47,6 +48,15 @@ const replaceShortcodes = (html: string) => {
|
||||
// return html.replace(regex, '$3');
|
||||
// };
|
||||
|
||||
export const renderElementorContent = (content: string, payload?: PagePayload) => {
|
||||
const transformedContent = replaceShortcodes(
|
||||
transformLinks(content)
|
||||
)
|
||||
return (
|
||||
<div dangerouslySetInnerHTML={{__html: transformedContent}}></div>
|
||||
// <HTMLRenderer content={transformedContent} />
|
||||
)
|
||||
}
|
||||
|
||||
export const renderPostContent = (content: string, payload?: PagePayload) => {
|
||||
|
||||
@@ -108,6 +118,13 @@ export const renderPostContent = (content: string, payload?: PagePayload) => {
|
||||
return (
|
||||
domNode
|
||||
);
|
||||
} else if (
|
||||
domNode &&
|
||||
domNode.type === 'tag' && domNode.tagName === 'html'
|
||||
) {
|
||||
return (
|
||||
<></>
|
||||
)
|
||||
}
|
||||
},
|
||||
})}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { DuckDBConnection, DuckDBInstance } from '@duckdb/node-api';
|
||||
|
||||
const instance = await DuckDBInstance.create('../public/jkhsakha.duckdb');
|
||||
const instance = await DuckDBInstance.create('./jkhsakha.duckdb');
|
||||
export const connection = await DuckDBConnection.create(instance)
|
||||
101
src/lib/utils.ts
101
src/lib/utils.ts
@@ -1,38 +1,106 @@
|
||||
import { containsCyrillic, transliterate } from "./transliterate";
|
||||
|
||||
// export const transformLinks = (html: string): string => {
|
||||
// if (!html) return html;
|
||||
|
||||
// // Regex to match specific domain links, excluding wp-content
|
||||
// // Now also captures the full URL to handle different parts
|
||||
// const regex = /(https?:\/\/)?(www\.)?new\.jkhsakha\.ru\/(?!wp-content)([^\s"']*)/g;
|
||||
|
||||
// return html.replace(regex, (match, protocol, www, path) => {
|
||||
// // Extract the full path including leading slash
|
||||
// let fullPath = path;
|
||||
|
||||
// // Make sure path starts with /
|
||||
// if (!fullPath.startsWith('/')) {
|
||||
// fullPath = '/' + fullPath;
|
||||
// }
|
||||
|
||||
// fullPath = decodeURIComponent(fullPath)
|
||||
|
||||
// // Check if the path contains Cyrillic characters
|
||||
// if (containsCyrillic(fullPath)) {
|
||||
// console.log("contains Cyrillic, transliterating:", fullPath);
|
||||
// // Split the path into segments
|
||||
// const pathSegments = fullPath.split('/').filter((segment: any) => segment.length > 0);
|
||||
|
||||
// // Transliterate each segment that contains Cyrillic
|
||||
// const transliteratedSegments = pathSegments.map((segment: any) => {
|
||||
// return containsCyrillic(segment) ? transliterate(segment) : segment;
|
||||
// });
|
||||
|
||||
// // Reconstruct the path
|
||||
// const transliteratedPath = '/' + transliteratedSegments.join('/');
|
||||
|
||||
// // Ensure the path ends with trailing slash if original had it
|
||||
// if (fullPath.endsWith('/') && !transliteratedPath.endsWith('/')) {
|
||||
// return transliteratedPath + '/';
|
||||
// }
|
||||
|
||||
// return transliteratedPath;
|
||||
// }
|
||||
|
||||
// // If no Cyrillic, return the original path
|
||||
// return fullPath;
|
||||
// });
|
||||
// };
|
||||
|
||||
export const transformLinks = (html: string): string => {
|
||||
if (!html) return html;
|
||||
|
||||
// Regex to match specific domain links, excluding wp-content
|
||||
// Now also captures the full URL to handle different parts
|
||||
const regex = /(https?:\/\/)?(www\.)?new\.jkhsakha\.ru\/(?!wp-content)([^\s"']*)/g;
|
||||
// First, replace wp-content/uploads links with storage URL
|
||||
const wpContentRegex = /(https?:\/\/)?(www\.)?new\.jkhsakha\.ru\/wp-content\/uploads\/([^\s"']*)/g;
|
||||
|
||||
return html.replace(regex, (match, protocol, www, path) => {
|
||||
// Extract the full path including leading slash
|
||||
let fullPath = path;
|
||||
|
||||
// Make sure path starts with /
|
||||
if (!fullPath.startsWith('/')) {
|
||||
fullPath = '/' + fullPath;
|
||||
html = html.replace(wpContentRegex, (match, protocol, www, path) => {
|
||||
const storageUrl = process.env.NEXT_PUBLIC_STORAGE_URL?.replace(/\/$/, ''); // Remove trailing slash if exists
|
||||
if (!storageUrl) {
|
||||
console.warn('NEXT_PUBLIC_STORAGE_URL is not defined');
|
||||
return match; // Return original if env var not set
|
||||
}
|
||||
|
||||
fullPath = decodeURIComponent(fullPath)
|
||||
// Decode and process the path for Cyrillic characters
|
||||
let fullPath = '/' + decodeURIComponent(path);
|
||||
|
||||
if (containsCyrillic(fullPath)) {
|
||||
console.log("contains Cyrillic, transliterating:", fullPath);
|
||||
const pathSegments = fullPath.split('/').filter((segment: any) => segment.length > 0);
|
||||
|
||||
const transliteratedSegments = pathSegments.map((segment: any) => {
|
||||
return containsCyrillic(segment) ? transliterate(segment) : segment;
|
||||
});
|
||||
|
||||
fullPath = '/' + transliteratedSegments.join('/');
|
||||
|
||||
if (path.endsWith('/') && !fullPath.endsWith('/')) {
|
||||
fullPath += '/';
|
||||
}
|
||||
}
|
||||
|
||||
return `${storageUrl}${fullPath}`;
|
||||
});
|
||||
|
||||
// Then handle other domain links (excluding wp-content)
|
||||
const otherLinksRegex = /(https?:\/\/)?(www\.)?new\.jkhsakha\.ru\/(?!wp-content)([^\s"']*)/g;
|
||||
|
||||
return html.replace(otherLinksRegex, (match, protocol, www, path) => {
|
||||
let fullPath = path;
|
||||
|
||||
if (!fullPath.startsWith('/')) {
|
||||
fullPath = '/' + fullPath;
|
||||
}
|
||||
|
||||
fullPath = decodeURIComponent(fullPath);
|
||||
|
||||
// Check if the path contains Cyrillic characters
|
||||
if (containsCyrillic(fullPath)) {
|
||||
console.log("contains Cyrillic, transliterating:", fullPath);
|
||||
// Split the path into segments
|
||||
const pathSegments = fullPath.split('/').filter((segment: any) => segment.length > 0);
|
||||
|
||||
// Transliterate each segment that contains Cyrillic
|
||||
const transliteratedSegments = pathSegments.map((segment: any) => {
|
||||
return containsCyrillic(segment) ? transliterate(segment) : segment;
|
||||
});
|
||||
|
||||
// Reconstruct the path
|
||||
const transliteratedPath = '/' + transliteratedSegments.join('/');
|
||||
|
||||
// Ensure the path ends with trailing slash if original had it
|
||||
if (fullPath.endsWith('/') && !transliteratedPath.endsWith('/')) {
|
||||
return transliteratedPath + '/';
|
||||
}
|
||||
@@ -40,7 +108,6 @@ export const transformLinks = (html: string): string => {
|
||||
return transliteratedPath;
|
||||
}
|
||||
|
||||
// If no Cyrillic, return the original path
|
||||
return fullPath;
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
export interface WPPostMeta {
|
||||
meta_id: number
|
||||
meta_key: string
|
||||
meta_value: string
|
||||
}
|
||||
export interface PostData {
|
||||
ID: string;
|
||||
guid: string;
|
||||
post_author: string;
|
||||
post_name: string;
|
||||
post_title: string;
|
||||
@@ -9,6 +15,14 @@ export interface PostData {
|
||||
post_date_gmt: string;
|
||||
post_modified: string;
|
||||
post_content: string;
|
||||
wp_postmeta?: WPPostMeta[]
|
||||
thumbnail?: PostData
|
||||
}
|
||||
|
||||
export interface PostCategory {
|
||||
id: number
|
||||
name: string
|
||||
slug: string
|
||||
}
|
||||
|
||||
export interface PagePayload {
|
||||
|
||||
6
src/utils/tailwind.ts
Normal file
6
src/utils/tailwind.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import clsx from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export const cn = (...inputs: Parameters<typeof clsx>) => {
|
||||
return twMerge(clsx(...inputs))
|
||||
}
|
||||
39
tailwind.config.ts
Normal file
39
tailwind.config.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
module.exports = {
|
||||
// ... other config
|
||||
safelist: [
|
||||
// Grid columns
|
||||
// 'grid-cols-1', 'grid-cols-2', 'grid-cols-3', 'grid-cols-4',
|
||||
// 'grid-cols-5', 'grid-cols-6', 'grid-cols-7', 'grid-cols-8',
|
||||
// 'grid-cols-9', 'grid-cols-10', 'grid-cols-11', 'grid-cols-12',
|
||||
// 'md:grid-cols-1', 'md:grid-cols-2', 'md:grid-cols-3', 'md:grid-cols-4',
|
||||
// 'md:grid-cols-5', 'md:grid-cols-6', 'md:grid-cols-7', 'md:grid-cols-8',
|
||||
// 'md:grid-cols-9', 'md:grid-cols-10', 'md:grid-cols-11', 'md:grid-cols-12',
|
||||
// 'lg:grid-cols-1', 'lg:grid-cols-2', 'lg:grid-cols-3', 'lg:grid-cols-4',
|
||||
// 'lg:grid-cols-5', 'lg:grid-cols-6', 'lg:grid-cols-7', 'lg:grid-cols-8',
|
||||
// 'lg:grid-cols-9', 'lg:grid-cols-10', 'lg:grid-cols-11', 'lg:grid-cols-12',
|
||||
|
||||
// // Grid rows
|
||||
// 'grid-rows-1', 'grid-rows-2', 'grid-rows-3', 'grid-rows-4',
|
||||
// 'grid-rows-5', 'grid-rows-6', 'grid-rows-7', 'grid-rows-8',
|
||||
// 'grid-rows-9', 'grid-rows-10', 'grid-rows-11', 'grid-rows-12',
|
||||
// 'md:grid-rows-1', 'md:grid-rows-2', 'md:grid-rows-3', 'md:grid-rows-4',
|
||||
// 'md:grid-rows-5', 'md:grid-rows-6', 'md:grid-rows-7', 'md:grid-rows-8',
|
||||
// 'md:grid-rows-9', 'md:grid-rows-10', 'md:grid-rows-11', 'md:grid-rows-12',
|
||||
// 'lg:grid-rows-1', 'lg:grid-rows-2', 'lg:grid-rows-3', 'lg:grid-rows-4',
|
||||
// 'lg:grid-rows-5', 'lg:grid-rows-6', 'lg:grid-rows-7', 'lg:grid-rows-8',
|
||||
// 'lg:grid-rows-9', 'lg:grid-rows-10', 'lg:grid-rows-11', 'lg:grid-rows-12',
|
||||
|
||||
// // Gaps
|
||||
// 'gap-0', 'gap-1', 'gap-2', 'gap-3', 'gap-4', 'gap-5', 'gap-6',
|
||||
// 'gap-7', 'gap-8', 'gap-9', 'gap-10', 'gap-11', 'gap-12',
|
||||
|
||||
// // Flex
|
||||
// 'flex', 'flex-row', 'flex-col',
|
||||
// 'justify-center', 'justify-between', 'justify-around', 'justify-start', 'justify-end', 'justify-evenly', 'justify-stretch',
|
||||
// 'items-center', 'items-end', 'items-start', 'items-stretch',
|
||||
|
||||
{
|
||||
pattern: /.*/,
|
||||
},
|
||||
],
|
||||
}
|
||||
Reference in New Issue
Block a user