testimonails added
27
.github/workflows/mdx-content.yml
vendored
|
@ -1,27 +0,0 @@
|
|||
name: Deploy MDX Content
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "data/pages/**"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "18"
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Run MDX build or processing script
|
||||
run: npm run build-mdx
|
|
@ -152,46 +152,6 @@ const AdminLogPage = () => {
|
|||
}
|
||||
};
|
||||
|
||||
const createNewPage = async () => {
|
||||
setLoading(true);
|
||||
const response = await fetch(`/api/mdx/pages`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ title: pageTitle }),
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
fetchPages();
|
||||
setLoading(false);
|
||||
toast({ description: "Page successfully created" });
|
||||
setOpen(false);
|
||||
setPageTitle("");
|
||||
} else {
|
||||
setLoading(false);
|
||||
toast({ description: "Page creation Failed", variant: "destructive" });
|
||||
}
|
||||
};
|
||||
|
||||
const handlePageSelect = async (slug: string) => {
|
||||
try {
|
||||
const response = await fetch(`/api/mdx/pages/${slug}`);
|
||||
if (response.ok) {
|
||||
const data: PageEntry = await response.json();
|
||||
setSelectedPage(data);
|
||||
} else {
|
||||
toast({
|
||||
description: "Failed to fetch page data",
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
} catch (error: any) {
|
||||
toast({
|
||||
description: error.message || "Failed to fetch page data",
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<section id="logs-page" className="wrapper container">
|
||||
<h1 className="text-3xl font-bold py-6">Server Logs Form</h1>
|
||||
|
@ -268,69 +228,6 @@ const AdminLogPage = () => {
|
|||
</form>
|
||||
</Form>
|
||||
|
||||
{/* Section to create new page */}
|
||||
<section id="create-page" className="py-16">
|
||||
<h2 className="text-3xl md:text-4xl font-bold mb-2">Multi Log page</h2>
|
||||
<Button variant={"secondary"} onClick={() => setOpen(true)}>
|
||||
Create New Page
|
||||
</Button>
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Enter Page Title</DialogTitle>
|
||||
</DialogHeader>
|
||||
<Input
|
||||
value={pageTitle}
|
||||
onChange={(e) => setPageTitle(e.target.value)}
|
||||
placeholder="Page Title"
|
||||
/>
|
||||
<DialogFooter>
|
||||
<Button onClick={createNewPage} disabled={loading}>
|
||||
Continue
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</section>
|
||||
|
||||
{/* Section to list and delete pages */}
|
||||
<section id="pages-list" className="pb-16">
|
||||
<h2 className="text-3xl md:text-4xl font-bold">Existing Pages</h2>
|
||||
<p className="mb-4">Total Pages: {pages.length}</p>
|
||||
<Table className="w-full mt-4 border-muted">
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className="border-b px-4 py-2">Slug</TableHead>
|
||||
<TableHead className="border-b px-4 py-2">Actions</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{pages.map((page) => (
|
||||
<TableRow key={page.slug}>
|
||||
<TableCell className="border-b px-4 py-2">
|
||||
<a
|
||||
href={`/changelogs/${page.slug}`}
|
||||
className="text-blue-500 underline"
|
||||
>
|
||||
{page.slug}
|
||||
</a>
|
||||
</TableCell>
|
||||
<TableCell className="border-b px-4 py-2">
|
||||
<Button
|
||||
variant={"outline"}
|
||||
onClick={() =>
|
||||
router.push(`/admin/changelogs/${page.slug}`)
|
||||
}
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</section>
|
||||
|
||||
{/* Section to list and delete logs */}
|
||||
<section id="logs-list" className="py-16 md:py-24">
|
||||
<h2 className="text-3xl md:text-4xl font-bold">Existing Logs</h2>
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
import fs from "fs";
|
||||
import path from "path";
|
||||
import matter from "gray-matter";
|
||||
import { serialize } from "next-mdx-remote/serialize";
|
||||
import { MDXRemote } from "next-mdx-remote/rsc";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import { ChangelogLayout } from "@/components/shared/providers/changelogLayout";
|
||||
import { getBlogPosts } from "@/lib/log";
|
||||
|
||||
const changelogsDir = path.resolve(process.cwd(), "data", "pages");
|
||||
|
||||
export default async function ChangelogPage({
|
||||
params,
|
||||
}: {
|
||||
params: { slug: string };
|
||||
}) {
|
||||
const { slug } = params;
|
||||
let posts = await getBlogPosts();
|
||||
let post = posts.find((post) => post.slug === params.slug);
|
||||
|
||||
try {
|
||||
return (
|
||||
<ChangelogLayout>
|
||||
<ReactMarkdown>{post?.content}</ReactMarkdown>
|
||||
</ChangelogLayout>
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("Error loading changelog page:", error);
|
||||
return <div>Error loading the page.</div>;
|
||||
}
|
||||
}
|
|
@ -5,17 +5,19 @@ import Hero from "@/components/shared/Hero";
|
|||
import HowItWorks from "@/components/shared/HowItWorks";
|
||||
import Newsletter from "@/components/shared/Newsletter";
|
||||
import Partners from "@/components/shared/Partners";
|
||||
import Testimonials from "@/components/shared/Testimonials";
|
||||
|
||||
const RootPage = () => {
|
||||
return (
|
||||
<>
|
||||
<Hero />
|
||||
<HowItWorks />
|
||||
<Testimonials />
|
||||
<Partners />
|
||||
<About />
|
||||
{/* <DataTable /> */}
|
||||
<Newsletter />
|
||||
<Faq />
|
||||
<Newsletter />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,66 +0,0 @@
|
|||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { promises as fs } from "fs";
|
||||
import path from "path";
|
||||
import matter from "gray-matter";
|
||||
|
||||
const changelogsDir = path.resolve(process.cwd(), "data/pages");
|
||||
|
||||
async function getMDXFiles(dir: string): Promise<string[]> {
|
||||
const files = await fs.readdir(dir);
|
||||
return files.filter((file) => file.endsWith(".mdx"));
|
||||
}
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
const mdxFiles = await getMDXFiles(changelogsDir);
|
||||
const pages = await Promise.all(
|
||||
mdxFiles.map(async (file) => {
|
||||
const filePath = path.join(changelogsDir, file);
|
||||
const content = await fs.readFile(filePath, "utf-8");
|
||||
const { data, content: mdxContent } = matter(content);
|
||||
const slug = path.basename(file, path.extname(file));
|
||||
return {
|
||||
metadata: data,
|
||||
slug,
|
||||
content: mdxContent,
|
||||
};
|
||||
})
|
||||
);
|
||||
return NextResponse.json(pages, { status: 200 });
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch pages:", error);
|
||||
return NextResponse.json(
|
||||
{ error: "Failed to fetch pages" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const { title } = await request.json();
|
||||
const slug = title.toLowerCase().replace(/\s+/g, "-");
|
||||
const filePath = path.join(changelogsDir, `${slug}.mdx`);
|
||||
|
||||
try {
|
||||
if (
|
||||
await fs
|
||||
.stat(filePath)
|
||||
.then(() => true)
|
||||
.catch(() => false)
|
||||
) {
|
||||
return NextResponse.json(
|
||||
{ error: "Page already exists" },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
await fs.writeFile(filePath, `---\ntitle: ${title}\n---\n`);
|
||||
return NextResponse.json({ title, slug }, { status: 201 });
|
||||
} catch (error) {
|
||||
console.error("Failed to create page:", error);
|
||||
return NextResponse.json(
|
||||
{ error: "Failed to create page" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { promises as fs } from "fs";
|
||||
import path from "path";
|
||||
import matter from "gray-matter";
|
||||
|
||||
// Define the path to the changelogs directory
|
||||
const pagesDir = path.join(process.cwd(), "data", "pages");
|
||||
|
||||
export async function GET(
|
||||
request: NextRequest,
|
||||
{ params }: { params: { slug: string } }
|
||||
) {
|
||||
const { slug } = params;
|
||||
const filePath = path.join(pagesDir, `${slug}.mdx`);
|
||||
|
||||
try {
|
||||
const content = await fs.readFile(filePath, "utf8");
|
||||
// Use gray-matter to parse the front matter and content
|
||||
const { data, content: mdxContent } = matter(content);
|
||||
return NextResponse.json({ title: data.title, content: mdxContent });
|
||||
} catch (error) {
|
||||
console.error("Failed to load page:", error);
|
||||
return NextResponse.json({ error: "Page not found" }, { status: 404 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function PUT(
|
||||
request: NextRequest,
|
||||
{ params }: { params: { slug: string } }
|
||||
) {
|
||||
const { slug } = params;
|
||||
const filePath = path.join(pagesDir, `${slug}.mdx`);
|
||||
const { title, content } = await request.json();
|
||||
|
||||
try {
|
||||
await fs.writeFile(filePath, `---\ntitle: ${title}\n---\n${content}`);
|
||||
return NextResponse.json({ title, slug, content });
|
||||
} catch (error) {
|
||||
console.error("Failed to update page:", error);
|
||||
return NextResponse.json(
|
||||
{ error: "Failed to update page" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function DELETE(
|
||||
request: NextRequest,
|
||||
{ params }: { params: { slug: string } }
|
||||
) {
|
||||
const { slug } = params;
|
||||
const filePath = path.join(pagesDir, `${slug}.mdx`);
|
||||
|
||||
try {
|
||||
await fs.unlink(filePath);
|
||||
return NextResponse.json({}, { status: 204 });
|
||||
} catch (error) {
|
||||
console.error("Failed to delete page:", error);
|
||||
return NextResponse.json(
|
||||
{ error: "Failed to delete page" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
55
components/cards/testimonialCard.tsx
Normal file
|
@ -0,0 +1,55 @@
|
|||
import Image from "next/image";
|
||||
import React from "react";
|
||||
|
||||
interface TestimonialCard {
|
||||
avatar: string;
|
||||
name: string;
|
||||
role?: string;
|
||||
testimonial: string;
|
||||
rating: number;
|
||||
}
|
||||
|
||||
const TestimonialCard = ({
|
||||
avatar,
|
||||
name,
|
||||
role,
|
||||
testimonial,
|
||||
rating,
|
||||
}: TestimonialCard) => {
|
||||
return (
|
||||
<li className="inline-block w-full">
|
||||
<div className="bg-[#1c1c1c] mx-auto mb-5 flex w-full cursor-default flex-col gap-4 rounded-2xl px-[30px] py-6 shadow-md transition-all hover:scale-[103%]">
|
||||
<div className="flex flex-row items-center gap-3">
|
||||
<div>
|
||||
<Image
|
||||
src={`/testimonials/${avatar}.webp`}
|
||||
alt="avatar1"
|
||||
width={40}
|
||||
height={40}
|
||||
className="rounded-full"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<div className="flex items-center gap-1">
|
||||
<div className="small-semibold text-white">{name}</div>
|
||||
</div>
|
||||
<div className="small-regular text-white-800">{role}</div>
|
||||
</div>
|
||||
</div>
|
||||
<p className="body-regular text-white">{testimonial}</p>
|
||||
<div className="hue-rotate-90 text-lg">
|
||||
{/* <Image
|
||||
src="/testimonials/stars.svg"
|
||||
alt="star"
|
||||
width={120}
|
||||
height={120}
|
||||
className="object-cover"
|
||||
/> */}
|
||||
{"⭐".repeat(rating)}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
export default TestimonialCard;
|
105
components/shared/Testimonials.tsx
Normal file
|
@ -0,0 +1,105 @@
|
|||
import React from "react";
|
||||
import TestimonialCard from "../cards/testimonialCard";
|
||||
|
||||
const testimonials = [
|
||||
{
|
||||
name: "John Doe",
|
||||
role: "CEO, Example Corp.",
|
||||
avatar: "avatar1",
|
||||
testimonial:
|
||||
"Working with this team was a fantastic experience. They developed our website exactly to our specifications, and everything was seamless and well-integrated.",
|
||||
rating: 5,
|
||||
},
|
||||
{
|
||||
name: "Jane Smith",
|
||||
role: "CEO, CleanCo",
|
||||
avatar: "avatar2",
|
||||
testimonial:
|
||||
"We're thrilled with the website. It's simple, clean, and has significantly boosted our sales. The developers did an excellent job.",
|
||||
rating: 4,
|
||||
},
|
||||
{
|
||||
name: "Sam Green",
|
||||
role: "Web Developer",
|
||||
avatar: "avatar3",
|
||||
testimonial:
|
||||
"Collaborating with this team to build a SaaS-integrated website was a perfect experience. I look forward to working with them again.",
|
||||
rating: 5,
|
||||
},
|
||||
{
|
||||
name: "Chris Brown",
|
||||
role: "Web Coder",
|
||||
avatar: "avatar4",
|
||||
testimonial:
|
||||
"The team's understanding of our needs and their ability to provide fitting solutions was impressive. Their support and guidance were invaluable.",
|
||||
rating: 4,
|
||||
},
|
||||
{
|
||||
name: "Alex Johnson",
|
||||
avatar: "avatar5",
|
||||
testimonial:
|
||||
"Exceptional service and outstanding results. They consistently deliver on time and within budget, making them our go-to partner for all our projects.",
|
||||
rating: 5,
|
||||
},
|
||||
{
|
||||
name: "Patricia Taylor",
|
||||
role: "Web Developer",
|
||||
avatar: "avatar6",
|
||||
testimonial:
|
||||
"It was great to work with them. I needed a design for a SaaS project, and it was delivered within 2 days.",
|
||||
rating: 4,
|
||||
},
|
||||
{
|
||||
name: "Emily Davis",
|
||||
role: "UX Designer, Creative Agency",
|
||||
avatar: "avatar7",
|
||||
testimonial:
|
||||
"Collaborating with them has been a pleasure. Their creativity and user-centric approach have significantly enhanced our product's usability.",
|
||||
rating: 5,
|
||||
},
|
||||
{
|
||||
name: "Michael Lee",
|
||||
avatar: "avatar8",
|
||||
testimonial:
|
||||
"They have a keen understanding of our business needs and consistently deliver top-notch solutions. Their reliability and efficiency are commendable.",
|
||||
rating: 5,
|
||||
},
|
||||
{
|
||||
name: "Sarah Wilson",
|
||||
avatar: "avatar9",
|
||||
testimonial:
|
||||
"Their dedication to client satisfaction is evident in everything they do. We've seen remarkable improvements in our processes thanks to their expertise.",
|
||||
rating: 4,
|
||||
},
|
||||
];
|
||||
|
||||
const Testimonials = () => {
|
||||
return (
|
||||
<section className="mx-auto flex w-full max-w-7xl flex-col pt-12 md:pt-24">
|
||||
<div className="flex flex-row items-center justify-center space-x-1">
|
||||
<span className="text-white/50 text-xs lg:text-base">Testimonials</span>
|
||||
</div>
|
||||
<h1 className="text-3xl md:text-5xl font-bold text-center">
|
||||
Hear it from{" "}
|
||||
<span className="bg-gradient-to-b from-green-200 to-primary text-transparent bg-clip-text">
|
||||
our users
|
||||
</span>
|
||||
</h1>
|
||||
|
||||
<div className="columns-1 gap-5 md:columns-2 lg:columns-3 py-6 mt-6">
|
||||
{testimonials.map((testimonial, idx) => (
|
||||
<TestimonialCard
|
||||
avatar={testimonial.avatar}
|
||||
name={testimonial.name}
|
||||
role={testimonial.role}
|
||||
testimonial={testimonial.testimonial}
|
||||
rating={testimonial.rating}
|
||||
key={idx}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default Testimonials;
|
|
@ -1,13 +0,0 @@
|
|||
---
|
||||
title: svrjs trail
|
||||
---
|
||||
# SVRJS this is good
|
||||
|
||||
## this is second heading
|
||||
|
||||
```json
|
||||
{hi this iajdiajsidj}
|
||||
|
||||
```
|
||||
|
||||
asdasidajsidjasi
|
35
lib/log.ts
|
@ -1,35 +0,0 @@
|
|||
import fs from "fs";
|
||||
import path from "path";
|
||||
import matter from "gray-matter";
|
||||
|
||||
function getMDXFiles(dir: string): string[] {
|
||||
return fs.readdirSync(dir).filter((file) => file.endsWith(".mdx"));
|
||||
}
|
||||
|
||||
function readMDXFile(filePath: string): { metadata: any; content: string } {
|
||||
const source = fs.readFileSync(filePath, "utf-8");
|
||||
const { data: metadata, content } = matter(source);
|
||||
return { metadata, content };
|
||||
}
|
||||
|
||||
function extractTweetIds(content: string): string[] {
|
||||
// Implement your tweet ID extraction logic here
|
||||
return [];
|
||||
}
|
||||
|
||||
export function getMDXData(dir: string) {
|
||||
let mdxFiles = getMDXFiles(dir);
|
||||
return mdxFiles.map((file) => {
|
||||
let { metadata, content } = readMDXFile(path.join(dir, file));
|
||||
let slug = path.basename(file, path.extname(file));
|
||||
return {
|
||||
metadata,
|
||||
slug,
|
||||
content,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export function getBlogPosts() {
|
||||
return getMDXData(path.join(process.cwd(), "data", "pages"));
|
||||
}
|
BIN
public/testimonials/avata10.webp
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
public/testimonials/avatar1.webp
Normal file
After Width: | Height: | Size: 8.4 KiB |
BIN
public/testimonials/avatar2.webp
Normal file
After Width: | Height: | Size: 63 KiB |
BIN
public/testimonials/avatar3.webp
Normal file
After Width: | Height: | Size: 7.3 KiB |
BIN
public/testimonials/avatar4.webp
Normal file
After Width: | Height: | Size: 81 KiB |
BIN
public/testimonials/avatar5.webp
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
public/testimonials/avatar6.webp
Normal file
After Width: | Height: | Size: 65 KiB |
BIN
public/testimonials/avatar7.webp
Normal file
After Width: | Height: | Size: 7.5 KiB |
BIN
public/testimonials/avatar8.webp
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
public/testimonials/avatar9.webp
Normal file
After Width: | Height: | Size: 6.3 KiB |
156
public/testimonials/stars.svg
Normal file
|
@ -0,0 +1,156 @@
|
|||
<svg
|
||||
width="101"
|
||||
height="20"
|
||||
viewBox="0 0 101 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M5.35352 18.3333L6.70768 12.4792L2.16602 8.54167L8.16602 8.02083L10.4993 2.5L12.8327 8.02083L18.8327 8.54167L14.291 12.4792L15.6452 18.3333L10.4993 15.2292L5.35352 18.3333Z"
|
||||
fill="url(#green)"
|
||||
></path>
|
||||
<path
|
||||
d="M25.35352 18.3333L26.70768 12.4792L22.16602 8.54167L28.16602 8.02083L30.4993 2.5L32.8327 8.02083L38.8327 8.54167L34.291 12.4792L35.6452 18.3333L30.4993 15.2292L25.35352 18.3333Z"
|
||||
fill="url(#green)"
|
||||
></path>
|
||||
<path
|
||||
d="M45.35352 18.3333L46.70768 12.4792L42.16602 8.54167L48.16602 8.02083L50.4993 2.5L52.8327 8.02083L58.8327 8.54167L54.291 12.4792L55.6452 18.3333L50.4993 15.2292L45.35352 18.3333Z"
|
||||
fill="url(#green)"
|
||||
></path>
|
||||
<path
|
||||
d="M65.35352 18.3333L66.70768 12.4792L62.16602 8.54167L68.16602 8.02083L70.4993 2.5L72.8327 8.02083L78.8327 8.54167L74.291 12.4792L75.6452 18.3333L70.4993 15.2292L65.35352 18.3333Z"
|
||||
fill="url(#green)"
|
||||
></path>
|
||||
<path
|
||||
d="M85.35352 18.3333L86.70768 12.4792L82.16602 8.54167L88.16602 8.02083L90.4993 2.5L92.8327 8.02083L98.8327 8.54167L94.291 12.4792L95.6452 18.3333L90.4993 15.2292L85.35352 18.3333Z"
|
||||
fill="url(#green)"
|
||||
></path>
|
||||
<defs>
|
||||
<linearGradient
|
||||
id="orange"
|
||||
x1="2.55563"
|
||||
y1="10.5169"
|
||||
x2="88.9626"
|
||||
y2="10.5169"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<animate
|
||||
attributeName="x1"
|
||||
dur="1.8s"
|
||||
values="80%; 0%; 80%"
|
||||
calcMode="spline"
|
||||
keySplines="0.4 0 0.6 1; 0.4 0 0.6 1"
|
||||
repeatCount="indefinite"
|
||||
></animate>
|
||||
<stop stop-color="#FF7170"></stop>
|
||||
<stop offset="1" stop-color="#FFE57F"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="blue"
|
||||
x1="2.55563"
|
||||
y1="10.5169"
|
||||
x2="88.9626"
|
||||
y2="10.5169"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<animate
|
||||
attributeName="x1"
|
||||
dur="1.8s"
|
||||
values="80%; 0%; 80%"
|
||||
calcMode="spline"
|
||||
keySplines="0.4 0 0.6 1; 0.4 0 0.6 1"
|
||||
repeatCount="indefinite"
|
||||
></animate>
|
||||
<stop stop-color="#4C73FF"></stop>
|
||||
<stop offset="1" stop-color="#389BFF"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
id="pink"
|
||||
x1="2.55563"
|
||||
y1="10.5169"
|
||||
x2="88.9626"
|
||||
y2="10.5169"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<animate
|
||||
attributeName="x1"
|
||||
dur="1.8s"
|
||||
values="80%; 0%; 80%"
|
||||
calcMode="spline"
|
||||
keySplines="0.4 0 0.6 1; 0.4 0 0.6 1"
|
||||
repeatCount="indefinite"
|
||||
></animate>
|
||||
<stop stop-color="#FF4CC2"></stop>
|
||||
<stop offset="1" stop-color="#F87393"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
id="green"
|
||||
x1="0.166016"
|
||||
y1="8.41663"
|
||||
x2="86.8327"
|
||||
y2="8.41663"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<animate
|
||||
attributeName="x1"
|
||||
dur="1.8s"
|
||||
values="80%; 0%; 80%"
|
||||
calcMode="spline"
|
||||
keySplines="0.4 0 0.6 1; 0.4 0 0.6 1"
|
||||
repeatCount="indefinite"
|
||||
></animate>
|
||||
<stop stop-color="#7AFFD7"></stop>
|
||||
<stop offset="1" stop-color="#00FFB2"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
id="gold"
|
||||
x1="2.55563"
|
||||
y1="10.5169"
|
||||
x2="88.9626"
|
||||
y2="10.5169"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<animate
|
||||
attributeName="x1"
|
||||
dur="1.8s"
|
||||
values="50%; 0%; 50%"
|
||||
calcMode="spline"
|
||||
keySplines="0.4 0 0.6 1; 0.4 0 0.6 1"
|
||||
repeatCount="indefinite"
|
||||
></animate>{" "}
|
||||
<animate
|
||||
attributeName="x1"
|
||||
dur="3s"
|
||||
values="50%; 0%; 50%"
|
||||
calcMode="spline"
|
||||
keySplines="0.4 0 0.6 1; 0.4 0 0.6 1"
|
||||
repeatCount="indefinite"
|
||||
></animate>
|
||||
<stop stop-color="#FF7170"></stop>
|
||||
<stop offset="1" stop-color="#FFE57F"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
id="purple"
|
||||
x1="1.13689"
|
||||
y1="4.45834"
|
||||
x2="18.5566"
|
||||
y2="5.48068"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<animate
|
||||
attributeName="x1"
|
||||
dur="1.8s"
|
||||
values="100%; 40%; 100%"
|
||||
calcMode="spline"
|
||||
keySplines="0.4 0 0.6 1; 0.4 0 0.6 1"
|
||||
repeatCount="indefinite"
|
||||
></animate>
|
||||
<stop stop-color="#854CFF"></stop>
|
||||
<stop offset="1" stop-color="#B673F8"></stop>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 5.5 KiB |
|
@ -1,50 +0,0 @@
|
|||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const { compile } = require("@mdx-js/mdx");
|
||||
const { remark } = require("remark");
|
||||
const { toVFile } = require("to-vfile");
|
||||
const { format } = require("prettier");
|
||||
const rehypeStringify = require("rehype-stringify");
|
||||
const remarkParse = require("remark-parse");
|
||||
const rehypeParse = require("rehype-parse");
|
||||
const { unified } = require("unified");
|
||||
|
||||
const mdxDir = path.join(__dirname, "../data/pages");
|
||||
const outputDir = path.join(__dirname, "../data/mdx");
|
||||
|
||||
if (!fs.existsSync(outputDir)) {
|
||||
fs.mkdirSync(outputDir, { recursive: true });
|
||||
}
|
||||
|
||||
fs.readdir(mdxDir, (err, files) => {
|
||||
if (err) throw err;
|
||||
|
||||
files.forEach(async (file) => {
|
||||
if (path.extname(file) === ".mdx") {
|
||||
const filePath = path.join(mdxDir, file);
|
||||
const outputFilePath = path.join(
|
||||
outputDir,
|
||||
path.basename(file, ".mdx") + ".html"
|
||||
);
|
||||
|
||||
try {
|
||||
const mdxContent = fs.readFileSync(filePath, "utf8");
|
||||
|
||||
const processedContent = await compile(mdxContent, {
|
||||
remarkPlugins: [remarkParse],
|
||||
rehypePlugins: [rehypeStringify],
|
||||
});
|
||||
|
||||
const html = processedContent.toString();
|
||||
|
||||
// ig optional?
|
||||
const formattedHtml = format(html, { parser: "html" });
|
||||
|
||||
fs.writeFileSync(outputFilePath, formattedHtml);
|
||||
console.log(`Processed ${file} -> ${outputFilePath}`);
|
||||
} catch (error) {
|
||||
console.error(`Failed to process ${file}:`, error);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|