Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
},
"scripts": {
"start": "tsx scripts/dev-server.ts",
"build": "tsc -noEmit && tsx src/generator/build-prod.ts",
"build:dev": "tsx src/generator/build-dev.ts",
"build": "tsc -noEmit && tsx src/generator/build.ts",
"build:dev": "tsx src/generator/build.ts",
"lint": "eslint \"**/*.{js,ts}\" --fix && stylelint \"src/**/*.css\" --fix",
"lint:check": "eslint \"**/*.{js,ts}\" && stylelint \"src/**/*.css\"",
"format": "prettier \"**/*.{css,html,js,json,ts}\" --write --ignore-path .gitignore",
Expand Down
3 changes: 0 additions & 3 deletions src/generator/build-dev.ts

This file was deleted.

10 changes: 0 additions & 10 deletions src/generator/build-prod.ts

This file was deleted.

86 changes: 43 additions & 43 deletions src/generator/build.ts
Original file line number Diff line number Diff line change
@@ -1,68 +1,68 @@
import fs from 'node:fs';
import path from 'node:path';
import { siteConfig } from '../config';
import { getPosts } from './get-posts/get-posts';
import { createAtomFeed } from './feeds/create-atom-feed';
import { createRssFeed } from './feeds/create-rss-feed';
import { createSitemap } from './feeds/create-sitemap';
import { renderPages } from './render-pages/render-pages';
import { DIR_DIST, DIR_SRC_PUBLIC } from './constants';
import {
BASE_URL_DEV,
BASE_URL_PROD,
DIR_DIST,
DIR_SRC_PUBLIC,
} from './constants';
import { optimize } from './optimize/optimize';
import { setState } from './state';
import { copySourceToTarget } from './utils';

type PartialBuildConfig = {
env: 'DEV' | 'PROD';
baseUrl: string;
};

export async function build(buildConfig: PartialBuildConfig): Promise<void> {
const config = {
config: siteConfig,
build: { ...buildConfig, buildDate: new Date() },
};

// Prepare the DIST directory.
fs.rmSync(DIR_DIST, { recursive: true, force: true });
fs.mkdirSync(DIR_DIST);
const config = {
config: siteConfig,
build: { ...getDeployInfo(), buildDate: new Date() },
};

// Copy the content to DIST.
copySourceToTarget(DIR_SRC_PUBLIC, DIR_DIST);
// Prepare the DIST directory.
fs.rmSync(DIR_DIST, { recursive: true, force: true });
fs.mkdirSync(DIR_DIST);

// Prepare the site data object to be able to create HTML pages.
const posts = getPosts(config.build);
const tags = [...new Set(posts.map((post) => post.meta.tags || []).flat())];
setState({ ...config, posts, tags });
// Copy the content to DIST.
copySourceToTarget(DIR_SRC_PUBLIC, DIR_DIST);

// Create the HTML pages.
const pages = await renderPages();
// Prepare the site data object to be able to create HTML pages.
const posts = getPosts(config.build);
const tags = [...new Set(posts.map((post) => post.meta.tags || []).flat())];
setState({ ...config, posts, tags });

// Optimize HTML pages and assets.
await optimize();
// Create the HTML pages.
const pages = await renderPages();

// Create feeds.
createAtomFeed();
createRssFeed();
createSitemap(pages);
}
// Optimize HTML pages and assets.
await optimize();

/**
* Copy the source directory to the target directory.
*/
function copySourceToTarget(source: string, target: string): void {
if (!fs.existsSync(target)) {
fs.mkdirSync(target);
}
// Create feeds.
createAtomFeed();
createRssFeed();
createSitemap(pages);

const entries = fs.readdirSync(source, { withFileTypes: true });
function getDeployInfo(): PartialBuildConfig {
const { CONTEXT, DEPLOY_PRIME_URL } = process.env;

for (const entry of entries) {
const sourcePath = path.join(source, entry.name);
const targetPath = path.join(target, entry.name);

if (entry.isDirectory()) {
copySourceToTarget(sourcePath, targetPath);
} else if (!['.md', '.ts'].includes(path.extname(sourcePath))) {
fs.copyFileSync(sourcePath, targetPath);
}
// Detect Netlify's Deploy Preview deployment.
if (CONTEXT === 'deploy-preview' && DEPLOY_PRIME_URL) {
return { baseUrl: DEPLOY_PRIME_URL, env: 'PROD' };
}
// Detect Netlify's production deployment.
if (CONTEXT === 'production') {
return { baseUrl: BASE_URL_PROD, env: 'PROD' };
}
// Ensure the build is not running in an unexpected Netlify environment.
// The base URL would need to be verified first.
if (typeof CONTEXT !== 'undefined') {
throw new Error('Unknown build environment');
}
return { baseUrl: BASE_URL_DEV, env: 'DEV' };
}
3 changes: 3 additions & 0 deletions src/generator/constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import path from 'node:path';

export const BASE_URL_DEV = 'http://localhost:3000/';
export const BASE_URL_PROD = 'https://tomherni.dev/';

export const DIR_DIST = path.resolve('dist/');
export const DIR_SRC_LAYOUTS = path.resolve('src/includes/layouts/');
export const DIR_SRC_PUBLIC = path.resolve('src/public/');
Expand Down
22 changes: 22 additions & 0 deletions src/generator/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,28 @@ export function createFile(file: string, content: string): void {
fs.writeFileSync(file, content);
}

/**
* Copy the source directory to the target directory.
*/
export function copySourceToTarget(source: string, target: string): void {
if (!fs.existsSync(target)) {
fs.mkdirSync(target);
}

const entries = fs.readdirSync(source, { withFileTypes: true });

for (const entry of entries) {
const sourcePath = path.join(source, entry.name);
const targetPath = path.join(target, entry.name);

if (entry.isDirectory()) {
copySourceToTarget(sourcePath, targetPath);
} else if (!['.md', '.ts'].includes(path.extname(sourcePath))) {
fs.copyFileSync(sourcePath, targetPath);
}
}
}

/**
* Deep find all files in a directory by file extension.
*/
Expand Down