Skip to content

Commit

Permalink
Rewritten core of blogs...
Browse files Browse the repository at this point in the history
  • Loading branch information
LeunensMichiel committed Nov 6, 2021
1 parent 9bb4dd6 commit 520e7cf
Show file tree
Hide file tree
Showing 29 changed files with 1,941 additions and 308 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

# production
/build
*.tsbuildinfo

# misc
.DS_Store
Expand Down
3 changes: 1 addition & 2 deletions .prettierrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,5 @@
"tabWidth": 2,
"printWidth": 80,
"singleQuote": true,
"trailingComma": "es5",
"jsxBracketSameLine": false
"trailingComma": "es5"
}
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ This is an opinionated starter template in `Next.js v11` which uses all best pra
- :white_check_mark: OnClickOutside and other usefull hooks
- :white_check_mark: Cookie consent
- :white_check_mark: Form validation
- :white_check_mark: MDX / Markdown page generation
- :x: Privacy Policy / Terms and conditions page
- :white_check_mark: MDX & MD page generation with i18n
- :white_check_mark: Privacy & Terms and conditions page

### UI-components

Expand Down Expand Up @@ -81,7 +81,7 @@ This is an opinionated starter template in `Next.js v11` which uses all best pra
- :white_check_mark: `robots.txt`
- :white_check_mark: Smooth scrolling with polyfill
- :hammer: Lighthouse optimizations
- :x: Inter-browser compatibility
- :hammer: Inter-browser compatibility

### Future

Expand Down
6 changes: 5 additions & 1 deletion components/common/Footer/Footer.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import Link from 'next/link';
import useTranslation from 'next-translate/useTranslation';

import styles from './Footer.module.scss';

const Footer = () => {
const { t } = useTranslation();
return (
<footer className={styles.footer}>{t('common:footer.footnote')}</footer>
<footer className={styles.footer}>
<span>{t('common:footer.footnote')}</span>
<Link href="/privacy">Privacy</Link>
</footer>
);
};

Expand Down
File renamed without changes.
76 changes: 76 additions & 0 deletions components/common/Page/MarkdownPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { ImageWithAspectRatio } from '@components/ui';
import cn from 'classnames';
import { MDXRemote, MDXRemoteSerializeResult } from 'next-mdx-remote';
import { NextSeo } from 'next-seo';
import useTranslation from 'next-translate/useTranslation';
import { FC } from 'react';

import styles from './MarkdownPage.module.scss';

export type IFrontmatter = {
slug: string;
date: string;
title: string;
description: string;
thumbnail?: string;
};

type MarkdownPageProps = {
mdxSource: MDXRemoteSerializeResult;
frontmatter: IFrontmatter;
locale?: string;
};

const MarkdownPage: FC<MarkdownPageProps> = ({
mdxSource,
frontmatter,
locale,
}) => {
const { t } = useTranslation();
const pageDate = new Date(frontmatter.date);

return (
<>
<NextSeo
title={frontmatter.title}
description={frontmatter.description}
openGraph={{
title: frontmatter.title,
description: frontmatter.description,
...(frontmatter.thumbnail && {
images: [
{
url: frontmatter.thumbnail,
width: 800,
height: 600,
alt: frontmatter.title,
},
],
}),
}}
/>
{mdxSource && (
<article className={cn(styles.article)}>
<header className={cn(styles.header, 'container padded')}>
<h1>{frontmatter.title}</h1>
<small>{`${t(
'common:date.published'
)} ${pageDate.toLocaleDateString(locale)}`}</small>
</header>
{frontmatter.thumbnail && (
<ImageWithAspectRatio
wrapperClassName={cn(styles.thumbnail)}
src={frontmatter.thumbnail}
aspectRatio="4/1"
/>
)}
<div className={cn(styles.content, 'container-page mx-auto padded')}>
<MDXRemote {...mdxSource} />
</div>
</article>
)}
</>
);
};

export default MarkdownPage;
1 change: 1 addition & 0 deletions components/common/Page/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as MarkdownPage } from './MarkdownPage';
1 change: 1 addition & 0 deletions components/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export { default as Head } from './Head';
export { default as LanguagePicker } from './LanguagePicker';
export { default as Layout } from './Layout';
export { default as Navbar } from './Navbar';
export { MarkdownPage } from './Page';
133 changes: 88 additions & 45 deletions lib/mdxUtils.ts
Original file line number Diff line number Diff line change
@@ -1,82 +1,125 @@
import fs from 'fs';
import matter from 'gray-matter';
import path, { join } from 'path';
import path from 'path';

type Items = {
type MarkdownData = {
[key: string]: string;
};

type Item = {
data: {
type MarkdownFile = {
data?: {
[key: string]: string;
};
content: string;
content?: string;
};

export const ITEM_PATH_TYPE = {
Post: path.join(process.cwd(), 'markdown/posts'),
};
type MARKDOWN_SUBFOLDER_TYPE = 'posts' | 'test';

function getMarkdownFolderPathByTypeAndLocale(
locale: string,
type?: MARKDOWN_SUBFOLDER_TYPE
): string {
return type
? path.join(process.cwd(), `markdown/${locale}/${type}`)
: path.join(process.cwd(), `markdown/${locale}`);
}

function getItemPaths(
type: typeof ITEM_PATH_TYPE[keyof typeof ITEM_PATH_TYPE]
function getMarkdownPathsByTypeAndLocale(
locale: string,
type?: MARKDOWN_SUBFOLDER_TYPE
): string[] {
const markdownFolderPath = getMarkdownFolderPathByTypeAndLocale(locale, type);
return (
fs
.readdirSync(type)
.readdirSync(markdownFolderPath)
// Only include md(x) files
.filter((itemPath) => /\.mdx?$/.test(itemPath))
.filter((markdownFolderPath) => /\.mdx?$/.test(markdownFolderPath))
);
}

export function getItem(
type: typeof ITEM_PATH_TYPE[keyof typeof ITEM_PATH_TYPE],
slug: string
): Item {
const fullPath = join(type, `${slug}.mdx`);
let fileContents;
if (fs.existsSync(fullPath)) {
fileContents = fs.readFileSync(fullPath, 'utf8');
} else {
fileContents = fs.readFileSync(join(type, `${slug}.md`), 'utf8');
export function readMarkdownFile(
slug: string,
locale: string,
type?: MARKDOWN_SUBFOLDER_TYPE
): MarkdownFile {
const markdownFolderPath = getMarkdownFolderPathByTypeAndLocale(locale, type);
const markdownFilePathForSlug = fs
.readdirSync(markdownFolderPath)
.filter((file) => file.endsWith('.mdx') || file.endsWith('.md'))
.find((file) => file.startsWith(slug));

if (!markdownFilePathForSlug)
throw new Error(`No markdown files found for given slug ${slug}`);

const fullPath = path.join(markdownFolderPath, markdownFilePathForSlug);

if (!fs.existsSync(fullPath)) {
throw new Error(`Markdown file not found for path ${path}`);
}

const fileContents = fs.readFileSync(fullPath, 'utf8');
const { data, content } = matter(fileContents);

return { data, content };
}

export function getItems(
type: typeof ITEM_PATH_TYPE[keyof typeof ITEM_PATH_TYPE],
export function getMarkdownFrontmatterAndContent(
filePath: string,
fields: string[] = []
): Items {
fields: string[] = [],
locale: string,
type?: MARKDOWN_SUBFOLDER_TYPE
): MarkdownData {
const slug = filePath.replace(/\.mdx?$/, '');
const { data, content } = getItem(type, slug);

const items: Items = {};
const { data, content } = readMarkdownFile(slug, locale, type);

const markdownData: MarkdownData = {};
// Ensure only the minimal needed data is exposed
fields.forEach((field) => {
for (const field of fields) {
if (field === 'slug') {
items[field] = slug;
markdownData[field] = slug;
}
if (field === 'content') {
items[field] = content;
if (field === 'content' && content) {
markdownData[field] = content;
}
if (data[field]) {
items[field] = data[field];
if (data && data[field]) {
markdownData[field] = data[field];
}
});
}

return items;
return markdownData;
}

export function getAllItemsByDate(
type: typeof ITEM_PATH_TYPE[keyof typeof ITEM_PATH_TYPE],
fields: string[] = []
): Items[] {
const filePaths = getItemPaths(type);
const posts = filePaths
.map((filePath) => getItems(type, filePath, fields))
export function getAllMarkdownByDate(
fields: string[] = [],
locale: string,
type?: MARKDOWN_SUBFOLDER_TYPE
): MarkdownData[] {
const markdownPaths = getMarkdownPathsByTypeAndLocale(locale, type);
const data = markdownPaths
.map((filePath) =>
getMarkdownFrontmatterAndContent(filePath, fields, locale, type)
)
.sort((item1, item2) => (item1.date > item2.date ? -1 : 1));
return posts;
return data;
}

export function getAllMarkdownSlugsForType(
locales: string[],
type: MARKDOWN_SUBFOLDER_TYPE
): string[] {
const markDownFolderPaths = locales?.map((locale) => {
return path.join(process.cwd(), `markdown/${locale}/${type}`);
});

const slugs = markDownFolderPaths
?.flatMap((path) =>
fs
.readdirSync(path)
// Only include md(x) files
.filter((path) => /\.mdx?$/.test(path))
)
?.map((slug) => slug.replace(/\.mdx?$/, ''));
const uniqueSlugs = [...new Set(slugs)];

return uniqueSlugs;
}
9 changes: 9 additions & 0 deletions markdown/en/algemene-voorwaarden.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
date: '2021-10-30'
title: Terms and conditions
description: These are the terms and conditions of site
---

## Our terms and conditions

English: Ipsum ea id incididunt sit deserunt voluptate eu ad dolore et enim quis. Sunt aute culpa quis adipisicing laborum occaecat commodo amet ut nisi incididunt proident pariatur non. Pariatur reprehenderit cillum enim nulla proident sunt ex nulla ex. Fugiat consequat officia do laboris aliqua veniam do. Anim fugiat esse proident amet. Eiusmod enim anim duis mollit.
File renamed without changes.
File renamed without changes.
File renamed without changes.
9 changes: 9 additions & 0 deletions markdown/en/privacybeleid.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
date: '2021-10-30'
title: Privacy policy
description: Privacy policy of site
---

## Our privacy policy

English: Ipsum ea id incididunt sit deserunt voluptate eu ad dolore et enim quis. Sunt aute culpa quis adipisicing laborum occaecat commodo amet ut nisi incididunt proident pariatur non. Pariatur reprehenderit cillum enim nulla proident sunt ex nulla ex. Fugiat consequat officia do laboris aliqua veniam do. Anim fugiat esse proident amet. Eiusmod enim anim duis mollit.
9 changes: 9 additions & 0 deletions markdown/fr/algemene-voorwaarden.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
date: '2021-10-30'
title: Termses et conditions
description: Ceci sont les termes et conditions de ce site
---

## Notre termses et conditions

Francais: Ipsum ea id incididunt sit deserunt voluptate eu ad dolore et enim quis. Sunt aute culpa quis adipisicing laborum occaecat commodo amet ut nisi incididunt proident pariatur non. Pariatur reprehenderit cillum enim nulla proident sunt ex nulla ex. Fugiat consequat officia do laboris aliqua veniam do. Anim fugiat esse proident amet. Eiusmod enim anim duis mollit.
Loading

0 comments on commit 520e7cf

Please sign in to comment.