Skip to content

Commit

Permalink
fix(nx-dev): Add post build script for blog og images
Browse files Browse the repository at this point in the history
  • Loading branch information
ndcunningham committed Jul 29, 2024
1 parent 55dc25f commit b6956e2
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 5 deletions.
16 changes: 12 additions & 4 deletions nx-dev/nx-dev/app/blog/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import type { Metadata, ResolvingMetadata } from 'next';
import { blogApi } from '../../../lib/blog.api';
import { BlogDetails } from '@nx/nx-dev/ui-blog';
import { DefaultLayout } from '@nx/nx-dev/ui-common';
import { workspaceRoot } from '@nx/devkit';
import * as path from 'path';

interface BlogPostDetailProps {
params: { slug: string };
}
Expand All @@ -12,9 +15,14 @@ export async function generateMetadata(
): Promise<Metadata> {
const post = await blogApi.getBlogPostBySlug(slug);
const previousImages = (await parent).openGraph?.images ?? [];
const openGraphImage = post?.cover_image
? post.cover_image.split('.').slice(0, -1)[0]
: 'nx-media';

const imageOrDefault = post?.cover_image || 'https://nx.dev/socials/nx-media';
const parsedPath = path.parse(imageOrDefault);
const ogImagePath = `${path.resolve(
workspaceRoot,
path.join(parsedPath.dir, parsedPath.name)
)}.png`;

return {
title: `${post.title} | Nx Blog`,
description: 'Latest news from the Nx & Nx Cloud core team',
Expand All @@ -24,7 +32,7 @@ export async function generateMetadata(
description: post.description,
images: [
{
url: `${openGraphImage}.png`,
url: ogImagePath,
width: 800,
height: 421,
alt: 'Nx: Smart, Fast and Extensible Build System',
Expand Down
3 changes: 2 additions & 1 deletion nx-dev/nx-dev/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"options": {
"commands": [
"nx run nx-dev:sitemap",
"ts-node -P ./scripts/tsconfig.scripts.json ./scripts/documentation/internal-link-checker.ts"
"ts-node -P ./scripts/tsconfig.scripts.json ./scripts/documentation/internal-link-checker.ts",
"ts-node -P ./scripts/tsconfig.scripts.json ./scripts/documentation/blog-og-image-checker.ts"
],
"parallel": false
},
Expand Down
98 changes: 98 additions & 0 deletions scripts/documentation/blog-og-image-checker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { workspaceRoot } from '@nx/devkit';
import { Node, parse, Tokenizer } from '@markdoc/markdoc';
import { load as yamlLoad } from '@zkochan/js-yaml';
import * as fs from 'fs';
import * as path from 'path';
import * as chalk from 'chalk';

const tokenizer = new Tokenizer({
allowComments: true,
});

const parseMarkdown: (markdown: string) => Node = (markdown) => {
const tokens = tokenizer.tokenize(markdown);
return parse(tokens);
};

export const extractFrontmatter = (
documentContent: string
): Record<string, any> => {
const ast = parseMarkdown(documentContent);
const frontmatter = ast.attributes['frontmatter']
? (yamlLoad(ast.attributes['frontmatter']) as Record<string, any>)
: {};
return frontmatter;
};

function checkImageExistsSync(imagePath: string): boolean {
try {
fs.accessSync(imagePath, fs.constants.F_OK);
return true;
} catch (error) {
return false;
}
}

console.log(`\n🔍 Checking blog OG images...\n`);

// Main
const blogRootPath = path.join(workspaceRoot, 'docs', 'blog');

const blogFiles: string[] = fs.readdirSync(blogRootPath);
const errors: string[] = [];
const allowedExtensions = ['.png', '.webp', '.jpg', '.jpeg'];

for (const blogFile of blogFiles) {
const blogFilePath = path.join(blogRootPath, blogFile);
if (!blogFile.endsWith('.md')) {
continue;
}
const blogContent = fs.readFileSync(blogFilePath, 'utf8');
const frontmatter = extractFrontmatter(blogContent);

if (!frontmatter.cover_image) {
console.warn(
chalk.yellow(
`⚠ Blog post: ${frontmatter.title} does not have a cover image\n`
)
);
continue;
}
const coverImagePath = path.join(
workspaceRoot,
'docs',
frontmatter.cover_image
);
const { ext, name, dir } = path.parse(coverImagePath);
if (!checkImageExistsSync(coverImagePath)) {
errors.push(
`Cover image for blog post: ${frontmatter.title} does not exist at ${coverImagePath}`
);
} else if (!allowedExtensions.includes(ext)) {
const hasAllowedImageType = allowedExtensions.some((allowedExt) => {
const ogImagePath = `${path.resolve(
workspaceRoot,
path.join(dir, name)
)}${allowedExt}`;
return checkImageExistsSync(ogImagePath);
});
if (!hasAllowedImageType) {
errors.push(
`OG image for blog post: ${
frontmatter.title
} does not have a valid extension. Allowed extensions are: ${allowedExtensions.join(
','
)}`
);
}
}
}

if (errors.length > 0) {
console.error(chalk.red(`✖ Blog OG Images errors:\n`));
errors.forEach((error) => console.error(chalk.red(error)));
process.exit(1);
}

console.log(chalk.green(`\n✔ Blog OG Images are valid`));
process.exit(0);

0 comments on commit b6956e2

Please sign in to comment.