diff --git a/content/updates/v0.1.7.de.md b/content/updates/v0.1.7.de.md new file mode 100644 index 00000000..73ddc433 --- /dev/null +++ b/content/updates/v0.1.7.de.md @@ -0,0 +1,19 @@ +--- +version: v0.1.7 +date: OKTOBER, 2025 +month: OKT +assets: 2 +contributorNote: Tellus massa commodo at neque eget morbi mus porta mauris. Ac elementum natoque massa arcu tellus lorem eu hac amet. +contributors: + - name: Mitwirkender + avatar: https://cdn.pixabay.com/photo/2025/04/02/18/48/background-9509852_1280.jpg + url: "#" +--- + +## Was hat sich geändert + + + +- Eleifend nunc dui ullamcorper lectus at sociis. Gravida eget velit amet at tortor duis. Convallis id pellentesque aenean orci vestibulum arcu nisi arcu. Egestas nulla ullamcorper vulputate venenatis. +- Feugiat convallis quam leo faucibus tristique sed vitae. Enim lectus consectetur eu facilisi nullam. Ut leo morbi condimentum sed. Quis nibh ornare mi orci morbi sed. +- Sit senectus nulla ullamcorper pretium ac vitae. Sem interdum elementum viverra in. Sit sit tincidunt libero vestibulum amet consectetur mi. Nulla etiam urna placerat id diam. diff --git a/content/updates/v0.1.7.en.md b/content/updates/v0.1.7.en.md new file mode 100644 index 00000000..0f587b02 --- /dev/null +++ b/content/updates/v0.1.7.en.md @@ -0,0 +1,19 @@ +--- +version: v0.1.7 +date: OKTOBER, 2025 +month: OKT +assets: 2 +contributorNote: Tellus massa commodo at neque eget morbi mus porta mauris. Ac elementum natoque massa arcu tellus lorem eu hac amet. +contributors: + - name: Contributor + avatar: https://cdn.pixabay.com/photo/2025/04/02/18/48/background-9509852_1280.jpg + url: "#" +--- + +## What's Changed + + + +- Eleifend nunc dui ullamcorper lectus at sociis. Gravida eget velit amet at tortor duis. Convallis id pellentesque aenean orci vestibulum arcu nisi arcu. Egestas nulla ullamcorper vulputate venenatis. +- Feugiat convallis quam leo faucibus tristique sed vitae. Enim lectus consectetur eu facilisi nullam. Ut leo morbi condimentum sed. Quis nibh ornare mi orci morbi sed. +- Sit senectus nulla ullamcorper pretium ac vitae. Sem interdum elementum viverra in. Sit sit tincidunt libero vestibulum amet consectetur mi. Nulla etiam urna placerat id diam. diff --git a/content/updates/v0.1.8.de.md b/content/updates/v0.1.8.de.md new file mode 100644 index 00000000..b80fec02 --- /dev/null +++ b/content/updates/v0.1.8.de.md @@ -0,0 +1,73 @@ +--- +version: v0.1.8 +date: NOVEMBER, 2025 +month: NOV +isLatest: true +assets: 2 +tags: + - Tortor + - Tellus + - Mattis + - Luctus +contributorNote: Tellus massa commodo at neque eget morbi mus porta mauris. Ac elementum natoque massa arcu tellus lorem eu hac amet. +contributors: + - name: Mitwirkender + avatar: https://cdn.pixabay.com/photo/2025/04/02/18/48/background-9509852_1280.jpg + url: "#" +--- + +## Überblick + +Pretium augue urna sit vulputate in. Venenatis amet dui augue et interdum. Dolor feugiat morbi pellentesque in at ullamcorper. Quis imperdiet sit ipsum et sodales amet urna. + +Pretium augue urna sit vulputate in. Venenatis amet dui augue et interdum. Dolor feugiat morbi pellentesque in at ullamcorper. Quis imperdiet sit ipsum et sodales amet urna. + +## Überarbeitete Dokumentation + + + +- docs: Beispiele zur Konfliktlösung bei Änderungsprotokollen zu docs/common_issues.md hinzugefügt +- docs: Abschnitt "Ein Problem pro Pull Request" zu examples/sdk_developers/common_issues.md hinzugefügt. +- docs: pyproject.toml Maintainer-Liste aktualisiert. +- docs: Social-Follow-Bereich zur README hinzugefügt +- docs: Beispiele zur Konfliktlösung bei Änderungsprotokollen zu docs/common_issues.md hinzugefügt +- docs: Abschnitt "Ein Problem pro Pull Request" zu examples/sdk_developers/common_issues.md hinzugefügt. +- docs: pyproject.toml Maintainer-Liste aktualisiert. +- docs: Social-Follow-Bereich zur README hinzugefügt + +## Fehlerbehebungen + + + +- Pharetra sed pellentesque pretium euismod risus iaculis netus. Ac scelerisque posuere viverra sit. Consequat in odio sed tempus faucibus risus. Malesuada turpis nisi lorem volutpat ullamcorper magna. +- Pharetra sed pellentesque pretium euismod risus iaculis netus. Ac scelerisque posuere viverra sit. Consequat in odio sed tempus faucibus risus. Malesuada turpis nisi lorem volutpat ullamcorper magna. + +## Neue Korrekturen + + + +- Pharetra sed pellentesque pretium euismod risus iaculis netus. Ac scelerisque posuere viverra sit. Consequat in odio sed tempus faucibus risus. Malesuada turpis nisi lorem volutpat ullamcorper magna. +- Nunc quis nec urna pellentesque. Mus tempor placerat at lacinia nulla justo iaculis bibendum pretium. Dis ullamcorper scelerisque eget ultricies fermentum fermentum nisi. Eu auctor lorem sed nisl elit posuere purus est. +- Quam enim rhoncus fames et vitae enim molestie tellus. Pulvinar eget diam vestibulum pellentesque sit fringilla ornare augue pellentesque. Consequat nec at proin et vitae elit. Vitae ut cursus suspendisse elementum euismod sit. +- Purus habitant consectetur vulputate gravida. Lacus in neque fermentum viverra eros viverra. Dui odio urna nunc volutpat. In nunc arcu augue eu eu tellus. + +## Neue Funktionen + + + +- Quis quam pellentesque at sed in sed orci. Purus varius non arcu cursus malesuada convallis nisl sem pulvinar. +- Nisl commodo quis blandit nibh. Odio mauris id eget quis tempor. +- Sed gravida morbi elit a sit. Nec non amet tortor purus neque amet libero. +- Consequat consectetur cras neque mattis. In quam aliquam mattis ut risus risus dis proin lorem. +- Quis quam pellentesque at sed in sed orci. Purus varius non arcu cursus malesuada convallis nisl sem pulvinar. +- Nisl commodo quis blandit nibh. Odio mauris id eget quis tempor. +- Sed gravida morbi elit a sit. Nec non amet tortor purus neque amet libero. +- Consequat consectetur cras neque mattis. In quam aliquam mattis ut risus risus dis proin lorem. + +## Was hat sich geändert + + + +- Eleifend nunc dui ullamcorper lectus at sociis. Gravida eget velit amet at tortor duis. Convallis id pellentesque aenean orci vestibulum arcu nisi arcu. Egestas nulla ullamcorper vulputate venenatis. +- Feugiat convallis quam leo faucibus tristique sed vitae. Enim lectus consectetur eu facilisi nullam. Ut leo morbi condimentum sed. Quis nibh ornare mi orci morbi sed. +- Sit senectus nulla ullamcorper pretium ac vitae. Sem interdum elementum viverra in. Sit sit tincidunt libero vestibulum amet consectetur mi. Nulla etiam urna placerat id diam. diff --git a/content/updates/v0.1.8.en.md b/content/updates/v0.1.8.en.md new file mode 100644 index 00000000..b01c32aa --- /dev/null +++ b/content/updates/v0.1.8.en.md @@ -0,0 +1,73 @@ +--- +version: v0.1.8 +date: NOVEMBER, 2025 +month: NOV +isLatest: true +assets: 2 +tags: + - Tortor + - Tellus + - Mattis + - Luctus +contributorNote: Tellus massa commodo at neque eget morbi mus porta mauris. Ac elementum natoque massa arcu tellus lorem eu hac amet. +contributors: + - name: Contributor + avatar: https://cdn.pixabay.com/photo/2025/04/02/18/48/background-9509852_1280.jpg + url: "#" +--- + +## Overview + +Pretium augue urna sit vulputate in. Venenatis amet dui augue et interdum. Dolor feugiat morbi pellentesque in at ullamcorper. Quis imperdiet sit ipsum et sodales amet urna. + +Pretium augue urna sit vulputate in. Venenatis amet dui augue et interdum. Dolor feugiat morbi pellentesque in at ullamcorper. Quis imperdiet sit ipsum et sodales amet urna. + +## Refactored Documentation + + + +- docs: added changelog conflict resolution examples to docs/common_issues.md +- docs: added "One Issue Per Pull Request" section to examples/sdk_developers/common_issues.md. +- docs: update pyproject.toml maintainers list. +- docs: added to README a social follow section +- docs: added changelog conflict resolution examples to docs/common_issues.md +- docs: added "One Issue Per Pull Request" section to examples/sdk_developers/common_issues.md. +- docs: update pyproject.toml maintainers list. +- docs: added to README a social follow section + +## Bug Fixes + + + +- Pharetra sed pellentesque pretium euismod risus iaculis netus. Ac scelerisque posuere viverra sit. Consequat in odio sed tempus faucibus risus. Malesuada turpis nisi lorem volutpat ullamcorper magna. +- Pharetra sed pellentesque pretium euismod risus iaculis netus. Ac scelerisque posuere viverra sit. Consequat in odio sed tempus faucibus risus. Malesuada turpis nisi lorem volutpat ullamcorper magna. + +## New Fixes + + + +- Pharetra sed pellentesque pretium euismod risus iaculis netus. Ac scelerisque posuere viverra sit. Consequat in odio sed tempus faucibus risus. Malesuada turpis nisi lorem volutpat ullamcorper magna. +- Nunc quis nec urna pellentesque. Mus tempor placerat at lacinia nulla justo iaculis bibendum pretium. Dis ullamcorper scelerisque eget ultricies fermentum fermentum nisi. Eu auctor lorem sed nisl elit posuere purus est. +- Quam enim rhoncus fames et vitae enim molestie tellus. Pulvinar eget diam vestibulum pellentesque sit fringilla ornare augue pellentesque. Consequat nec at proin et vitae elit. Vitae ut cursus suspendisse elementum euismod sit. +- Purus habitant consectetur vulputate gravida. Lacus in neque fermentum viverra eros viverra. Dui odio urna nunc volutpat. In nunc arcu augue eu eu tellus. + +## New Features + + + +- Quis quam pellentesque at sed in sed orci. Purus varius non arcu cursus malesuada convallis nisl sem pulvinar. +- Nisl commodo quis blandit nibh. Odio mauris id eget quis tempor. +- Sed gravida morbi elit a sit. Nec non amet tortor purus neque amet libero. +- Consequat consectetur cras neque mattis. In quam aliquam mattis ut risus risus dis proin lorem. +- Quis quam pellentesque at sed in sed orci. Purus varius non arcu cursus malesuada convallis nisl sem pulvinar. +- Nisl commodo quis blandit nibh. Odio mauris id eget quis tempor. +- Sed gravida morbi elit a sit. Nec non amet tortor purus neque amet libero. +- Consequat consectetur cras neque mattis. In quam aliquam mattis ut risus risus dis proin lorem. + +## What's Changed + + + +- Eleifend nunc dui ullamcorper lectus at sociis. Gravida eget velit amet at tortor duis. Convallis id pellentesque aenean orci vestibulum arcu nisi arcu. Egestas nulla ullamcorper vulputate venenatis. +- Feugiat convallis quam leo faucibus tristique sed vitae. Enim lectus consectetur eu facilisi nullam. Ut leo morbi condimentum sed. Quis nibh ornare mi orci morbi sed. +- Sit senectus nulla ullamcorper pretium ac vitae. Sem interdum elementum viverra in. Sit sit tincidunt libero vestibulum amet consectetur mi. Nulla etiam urna placerat id diam. diff --git a/locales/de.json b/locales/de.json index e7bf1a18..0bb624ee 100644 --- a/locales/de.json +++ b/locales/de.json @@ -259,5 +259,21 @@ "changeLanguage": "Sprache ändern", "english": "Englisch", "german": "Deutsch" + }, + "updates": { + "metaTitle": "Updates & Changelog | Open Elements", + "metaDescription": "Bleiben Sie auf dem Laufenden über die neuesten Funktionen, Verbesserungen und Fehlerbehebungen für Open Elements.", + "title": "Updates & Changelog", + "description": "Bleiben Sie auf dem Laufenden über die neuesten Funktionen, Verbesserungen und Fehlerbehebungen", + "latest": "Neueste", + "overview": "Überblick", + "contributors": "Mitwirkende", + "assets": "Ressourcen", + "seeMore": "Mehr anzeigen", + "seeLess": "Weniger anzeigen", + "badge": "Semper", + "newFeatures": "Neue Funktionen", + "decorationAlt": "Dekoratives Element", + "underlineAlt": "Grafisches Element zum Unterstreichen des Textes" } } diff --git a/locales/en.json b/locales/en.json index f2a9ad8f..5ee03d33 100644 --- a/locales/en.json +++ b/locales/en.json @@ -211,5 +211,21 @@ "subscription": { "contactUs": "Contact us" } + }, + "updates": { + "metaTitle": "Updates & Changelog | Open Elements", + "metaDescription": "Stay up to date with the latest features, improvements, and bug fixes for Open Elements.", + "title": "Updates & Changelog", + "description": "Stay up to date with the latest features, improvements, and bug fixes", + "latest": "Latest", + "overview": "Overview", + "contributors": "Contributors", + "assets": "Assets", + "seeMore": "See More", + "seeLess": "See Less", + "badge": "Semper", + "newFeatures": "New Features", + "decorationAlt": "Decorative element", + "underlineAlt": "Graphical element that underlines the text" } } \ No newline at end of file diff --git a/next.config.js b/next.config.js index 9ef3b5e4..567b1fcd 100644 --- a/next.config.js +++ b/next.config.js @@ -6,6 +6,14 @@ const withNextIntl = createNextIntlPlugin(); const nextConfig = { reactStrictMode: true, // output: "standalone", // Disabled for local development - enable on deployment platform if needed + images: { + remotePatterns: [ + { + protocol: 'https', + hostname: 'cdn.pixabay.com', + }, + ], + }, }; export default withNextIntl(nextConfig); diff --git a/public/icons/greenTick.svg b/public/icons/greenTick.svg new file mode 100644 index 00000000..6101006c --- /dev/null +++ b/public/icons/greenTick.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/purpleTick.svg b/public/icons/purpleTick.svg new file mode 100644 index 00000000..14dfdf7f --- /dev/null +++ b/public/icons/purpleTick.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/icons/redTick.svg b/public/icons/redTick.svg new file mode 100644 index 00000000..ca9beec0 --- /dev/null +++ b/public/icons/redTick.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/star.svg b/public/icons/star.svg new file mode 100644 index 00000000..bbe38f71 --- /dev/null +++ b/public/icons/star.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/illustrations/book.png b/public/illustrations/book.png new file mode 100644 index 00000000..1a8adabd Binary files /dev/null and b/public/illustrations/book.png differ diff --git a/public/illustrations/book.svg b/public/illustrations/book.svg new file mode 100644 index 00000000..fbf4e1e7 --- /dev/null +++ b/public/illustrations/book.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/illustrations/green-arrow.svg b/public/illustrations/green-arrow.svg new file mode 100644 index 00000000..3281ac64 --- /dev/null +++ b/public/illustrations/green-arrow.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/public/illustrations/plane-sm.svg b/public/illustrations/plane-sm.svg new file mode 100644 index 00000000..bab11e07 --- /dev/null +++ b/public/illustrations/plane-sm.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/public/illustrations/plane.svg b/public/illustrations/plane.svg new file mode 100644 index 00000000..f89f8093 --- /dev/null +++ b/public/illustrations/plane.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/public/illustrations/round11.svg b/public/illustrations/round11.svg new file mode 100644 index 00000000..b438dcba --- /dev/null +++ b/public/illustrations/round11.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/illustrations/sky-round.svg b/public/illustrations/sky-round.svg new file mode 100644 index 00000000..736d43aa --- /dev/null +++ b/public/illustrations/sky-round.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/app/[locale]/impressum/page.tsx b/src/app/[locale]/impressum/page.tsx new file mode 100644 index 00000000..0ecb7653 --- /dev/null +++ b/src/app/[locale]/impressum/page.tsx @@ -0,0 +1,92 @@ +import Image from 'next/image' +import type { Metadata } from 'next' + +interface ImpressumPageProps { + params: Promise<{ + locale: string + }> +} + +export async function generateMetadata({ params }: ImpressumPageProps): Promise { + const { locale } = await params + + const title = locale === 'de' ? 'Impressum - Open Elements' : 'Impressum - Open Elements' + const description = locale === 'de' ? 'Impressum' : 'Impressum' + + return { + title, + description, + openGraph: { + type: 'website', + title, + description, + siteName: 'Open Elements', + locale: locale === 'de' ? 'de_DE' : 'en_US', + }, + } +} + +export default async function ImpressumPage({ params }: ImpressumPageProps) { + const { locale } = await params + + const contentHtml = + locale === 'de' + ? ` +

+ Open Elements GmbH

+ Gerhart-Hauptmann-Str. 49B
+ 51379 Leverkusen

+ info@open-elements.de
+ Telefon: 0151-22684622

+ Geschäftsführer: Hendrik Ebbers
+ Amtsgericht Köln
+ Registernummer: HRB 112036
+ Umsatzsteuer-Identifikationsnummer: DE 355815175

+ Inhaltlich Verantwortlicher gemäß § 55 Absatz 2 RStV: Hendrik Ebbers, Gerhart-Hauptmann-Str. 49B, 51379 Leverkusen +

+` + : ` +

+ Open Elements GmbH

+ Gerhart-Hauptmann-Str. 49B
+ 51379 Leverkusen
+ Germany

+ info@open-elements.de
+ Fon: +49 151-22684622

+ Managing director: Hendrik Ebbers
+ Local Court Cologne
+ Registration number: HRB 112036
+ Sales tax identification number: DE 355815175

+ Responsible for the content according to § 55 paragraph 2 RStV: Hendrik Ebbers, Gerhart-Hauptmann-Str. 49B, 51379 Leverkusen +

+` + + return ( +
+
+
+
+

Impressum

+ {locale +
+
+
+ +
+
+
+
+
+
+ ) +} \ No newline at end of file diff --git a/src/app/[locale]/layout.tsx b/src/app/[locale]/layout.tsx index 694a5bb8..c8439991 100644 --- a/src/app/[locale]/layout.tsx +++ b/src/app/[locale]/layout.tsx @@ -4,8 +4,6 @@ import { notFound } from 'next/navigation'; import { routing } from '@/i18n/routing'; import type { Metadata } from 'next' import { Montserrat } from 'next/font/google' -import Script from 'next/script' -import '../globals.css' import Navbar from '@/components/Navbar' import Footer from '@/components/Footer' import Script from 'next/script'; diff --git a/src/app/[locale]/updates/page.tsx b/src/app/[locale]/updates/page.tsx new file mode 100644 index 00000000..dc09673f --- /dev/null +++ b/src/app/[locale]/updates/page.tsx @@ -0,0 +1,34 @@ +import { getAllUpdates } from '@/lib/updates'; +import { getTranslations } from 'next-intl/server'; +import UpdatesClient from '@/components/UpdatesClient'; + +export async function generateMetadata({ + params, +}: { + params: Promise<{ locale: string }>; +}) { + const { locale } = await params; + const t = await getTranslations({ locale, namespace: 'updates' }); + + return { + title: t('metaTitle'), + description: t('metaDescription'), + openGraph: { + title: t('metaTitle'), + description: t('metaDescription'), + type: 'website', + }, + }; +} + +export default async function UpdatesPage({ + params, +}: { + params: Promise<{ locale: string }>; +}) { + const { locale } = await params; + const updates = getAllUpdates(locale); + + return ; +} + diff --git a/src/components/UpdatesClient.tsx b/src/components/UpdatesClient.tsx new file mode 100644 index 00000000..b1bec328 --- /dev/null +++ b/src/components/UpdatesClient.tsx @@ -0,0 +1,361 @@ +'use client'; + +import { useState } from 'react'; +import Image from 'next/image'; +import type { Update, UpdateSection } from '@/types/updates'; +import { useTranslations } from 'next-intl'; + +// Collapsible Section Component +function CollapsibleSection({ section }: { section: UpdateSection }) { + const [open, setOpen] = useState(false); + const t = useTranslations('updates'); + + const getIcon = (iconType?: string) => { + const icons = { + red: '/icons/redTick.svg', + green: '/icons/greenTick.svg', + purple: '/icons/purpleTick.svg', + star: '/icons/star.svg', + }; + return iconType ? icons[iconType as keyof typeof icons] : null; + }; + + const getIconSize = (iconType?: string) => { + return iconType === 'star' ? 'size-4 mt-1.5' : 'size-6'; + }; + + const icon = getIcon(section.icon); + const iconSize = getIconSize(section.icon); + + if (!section.collapsible) { + return ( +
+

{section.title}

+
+
    + {section.items.map((item, idx) => ( +
  • + {icon && ( + icon + )} + {item.text} +
  • + ))} +
+
+
+ ); + } + + const visibleItems = section.items.slice(0, 4); + const hiddenItems = section.items.slice(4); + + return ( +
+

{section.title}

+
+
    + {visibleItems.map((item, idx) => ( +
  • + {icon && ( + icon + )} + {item.text} +
  • + ))} +
+ {hiddenItems.length > 0 && open && ( +
    + {hiddenItems.map((item, idx) => ( +
  • + {icon && ( + icon + )} + {item.text} +
  • + ))} +
+ )} +
+ {hiddenItems.length > 0 && ( + + )} +
+ ); +} + +// Truncated Section Component +function TruncatedSection({ section }: { section: UpdateSection }) { + const [open, setOpen] = useState(false); + const t = useTranslations('updates'); + + const icon = section.icon === 'star' ? '/icons/star.svg' : null; + + return ( +
+
+

{section.title}

+ + {t('badge')} + +
+

{t('newFeatures')}

+
+
    + {!open && ( +
    + )} + {section.items.map((item, idx) => ( +
  • + {icon && ( + icon + )} + {item.text} +
  • + ))} +
+ +
+
+ ); +} + +// Update Card Component +function UpdateCard({ update, isLast }: { update: Update; isLast?: boolean }) { + const t = useTranslations('updates'); + + return ( +
  • +
    +
    +
    + {isLast && ( +
    + )} +

    + {update.month} +

    +
    +
    +
    +
    +
    + +
    +

    + {update.version} + {update.isLatest && ( + + {t('latest')} + + )} +

    + + +
    + {update.overview && ( +
    +

    {t('overview')}

    +
    + {update.overview.map((text, idx) => ( +

    + {text} +

    + ))} +
    +
    + )} + + {update.sections.map((section, idx) => { + const isSpecialSection = + section.title.toLowerCase().includes("what's changed") || + section.title.toLowerCase().includes('was hat sich geändert'); + + if (isSpecialSection) { + return ; + } + return ; + })} + + {update.assets && ( +
    +

    + + + + {t('assets')} + + {update.assets} + +

    +
    + )} + + {update.tags && ( +
    +
    + {update.tags.map((tag, idx) => ( + #{tag} + ))} +
    +
    + )} + + {update.contributors && ( +
    +

    {t('contributors')}

    +
    + {update.contributors.map((contributor, idx) => ( + + {contributor.name} + + ))} +
    + {update.contributorNote && ( +

    {update.contributorNote}

    + )} +
    + )} +
    +
    +
  • + ); +} + +// Main Updates Client Component +export default function UpdatesClient({ updates }: { updates: Update[] }) { + const t = useTranslations('updates'); + + return ( +
    +
    + {t('decorationAlt')} + {t('decorationAlt')} + {t('decorationAlt')} + +
    +
    +

    {t('title')}

    +

    {t('description')}

    + {t('underlineAlt')} +
    +
    +
    + +
      + {updates.map((update, idx) => ( + + ))} +
    +
    + ); +} diff --git a/src/data/updates.ts b/src/data/updates.ts new file mode 100644 index 00000000..084d4ef6 --- /dev/null +++ b/src/data/updates.ts @@ -0,0 +1,208 @@ +import type { Update } from '@/types/updates'; + +/** + * Updates data for the changelog page. + * Add new updates at the beginning of the array. + * Mark the most recent update with `isLatest: true`. + */ +export const updatesData: Update[] = [ + { + version: 'v0.1.8', + date: 'NOVEMBER, 2025', + month: 'NOV', + isLatest: true, + overview: [ + 'Pretium augue urna sit vulputate in. Venenatis amet dui augue et interdum. Dolor feugiat morbi pellentesque in at ullamcorper. Quis imperdiet sit ipsum et sodales amet urna.', + 'Pretium augue urna sit vulputate in. Venenatis amet dui augue et interdum. Dolor feugiat morbi pellentesque in at ullamcorper. Quis imperdiet sit ipsum et sodales amet urna.', + ], + sections: [ + { + title: 'Refactored Documentation:', + collapsible: true, + items: [ + { text: 'docs: added changelog conflict resolution examples to docs/common_issues.md' }, + { + text: 'docs: added "One Issue Per Pull Request" section to examples/sdk_developers/common_issues.md.', + }, + { text: 'docs: update pyproject.toml maintainers list.' }, + { text: 'docs: added to README a social follow section' }, + { text: 'docs: added changelog conflict resolution examples to docs/common_issues.md' }, + { + text: 'docs: added "One Issue Per Pull Request" section to examples/sdk_developers/common_issues.md.', + }, + { text: 'docs: update pyproject.toml maintainers list.' }, + { text: 'docs: added to README a social follow section' }, + ], + }, + { + title: 'Bug Fixes:', + icon: 'red', + items: [ + { + text: 'Pharetra sed pellentesque pretium euismod risus iaculis netus. Ac scelerisque posuere viverra sit. Consequat in odio sed tempus faucibus risus. Malesuada turpis nisi lorem volutpat ullamcorper magna.', + }, + { + text: 'Pharetra sed pellentesque pretium euismod risus iaculis netus. Ac scelerisque posuere viverra sit. Consequat in odio sed tempus faucibus risus. Malesuada turpis nisi lorem volutpat ullamcorper magna.', + }, + ], + }, + { + title: 'New Fixes:', + icon: 'green', + items: [ + { + text: 'Pharetra sed pellentesque pretium euismod risus iaculis netus. Ac scelerisque posuere viverra sit. Consequat in odio sed tempus faucibus risus. Malesuada turpis nisi lorem volutpat ullamcorper magna.', + }, + { + text: 'Nunc quis nec urna pellentesque. Mus tempor placerat at lacinia nulla justo iaculis bibendum pretium. Dis ullamcorper scelerisque eget ultricies fermentum fermentum nisi. Eu auctor lorem sed nisl elit posuere purus est.', + }, + { + text: 'Quam enim rhoncus fames et vitae enim molestie tellus. Pulvinar eget diam vestibulum pellentesque sit fringilla ornare augue pellentesque. Consequat nec at proin et vitae elit. Vitae ut cursus suspendisse elementum euismod sit.', + }, + { + text: 'Purus habitant consectetur vulputate gravida. Lacus in neque fermentum viverra eros viverra. Dui odio urna nunc volutpat. In nunc arcu augue eu eu tellus.', + }, + ], + }, + { + title: 'New Features:', + icon: 'purple', + collapsible: true, + items: [ + { + text: 'Quis quam pellentesque at sed in sed orci. Purus varius non arcu cursus malesuada convallis nisl sem pulvinar.', + }, + { text: 'Nisl commodo quis blandit nibh. Odio mauris id eget quis tempor.' }, + { text: 'Sed gravida morbi elit a sit. Nec non amet tortor purus neque amet libero.' }, + { + text: 'Consequat consectetur cras neque mattis. In quam aliquam mattis ut risus risus dis proin lorem.', + }, + { + text: 'Quis quam pellentesque at sed in sed orci. Purus varius non arcu cursus malesuada convallis nisl sem pulvinar.', + }, + { text: 'Nisl commodo quis blandit nibh. Odio mauris id eget quis tempor.' }, + { text: 'Sed gravida morbi elit a sit. Nec non amet tortor purus neque amet libero.' }, + { + text: 'Consequat consectetur cras neque mattis. In quam aliquam mattis ut risus risus dis proin lorem.', + }, + ], + }, + { + title: "What's Changed", + icon: 'star', + items: [ + { + text: 'Eleifend nunc dui ullamcorper lectus at sociis. Gravida eget velit amet at tortor duis. Convallis id pellentesque aenean orci vestibulum arcu nisi arcu. Egestas nulla ullamcorper vulputate venenatis.', + }, + { + text: 'Feugiat convallis quam leo faucibus tristique sed vitae. Enim lectus consectetur eu facilisi nullam. Ut leo morbi condimentum sed. Quis nibh ornare mi orci morbi sed.', + }, + { + text: 'Sit senectus nulla ullamcorper pretium ac vitae. Sem interdum elementum viverra in. Sit sit tincidunt libero vestibulum amet consectetur mi. Nulla etiam urna placerat id diam.', + }, + ], + }, + ], + assets: 2, + tags: ['Tortor', 'Tellus', 'Mattis', 'Luctus', 'Tellus'], + contributors: Array(23).fill({ + name: 'Contributor', + avatar: 'https://cdn.pixabay.com/photo/2025/04/02/18/48/background-9509852_1280.jpg', + url: '#', + }), + contributorNote: + 'Tellus massa commodo at neque eget morbi mus porta mauris. Ac elementum natoque massa arcu tellus lorem eu hac amet.', + }, + { + version: 'v0.1.7', + date: 'OKTOBER, 2025', + month: 'OKT', + sections: [ + { + title: "What's Changed", + icon: 'star', + items: [ + { + text: 'Eleifend nunc dui ullamcorper lectus at sociis. Gravida eget velit amet at tortor duis. Convallis id pellentesque aenean orci vestibulum arcu nisi arcu. Egestas nulla ullamcorper vulputate venenatis.', + }, + { + text: 'Feugiat convallis quam leo faucibus tristique sed vitae. Enim lectus consectetur eu facilisi nullam. Ut leo morbi condimentum sed. Quis nibh ornare mi orci morbi sed.', + }, + { + text: 'Sit senectus nulla ullamcorper pretium ac vitae. Sem interdum elementum viverra in. Sit sit tincidunt libero vestibulum amet consectetur mi. Nulla etiam urna placerat id diam.', + }, + ], + }, + ], + assets: 2, + contributors: Array(5).fill({ + name: 'Contributor', + avatar: 'https://cdn.pixabay.com/photo/2025/04/02/18/48/background-9509852_1280.jpg', + url: '#', + }), + contributorNote: + 'Tellus massa commodo at neque eget morbi mus porta mauris. Ac elementum natoque massa arcu tellus lorem eu hac amet.', + }, + { + version: 'v0.1.6', + date: 'August, 2025', + month: 'AUG', + sections: [ + { + title: "What's Changed", + icon: 'star', + items: [ + { + text: 'Eleifend nunc dui ullamcorper lectus at sociis. Gravida eget velit amet at tortor duis. Convallis id pellentesque aenean orci vestibulum arcu nisi arcu. Egestas nulla ullamcorper vulputate venenatis.', + }, + { + text: 'Feugiat convallis quam leo faucibus tristique sed vitae. Enim lectus consectetur eu facilisi nullam. Ut leo morbi condimentum sed. Quis nibh ornare mi orci morbi sed.', + }, + { + text: 'Sit senectus nulla ullamcorper pretium ac vitae. Sem interdum elementum viverra in. Sit sit tincidunt libero vestibulum amet consectetur mi. Nulla etiam urna placerat id diam.', + }, + { + text: 'Eleifend nunc dui ullamcorper lectus at sociis. Gravida eget velit amet at tortor duis. Convallis id pellentesque aenean orci vestibulum arcu nisi arcu. Egestas nulla ullamcorper vulputate venenatis.', + }, + { + text: 'Feugiat convallis quam leo faucibus tristique sed vitae. Enim lectus consectetur eu facilisi nullam. Ut leo morbi condimentum sed. Quis nibh ornare mi orci morbi sed.', + }, + { + text: 'Sit senectus nulla ullamcorper pretium ac vitae. Sem interdum elementum viverra in. Sit sit tincidunt libero vestibulum amet consectetur mi. Nulla etiam urna placerat id diam.', + }, + ], + }, + ], + }, + { + version: 'v0.1.5', + date: 'September, 2025', + month: 'SEP', + sections: [ + { + title: "What's Changed", + icon: 'star', + items: [ + { + text: 'Eleifend nunc dui ullamcorper lectus at sociis. Gravida eget velit amet at tortor duis. Convallis id pellentesque aenean orci vestibulum arcu nisi arcu. Egestas nulla ullamcorper vulputate venenatis.', + }, + { + text: 'Feugiat convallis quam leo faucibus tristique sed vitae. Enim lectus consectetur eu facilisi nullam. Ut leo morbi condimentum sed. Quis nibh ornare mi orci morbi sed.', + }, + { + text: 'Sit senectus nulla ullamcorper pretium ac vitae. Sem interdum elementum viverra in. Sit sit tincidunt libero vestibulum amet consectetur mi. Nulla etiam urna placerat id diam.', + }, + { + text: 'Eleifend nunc dui ullamcorper lectus at sociis. Gravida eget velit amet at tortor duis. Convallis id pellentesque aenean orci vestibulum arcu nisi arcu. Egestas nulla ullamcorper vulputate venenatis.', + }, + { + text: 'Feugiat convallis quam leo faucibus tristique sed vitae. Enim lectus consectetur eu facilisi nullam. Ut leo morbi condimentum sed. Quis nibh ornare mi orci morbi sed.', + }, + { + text: 'Sit senectus nulla ullamcorper pretium ac vitae. Sem interdum elementum viverra in. Sit sit tincidunt libero vestibulum amet consectetur mi. Nulla etiam urna placerat id diam.', + }, + ], + }, + ], + }, +]; diff --git a/src/lib/updates.ts b/src/lib/updates.ts new file mode 100644 index 00000000..9ebb64b7 --- /dev/null +++ b/src/lib/updates.ts @@ -0,0 +1,205 @@ +import fs from 'fs'; +import path from 'path'; +import matter from 'gray-matter'; +import type { Update, UpdateSection } from '@/types/updates'; + +const updatesDirectory = path.join(process.cwd(), 'content/updates'); + +interface RawSection { + title: string; + content: string; + metadata: { + icon?: 'red' | 'green' | 'purple' | 'star'; + collapsible?: boolean; + special?: boolean; + }; +} + +/** + * Parse markdown content into sections + */ +function parseMarkdownSections(content: string): { + overview?: string[]; + sections: UpdateSection[]; +} { + const lines = content.split('\n'); + const overview: string[] = []; + const rawSections: RawSection[] = []; + let currentSection: RawSection | null = null; + let isOverview = false; + + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + + // Check for h2 heading (## Title) + if (line.startsWith('## ')) { + // Save previous section + if (currentSection) { + rawSections.push(currentSection); + } + + const title = line.substring(3).trim(); + isOverview = title.toLowerCase() === 'overview' || title.toLowerCase() === 'überblick'; + + if (!isOverview) { + // Start new section + currentSection = { + title, + content: '', + metadata: {}, + }; + } + continue; + } + + // Check for HTML comments with metadata + if (line.trim().startsWith('')) { + const comment = line.trim().slice(4, -3).trim(); + if (currentSection) { + // Parse metadata from comment + const parts = comment.split(',').map((p) => p.trim()); + parts.forEach((part) => { + if (!currentSection) return; + if (part === 'collapsible') { + currentSection.metadata.collapsible = true; + } else if (part === 'special') { + currentSection.metadata.special = true; + } else if (part.startsWith('icon:')) { + const icon = part.split(':')[1].trim() as any; + currentSection.metadata.icon = icon; + } + }); + } + continue; + } + + // Add content to current section or overview + if (isOverview && line.trim()) { + overview.push(line.trim()); + } else if (currentSection) { + currentSection.content += line + '\n'; + } + } + + // Don't forget the last section + if (currentSection) { + rawSections.push(currentSection); + } + + // Convert raw sections to UpdateSection format + const sections: UpdateSection[] = rawSections.map((rawSection) => { + // Parse list items from content + const items = rawSection.content + .split('\n') + .filter((line) => line.trim().startsWith('-')) + .map((line) => ({ + text: line.trim().substring(1).trim(), + })); + + const section: UpdateSection = { + title: rawSection.title, + items, + }; + + if (rawSection.metadata.icon) { + section.icon = rawSection.metadata.icon; + } + + if (rawSection.metadata.collapsible) { + section.collapsible = true; + } + + return section; + }); + + return { + overview: overview.length > 0 ? overview : undefined, + sections, + }; +} + +/** + * Get all update files for a specific locale + */ +export function getUpdateFiles(locale: string): string[] { + if (!fs.existsSync(updatesDirectory)) { + return []; + } + + const files = fs.readdirSync(updatesDirectory); + return files + .filter((file) => file.endsWith(`.${locale}.md`)) + .sort() + .reverse(); // Most recent first +} + +/** + * Parse a single update file + */ +export function parseUpdateFile(filename: string, locale: string): Update | null { + const fullPath = path.join(updatesDirectory, filename); + + if (!fs.existsSync(fullPath)) { + return null; + } + + const fileContents = fs.readFileSync(fullPath, 'utf8'); + const { data, content } = matter(fileContents); + + const { overview, sections } = parseMarkdownSections(content); + + const update: Update = { + version: data.version, + date: data.date, + month: data.month, + isLatest: data.isLatest || false, + sections, + }; + + if (overview) { + update.overview = overview; + } + + if (data.assets) { + update.assets = data.assets; + } + + if (data.tags) { + update.tags = data.tags; + } + + if (data.contributors) { + update.contributors = data.contributors; + } + + if (data.contributorNote) { + update.contributorNote = data.contributorNote; + } + + return update; +} + +/** + * Get all updates for a specific locale + */ +export function getAllUpdates(locale: string): Update[] { + const files = getUpdateFiles(locale); + const updates: Update[] = []; + + for (const filename of files) { + const update = parseUpdateFile(filename, locale); + if (update) { + updates.push(update); + } + } + + return updates; +} + +/** + * Get a single update by version + */ +export function getUpdateByVersion(version: string, locale: string): Update | null { + const filename = `${version}.${locale}.md`; + return parseUpdateFile(filename, locale); +} diff --git a/src/types/updates.ts b/src/types/updates.ts new file mode 100644 index 00000000..3a9a0e3d --- /dev/null +++ b/src/types/updates.ts @@ -0,0 +1,29 @@ +export interface Contributor { + name: string; + avatar: string; + url: string; +} + +export interface UpdateItem { + text: string; +} + +export interface UpdateSection { + title: string; + items: UpdateItem[]; + icon?: 'red' | 'green' | 'purple' | 'star'; + collapsible?: boolean; +} + +export interface Update { + version: string; + date: string; + month: string; + isLatest?: boolean; + overview?: string[]; + sections: UpdateSection[]; + assets?: number; + tags?: string[]; + contributors?: Contributor[]; + contributorNote?: string; +}