fossbook 0.0.2

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.
Files changed (53) hide show
  1. package/README.md +246 -0
  2. package/bin/fossbook.js +119 -0
  3. package/lib/all_posts.js +32 -0
  4. package/lib/assets/placeholder.svg +4 -0
  5. package/lib/deploy.js +202 -0
  6. package/lib/home.js +59 -0
  7. package/lib/index.js +79 -0
  8. package/lib/init.js +253 -0
  9. package/lib/mod/config.js +98 -0
  10. package/lib/mod/marked.js +95 -0
  11. package/lib/mod/page.js +115 -0
  12. package/lib/mod/page_base.js +97 -0
  13. package/lib/new.js +48 -0
  14. package/lib/posts.js +42 -0
  15. package/lib/server.js +14 -0
  16. package/lib/tag/index.js +69 -0
  17. package/lib/tag/tag.js +29 -0
  18. package/package.json +45 -0
  19. package/themes/archie/assets/fonts/ComicNeue-Bold.ttf +0 -0
  20. package/themes/archie/assets/fonts/ComicNeue-BoldItalic.ttf +0 -0
  21. package/themes/archie/assets/fonts/ComicNeue-Italic.ttf +0 -0
  22. package/themes/archie/assets/fonts/ComicNeue-Light.ttf +0 -0
  23. package/themes/archie/assets/fonts/ComicNeue-LightItalic.ttf +0 -0
  24. package/themes/archie/assets/fonts/ComicNeue-Regular.ttf +0 -0
  25. package/themes/archie/assets/fonts/LyonDisplay-Bold.otf +0 -0
  26. package/themes/archie/assets/fonts/OFL.txt +93 -0
  27. package/themes/archie/assets/fonts/fira-sans-v10-latin-regular.eot +0 -0
  28. package/themes/archie/assets/fonts/fira-sans-v10-latin-regular.svg +330 -0
  29. package/themes/archie/assets/fonts/fira-sans-v10-latin-regular.ttf +0 -0
  30. package/themes/archie/assets/fonts/fira-sans-v10-latin-regular.woff +0 -0
  31. package/themes/archie/assets/fonts/fira-sans-v10-latin-regular.woff2 +0 -0
  32. package/themes/archie/assets/fonts/ibm-plex-mono-v6-latin-500italic.eot +0 -0
  33. package/themes/archie/assets/fonts/ibm-plex-mono-v6-latin-500italic.svg +365 -0
  34. package/themes/archie/assets/fonts/ibm-plex-mono-v6-latin-500italic.ttf +0 -0
  35. package/themes/archie/assets/fonts/ibm-plex-mono-v6-latin-500italic.woff +0 -0
  36. package/themes/archie/assets/fonts/ibm-plex-mono-v6-latin-500italic.woff2 +0 -0
  37. package/themes/archie/assets/fonts/roboto-mono-v12-latin-regular.eot +0 -0
  38. package/themes/archie/assets/fonts/roboto-mono-v12-latin-regular.svg +405 -0
  39. package/themes/archie/assets/fonts/roboto-mono-v12-latin-regular.ttf +0 -0
  40. package/themes/archie/assets/fonts/roboto-mono-v12-latin-regular.woff +0 -0
  41. package/themes/archie/assets/fonts/roboto-mono-v12-latin-regular.woff2 +0 -0
  42. package/themes/archie/assets/images/node-ssg-1.png +0 -0
  43. package/themes/archie/assets/images/node-ssg-2.png +0 -0
  44. package/themes/archie/assets/styles/fonts.css +51 -0
  45. package/themes/archie/assets/styles/highlights.css +75 -0
  46. package/themes/archie/assets/styles/main.css +402 -0
  47. package/themes/archie/layouts/all_posts.html +42 -0
  48. package/themes/archie/layouts/home.html +62 -0
  49. package/themes/archie/layouts/page.html +50 -0
  50. package/themes/archie/layouts/partials/footer.html +10 -0
  51. package/themes/archie/layouts/post.html +82 -0
  52. package/themes/archie/layouts/tag.html +43 -0
  53. package/themes/archie/layouts/tag_list.html +44 -0
package/README.md ADDED
@@ -0,0 +1,246 @@
1
+ # Fossbook
2
+
3
+ A lightweight static blog site generator for GitHub Pages, similar to Hugo but built with Node.js.
4
+
5
+ ## Features
6
+
7
+ - **Markdown-based** — Write posts in Markdown with YAML front-matter
8
+ - **Pagination** — Automatic home page pagination
9
+ - **Tags** — Tag-based categorization with tag index and per-tag listing pages
10
+ - **Theming** — Bundled Archie theme with support for custom themes
11
+ - **SEO** — Open Graph and Twitter Card meta tags out of the box
12
+ - **GitHub Pages** — Built-in CNAME support for custom domains
13
+ - **Dev server** — Local preview server with Express
14
+ - **Syntax highlighting** — Code block highlighting via highlight.js
15
+
16
+ ## Quick Start
17
+
18
+ ### Install globally
19
+
20
+ ```bash
21
+ npm install -g fossbook
22
+ ```
23
+
24
+ ### Create a new site
25
+
26
+ ```bash
27
+ mkdir my-blog && cd my-blog
28
+ fossbook init
29
+ ```
30
+
31
+ This creates the following structure:
32
+
33
+ ```
34
+ my-blog/
35
+ ├── content/
36
+ │ ├── about.md
37
+ │ └── posts/
38
+ ├── static/
39
+ │ └── images/
40
+ ├── fossbook.config.js
41
+ └── package.json
42
+ ```
43
+
44
+ ### Create a new post
45
+
46
+ ```bash
47
+ fossbook new "My First Post"
48
+ ```
49
+
50
+ This creates `content/posts/My First Post/index.md` with pre-filled front-matter and an `images/` directory.
51
+
52
+ ### Build the site
53
+
54
+ ```bash
55
+ fossbook build
56
+ ```
57
+
58
+ ### Preview locally
59
+
60
+ ```bash
61
+ fossbook serve
62
+ ```
63
+
64
+ Open http://localhost:3000 to view your site.
65
+
66
+ ## Configuration
67
+
68
+ Create a `fossbook.config.js` in your project root:
69
+
70
+ ```js
71
+ module.exports = {
72
+ blogName: "My Blog",
73
+ authorName: "Your Name",
74
+ authorDescription: "A short bio",
75
+ authorWebsite: "https://example.com",
76
+ blogDescription: "A blog about things",
77
+ blogsite: "https://example.com",
78
+
79
+ // Optional
80
+ githubCNAME: "example.com",
81
+ googleAnalyticsID: "",
82
+ authorTwitter: "@you",
83
+ siteTwitter: "@yourblog",
84
+ githubRepository: "https://github.com/you/your-blog",
85
+ image: "https://example.com/default-image.png",
86
+ theme: "archie",
87
+
88
+ // Directory overrides (defaults shown)
89
+ content: "./content",
90
+ postsDir: "./content/posts",
91
+ outputDir: "./public",
92
+ staticDir: "./static",
93
+ themesDir: "./themes",
94
+ };
95
+ ```
96
+
97
+ ## Content Format
98
+
99
+ ### Post front-matter
100
+
101
+ ```markdown
102
+ ---
103
+ title: My Post Title
104
+ date: 2026-02-17
105
+ description: "A brief summary of the post"
106
+ image: "feature.png"
107
+ tags: "JavaScript, Node.js, Static Site"
108
+ ---
109
+
110
+ Your Markdown content here...
111
+ ```
112
+
113
+ ### Directory structure
114
+
115
+ ```
116
+ content/posts/My Post Title/
117
+ ├── index.md
118
+ └── images/
119
+ └── feature.png
120
+ ```
121
+
122
+ ## CLI Reference
123
+
124
+ ```
125
+ Usage: fossbook <command> [options]
126
+
127
+ Commands:
128
+ build Build the static site
129
+ serve Build and start a local dev server
130
+ new <title> Create a new post
131
+ init Create a new fossbook site project
132
+
133
+ Options:
134
+ -c, --config Path to config file (default: ./fossbook.config.js)
135
+ -o, --output Output directory (default: ./public)
136
+ -p, --port Dev server port (default: 3000)
137
+ -v, --version Show version number
138
+ -h, --help Show help
139
+ ```
140
+
141
+ ## Theming
142
+
143
+ Fossbook ships with the Archie theme by default. To use a custom theme:
144
+
145
+ 1. Create a `themes/<your-theme>/` directory in your project
146
+ 2. Add `layouts/` (HTML templates) and `assets/` (CSS, fonts, images)
147
+ 3. Set `theme: "your-theme"` in `fossbook.config.js`
148
+
149
+ Theme resolution order: user project `themes/` → built-in `themes/`.
150
+
151
+ ### Required layout files
152
+
153
+ ```
154
+ layouts/
155
+ ├── home.html # Home page with pagination
156
+ ├── post.html # Individual post page
157
+ ├── page.html # Static pages (e.g., about)
158
+ ├── all_posts.html # All posts listing
159
+ ├── tag.html # Per-tag listing
160
+ ├── tag_list.html # Tag index page
161
+ └── partials/
162
+ └── footer.html # Footer partial
163
+ ```
164
+
165
+ ## Deploying to GitHub Pages
166
+
167
+ Fossbook can automatically deploy your blog to GitHub Pages using GitHub Actions.
168
+
169
+ ### Prerequisites: Install GitHub CLI (`gh`)
170
+
171
+ The `fossbook deploy` command uses the GitHub CLI to create repositories and monitor deployments.
172
+
173
+ **Linux (Debian/Ubuntu):**
174
+
175
+ ```bash
176
+ sudo apt install gh
177
+ ```
178
+
179
+ **macOS:**
180
+
181
+ ```bash
182
+ brew install gh
183
+ ```
184
+
185
+ **Windows:**
186
+
187
+ ```bash
188
+ winget install GitHub.cli
189
+ ```
190
+
191
+ Then authenticate with your GitHub account:
192
+
193
+ ```bash
194
+ gh auth login
195
+ ```
196
+
197
+ Follow the prompts to log in via browser or token.
198
+
199
+ ### Initialize with GitHub
200
+
201
+ ```bash
202
+ mkdir my-blog && cd my-blog
203
+ fossbook init --github
204
+ ```
205
+
206
+ This will:
207
+ 1. Scaffold the site project (config, content directories)
208
+ 2. Create a GitHub repository for your blog
209
+ 3. Generate `.github/workflows/deploy.yml` for automatic deployments
210
+ 4. Push the initial commit to GitHub
211
+
212
+ ### Publish a post
213
+
214
+ ```bash
215
+ fossbook new "My New Article"
216
+ # ... edit content/posts/My New Article/index.md ...
217
+ fossbook deploy
218
+ ```
219
+
220
+ Fossbook will build the site, commit, push to GitHub, wait for the CI/CD pipeline to finish, and display the live URL:
221
+
222
+ ```
223
+ Building site... done.
224
+ Committing: "Publish: My New Article"
225
+ Pushing to origin/main...
226
+ Waiting for GitHub Pages deployment... ✓
227
+
228
+ ✅ Published! View your article at:
229
+ https://username.github.io/my-blog/My%20New%20Article/
230
+ ```
231
+
232
+ **Deploy options:**
233
+
234
+ ```bash
235
+ fossbook deploy --message "Update homepage" # Custom commit message
236
+ fossbook deploy --no-wait # Push without waiting for CI
237
+ ```
238
+
239
+ ## License
240
+
241
+ - Generator code: [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause)
242
+ - Archie theme: [MIT License](https://github.com/athul/archie?tab=MIT-1-ov-file#readme)
243
+
244
+ ## Credits
245
+
246
+ Adapted from [kartiknair's blog](https://github.com/kartiknair/blog) and styled using the [Archie theme](https://github.com/athul/archie).
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env node
2
+
3
+ const path = require("path");
4
+ const { loadConfig } = require("../lib/mod/config");
5
+
6
+ const args = process.argv.slice(2);
7
+ const command = args[0];
8
+
9
+ function printHelp() {
10
+ console.log(`
11
+ Usage: fossbook <command> [options]
12
+
13
+ Commands:
14
+ build Build the static site
15
+ serve Build and start a local dev server
16
+ new <title> Create a new post
17
+ init Create a new fossbook site project
18
+ deploy Build, commit, push, and monitor deployment
19
+
20
+ Options:
21
+ -c, --config Path to config file (default: ./fossbook.config.js)
22
+ -o, --output Output directory (default: ./public)
23
+ -p, --port Dev server port (default: 3000)
24
+ --clean Remove output directory before build (default: true)
25
+ --github (init) Also create a GitHub repo and push
26
+ -m, --message (deploy) Custom commit message
27
+ --no-wait (deploy) Push without waiting for CI status
28
+ --draft (deploy) Commit locally without pushing
29
+ -v, --version Show version number
30
+ -h, --help Show help
31
+ `);
32
+ }
33
+
34
+ function getOption(flag, alias) {
35
+ const idx = args.indexOf(flag);
36
+ const aliasIdx = alias ? args.indexOf(alias) : -1;
37
+ const foundIdx = idx !== -1 ? idx : aliasIdx;
38
+ if (foundIdx !== -1 && foundIdx + 1 < args.length) {
39
+ return args[foundIdx + 1];
40
+ }
41
+ return null;
42
+ }
43
+
44
+ function hasFlag(flag, alias) {
45
+ return args.includes(flag) || (alias && args.includes(alias));
46
+ }
47
+
48
+ if (hasFlag("-v", "--version")) {
49
+ const pkg = require("../package.json");
50
+ console.log(`fossbook v${pkg.version}`);
51
+ process.exit(0);
52
+ }
53
+
54
+ if (hasFlag("-h", "--help") || !command) {
55
+ printHelp();
56
+ process.exit(0);
57
+ }
58
+
59
+ const configPath = getOption("-c", "--config");
60
+
61
+ switch (command) {
62
+ case "build": {
63
+ const config = loadConfig(configPath);
64
+ const outputOverride = getOption("-o", "--output");
65
+ if (outputOverride) config.dev.outdir = outputOverride;
66
+
67
+ const { build } = require("../lib/index");
68
+ build(config);
69
+ break;
70
+ }
71
+
72
+ case "serve": {
73
+ const config = loadConfig(configPath);
74
+ const outputOverride = getOption("-o", "--output");
75
+ if (outputOverride) config.dev.outdir = outputOverride;
76
+ const port = getOption("-p", "--port") || 3000;
77
+
78
+ const { build } = require("../lib/index");
79
+ build(config);
80
+
81
+ const { serve } = require("../lib/server");
82
+ serve(config, Number(port));
83
+ break;
84
+ }
85
+
86
+ case "new": {
87
+ const title = args[1];
88
+ if (!title) {
89
+ console.error('Error: Please provide a post title. Usage: fossbook new "My Post Title"');
90
+ process.exit(1);
91
+ }
92
+ const config = loadConfig(configPath);
93
+ const { createPost } = require("../lib/new");
94
+ createPost(config, title);
95
+ break;
96
+ }
97
+
98
+ case "init": {
99
+ const { initProject } = require("../lib/init");
100
+ initProject({ github: hasFlag("--github") });
101
+ break;
102
+ }
103
+
104
+ case "deploy": {
105
+ const config = loadConfig(configPath);
106
+ const { deploy } = require("../lib/deploy");
107
+ deploy(config, {
108
+ message: getOption("-m", "--message"),
109
+ noWait: hasFlag("--no-wait"),
110
+ draft: hasFlag("--draft"),
111
+ });
112
+ break;
113
+ }
114
+
115
+ default:
116
+ console.error(`Unknown command: ${command}`);
117
+ printHelp();
118
+ process.exit(1);
119
+ }
@@ -0,0 +1,32 @@
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+ const PageBase = require("./mod/page_base");
4
+
5
+ module.exports = class AllPostsPage extends PageBase {
6
+ constructor(config) {
7
+ super(config);
8
+ }
9
+
10
+ // posts: array of Page objects
11
+ generateContent(posts) {
12
+ const pageTitle = "All posts";
13
+ if (!fs.existsSync(`${this.config.dev.outdir}/all_posts/`))
14
+ fs.mkdirSync(`${this.config.dev.outdir}/all_posts/`);
15
+
16
+ const data = { posts: posts, pageTitle: pageTitle };
17
+ this.url = `${this.config.blogsite}/posts.html`;
18
+ this.title = `${this.config.blogName}: ${data.pageTitle}`;
19
+ this.description = "All posts";
20
+ this.imageURL = this.config.image;
21
+
22
+ const templatePath = path.join(this.config.themePath, "layouts", "all_posts.html");
23
+ fs.writeFileSync(
24
+ `${this.config.dev.outdir}/all_posts/index.html`,
25
+ this.generateHTML(templatePath, data),
26
+ (e) => {
27
+ if (e) throw e;
28
+ console.log(`posts.html was created successfully`);
29
+ },
30
+ );
31
+ }
32
+ };
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="800" height="400" viewBox="0 0 800 400">
2
+ <rect width="800" height="400" fill="#f0f0f0"/>
3
+ <text x="400" y="200" font-family="Arial, sans-serif" font-size="32" fill="#999" text-anchor="middle" dominant-baseline="middle">Your Image Here</text>
4
+ </svg>
package/lib/deploy.js ADDED
@@ -0,0 +1,202 @@
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+ const { execSync, exec } = require("child_process");
4
+ const { build } = require("./index");
5
+
6
+ /**
7
+ * Deploy the blog: build → commit → push → poll CI → show URL.
8
+ */
9
+ async function deploy(config, options = {}) {
10
+ const cwd = process.cwd();
11
+ const deployConfig = config.deploy || {};
12
+ const branch = deployConfig.branch || "main";
13
+ const remote = deployConfig.remote || "origin";
14
+
15
+ // 1. Build the site
16
+ console.log("Building site...");
17
+ build(config);
18
+ console.log("Build complete.\n");
19
+
20
+ // 2. Check git is initialized
21
+ if (!fs.existsSync(path.join(cwd, ".git"))) {
22
+ console.error("Error: Not a git repository. Run 'fossbook init --github' first.");
23
+ process.exit(1);
24
+ }
25
+
26
+ // 3. Stage all changes
27
+ execSync("git add -A", { cwd, stdio: "inherit" });
28
+
29
+ // 4. Check if there are changes to commit
30
+ try {
31
+ execSync("git diff --cached --quiet", { cwd });
32
+ console.log("No changes to commit.");
33
+ return;
34
+ } catch {
35
+ // There are staged changes — continue
36
+ }
37
+
38
+ // 5. Determine commit message
39
+ let commitMessage = options.message;
40
+ if (!commitMessage) {
41
+ commitMessage = detectNewPost(config) || "Update blog";
42
+ }
43
+
44
+ // 6. Commit
45
+ console.log(`Committing: "${commitMessage}"`);
46
+ execSync(`git commit -m "${commitMessage.replace(/"/g, '\\"')}"`, {
47
+ cwd,
48
+ stdio: "inherit",
49
+ });
50
+
51
+ // 7. If --draft, stop here
52
+ if (options.draft) {
53
+ console.log("\nDraft committed locally. Run 'fossbook deploy' again to push.");
54
+ return;
55
+ }
56
+
57
+ // 8. Push
58
+ console.log(`\nPushing to ${remote}/${branch}...`);
59
+ try {
60
+ execSync(`git push ${remote} ${branch}`, { cwd, stdio: "inherit" });
61
+ } catch (e) {
62
+ console.error(`Error: Failed to push to ${remote}/${branch}.`);
63
+ console.error("Make sure the remote exists and you have push access.");
64
+ process.exit(1);
65
+ }
66
+
67
+ // 9. Wait for CI/CD and show URL
68
+ if (options.noWait) {
69
+ console.log("\nPushed! Skipping CI/CD status check (--no-wait).");
70
+ printSiteUrl(config);
71
+ return;
72
+ }
73
+
74
+ await waitForDeployment(cwd, config);
75
+ }
76
+
77
+ /**
78
+ * Detect if a new post was added and return a commit message.
79
+ */
80
+ function detectNewPost(config) {
81
+ try {
82
+ const diffOutput = execSync("git diff --cached --name-only", {
83
+ encoding: "utf-8",
84
+ });
85
+ const postsDir = config.postsDir || "./content/posts";
86
+ const newPosts = diffOutput
87
+ .split("\n")
88
+ .filter((f) => f.startsWith(postsDir.replace("./", "")) && f.endsWith("index.md"))
89
+ .map((f) => {
90
+ // Extract post title from path like "content/posts/My Post/index.md"
91
+ const parts = f.split("/");
92
+ return parts[parts.length - 2];
93
+ });
94
+
95
+ if (newPosts.length === 1) {
96
+ return `Publish: ${newPosts[0]}`;
97
+ } else if (newPosts.length > 1) {
98
+ return `Publish ${newPosts.length} new posts`;
99
+ }
100
+ } catch {
101
+ // Fall through
102
+ }
103
+ return null;
104
+ }
105
+
106
+ /**
107
+ * Wait for GitHub Actions deployment to complete, then show the URL.
108
+ */
109
+ async function waitForDeployment(cwd, config) {
110
+ // Check if gh is available
111
+ const hasGh = isGhAvailable();
112
+
113
+ if (!hasGh) {
114
+ console.log("\nGitHub CLI (gh) not found. Cannot monitor deployment status.");
115
+ console.log("Install it to see live deployment progress: https://cli.github.com/");
116
+ printSiteUrl(config);
117
+ return;
118
+ }
119
+
120
+ console.log("\nWaiting for GitHub Pages deployment...");
121
+
122
+ try {
123
+ // Wait a moment for the workflow to be triggered
124
+ await sleep(3000);
125
+
126
+ // Get the latest workflow run
127
+ const runJson = execSync(
128
+ 'gh run list --workflow=deploy.yml --limit=1 --json databaseId,status,conclusion',
129
+ { cwd, encoding: "utf-8" }
130
+ );
131
+ const runs = JSON.parse(runJson);
132
+
133
+ if (runs.length === 0) {
134
+ console.log("No workflow runs found. The deployment may not be configured yet.");
135
+ console.log("Enable GitHub Pages: Settings → Pages → Source → GitHub Actions");
136
+ return;
137
+ }
138
+
139
+ const runId = runs[0].databaseId;
140
+
141
+ // Watch the run
142
+ console.log(`Monitoring workflow run #${runId}...`);
143
+ execSync(`gh run watch ${runId}`, { cwd, stdio: "inherit" });
144
+
145
+ // Check result
146
+ const resultJson = execSync(
147
+ `gh run view ${runId} --json conclusion`,
148
+ { cwd, encoding: "utf-8" }
149
+ );
150
+ const result = JSON.parse(resultJson);
151
+
152
+ if (result.conclusion === "success") {
153
+ console.log("\n✅ Deployment successful!");
154
+ printSiteUrl(config);
155
+ } else {
156
+ console.error(`\n❌ Deployment failed (conclusion: ${result.conclusion}).`);
157
+ console.log(`View details: gh run view ${runId} --log`);
158
+ process.exit(1);
159
+ }
160
+ } catch (e) {
161
+ console.warn("\nCould not monitor deployment status.");
162
+ console.log("Check your deployment at: https://github.com → Actions tab");
163
+ printSiteUrl(config);
164
+ }
165
+ }
166
+
167
+ /**
168
+ * Print the site URL based on config.
169
+ */
170
+ function printSiteUrl(config) {
171
+ const siteUrl = config.blogsite || config.githubCNAME;
172
+ if (siteUrl && siteUrl !== "http://localhost:3000") {
173
+ console.log(`\nView your site at: ${siteUrl}`);
174
+ } else {
175
+ // Try to infer from git remote
176
+ try {
177
+ const remoteUrl = execSync("git remote get-url origin", { encoding: "utf-8" }).trim();
178
+ const match = remoteUrl.match(/github\.com[:/](.+?)(?:\.git)?$/);
179
+ if (match) {
180
+ const [owner, repo] = match[1].split("/");
181
+ console.log(`\nView your site at: https://${owner}.github.io/${repo}/`);
182
+ }
183
+ } catch {
184
+ console.log("\nYour site will be available on GitHub Pages once deployment completes.");
185
+ }
186
+ }
187
+ }
188
+
189
+ function isGhAvailable() {
190
+ try {
191
+ execSync("gh --version", { stdio: "ignore" });
192
+ return true;
193
+ } catch {
194
+ return false;
195
+ }
196
+ }
197
+
198
+ function sleep(ms) {
199
+ return new Promise((resolve) => setTimeout(resolve, ms));
200
+ }
201
+
202
+ module.exports = { deploy };
package/lib/home.js ADDED
@@ -0,0 +1,59 @@
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+ const PageBase = require("./mod/page_base");
4
+
5
+ module.exports = class Pagination extends PageBase {
6
+ constructor(config) {
7
+ super(config);
8
+ }
9
+
10
+ generateContent(posts) {
11
+ const postsPerPage = 5;
12
+ const numPages = Math.ceil(posts.length / postsPerPage);
13
+
14
+ if (fs.existsSync(`${this.config.dev.outdir}/page`))
15
+ fs.rmSync(`${this.config.dev.outdir}/page`, { recursive: true });
16
+
17
+ fs.mkdirSync(`${this.config.dev.outdir}/page`);
18
+
19
+ // copy content/page/1.html to outdir/page/1.html
20
+ const contentPagePath = path.join(this.config.dev.content, "page", "1.html");
21
+ if (fs.existsSync(contentPagePath))
22
+ fs.copyFileSync(
23
+ contentPagePath,
24
+ `${this.config.dev.outdir}/page/1.html`,
25
+ );
26
+
27
+ for (let i = 0; i < numPages; i++) {
28
+ const pagePosts = posts.slice(i * postsPerPage, (i + 1) * postsPerPage);
29
+
30
+ let filePath;
31
+ let url;
32
+ if (i === 0) {
33
+ filePath = `${this.config.dev.outdir}/index.html`;
34
+ url = this.config.blogsite;
35
+ } else {
36
+ filePath = `${this.config.dev.outdir}/page/${i + 1}.html`;
37
+ url = `${this.config.blogsite}/page/${i + 1}.html`;
38
+ }
39
+ const prev = i - 1 >= 0 ? i : null;
40
+ const next = i + 1 < numPages ? i + 2 : null;
41
+
42
+ console.log("prev", prev, "next", next);
43
+ this.url = url;
44
+ this.title = `${this.config.blogName}`;
45
+ this.imageURL = this.config.image;
46
+ const data = { posts: pagePosts, prev: prev, next: next };
47
+
48
+ const templatePath = path.join(this.config.themePath, "layouts", "home.html");
49
+ fs.writeFile(
50
+ `${filePath}`,
51
+ this.generateHTML(templatePath, data),
52
+ (e) => {
53
+ if (e) throw e;
54
+ console.log(`page/${i + 1}.html was created successfully`);
55
+ },
56
+ );
57
+ }
58
+ }
59
+ };