ci: add Makefile and stricter eslint config
This commit is contained in:
+83
-71
@@ -1,129 +1,141 @@
|
||||
import fs from 'fs'
|
||||
import process from 'process'
|
||||
import { Feed } from 'feed'
|
||||
import articlesConfig from './articles/config.json'
|
||||
import fs from "fs";
|
||||
import process from "process";
|
||||
import { Feed } from "feed";
|
||||
import articlesConfig from "./articles/config.json";
|
||||
|
||||
function getFiles(dir: string): string[] {
|
||||
return fs.readdirSync(dir).flatMap((name) => {
|
||||
const path = `${dir}/${name}`
|
||||
const path = `${dir}/${name}`;
|
||||
if (fs.statSync(path).isDirectory()) {
|
||||
return getFiles(path)
|
||||
return getFiles(path);
|
||||
} else {
|
||||
return [path]
|
||||
return [path];
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
const METADATA_BLOCK_REGEX = /^---\n([\s\S]*?)---\n/m
|
||||
const METADATA_REGEX = /^(\w+):(.*)$/gm
|
||||
const METADATA_BLOCK_REGEX = /^---\n([\s\S]*?)---\n/m;
|
||||
const METADATA_REGEX = /^(\w+):(.*)$/gm;
|
||||
|
||||
function readArticleMetadata(path: string): Record<string, string> | null {
|
||||
const content = fs.readFileSync(path, { encoding: 'utf8' })
|
||||
const match: RegExpExecArray | null = METADATA_BLOCK_REGEX.exec(content)
|
||||
if (!match || !match[1]) {
|
||||
console.warn(`No metadata for: ${path}`)
|
||||
return null
|
||||
const content = fs.readFileSync(path, { encoding: "utf8" });
|
||||
const match: RegExpExecArray | null = METADATA_BLOCK_REGEX.exec(content);
|
||||
if (!match?.[1]) {
|
||||
console.warn(`No metadata for: ${path}`);
|
||||
return null;
|
||||
}
|
||||
let subMatch: RegExpExecArray | null = null
|
||||
let subMatch: RegExpExecArray | null = null;
|
||||
const metadata: Record<string, string> = {
|
||||
path: path.replaceAll('/index.md', ''),
|
||||
}
|
||||
path: path.replaceAll("/index.md", ""),
|
||||
};
|
||||
do {
|
||||
subMatch = METADATA_REGEX.exec(match[1])
|
||||
if (subMatch && subMatch[1] && subMatch[2]) {
|
||||
metadata[subMatch[1]] = subMatch[2].trim()
|
||||
subMatch = METADATA_REGEX.exec(match[1]);
|
||||
if (subMatch?.[1] && subMatch[2]) {
|
||||
metadata[subMatch[1]] = subMatch[2].trim();
|
||||
}
|
||||
} while (subMatch)
|
||||
return metadata
|
||||
} while (subMatch);
|
||||
return metadata;
|
||||
}
|
||||
|
||||
function formatArticlePage(metadata: Record<string, string>, baseHtml: string): string {
|
||||
let outHtml = baseHtml
|
||||
outHtml = outHtml.replace(/<.*?property="og:url".*?>/gm, '')
|
||||
function formatArticlePage(
|
||||
metadata: Record<string, string>,
|
||||
baseHtml: string,
|
||||
): string {
|
||||
let outHtml = baseHtml;
|
||||
outHtml = outHtml.replace(/<.*?property="og:url".*?>/gm, "");
|
||||
outHtml = outHtml.replace(
|
||||
/<\/head>/gm,
|
||||
`<meta property="og:url" content="${articlesConfig['base_url']}${metadata.path}/">\n</head>`,
|
||||
)
|
||||
const blog_title = articlesConfig['title']?.replace(/(<([^>]+)>)/gi, '').trim()
|
||||
`<meta property="og:url" content="${articlesConfig.base_url}${metadata.path}/">\n</head>`,
|
||||
);
|
||||
const blog_title = articlesConfig.title.replace(/(<([^>]+)>)/gi, "").trim();
|
||||
if (metadata.title) {
|
||||
const title = metadata.title.replace(/(<([^>]+)>)/gi, '').trim()
|
||||
outHtml = outHtml.replace(/<title>.*?<\/title>/gm, `<title>${blog_title} — ${title}</title>`)
|
||||
outHtml = outHtml.replace(/<.*?property="og:title".*?>/gm, '')
|
||||
const title = metadata.title.replace(/(<([^>]+)>)/gi, "").trim();
|
||||
outHtml = outHtml.replace(
|
||||
/<title>.*?<\/title>/gm,
|
||||
`<title>${blog_title} — ${title}</title>`,
|
||||
);
|
||||
outHtml = outHtml.replace(/<.*?property="og:title".*?>/gm, "");
|
||||
outHtml = outHtml.replace(
|
||||
/<\/head>/gm,
|
||||
`<meta property="og:title" content="${title}">\n</head>`,
|
||||
)
|
||||
outHtml = outHtml.replace(/<.*?property="og:description".*?>/gm, '')
|
||||
);
|
||||
outHtml = outHtml.replace(/<.*?property="og:description".*?>/gm, "");
|
||||
outHtml = outHtml.replace(
|
||||
/<\/head>/gm,
|
||||
`<meta property="og:description" content="${blog_title}">\n</head>`,
|
||||
)
|
||||
);
|
||||
}
|
||||
if (metadata.thumbnail) {
|
||||
outHtml = outHtml.replace(/<.*?property="og:image".*?>/gm, '')
|
||||
outHtml = outHtml.replace(/<.*?property="og:image".*?>/gm, "");
|
||||
outHtml = outHtml.replace(
|
||||
/<\/head>/gm,
|
||||
`<meta property="og:image" content="${metadata.thumbnail.replace('./', articlesConfig['base_url'] + metadata.path + '/')}">\n</head>`,
|
||||
)
|
||||
`<meta property="og:image" content="${metadata.thumbnail.replace("./", articlesConfig.base_url + metadata.path + "/")}">\n</head>`,
|
||||
);
|
||||
}
|
||||
return outHtml
|
||||
return outHtml;
|
||||
}
|
||||
|
||||
function addFeedArticle(metadata: Record<string, string>, feed: Feed) {
|
||||
if (metadata.draft !== 'true') {
|
||||
if (metadata.draft !== "true") {
|
||||
feed.addItem({
|
||||
title: metadata.title.replace(/(<([^>]+)>)/gi, '').trim(),
|
||||
title: metadata.title.replace(/(<([^>]+)>)/gi, "").trim(),
|
||||
id: metadata.path,
|
||||
link: `${articlesConfig['base_url']}${metadata.path}/`,
|
||||
link: `${articlesConfig.base_url}${metadata.path}/`,
|
||||
date: new Date(Date.parse(metadata.date)),
|
||||
image: metadata.thumbnail.replace('./', articlesConfig['base_url'] + metadata.path + '/'),
|
||||
})
|
||||
image: metadata.thumbnail.replace(
|
||||
"./",
|
||||
articlesConfig.base_url + metadata.path + "/",
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const indexContent = fs.readFileSync('dist/index.html', { encoding: 'utf8' })
|
||||
const indexContent = fs.readFileSync("dist/index.html", { encoding: "utf8" });
|
||||
|
||||
if (!indexContent) {
|
||||
console.error('Could not read dist/index.html')
|
||||
process.exit(1)
|
||||
console.error("Could not read dist/index.html");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const metadatas = getFiles('articles')
|
||||
.filter((path) => path.match(/\/index.md$/))
|
||||
const metadatas = getFiles("articles")
|
||||
.filter((path) => /\/index.md$/.exec(path))
|
||||
.map((path) => readArticleMetadata(path))
|
||||
.filter((metadata) => !!metadata)
|
||||
.filter((metadata) => !!metadata);
|
||||
|
||||
const feed = new Feed({
|
||||
title: articlesConfig['title']?.replace(/(<([^>]+)>)/gi, '').trim() ?? '',
|
||||
id: articlesConfig['base_url'],
|
||||
link: articlesConfig['base_url'],
|
||||
language: articlesConfig['lang'],
|
||||
favicon: articlesConfig['base_url'] + 'articles/favicon.ico',
|
||||
generator: 'md-blog',
|
||||
title: articlesConfig.title.replace(/(<([^>]+)>)/gi, "").trim(),
|
||||
id: articlesConfig.base_url,
|
||||
link: articlesConfig.base_url,
|
||||
language: articlesConfig.lang,
|
||||
favicon: articlesConfig.base_url + "articles/favicon.ico",
|
||||
generator: "md-blog",
|
||||
feedLinks: {
|
||||
json: articlesConfig['base_url'] + 'feed.json',
|
||||
atom: articlesConfig['base_url'] + 'atom.xml',
|
||||
rss: articlesConfig['base_url'] + 'rss',
|
||||
json: articlesConfig.base_url + "feed.json",
|
||||
atom: articlesConfig.base_url + "atom.xml",
|
||||
rss: articlesConfig.base_url + "rss",
|
||||
},
|
||||
updated: new Date(
|
||||
Math.max(
|
||||
0,
|
||||
...metadatas
|
||||
.filter((metadata) => metadata.draft !== 'true')
|
||||
.filter((metadata) => metadata.draft !== "true")
|
||||
.map((metadata) => Date.parse(metadata.date)),
|
||||
),
|
||||
),
|
||||
})
|
||||
});
|
||||
|
||||
metadatas.forEach((metadata) => {
|
||||
fs.writeFileSync(`dist/${metadata.path}/index.html`, formatArticlePage(metadata, indexContent))
|
||||
console.info(`Wrote dist/${metadata.path}/index.html`)
|
||||
addFeedArticle(metadata, feed)
|
||||
})
|
||||
fs.writeFileSync(
|
||||
`dist/${metadata.path}/index.html`,
|
||||
formatArticlePage(metadata, indexContent),
|
||||
);
|
||||
console.info(`Wrote dist/${metadata.path}/index.html`);
|
||||
addFeedArticle(metadata, feed);
|
||||
});
|
||||
|
||||
fs.writeFileSync('dist/feed.json', feed.json1())
|
||||
console.info(`Wrote dist/feed.json`)
|
||||
fs.writeFileSync('dist/atom.xml', feed.atom1())
|
||||
console.info(`Wrote dist/atom.xml`)
|
||||
fs.writeFileSync('dist/rss.xml', feed.rss2())
|
||||
console.info(`Wrote dist/rss.xml`)
|
||||
fs.writeFileSync("dist/feed.json", feed.json1());
|
||||
console.info(`Wrote dist/feed.json`);
|
||||
fs.writeFileSync("dist/atom.xml", feed.atom1());
|
||||
console.info(`Wrote dist/atom.xml`);
|
||||
fs.writeFileSync("dist/rss.xml", feed.rss2());
|
||||
console.info(`Wrote dist/rss.xml`);
|
||||
|
||||
Reference in New Issue
Block a user