basecampjs 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +63 -13
- package/package.json +4 -2
package/index.js
CHANGED
|
@@ -11,6 +11,8 @@ import matter from "gray-matter";
|
|
|
11
11
|
import MarkdownIt from "markdown-it";
|
|
12
12
|
import nunjucks from "nunjucks";
|
|
13
13
|
import { Liquid } from "liquidjs";
|
|
14
|
+
import { minify as minifyCss } from "csso";
|
|
15
|
+
import { minify as minifyHtml } from "html-minifier-terser";
|
|
14
16
|
|
|
15
17
|
const cwd = process.cwd();
|
|
16
18
|
const md = new MarkdownIt({ html: true, linkify: true, typographer: true });
|
|
@@ -21,6 +23,8 @@ const defaultConfig = {
|
|
|
21
23
|
outDir: "dist",
|
|
22
24
|
templateEngine: "nunjucks",
|
|
23
25
|
markdown: true,
|
|
26
|
+
minifyCSS: false,
|
|
27
|
+
minifyHTML: false,
|
|
24
28
|
integrations: { nunjucks: true, liquid: false, vue: false, alpine: false }
|
|
25
29
|
};
|
|
26
30
|
|
|
@@ -69,6 +73,45 @@ async function copyPublic(publicDir, outDir) {
|
|
|
69
73
|
}
|
|
70
74
|
}
|
|
71
75
|
|
|
76
|
+
async function minifyCSSFiles(outDir) {
|
|
77
|
+
const files = await walkFiles(outDir);
|
|
78
|
+
const cssFiles = files.filter((file) => extname(file).toLowerCase() === ".css");
|
|
79
|
+
|
|
80
|
+
await Promise.all(cssFiles.map(async (file) => {
|
|
81
|
+
try {
|
|
82
|
+
const css = await readFile(file, "utf8");
|
|
83
|
+
const { css: minified } = minifyCss(css);
|
|
84
|
+
await writeFile(file, minified, "utf8");
|
|
85
|
+
} catch (err) {
|
|
86
|
+
console.error(kolor.red(`Failed to minify CSS ${relative(outDir, file)}: ${err.message}`));
|
|
87
|
+
}
|
|
88
|
+
}));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async function minifyHTMLFiles(outDir, config) {
|
|
92
|
+
const files = await walkFiles(outDir);
|
|
93
|
+
const htmlFiles = files.filter((file) => extname(file).toLowerCase() === ".html");
|
|
94
|
+
|
|
95
|
+
await Promise.all(htmlFiles.map(async (file) => {
|
|
96
|
+
try {
|
|
97
|
+
const html = await readFile(file, "utf8");
|
|
98
|
+
const minified = await minifyHtml(html, {
|
|
99
|
+
collapseWhitespace: true,
|
|
100
|
+
removeComments: true,
|
|
101
|
+
minifyCSS: !!config.minifyCSS,
|
|
102
|
+
minifyJS: true,
|
|
103
|
+
keepClosingSlash: true,
|
|
104
|
+
removeRedundantAttributes: true,
|
|
105
|
+
removeScriptTypeAttributes: true,
|
|
106
|
+
removeStyleLinkTypeAttributes: true
|
|
107
|
+
});
|
|
108
|
+
await writeFile(file, minified, "utf8");
|
|
109
|
+
} catch (err) {
|
|
110
|
+
console.error(kolor.red(`Failed to minify HTML ${relative(outDir, file)}: ${err.message}`));
|
|
111
|
+
}
|
|
112
|
+
}));
|
|
113
|
+
}
|
|
114
|
+
|
|
72
115
|
async function walkFiles(dir) {
|
|
73
116
|
const results = [];
|
|
74
117
|
if (!existsSync(dir)) return results;
|
|
@@ -111,15 +154,11 @@ function toUrlPath(outRel) {
|
|
|
111
154
|
return `/${normalized}`;
|
|
112
155
|
}
|
|
113
156
|
|
|
114
|
-
function pageContext(frontmatter, html, config, relPath, data,
|
|
157
|
+
function pageContext(frontmatter, html, config, relPath, data, path = "/") {
|
|
115
158
|
return {
|
|
116
159
|
site: { name: config.siteName, config },
|
|
117
|
-
page: { ...frontmatter, content: html, source: relPath,
|
|
118
|
-
|
|
119
|
-
content: html,
|
|
120
|
-
data,
|
|
121
|
-
collections: data,
|
|
122
|
-
...data
|
|
160
|
+
page: { ...frontmatter, content: html, source: relPath, path },
|
|
161
|
+
collections: data
|
|
123
162
|
};
|
|
124
163
|
}
|
|
125
164
|
|
|
@@ -133,8 +172,9 @@ async function renderWithLayout(layoutName, html, ctx, env, liquidEnv) {
|
|
|
133
172
|
const ext = extname(layoutName).toLowerCase();
|
|
134
173
|
const layoutCtx = {
|
|
135
174
|
...ctx,
|
|
175
|
+
frontmatter: ctx.page || {},
|
|
136
176
|
content: html,
|
|
137
|
-
title: ctx.
|
|
177
|
+
title: ctx.page?.title ?? ctx.site?.name
|
|
138
178
|
};
|
|
139
179
|
|
|
140
180
|
if (ext === ".njk") {
|
|
@@ -154,14 +194,14 @@ async function renderPage(filePath, { pagesDir, layoutsDir, outDir, env, liquidE
|
|
|
154
194
|
const ext = extname(filePath).toLowerCase();
|
|
155
195
|
const outRel = rel.replace(/\.liquid(\.html)?$/i, ".html").replace(ext, ".html");
|
|
156
196
|
const outPath = join(outDir, outRel);
|
|
157
|
-
const
|
|
197
|
+
const path = toUrlPath(outRel);
|
|
158
198
|
await ensureDir(dirname(outPath));
|
|
159
199
|
|
|
160
200
|
if (ext === ".md") {
|
|
161
201
|
const raw = await readFile(filePath, "utf8");
|
|
162
202
|
const parsed = matter(raw);
|
|
163
203
|
const html = md.render(parsed.content);
|
|
164
|
-
const ctx = pageContext(parsed.data, html, config, rel, data,
|
|
204
|
+
const ctx = pageContext(parsed.data, html, config, rel, data, path);
|
|
165
205
|
const rendered = await renderWithLayout(parsed.data.layout, html, ctx, env, liquidEnv);
|
|
166
206
|
await writeFile(outPath, rendered, "utf8");
|
|
167
207
|
return;
|
|
@@ -170,7 +210,7 @@ async function renderPage(filePath, { pagesDir, layoutsDir, outDir, env, liquidE
|
|
|
170
210
|
if (ext === ".njk") {
|
|
171
211
|
const raw = await readFile(filePath, "utf8");
|
|
172
212
|
const parsed = matter(raw);
|
|
173
|
-
const ctx = pageContext(parsed.data, parsed.content, config, rel, data,
|
|
213
|
+
const ctx = pageContext(parsed.data, parsed.content, config, rel, data, path);
|
|
174
214
|
const templateName = rel.replace(/\\/g, "/");
|
|
175
215
|
let pageHtml = env.renderString(parsed.content, ctx, { path: templateName });
|
|
176
216
|
if (shouldRenderMarkdown(parsed.data, config, false)) {
|
|
@@ -184,7 +224,7 @@ async function renderPage(filePath, { pagesDir, layoutsDir, outDir, env, liquidE
|
|
|
184
224
|
if (ext === ".liquid" || filePath.toLowerCase().endsWith(".liquid.html")) {
|
|
185
225
|
const raw = await readFile(filePath, "utf8");
|
|
186
226
|
const parsed = matter(raw);
|
|
187
|
-
const ctx = pageContext(parsed.data, parsed.content, config, rel, data,
|
|
227
|
+
const ctx = pageContext(parsed.data, parsed.content, config, rel, data, path);
|
|
188
228
|
let pageHtml = await liquidEnv.parseAndRender(parsed.content, ctx);
|
|
189
229
|
if (shouldRenderMarkdown(parsed.data, config, false)) {
|
|
190
230
|
pageHtml = md.render(pageHtml);
|
|
@@ -197,7 +237,7 @@ async function renderPage(filePath, { pagesDir, layoutsDir, outDir, env, liquidE
|
|
|
197
237
|
if (ext === ".html") {
|
|
198
238
|
const raw = await readFile(filePath, "utf8");
|
|
199
239
|
const parsed = matter(raw);
|
|
200
|
-
const ctx = pageContext(parsed.data, parsed.content, config, rel, data,
|
|
240
|
+
const ctx = pageContext(parsed.data, parsed.content, config, rel, data, path);
|
|
201
241
|
let pageHtml = parsed.content;
|
|
202
242
|
if (shouldRenderMarkdown(parsed.data, config, false)) {
|
|
203
243
|
pageHtml = md.render(pageHtml);
|
|
@@ -233,6 +273,16 @@ async function build(cwdArg = cwd) {
|
|
|
233
273
|
|
|
234
274
|
await Promise.all(files.map((file) => renderPage(file, { pagesDir, layoutsDir, outDir, env, liquidEnv, config, data })));
|
|
235
275
|
|
|
276
|
+
if (config.minifyCSS) {
|
|
277
|
+
await minifyCSSFiles(outDir);
|
|
278
|
+
console.log(kolor.green("CSS minified"));
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if (config.minifyHTML) {
|
|
282
|
+
await minifyHTMLFiles(outDir, config);
|
|
283
|
+
console.log(kolor.green("HTML minified"));
|
|
284
|
+
}
|
|
285
|
+
|
|
236
286
|
console.log(kolor.green(`Built ${files.length} page(s) → ${relative(cwdArg, outDir)}`));
|
|
237
287
|
}
|
|
238
288
|
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "basecampjs",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "BasecampJS engine for
|
|
5
|
+
"description": "BasecampJS engine for CampsiteJS static site generator.",
|
|
6
6
|
"bin": {
|
|
7
7
|
"campsite": "./index.js"
|
|
8
8
|
},
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
".": "./index.js"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
+
"csso": "^5.0.5",
|
|
15
|
+
"html-minifier-terser": "^7.2.0",
|
|
14
16
|
"chokidar": "^3.6.0",
|
|
15
17
|
"gray-matter": "^4.0.3",
|
|
16
18
|
"kolorist": "^1.8.0",
|