diff --git a/app/manage-breast-screening/2026/03/my-amazing-post/ed-forgot-to-add-a-file-extension b/app/manage-breast-screening/2026/03/my-amazing-post/ed-forgot-to-add-a-file-extension new file mode 100644 index 000000000..2604ac846 --- /dev/null +++ b/app/manage-breast-screening/2026/03/my-amazing-post/ed-forgot-to-add-a-file-extension @@ -0,0 +1,3 @@ +--- +title: This is my great post +--- diff --git a/eleventy.config.js b/eleventy.config.js index 300ae630b..9bfd3cc02 100644 --- a/eleventy.config.js +++ b/eleventy.config.js @@ -2,6 +2,8 @@ import fs from 'node:fs/promises' import { nhsukEleventyPlugin } from '@x-govuk/nhsuk-eleventy-plugin' +import { findFileWithoutExtension } from './lib/find-file-without-extension.js' + const serviceName = 'Digital prevention services design history' export default function (eleventyConfig) { @@ -174,6 +176,17 @@ export default function (eleventyConfig) { // Reset contents of output directory before each build eleventyConfig.on('eleventy.before', async ({ directories, runMode }) => { + // Check for files without extensions in the app directory + const fileWithoutExtension = await findFileWithoutExtension( + directories.input + ) + + if (fileWithoutExtension) { + throw new Error( + `Found file without extension: ${fileWithoutExtension}\n\nDid you forget to add an .md to it?` + ) + } + if (runMode === 'build') { await fs.rm(directories.output, { force: true, diff --git a/lib/find-file-without-extension.js b/lib/find-file-without-extension.js new file mode 100644 index 000000000..dd20da71d --- /dev/null +++ b/lib/find-file-without-extension.js @@ -0,0 +1,38 @@ +import fs from 'node:fs/promises' +import path from 'node:path' + +/** + * Recursively find the first file without an extension in a directory + * + * @param {string} dir - Directory to search + * @returns {Promise} - Path of first file without extension, or null + */ +export async function findFileWithoutExtension(dir) { + async function scan(currentDir) { + const entries = await fs.readdir(currentDir, { withFileTypes: true }) + + for (const entry of entries) { + const fullPath = path.join(currentDir, entry.name) + + if (entry.isDirectory()) { + // Skip directories starting with underscore (e.g. _layouts, _components) + if (!entry.name.startsWith('_')) { + const found = await scan(fullPath) + if (found) return found + } + } else if (entry.isFile()) { + // Skip hidden files (e.g. .gitkeep) + if (!entry.name.startsWith('.')) { + // Check if the file has no extension + const ext = path.extname(entry.name) + if (ext === '') { + return fullPath + } + } + } + } + return null + } + + return scan(dir) +}