aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Dockerfile9
-rw-r--r--app/builder/pageDirectory.ts63
-rw-r--r--package-lock.json51
-rw-r--r--package.json10
-rw-r--r--tsconfig.json3
5 files changed, 82 insertions, 54 deletions
diff --git a/Dockerfile b/Dockerfile
index dc681f8..9975b3e 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM node:alpine AS build
+FROM node:20-alpine AS build
WORKDIR /app
@@ -6,16 +6,15 @@ COPY --chown=node:node package*.json ./
COPY --chown=node:node tsconfig.json ./
-RUN npm i -g typescript\
- && npm i
+RUN npm i
COPY --chown=node:node app app
-RUN tsc
+RUN npx tsc
-FROM node:alpine
+FROM node:20-alpine
LABEL org.opencontainers.image.source=https://github.com/LMBishop/panulat
diff --git a/app/builder/pageDirectory.ts b/app/builder/pageDirectory.ts
index 1aed94e..82c14fa 100644
--- a/app/builder/pageDirectory.ts
+++ b/app/builder/pageDirectory.ts
@@ -1,9 +1,10 @@
-import { readFileSync } from 'fs';
-import glob from 'glob';
-import { logger } from '../logger.js'
-import { marked } from 'marked';
-import { gfmHeadingId } from 'marked-gfm-heading-id';
-import matter from 'gray-matter';
+import { readFileSync } from "fs";
+import glob from "glob";
+import { logger } from "../logger.js";
+import { marked } from "marked";
+import { gfmHeadingId } from "marked-gfm-heading-id";
+import markedFootnote from "marked-footnote";
+import matter from "gray-matter";
marked.use(gfmHeadingId());
@@ -11,19 +12,21 @@ export async function parsePage(page: Page) {
try {
const frontmatter = matter(page.raw);
const config = frontmatter.data;
- const html = marked.parse(frontmatter.content, { mangle: false });
+ const html = marked
+ .use(markedFootnote())
+ .parse(frontmatter.content, { mangle: false });
page.html = html;
page.config = config;
- page.view = config.view || 'index';
+ page.view = config.view || "index";
page.buildTime = Date.now();
- } catch (e) {
+ } catch (e) {
logger.error(`Failed to parse page ${page.originalPath}: ${e.message}`);
}
}
function loadRaw(path: string): string {
- return readFileSync(`${path}`, 'utf-8');
+ return readFileSync(`${path}`, "utf-8");
}
export class PageDirectory {
@@ -31,7 +34,7 @@ export class PageDirectory {
private pages: Record<string, Page> = {};
private lastFullBuild: number;
-
+
constructor(pagesPath: string) {
this.pagesPath = pagesPath;
@@ -39,22 +42,22 @@ export class PageDirectory {
delete this.pages[page];
}
}
-
+
public init = async (): Promise<void> => {
- const localPages = glob.sync(`**/*.{md,html}`, { cwd: this.pagesPath })
+ const localPages = glob.sync(`**/*.{md,html}`, { cwd: this.pagesPath });
for (const page in localPages) {
await this.loadPage(localPages[page]);
}
this.lastFullBuild = Date.now();
- }
-
+ };
+
public loadPage = async (page: string): Promise<Page> => {
- let route = `/${page.replace(/\.[^.]*$/,'')}`;
+ let route = `/${page.replace(/\.[^.]*$/, "")}`;
let name = /[^/]*$/.exec(route)[0];
let originalPath = page;
- let fullPath = `${this.pagesPath}/${page}`
- let buildPath = `${process.env.OUTPUT_DIR}/${route}.html`
- let view = `${route}`
+ let fullPath = `${this.pagesPath}/${page}`;
+ let buildPath = `${process.env.OUTPUT_DIR}/${route}.html`;
+ let view = `${route}`;
let raw: string;
try {
raw = loadRaw(fullPath);
@@ -72,18 +75,18 @@ export class PageDirectory {
view: view,
raw: raw,
buildTime: 0,
- config: {}
- }
-
+ config: {},
+ };
+
await parsePage(this.pages[route]);
-
+
return this.pages[route];
- }
-
+ };
+
public removePage = (page: string): void => {
- let route = page.replace(/\.[^.]*$/,'')
+ let route = page.replace(/\.[^.]*$/, "");
delete this.pages[route];
- }
+ };
public get(name: string): Page {
const page = this.pages[name];
@@ -97,9 +100,11 @@ export class PageDirectory {
public getPages(): Page[] {
return Object.values(this.pages);
}
-
+
public getPagesBeginningWith(prefix: string): Page[] {
- return Object.values(this.pages).filter(page => page.route.startsWith(prefix));
+ return Object.values(this.pages).filter((page) =>
+ page.route.startsWith(prefix)
+ );
}
}
diff --git a/package-lock.json b/package-lock.json
index ced5197..8651bb7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,8 +8,6 @@
"name": "panulat",
"version": "1.2",
"dependencies": {
- "@types/clean-css": "^4.2.6",
- "@types/html-minifier-terser": "^7.0.0",
"axios": "^1.4.0",
"chokidar": "^3.5.3",
"clean-css": "^5.3.2",
@@ -21,7 +19,8 @@
"glob": "^7.2.0",
"gray-matter": "^4.0.3",
"html-minifier-terser": "^7.2.0",
- "marked": "^6.0.0",
+ "marked": "^7.0.0",
+ "marked-footnote": "^1.2.4",
"marked-gfm-heading-id": "^3.0.6",
"sass": "^1.66.1",
"uglify-js": "^3.17.4",
@@ -29,15 +28,18 @@
"ws": "^8.13.0"
},
"devDependencies": {
+ "@types/clean-css": "^4.2.6",
"@types/dateformat": "^5.0.0",
"@types/escape-html": "^1.0.1",
"@types/express": "^4.17.13",
"@types/glob": "^7.2.0",
+ "@types/html-minifier-terser": "^7.0.0",
"@types/uglify-js": "^3.17.1",
"@types/ws": "^8.5.4",
"@typescript-eslint/eslint-plugin": "^5.7.0",
"@typescript-eslint/parser": "^5.7.0",
- "eslint": "^8.5.0"
+ "eslint": "^8.5.0",
+ "typescript": "5.5.4"
}
},
"node_modules/@aashutoshrathi/word-wrap": {
@@ -257,6 +259,7 @@
"version": "4.2.6",
"resolved": "https://registry.npmjs.org/@types/clean-css/-/clean-css-4.2.6.tgz",
"integrity": "sha512-Ze1tf+LnGPmG6hBFMi0B4TEB0mhF7EiMM5oyjLDNPE9hxrPU0W+5+bHvO+eFPA+bt0iC1zkQMoU/iGdRVjcRbw==",
+ "dev": true,
"dependencies": {
"@types/node": "*",
"source-map": "^0.6.0"
@@ -320,7 +323,8 @@
"node_modules/@types/html-minifier-terser": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-7.0.0.tgz",
- "integrity": "sha512-hw3bhStrg5e3FQT8qZKCJTrzt/UbEaunU1xRWJ+aNOTmeBMvE3S4Ml2HiiNnZgL8izu0LFVkHUoPFXL1s5QNpQ=="
+ "integrity": "sha512-hw3bhStrg5e3FQT8qZKCJTrzt/UbEaunU1xRWJ+aNOTmeBMvE3S4Ml2HiiNnZgL8izu0LFVkHUoPFXL1s5QNpQ==",
+ "dev": true
},
"node_modules/@types/http-errors": {
"version": "2.0.1",
@@ -347,9 +351,13 @@
"dev": true
},
"node_modules/@types/node": {
- "version": "20.4.8",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.8.tgz",
- "integrity": "sha512-0mHckf6D2DiIAzh8fM8f3HQCvMKDpK94YQ0DSVkfWTG9BZleYIWudw9cJxX8oCk9bM+vAkDyujDV6dmKHbvQpg=="
+ "version": "20.16.5",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.5.tgz",
+ "integrity": "sha512-VwYCweNo3ERajwy0IUlqqcyZ8/A7Zwa9ZP3MnENWcB11AejO+tLy3pu850goUW2FC/IJMdZUfKpX/yxL1gymCA==",
+ "dev": true,
+ "dependencies": {
+ "undici-types": "~6.19.2"
+ }
},
"node_modules/@types/qs": {
"version": "6.9.7",
@@ -2194,9 +2202,9 @@
}
},
"node_modules/marked": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/marked/-/marked-6.0.0.tgz",
- "integrity": "sha512-7E3m/xIlymrFL5gWswIT4CheIE3fDeh51NV09M4x8iOc7NDYlyERcQMLAIHcSlrvwliwbPQ4OGD+MpPSYiQcqw==",
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/marked/-/marked-7.0.5.tgz",
+ "integrity": "sha512-lwNAFTfXgqpt/XvK17a/8wY9/q6fcSPZT1aP6QW0u74VwaJF/Z9KbRcX23sWE4tODM+AolJNcUtErTkgOeFP/Q==",
"bin": {
"marked": "bin/marked.js"
},
@@ -2204,6 +2212,14 @@
"node": ">= 16"
}
},
+ "node_modules/marked-footnote": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/marked-footnote/-/marked-footnote-1.2.4.tgz",
+ "integrity": "sha512-DB2Kl+wFh6YwZd70qABMY6WUkG1UuyqoNTFoDfGyG79Pz24neYtLBkB+45a7o72V7gkfvbC3CGzIYFobxfMT1Q==",
+ "peerDependencies": {
+ "marked": ">=7.0.0"
+ }
+ },
"node_modules/marked-gfm-heading-id": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/marked-gfm-heading-id/-/marked-gfm-heading-id-3.0.6.tgz",
@@ -3108,11 +3124,10 @@
}
},
"node_modules/typescript": {
- "version": "5.1.6",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz",
- "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==",
+ "version": "5.5.4",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz",
+ "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==",
"dev": true,
- "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -3132,6 +3147,12 @@
"node": ">=0.8.0"
}
},
+ "node_modules/undici-types": {
+ "version": "6.19.8",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
+ "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
+ "dev": true
+ },
"node_modules/unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
diff --git a/package.json b/package.json
index a953c9c..286b2a2 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "panulat",
- "version": "1.2",
+ "version": "1.3",
"description": "",
"main": "app/index.mjs",
"scripts": {
@@ -9,8 +9,6 @@
},
"author": "Leonardo Bishop",
"dependencies": {
- "@types/clean-css": "^4.2.6",
- "@types/html-minifier-terser": "^7.0.0",
"axios": "^1.4.0",
"chokidar": "^3.5.3",
"clean-css": "^5.3.2",
@@ -22,7 +20,8 @@
"glob": "^7.2.0",
"gray-matter": "^4.0.3",
"html-minifier-terser": "^7.2.0",
- "marked": "^6.0.0",
+ "marked": "^7.0.0",
+ "marked-footnote": "^1.2.4",
"marked-gfm-heading-id": "^3.0.6",
"sass": "^1.66.1",
"uglify-js": "^3.17.4",
@@ -31,6 +30,8 @@
},
"type": "module",
"devDependencies": {
+ "@types/clean-css": "^4.2.6",
+ "@types/html-minifier-terser": "^7.0.0",
"@types/dateformat": "^5.0.0",
"@types/escape-html": "^1.0.1",
"@types/express": "^4.17.13",
@@ -39,6 +40,7 @@
"@types/ws": "^8.5.4",
"@typescript-eslint/eslint-plugin": "^5.7.0",
"@typescript-eslint/parser": "^5.7.0",
+ "typescript": "5.5.4",
"eslint": "^8.5.0"
}
}
diff --git a/tsconfig.json b/tsconfig.json
index 90ae06b..996d9fd 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -6,7 +6,8 @@
"module": "es2022",
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
- "strict": false
+ "strict": false,
+ "skipLibCheck": true
},
"include": ["./app/**/*.ts"],
}