generated from nhcarrigan/template
This commit is contained in:
@@ -0,0 +1,38 @@
|
|||||||
|
name: Node.js CI
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint:
|
||||||
|
name: Lint and Test
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout Source Files
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Use Node.js v22
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 22
|
||||||
|
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@v2
|
||||||
|
with:
|
||||||
|
version: 9
|
||||||
|
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: pnpm install
|
||||||
|
|
||||||
|
- name: Lint Source Files
|
||||||
|
run: pnpm run lint
|
||||||
|
|
||||||
|
- name: Verify Build
|
||||||
|
run: pnpm run build
|
||||||
|
|
||||||
|
- name: Run Tests
|
||||||
|
run: pnpm run test
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
prod
|
||||||
|
node_modules
|
||||||
|
review.md
|
||||||
|
content/**/*
|
||||||
|
!.gitkeep
|
||||||
|
fcc-review-pages.pdf
|
||||||
Vendored
+6
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"editor.codeActionsOnSave": {
|
||||||
|
"source.fixAll.eslint": "explicit"
|
||||||
|
},
|
||||||
|
"eslint.validate": ["typescript"],
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
This directory is where your markdown files go.
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import NaomisConfig from '@nhcarrigan/eslint-config';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
...NaomisConfig,
|
||||||
|
{
|
||||||
|
rules: {
|
||||||
|
"no-console" : "off",
|
||||||
|
"no-await-in-loop": "off"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"name": "fcc-review-generator",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "A quick tool that aggregates all of the review pages from freeCodeCamp into a single page.",
|
||||||
|
"main": "index.js",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"postinstall": "pnpx puppeteer browsers install chrome",
|
||||||
|
"start": "tsx src/index.ts",
|
||||||
|
"build": "tsc",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"lint": "eslint src --max-warnings 0"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"packageManager": "pnpm@10.18.0",
|
||||||
|
"devDependencies": {
|
||||||
|
"@nhcarrigan/eslint-config": "5.2.0",
|
||||||
|
"@nhcarrigan/typescript-config": "4.0.0",
|
||||||
|
"@types/node": "24.7.0",
|
||||||
|
"eslint": "9.37.0",
|
||||||
|
"tsx": "4.20.6",
|
||||||
|
"typescript": "5.9.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"md-to-pdf": "5.2.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
+5486
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,46 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/naming-convention -- The settings are snake case. */
|
||||||
|
/**
|
||||||
|
* @copyright NHCarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { PdfConfig } from "md-to-pdf/dist/lib/config.js";
|
||||||
|
|
||||||
|
export const options: Partial<PdfConfig> = {
|
||||||
|
pdf_options: {
|
||||||
|
displayHeaderFooter: true,
|
||||||
|
footerTemplate: `<section>
|
||||||
|
<div class="flexy"><p><a href='https://chat.nhcarrigan.com'>Join Naomi's Discord</a></p><p>Page <span class="pageNumber"></span>
|
||||||
|
of <span class="totalPages"></span></p></div>
|
||||||
|
</section>`,
|
||||||
|
format: "Legal",
|
||||||
|
headerTemplate: ` <style>
|
||||||
|
section {
|
||||||
|
margin: 0 auto;
|
||||||
|
font-family: system-ui;
|
||||||
|
font-size: 11px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.flexy {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.centre {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<section class="centre">
|
||||||
|
<span>Naomi's freeCodeCamp Review</span>
|
||||||
|
</section>`,
|
||||||
|
margin: {
|
||||||
|
bottom: "0.75in",
|
||||||
|
left: "0.75in",
|
||||||
|
right: "0.75in",
|
||||||
|
top: "0.75in",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* @copyright NHCarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const starterText = `# Naomi's freeCodeCamp Review
|
||||||
|
|
||||||
|
Hello! This PDF contains all of the review pages (unless I missed one) from freeCodeCamp's full stack developer curriculum.
|
||||||
|
|
||||||
|
Before we dive in, a quick disclaimer: This is not an officially sanctioned document, and I make no warranty that the information in this document will be kept up to date. This version was created on ${new Date().toLocaleDateString("en-GB", { day: "numeric", month: "long", year: "numeric" })}.
|
||||||
|
|
||||||
|
Questions? Comments? Document is out of date and you want to scream at me about it? https://chat.nhcarrigan.com
|
||||||
|
|
||||||
|
HERE WE GO!\n\n`;
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
/**
|
||||||
|
* @copyright NHCarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
readFile,
|
||||||
|
appendFile,
|
||||||
|
writeFile,
|
||||||
|
readdir,
|
||||||
|
unlink,
|
||||||
|
} from "node:fs/promises";
|
||||||
|
import { join } from "node:path";
|
||||||
|
import { mdToPdf } from "md-to-pdf";
|
||||||
|
import { options } from "./config/options.js";
|
||||||
|
import { starterText } from "./config/text.js";
|
||||||
|
|
||||||
|
const readDirectoryRecursively = async(
|
||||||
|
directory: string,
|
||||||
|
): Promise<Array<string>> => {
|
||||||
|
const dirents = await readdir(directory, { withFileTypes: true });
|
||||||
|
const files = await Promise.all(
|
||||||
|
dirents.map(async(dirent) => {
|
||||||
|
const result = join(directory, dirent.name);
|
||||||
|
return dirent.isDirectory()
|
||||||
|
? await readDirectoryRecursively(result)
|
||||||
|
: result;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
return files.flat();
|
||||||
|
};
|
||||||
|
|
||||||
|
const rollupFiles = async(
|
||||||
|
inputDirectory: string,
|
||||||
|
outputFile: string,
|
||||||
|
): Promise<void> => {
|
||||||
|
try {
|
||||||
|
await writeFile(outputFile, `${starterText}\n`);
|
||||||
|
const files = await readDirectoryRecursively(inputDirectory);
|
||||||
|
for (const file of files) {
|
||||||
|
if (file === ".gitkeep") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (file.endsWith(".md")) {
|
||||||
|
const content = await readFile(file, "utf8");
|
||||||
|
const strippedFrontmatter = content.
|
||||||
|
replace(/^---\n[\S\s]*?\n---\n/, "").
|
||||||
|
trim();
|
||||||
|
// Title is in front matter
|
||||||
|
const title = /^title: (?<title>.*)/m.exec(content)?.groups?.title;
|
||||||
|
console.log(title);
|
||||||
|
const strippedFccHeadings = strippedFrontmatter.
|
||||||
|
replace(/^#+ --.*--/, "").
|
||||||
|
trim();
|
||||||
|
await appendFile(
|
||||||
|
outputFile,
|
||||||
|
`---\n\n# ${title ?? "Unknown"}\n${strippedFccHeadings}\n\n`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(`Successfully rolled up files into ${outputFile}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error rolling up files:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const createPdf = async(inputPath: string): Promise<void> => {
|
||||||
|
const pdf = await mdToPdf({ path: inputPath }, options);
|
||||||
|
console.log("PDF created!");
|
||||||
|
await writeFile("./fcc-review-pages.pdf", pdf.content);
|
||||||
|
console.log("PDF written to disk!");
|
||||||
|
};
|
||||||
|
|
||||||
|
const inputDirectory = "./content";
|
||||||
|
const outputFilePath = "./review.md";
|
||||||
|
|
||||||
|
await rollupFiles(inputDirectory, outputFilePath);
|
||||||
|
await createPdf(outputFilePath);
|
||||||
|
await unlink(outputFilePath);
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"extends": "@nhcarrigan/typescript-config",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "./prod",
|
||||||
|
"rootDir": "./src"
|
||||||
|
},
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user