style: format with new style

This commit is contained in:
taskylizard
2024-01-25 16:32:45 +00:00
parent bc3bbaafeb
commit ef422dcda8
43 changed files with 686 additions and 583 deletions

View File

@@ -1,15 +1,20 @@
<script setup lang="ts">
defineProps<{ title: string; description?: string }>();
defineProps<{ title: string; description?: string }>()
</script>
<template>
<div
tw="w-full h-full bg-black flex flex-col"
style="background-image: url(https://fmhy.pages.dev/og.png)">
<div tw="p-10 w-full min-h-0 grow flex flex-col items-center justify-between">
style="background-image: url(https://fmhy.pages.dev/og.png)"
>
<div
tw="p-10 w-full min-h-0 grow flex flex-col items-center justify-between"
>
<div tw="w-full flex justify-between items-center text-5xl font-medium">
<div tw="flex items-center">
<div tw="text-zinc-100 ml-2 mt-1 font-semibold">freemediaheckyeah</div>
<div tw="text-zinc-100 ml-2 mt-1 font-semibold">
freemediaheckyeah
</div>
</div>
</div>
<div tw="w-full pr-56 flex flex-col items-start justify-end">

View File

@@ -2,7 +2,7 @@
* Barrel generated using @taskylizard/tasker.
*/
export * from "./meta";
export * from "./opengraph";
export * from "./rss";
export * from "./satoriConfig";
export * from './meta'
export * from './opengraph'
export * from './rss'
export * from './satoriConfig'

View File

@@ -1,89 +1,100 @@
import type { HeadConfig, TransformContext } from "vitepress";
import type { HeadConfig, TransformContext } from 'vitepress'
export function generateMeta(context: TransformContext, hostname: string) {
const head: HeadConfig[] = [];
const { pageData } = context;
const head: HeadConfig[] = []
const { pageData } = context
const url = `${hostname}/${pageData.relativePath.replace(/((^|\/)index)?\.md$/, "$2")}`;
const url = `${hostname}/${pageData.relativePath.replace(/((^|\/)index)?\.md$/, '$2')}`
head.push(
["link", { rel: "canonical", href: url }],
["meta", { property: "og:url", content: url }],
["meta", { name: "twitter:url", content: url }],
["meta", { name: "twitter:card", content: "summary_large_image" }],
["meta", { property: "og:title", content: pageData.frontmatter.title }],
["meta", { name: "twitter:title", content: pageData.frontmatter.title }],
);
['link', { rel: 'canonical', href: url }],
['meta', { property: 'og:url', content: url }],
['meta', { name: 'twitter:url', content: url }],
['meta', { name: 'twitter:card', content: 'summary_large_image' }],
['meta', { property: 'og:title', content: pageData.frontmatter.title }],
['meta', { name: 'twitter:title', content: pageData.frontmatter.title }]
)
if (pageData.frontmatter.description) {
head.push(
[
"meta",
'meta',
{
property: "og:description",
content: pageData.frontmatter.description,
},
property: 'og:description',
content: pageData.frontmatter.description
}
],
[
"meta",
'meta',
{
name: "twitter:description",
content: pageData.frontmatter.description,
},
],
);
name: 'twitter:description',
content: pageData.frontmatter.description
}
]
)
}
if (pageData.frontmatter.image) {
head.push([
"meta",
'meta',
{
property: "og:image",
content: `${hostname}/${pageData.frontmatter.image.replace(/^\//, "")}`,
},
]);
property: 'og:image',
content: `${hostname}/${pageData.frontmatter.image.replace(/^\//, '')}`
}
])
head.push([
"meta",
'meta',
{
name: "twitter:image",
content: `${hostname}/${pageData.frontmatter.image.replace(/^\//, "")}`,
},
]);
name: 'twitter:image',
content: `${hostname}/${pageData.frontmatter.image.replace(/^\//, '')}`
}
])
} else {
const url = pageData.filePath.replace("index.md", "").replace(".md", "");
const imageUrl = `${url}/__og_image__/og.png`.replaceAll("//", "/").replace(/^\//, "");
const url = pageData.filePath.replace('index.md', '').replace('.md', '')
const imageUrl = `${url}/__og_image__/og.png`
.replaceAll('//', '/')
.replace(/^\//, '')
head.push(
["meta", { property: "og:image", content: `${hostname}/${imageUrl}` }],
["meta", { property: "og:image:width", content: "1200" }],
["meta", { property: "og:image:height", content: "628" }],
["meta", { property: "og:image:type", content: "image/png" }],
["meta", { property: "og:image:alt", content: pageData.frontmatter.title }],
["meta", { name: "twitter:image", content: `${hostname}/${imageUrl}` }],
["meta", { name: "twitter:image:width", content: "1200" }],
["meta", { name: "twitter:image:height", content: "628" }],
["meta", { name: "twitter:image:alt", content: pageData.frontmatter.title }],
);
['meta', { property: 'og:image', content: `${hostname}/${imageUrl}` }],
['meta', { property: 'og:image:width', content: '1200' }],
['meta', { property: 'og:image:height', content: '628' }],
['meta', { property: 'og:image:type', content: 'image/png' }],
[
'meta',
{ property: 'og:image:alt', content: pageData.frontmatter.title }
],
['meta', { name: 'twitter:image', content: `${hostname}/${imageUrl}` }],
['meta', { name: 'twitter:image:width', content: '1200' }],
['meta', { name: 'twitter:image:height', content: '628' }],
[
'meta',
{ name: 'twitter:image:alt', content: pageData.frontmatter.title }
]
)
}
if (pageData.frontmatter.tag) {
head.push(["meta", { property: "article:tag", content: pageData.frontmatter.tag }]);
head.push([
'meta',
{ property: 'article:tag', content: pageData.frontmatter.tag }
])
}
if (pageData.frontmatter.date) {
head.push([
"meta",
'meta',
{
property: "article:published_time",
content: pageData.frontmatter.date,
},
]);
property: 'article:published_time',
content: pageData.frontmatter.date
}
])
}
if (pageData.lastUpdated && pageData.frontmatter.lastUpdated !== false) {
head.push([
"meta",
'meta',
{
property: "article:modified_time",
content: new Date(pageData.lastUpdated).toISOString(),
},
]);
property: 'article:modified_time',
content: new Date(pageData.lastUpdated).toISOString()
}
])
}
return head;
return head
}

View File

@@ -1,71 +1,71 @@
import { mkdir, readFile, writeFile } from "node:fs/promises";
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { createContentLoader } from "vitepress";
import type { ContentData, SiteConfig } from "vitepress";
import { type SatoriOptions, satoriVue } from "x-satori/vue";
import { renderAsync } from "@resvg/resvg-js";
import consola from "consola";
import { mkdir, readFile, writeFile } from 'node:fs/promises'
import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { createContentLoader } from 'vitepress'
import type { ContentData, SiteConfig } from 'vitepress'
import { type SatoriOptions, satoriVue } from 'x-satori/vue'
import { renderAsync } from '@resvg/resvg-js'
import consola from 'consola'
const __dirname = dirname(fileURLToPath(import.meta.url));
const __fonts = resolve(__dirname, "../fonts");
const __dirname = dirname(fileURLToPath(import.meta.url))
const __fonts = resolve(__dirname, '../fonts')
export async function generateImages(config: SiteConfig): Promise<void> {
const pages = await createContentLoader("**/*.md", { excerpt: true }).load();
const template = await readFile(resolve(__dirname, "./Template.vue"), "utf-8");
const pages = await createContentLoader('**/*.md', { excerpt: true }).load()
const template = await readFile(resolve(__dirname, './Template.vue'), 'utf-8')
const fonts: SatoriOptions["fonts"] = [
const fonts: SatoriOptions['fonts'] = [
{
name: "Inter",
data: await readFile(resolve(__fonts, "Inter-Regular.otf")),
name: 'Inter',
data: await readFile(resolve(__fonts, 'Inter-Regular.otf')),
weight: 400,
style: "normal",
style: 'normal'
},
{
name: "Inter",
data: await readFile(resolve(__fonts, "Inter-Medium.otf")),
name: 'Inter',
data: await readFile(resolve(__fonts, 'Inter-Medium.otf')),
weight: 500,
style: "normal",
style: 'normal'
},
{
name: "Inter",
data: await readFile(resolve(__fonts, "Inter-SemiBold.otf")),
name: 'Inter',
data: await readFile(resolve(__fonts, 'Inter-SemiBold.otf')),
weight: 600,
style: "normal",
style: 'normal'
},
{
name: "Inter",
data: await readFile(resolve(__fonts, "Inter-Bold.otf")),
name: 'Inter',
data: await readFile(resolve(__fonts, 'Inter-Bold.otf')),
weight: 700,
style: "normal",
},
];
style: 'normal'
}
]
for (const page of pages) {
await generateImage({
page,
template,
outDir: config.outDir,
fonts,
});
fonts
})
}
return consola.info("Generated opengraph images.");
return consola.info('Generated opengraph images.')
}
interface GenerateImagesOptions {
page: ContentData;
template: string;
outDir: string;
fonts: SatoriOptions["fonts"];
page: ContentData
template: string
outDir: string
fonts: SatoriOptions['fonts']
}
async function generateImage({
page,
template,
outDir,
fonts,
fonts
}: GenerateImagesOptions): Promise<void> {
const { frontmatter, url } = page;
const { frontmatter, url } = page
const options: SatoriOptions = {
width: 1200,
@@ -73,24 +73,24 @@ async function generateImage({
fonts,
props: {
title:
frontmatter.layout === "home"
frontmatter.layout === 'home'
? frontmatter.hero.name ?? frontmatter.title
: frontmatter.title,
description:
frontmatter.layout === "home"
frontmatter.layout === 'home'
? frontmatter.hero.tagline ?? frontmatter.description
: frontmatter.description,
},
};
: frontmatter.description
}
}
const svg = await satoriVue(options, template);
const svg = await satoriVue(options, template)
const render = await renderAsync(svg);
const render = await renderAsync(svg)
const outputFolder = resolve(outDir, url.slice(1), "__og_image__");
const outputFile = resolve(outputFolder, "og.png");
const outputFolder = resolve(outDir, url.slice(1), '__og_image__')
const outputFile = resolve(outputFolder, 'og.png')
await mkdir(outputFolder, { recursive: true });
await mkdir(outputFolder, { recursive: true })
await writeFile(outputFile, render.asPng());
await writeFile(outputFile, render.asPng())
}

View File

@@ -1,9 +1,13 @@
import path from "node:path";
import { writeFileSync } from "node:fs";
import { Feed } from "feed";
import { createContentLoader, type ContentData, type SiteConfig } from "vitepress";
import consola from "consola";
import { meta } from "../constants";
import path from 'node:path'
import { writeFileSync } from 'node:fs'
import { Feed } from 'feed'
import {
createContentLoader,
type ContentData,
type SiteConfig
} from 'vitepress'
import consola from 'consola'
import { meta } from '../constants'
export async function generateFeed(config: SiteConfig): Promise<void> {
const feed: Feed = new Feed({
@@ -11,32 +15,35 @@ export async function generateFeed(config: SiteConfig): Promise<void> {
link: meta.hostname,
title: `FMHY blog`,
description: meta.description,
language: "en-US",
image: "https://github.com/fmhy.png",
language: 'en-US',
image: 'https://github.com/fmhy.png',
favicon: `${meta.hostname}/favicon.ico`,
copyright: `Copyright (c) 2023-present FMHY`,
});
copyright: `Copyright (c) 2023-present FMHY`
})
const posts: ContentData[] = await createContentLoader("posts/*.md", {
const posts: ContentData[] = await createContentLoader('posts/*.md', {
excerpt: true,
render: true,
transform: (rawData) => {
return rawData.sort((a, b) => {
return Number(new Date(b.frontmatter.date)) - Number(new Date(a.frontmatter.date));
});
},
}).load();
return (
Number(new Date(b.frontmatter.date)) -
Number(new Date(a.frontmatter.date))
)
})
}
}).load()
for (const { url, frontmatter, html } of posts) {
feed.addItem({
title: frontmatter.title as string,
id: `${meta.hostname}${url.replace(/\/\d+\./, "/")}`,
link: `${meta.hostname}${url.replace(/\/\d+\./, "/")}`,
id: `${meta.hostname}${url.replace(/\/\d+\./, '/')}`,
link: `${meta.hostname}${url.replace(/\/\d+\./, '/')}`,
date: frontmatter.date,
content: html!,
});
content: html!
})
}
writeFileSync(path.join(config.outDir, "feed.rss"), feed.rss2());
return consola.info("Generated rss feed.");
writeFileSync(path.join(config.outDir, 'feed.rss'), feed.rss2())
return consola.info('Generated rss feed.')
}

View File

@@ -1,47 +1,47 @@
import { readFile } from "node:fs/promises";
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import type { SatoriOptions } from "x-satori/vue";
import { defineSatoriConfig } from "x-satori/vue";
import { readFile } from 'node:fs/promises'
import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import type { SatoriOptions } from 'x-satori/vue'
import { defineSatoriConfig } from 'x-satori/vue'
const __dirname = dirname(fileURLToPath(import.meta.url));
const __fonts = resolve(__dirname, "../fonts");
const __dirname = dirname(fileURLToPath(import.meta.url))
const __fonts = resolve(__dirname, '../fonts')
const fonts: SatoriOptions["fonts"] = [
const fonts: SatoriOptions['fonts'] = [
{
name: "Inter",
data: await readFile(resolve(__fonts, "Inter-Regular.otf")),
name: 'Inter',
data: await readFile(resolve(__fonts, 'Inter-Regular.otf')),
weight: 400,
style: "normal",
style: 'normal'
},
{
name: "Inter",
data: await readFile(resolve(__fonts, "Inter-Medium.otf")),
name: 'Inter',
data: await readFile(resolve(__fonts, 'Inter-Medium.otf')),
weight: 500,
style: "normal",
style: 'normal'
},
{
name: "Inter",
data: await readFile(resolve(__fonts, "Inter-SemiBold.otf")),
name: 'Inter',
data: await readFile(resolve(__fonts, 'Inter-SemiBold.otf')),
weight: 600,
style: "normal",
style: 'normal'
},
{
name: "Inter",
data: await readFile(resolve(__fonts, "Inter-Bold.otf")),
name: 'Inter',
data: await readFile(resolve(__fonts, 'Inter-Bold.otf')),
weight: 700,
style: "normal",
},
];
style: 'normal'
}
]
export default defineSatoriConfig({
width: 1200,
height: 628,
fonts,
props: {
title: "Title",
title: 'Title',
description:
"Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint cillum sint consectetur cupidatat.",
dir: "/j",
},
});
'Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint cillum sint consectetur cupidatat.',
dir: '/j'
}
})