Website: markdown to release (#4146)

* website: markdown to release

* remove Image.png

* fixed font weight

* Change folder structure

* remove react-markdown

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
This commit is contained in:
brendanlaschke
2024-02-24 12:29:37 +01:00
committed by GitHub
parent 87f7c75057
commit a2eca16646
7 changed files with 278 additions and 0 deletions

View File

@ -0,0 +1,36 @@
'use client';
import styled from '@emotion/styled';
const StyledLineContainer = styled.div`
width: 810px;
margin: 0 auto;
display: flex;
@media (max-width: 810px) {
width: auto;
margin: 24px 0;
display: block;
}
`;
const StyledLine = styled.div`
height: 1px;
background-color: #d9d9d9;
margin-bottom: 48px;
margin-left: 148px;
margin-top: 48px;
width: 100%;
@media (max-width: 810px) {
margin: 0;
}
`;
export const Line = () => {
return (
<StyledLineContainer>
<StyledLine />
</StyledLineContainer>
);
};

View File

@ -0,0 +1,110 @@
'use client';
import styled from '@emotion/styled';
import { Gabarito } from 'next/font/google';
import { compileMDX } from 'next-mdx-remote/rsc';
import remarkBehead from 'remark-behead';
import gfm from 'remark-gfm';
import { ReleaseNote } from '@/app/get-releases';
const StyledContainer = styled.div`
width: 810px;
margin: 0 auto;
display: flex;
font-weight: 400;
@media (max-width: 810px) {
width: auto;
margin: 24px 0;
display: block;
}
`;
const StyledVersion = styled.div`
text-align: center;
width: 148px;
font-size: 24px;
display: flex;
flex-flow: column;
align-items: start;
font-weight: 500;
@media (max-width: 810px) {
width: 100%;
font-size: 20px;
flex-flow: row;
justify-content: space-between;
}
`;
const StyledRelease = styled.span`
color: #b3b3b3;
`;
const StyledDate = styled.span`
color: #474747;
font-size: 16px;
`;
const StlyedContent = styled.div`
flex: 1;
h3 {
color: #141414;
font-size: 40px;
margin: 0;
}
p {
color: #474747;
font-size: 16px;
line-height: 28.8px;
color: #818181;
font-weight: 400;
}
img {
max-width: 100%;
}
`;
const gabarito = Gabarito({
weight: ['400', '500'],
subsets: ['latin'],
display: 'swap',
adjustFontFallback: false,
});
export const Release = async ({ release }: { release: ReleaseNote }) => {
let mdxSource;
try {
mdxSource = await compileMDX({
source: release.content,
options: {
mdxOptions: {
remarkPlugins: [gfm, [remarkBehead, { depth: 2 }]],
},
},
});
mdxSource = mdxSource.content;
} catch (error) {
console.error('An error occurred during MDX rendering:', error);
mdxSource = `<p>Oops! Something went wrong.</p> ${error}`;
}
return (
<StyledContainer className={gabarito.className}>
<StyledVersion>
<StyledRelease>{release.release}</StyledRelease>
<StyledDate>
{release.date.endsWith(new Date().getFullYear().toString())
? release.date.slice(0, -5)
: release.date}
</StyledDate>
</StyledVersion>
<StlyedContent>{mdxSource}</StlyedContent>
</StyledContainer>
);
};

View File

@ -0,0 +1,30 @@
'use client';
import styled from '@emotion/styled';
const StyledTitle = styled.div`
margin: 64px auto;
text-align: center;
font-size: 1.8em;
@media (max-width: 810px) {
font-size: 1em;
margin: 16px auto;
}
`;
const StyledHeader = styled.h1`
color: #b3b3b3;
margin: 0;
`;
const StyledSubHeader = styled.h1`
margin: 0;
`;
export const Title = () => {
return (
<StyledTitle>
<StyledHeader>Latest</StyledHeader>
<StyledSubHeader>Releases</StyledSubHeader>
</StyledTitle>
);
};

View File

@ -0,0 +1,49 @@
import fs from 'fs';
import matter from 'gray-matter';
export interface ReleaseNote {
slug: string;
date: string;
release: string;
content: string;
}
function compareSemanticVersions(a: string, b: string) {
const a1 = a.split('.');
const b1 = b.split('.');
const len = Math.min(a1.length, b1.length);
for (let i = 0; i < len; i++) {
const a2 = +a1[i] || 0;
const b2 = +b1[i] || 0;
if (a2 !== b2) {
return a2 > b2 ? 1 : -1;
}
}
return b1.length - a1.length;
}
export async function getReleases(): Promise<ReleaseNote[]> {
const files = fs.readdirSync('src/content/releases');
const releasenotes: ReleaseNote[] = [];
for (const fileName of files) {
if (!fileName.endsWith('.md') && !fileName.endsWith('.mdx')) {
continue;
}
const file = fs.readFileSync(`src/content/releases/${fileName}`, 'utf-8');
const { data: frontmatter, content } = matter(file);
releasenotes.push({
slug: fileName.slice(0, -4),
date: frontmatter.Date,
release: frontmatter.release,
content: content,
});
}
releasenotes.sort((a, b) => compareSemanticVersions(b.release, a.release));
return releasenotes;
}

View File

@ -0,0 +1,32 @@
import React from 'react';
import { Metadata } from 'next';
import { Line } from '@/app/_components/releases/Line';
import { Release } from '@/app/_components/releases/Release';
import { Title } from '@/app/_components/releases/StyledTitle';
import { ContentContainer } from '@/app/_components/ui/layout/ContentContainer';
import { getReleases } from '@/app/get-releases';
export const metadata: Metadata = {
title: 'Twenty - Releases',
description: 'Latest releases of Twenty',
};
const Home = async () => {
const releases = await getReleases();
return (
<ContentContainer>
<Title />
{releases.map((note, index) => (
<React.Fragment key={note.slug}>
<Release release={note} />
{index != releases.length - 1 && <Line />}
</React.Fragment>
))}
</ContentContainer>
);
};
export default Home;