Remove contentlayer, bump next

This commit is contained in:
Jakob Kordež
2024-06-10 12:58:00 +02:00
parent 94aa29e252
commit 14f67288fb
18 changed files with 2579 additions and 3390 deletions

2
.gitignore vendored
View File

@ -1,7 +1,5 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
.contentlayer/
package-lock.json
# dependencies

View File

@ -7,9 +7,9 @@ authors:
image: "/images/gallery/stol_skupinska.jpg"
---
Včeraj smo se Aleks [S51PA], Domen, Kimi, Primož [S54UNC], Sergio [OE8CXC] in Žiga [S50ZK] odpravili na pohod na Karavanški Stol.
Včeraj smo se Aleks [S51PA], Domen, Kimi, Primož [S54UNC], Sergio [OE8CXC] in Žiga [S50ZK] odpravili na pohod na Karavanški Stol.
Po 3-urnem pohodu smo se v Prešernovi koči okrepčali ter srečali s skrbnikom repetitorja Stol, Alenom [S56RAL], ki nam je tudi razkazal bivak. Odpravili smo se proti SOTA vrhu S5/KA-001, ki smo ga tudi aktivirali. Po končani aktivaciji smo na bivaku postavili še Diamond X300 anteno in z njo opravili nekaj zvez.
Po 3-urnem pohodu smo se v Prešernovi koči okrepčali ter srečali s skrbnikom repetitorja Stol, Alenom [S56RAL], ki nam je tudi razkazal bivak. Odpravili smo se proti SOTA vrhu S5/KA-001, ki smo ga tudi aktivirali. Po končani aktivaciji smo na bivaku postavili še Diamond X300 anteno in z njo opravili nekaj zvez.
Po prihodu v dolino smo se ustavili na Bledu pri našem članu Jerneju [S54JR], ki nas je pogostil z domačimi dobrotami. Po končani pogostitvi smo se še ohladili v prijetno toplem Blejskem jezeru.

View File

@ -1,5 +1,4 @@
const path = require("path");
const ncl = require("next-contentlayer");
/** @type {import('next').NextConfig} */
const nextConfig = {
@ -9,4 +8,4 @@ const nextConfig = {
},
};
module.exports = ncl.withContentlayer(nextConfig);
module.exports = nextConfig;

View File

@ -14,31 +14,33 @@
"@fortawesome/free-brands-svg-icons": "^6.2.1",
"@fortawesome/free-solid-svg-icons": "^6.2.1",
"@fortawesome/react-fontawesome": "^0.2.0",
"@types/node": "^20.6.5",
"@types/react": "^18.2.22",
"@types/react-dom": "^18.2.7",
"@types/rss": "^0.0.32",
"bulma": "^0.9.4",
"contentlayer": "0.3.2",
"eslint": "^8.50.0",
"eslint-config-next": "^13.5.2",
"exifreader": "^4.12.0",
"next": "^13.5.2",
"next-contentlayer": "0.3.2",
"next": "^14.2.3",
"next-mdx-remote": "^5.0.0",
"next-plausible": "^3.7.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"rehype-autolink-headings": "^6.1.1",
"rehype-pretty-code": "^0.9.3",
"rehype-slug": "^5.1.0",
"remark-gfm": "^3.0.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"rehype-autolink-headings": "^7.1.0",
"rehype-pretty-code": "^0.13.0",
"rehype-slug": "^6.0.0",
"remark-gfm": "^4.0.0",
"rss": "^1.2.2",
"sass": "^1.68.0",
"sharp": "^0.32.6",
"shiki": "^0.14.0",
"typescript": "^5.2.2"
"shiki": "^1.2.1"
},
"devDependencies": {
"prettier": "^2.8.3"
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"@types/rss": "^0.0.32",
"@typescript-eslint/eslint-plugin": "^7.3.1",
"@typescript-eslint/parser": "^7.3.1",
"eslint": "^8",
"eslint-config-next": "^14.1.3",
"eslint-config-prettier": "^9.0.0",
"prettier": "^3.2.5",
"sass": "^1.68.0",
"typescript": "^5.4.5"
}
}

View File

@ -1,12 +1,10 @@
import { notFound } from "next/navigation";
import { allBlogs } from "contentlayer/generated";
import { useMDXComponent } from "next-contentlayer/hooks";
import { allBlogs } from "@/util/posts";
import { Metadata } from "next";
import { DiscordInvite } from "@/components/discord_invite";
import ModalImage from "@/components/modal_image";
import { MDX } from "@/components/mdx";
export function generateStaticParams() {
return allBlogs.map((post) => ({ slug: post.slug }));
export async function generateStaticParams() {
return (await allBlogs).map((post) => ({ slug: post.slug }));
}
interface BlogPageProps {
@ -15,8 +13,10 @@ interface BlogPageProps {
};
}
export function generateMetadata({ params }: BlogPageProps): Metadata {
const post = allBlogs.find((post) => post.slug === params.slug);
export async function generateMetadata({
params,
}: BlogPageProps): Promise<Metadata> {
const post = (await allBlogs).find((post) => post.slug === params.slug);
if (!post) return {};
@ -37,41 +37,13 @@ export function generateMetadata({ params }: BlogPageProps): Metadata {
};
}
function BlogImage(props: any) {
return (
<div className="mb-4 is-flex">
<div className="mx-auto blog-img">
<ModalImage
image={props.src}
alt={props.alt}
height={800}
width={800}
{...props}
/>
</div>
</div>
);
}
function Paragraph(props: any) {
return <div className="mb-4" {...props} />;
}
const components = {
p: Paragraph,
img: BlogImage,
DiscordInvite,
};
export default function Blog({ params }: BlogPageProps) {
const post = allBlogs.find((post) => post.slug === params.slug);
export default async function Blog({ params }: BlogPageProps) {
const post = (await allBlogs).find((post) => post.slug === params.slug);
if (!post) {
notFound();
}
const Component = useMDXComponent(post.body.code);
return (
<div className="container blog-container">
<section className="section">
@ -90,7 +62,7 @@ export default function Blog({ params }: BlogPageProps) {
</div>
</div>
<article>
<Component components={components} />
<MDX source={post.content} />
</article>
</div>
</section>

View File

@ -1,5 +1,5 @@
import { Metadata } from "next";
import { allBlogs } from "contentlayer/generated";
import { allBlogs } from "@/util/posts";
import { ArticleLink } from "@/components/article_link";
export const metadata: Metadata = {
@ -11,7 +11,7 @@ export const metadata: Metadata = {
},
};
export default function BlogPage() {
export default async function BlogPage() {
return (
<div className="container">
<section className="section">
@ -21,7 +21,7 @@ export default function BlogPage() {
className="is-flex is-flex-direction-column is-align-items-start"
style={{ gap: "1rem" }}
>
{allBlogs
{(await allBlogs)
.sort((a, b) => {
const dateA = new Date(a.publishedAt).valueOf();
const dateB = new Date(b.publishedAt).valueOf();

View File

@ -1,5 +1,5 @@
import RSS from "rss";
import { allBlogs, Blog } from "contentlayer/generated";
import { allBlogs, BlogPost } from "@/util/posts";
function buildAuthorList(authors: string[]): string {
let toReturn: string = "";
@ -25,8 +25,8 @@ export async function GET() {
language: "sl",
});
allBlogs
.sort((a: Blog, b: Blog) => {
(await allBlogs)
.sort((a: BlogPost, b: BlogPost) => {
const dateA = new Date(a.publishedAt).valueOf();
const dateB = new Date(b.publishedAt).valueOf();
if (dateA !== dateB) {
@ -35,7 +35,7 @@ export async function GET() {
return a.title.localeCompare(b.title);
})
.map((blog: Blog) =>
.map((blog: BlogPost) =>
feed.item({
title: blog.title,
guid: blog.slug,
@ -43,7 +43,7 @@ export async function GET() {
date: blog.publishedAt,
description: blog.summary,
author: buildAuthorList(blog.authors),
})
}),
);
return new Response(feed.xml({ indent: true }), {

View File

@ -26,7 +26,7 @@ export default async function Gallery() {
alt: exif?.ImageDescription?.description ?? "",
time: exif?.DateTimeOriginal?.description,
};
})
}),
);
const images = imgWithMeta.sort((a, b) => {

View File

@ -5,10 +5,14 @@ import "@fortawesome/fontawesome-svg-core/styles.css";
config.autoAddCss = false;
import Header from "@/components/header";
import { Metadata } from "next";
import { Metadata, Viewport } from "next";
import PlausibleProvider from "next-plausible";
import Footer from "@/components/footer";
export const viewport: Viewport = {
themeColor: "#FF5100",
};
export const metadata: Metadata = {
title: {
default: "Radioklub Vegova",
@ -16,7 +20,6 @@ export const metadata: Metadata = {
},
description: "Spletna stran Radiokluba Vegova",
metadataBase: new URL("https://www.s59veg.si"),
themeColor: "#FF5100",
openGraph: {
title: {
default: "Radioklub Vegova",

View File

@ -1,7 +1,6 @@
import Image from "next/image";
import Link from "next/link";
import { Metadata } from "next";
import { allBlogs } from "contentlayer/generated";
import { allBlogs } from "@/util/posts";
import { DiscordInvite } from "@/components/discord_invite";
import { ArticleLink } from "@/components/article_link";
import ModalImage from "@/components/modal_image";
@ -13,7 +12,9 @@ export const metadata: Metadata = {
},
};
export default function Home() {
export default async function Home() {
const blogs = await allBlogs;
return (
<div className="container">
<section className="section">
@ -68,7 +69,7 @@ export default function Home() {
</div>
<h3>Najnovejše objave</h3>
<div className="article-grid">
{allBlogs
{blogs
.sort((a, b) => {
const dateA = new Date(a.publishedAt).valueOf();
const dateB = new Date(b.publishedAt).valueOf();

View File

@ -1,7 +1,7 @@
import { allBlogs } from "contentlayer/generated";
import { allBlogs } from "@/util/posts";
import { MetadataRoute } from "next";
export default function sitemap(): MetadataRoute.Sitemap {
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const host = "https://www.s59veg.si";
const pages = ["", "/blog", "/galerija", "/tecaj"].map((url) => ({
@ -9,7 +9,7 @@ export default function sitemap(): MetadataRoute.Sitemap {
lastModified: new Date(),
}));
const posts = allBlogs.map((post) => ({
const posts = (await allBlogs).map((post) => ({
url: `${host}/blog/${post.slug}`,
lastModified: new Date(post.publishedAt),
}));

View File

@ -1,9 +1,9 @@
import { Blog } from "contentlayer/generated";
import { BlogPost } from "@/util/posts";
import Image from "next/image";
import Link from "next/link";
interface ArticleLinkProps {
post: Blog;
post: BlogPost;
}
export function ArticleLink({ post }: ArticleLinkProps) {

View File

@ -2,14 +2,12 @@ import {
faDiscord,
faFacebook,
faInstagram,
faYoutube,
} from "@fortawesome/free-brands-svg-icons";
import {
faEnvelope,
faFilm,
faPhone,
faRss,
faVideo,
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import Image from "next/image";

73
src/components/mdx.tsx Normal file
View File

@ -0,0 +1,73 @@
import { MDXRemote } from "next-mdx-remote/rsc";
import remarkGfm from "remark-gfm";
import rehypeSlug from "rehype-slug";
import rehypePrettyCode from "rehype-pretty-code";
import ModalImage from "./modal_image";
import { DiscordInvite } from "./discord_invite";
function BlogImage(props: any) {
return (
<div className="mb-4 is-flex">
<div className="mx-auto blog-img">
<ModalImage
image={props.src}
alt={props.alt}
height={800}
width={800}
{...props}
/>
</div>
</div>
);
}
function Paragraph(props: any) {
return <div className="mb-4" {...props} />;
}
const components = {
p: Paragraph,
img: BlogImage,
DiscordInvite,
};
export function MDX({ source }: { source: string }) {
return (
<MDXRemote
source={source}
components={components}
options={{
parseFrontmatter: true,
mdxOptions: {
remarkPlugins: [remarkGfm],
rehypePlugins: [
rehypeSlug,
[
rehypePrettyCode,
{
theme: "one-dark-pro",
onVisitLine(node: { children: string | any[] }) {
// Prevent lines from collapsing in `display: grid` mode, and allow empty
// lines to be copy/pasted
if (node.children.length === 0) {
node.children = [{ type: "text", value: " " }];
}
},
onVisitHighlightedLine(node: {
properties: { className: string[] };
}) {
node.properties.className.push("line--highlighted");
},
onVisitHighlightedWord(node: {
properties: { className: string[] };
}) {
node.properties.className = ["word--highlighted"];
},
},
],
],
},
}}
/>
);
}

View File

@ -3,7 +3,9 @@
color: white;
font-weight: 500;
transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out;
transition:
background-color 0.2s ease-in-out,
color 0.2s ease-in-out;
&:hover,
&:active,

46
src/util/posts.ts Normal file
View File

@ -0,0 +1,46 @@
import fs from "fs";
import { serialize } from "next-mdx-remote/serialize";
import path from "path";
export interface BlogPost {
title: string;
publishedAt: string;
summary: string;
authors: string[];
slug: string;
image?: string;
content: string;
}
const getBlogs = async (): Promise<BlogPost[]> => {
const fPath = path.join(process.cwd(), "content/blog");
const files = fs.readdirSync(fPath);
const posts = await Promise.all(
files.map(async (file) => {
const source = fs.readFileSync(path.join(fPath, file), "utf8");
const x = await serialize(source, { parseFrontmatter: true });
return {
title: x.frontmatter.title as string,
publishedAt: x.frontmatter.publishedAt as string,
summary: x.frontmatter.summary as string,
authors: x.frontmatter.authors as string[],
slug: file.replace(/\.mdx$/, ""),
image: x.frontmatter.image as string | undefined,
content: source,
};
}),
);
return posts.sort((a, b) => {
const dateA = new Date(a.publishedAt).valueOf();
const dateB = new Date(b.publishedAt).valueOf();
if (dateA !== dateB) {
return dateB - dateA;
}
return a.title.localeCompare(b.title);
});
};
export const allBlogs: Promise<BlogPost[]> = getBlogs();

View File

@ -16,8 +16,7 @@
"incremental": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
"contentlayer/generated": ["./.contentlayer/generated"]
"@/*": ["./src/*"]
},
"plugins": [
{
@ -25,12 +24,6 @@
}
]
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".contentlayer/generated",
".next/types/**/*.ts"
],
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}

5690
yarn.lock

File diff suppressed because it is too large Load Diff